{"version":3,"sources":["../../../bin/start.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { ChildProcess, exec, spawn } from 'child_process'\nimport { program } from 'commander'\nimport fs from 'fs'\nimport { globSync } from 'glob'\nimport ini from 'ini'\nimport os from 'os'\nimport path from 'path'\n\nprogram.option('-b, --beta', 'start beta')\nprogram.parse(process.argv)\nconst options = program.opts()\n\ntype ProfileConfig = {\n  path: string\n  name?: string\n}\n\ntype ZoteroConfig = {\n  path?: string\n  log?: string\n  db?: string\n}\n\ntype PluginConfig = {\n  source: string\n  build: string\n}\n\ntype PreferenceConfig = Record<string, string | number | boolean | null>\n\nclass Config {\n  public profile: ProfileConfig\n  public zotero: ZoteroConfig\n  public plugin: PluginConfig\n  public preference: PreferenceConfig\n  public windows: boolean\n\n  constructor() {\n    const config_file = 'zotero-plugin.ini'\n    if (!fs.existsSync(config_file)) {\n      throw new Error(`Cannot find ${config_file}`)\n    }\n\n    const config = ini.parse(fs.readFileSync(config_file, 'utf-8'))\n\n    // Initialize profile configuration\n    this.profile = {\n      path: this.expandUserPath(config.profile?.path || ''),\n      name: config.profile?.name,\n    }\n\n    if (!this.profile.path) throw new Error('no profile path')\n\n    this.zotero = {\n      path: config.zotero?.[options.beta ? 'beta' : 'path'],\n      log: config.zotero?.log,\n      db: config.zotero?.db,\n    }\n\n    const beta = options.beta ? '-beta' : ''\n    if (this.zotero.path) {\n      this.zotero.path = this.expandUserPath(this.zotero.path)\n    }\n    else {\n      switch (os.platform()) {\n        case 'darwin':\n          this.zotero.path = `/Applications/Zotero${beta}.app/Contents/MacOS/zotero`\n          break\n        case 'linux':\n          this.zotero.path = `/usr/lib/zotero${beta}/zotero`\n          break\n        case 'win32':\n          this.zotero.path = `C:/Program Files (x86)/Zotero${beta}/Zotero.exe`\n          break\n        default:\n          throw new Error(`${os.platform()} not supported`)\n      }\n    }\n\n    this.windows = os.platform() === 'win32'\n\n    if (this.zotero.log) this.zotero.log = this.expandUserPath(this.zotero.log)\n\n    const source = config.plugin?.source || this.find_source()\n    if (!source) {\n      throw new Error('Plugin source not found.')\n    }\n    this.plugin = {\n      source: path.resolve(source),\n      build: config.plugin?.build || 'npm run build',\n    }\n\n    this.preference = {}\n    if (config.preferences) {\n      for (const key in config.preferences) {\n        if (Object.prototype.hasOwnProperty.call(config.preferences, key)) {\n          this.preference[key] = this.pref_value(config.preferences[key] as string)\n        }\n      }\n    }\n\n    this.preference['extensions.autoDisableScopes'] = 0\n    this.preference['extensions.enableScopes'] = 15\n    this.preference['extensions.startupScanScopes'] = 15\n    this.preference['extensions.zotero.debug.log'] = true\n    this.preference['extensions.lastAppBuildId'] = null\n    this.preference['extensions.lastAppVersion'] = null\n  }\n\n  private expandUserPath(p: string): string {\n    return p.startsWith('~') ? path.join(os.homedir(), p.slice(1)) : p\n  }\n\n  private find_source(): string | false {\n    const rdfs = globSync(path.join('*', 'manifest.json'))\n    if (rdfs.length > 0) {\n      return path.dirname(rdfs[0])\n    }\n    if (fs.existsSync('build')) {\n      return 'build'\n    }\n    return false\n  }\n\n  private pref_value(v: string): string | number | boolean | null {\n    if (v === 'true') return true\n    if (v === 'false') return false\n    if (v === 'null') return null\n    try {\n      return JSON.parse(v) as string | number | boolean\n    }\n    catch (e) {\n      return v\n    }\n  }\n}\n\nconst config = new Config()\n\nfunction patch_prefs(prefs: string, add_config: boolean): void {\n  const prefs_path = path.join(config.profile.path, `${prefs}.js`)\n  if (!fs.existsSync(prefs_path)) return\n\n  const lines = fs.readFileSync(prefs_path, 'utf-8').split('\\n')\n  const new_lines: string[] = []\n\n  for (const line of lines) {\n    const match = line.match(/user_pref\\(\"(.+?)\"/)\n    if (!match || !(match[1] in config.preference)) {\n      new_lines.push(line)\n    }\n  }\n\n  if (add_config) {\n    for (const [key, value] of Object.entries(config.preference)) {\n      if (value !== null) {\n        new_lines.push(`user_pref(${JSON.stringify(key)}, ${JSON.stringify(value)});`)\n      }\n    }\n  }\n\n  fs.writeFileSync(prefs_path, new_lines.join('\\n'))\n}\n\nasync function main() {\n  try {\n    patch_prefs('prefs', false)\n    patch_prefs('user', true)\n\n    if (config.plugin.build) {\n      await new Promise<void>((resolve, reject) => {\n        exec(config.plugin.build, (error, stdout, stderr) => {\n          if (error) {\n            reject(error)\n          }\n          else {\n            resolve()\n          }\n        })\n      })\n    }\n\n    if (config.zotero.db) {\n      fs.copyFileSync(config.zotero.db, path.join(config.profile.path, 'zotero', 'zotero.sqlite'))\n    }\n\n    const manifest = JSON.parse(fs.readFileSync(path.join(config.plugin.source, 'manifest.json'), 'utf-8'))\n\n    const addonId = manifest?.applications?.zotero?.id\n    if (!addonId) {\n      throw new Error('Could not find addon ID in manifest.json')\n    }\n\n    const plugin_path = path.join(config.profile.path, 'extensions', addonId)\n    const sources = config.plugin.source\n    const proxyPath = config.windows ? sources.replace(/\\\\/g, '\\\\\\\\') : sources\n\n    console.log('Writing addon source path to proxy file')\n    console.log('Source path:', sources)\n    console.log('Proxy file path:', plugin_path)\n\n    fs.writeFileSync(plugin_path, proxyPath)\n\n    const cmd = [\n      config.zotero.path,\n      '-purgecaches',\n      '-P',\n      config.profile.name,\n      config.windows ? '-ZoteroDebug' : '-ZoteroDebugText',\n      '-jsconsole',\n      '-datadir',\n      'profile',\n    ]\n    let child: ChildProcess\n    if (config.zotero.log) {\n      const log = fs.openSync(config.zotero.log, 'w')\n      child = spawn(cmd[0], cmd.slice(1), {\n        detached: true,\n        stdio: ['ignore', log, 'ignore'],\n      })\n    }\n    else {\n      child = spawn(cmd[0], cmd.slice(1))\n    }\n    child.unref()\n  }\n  catch (err) {\n    console.error(err)\n  }\n}\n\nmain()\n"],"mappings":"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","names":["fs","config","ini","os","path"]}