@any-listen/extension-kit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,92 @@
1
+ import path from "node:path";
2
+ import fs from "node:fs/promises";
3
+ import { build } from "vite";
4
+ //#region src/state.ts
5
+ var state = {
6
+ srcDir: "",
7
+ distDir: "",
8
+ outputDir: "",
9
+ i18nDir: "",
10
+ resourcesDir: "",
11
+ isIsolateMode: false,
12
+ mainEntry: "",
13
+ isolatePreloadEntry: ""
14
+ };
15
+ //#endregion
16
+ //#region src/constants.ts
17
+ var EXTENSION = {
18
+ pkgExtName: "alix",
19
+ mainifestName: "manifest.json",
20
+ signFileName: "sig",
21
+ extBundleFileName: "ext.tgz",
22
+ entryFileName: "main.js",
23
+ versionInfoName: "version.json"
24
+ };
25
+ //#endregion
26
+ //#region src/utils.ts
27
+ var ROOT_DIR = path.join(import.meta.dirname.split("node_modules")[0]);
28
+ var buildPath = (subPath) => {
29
+ if (path.isAbsolute(subPath)) return subPath;
30
+ return path.join(ROOT_DIR, subPath);
31
+ };
32
+ var getConfig = async () => {
33
+ var _config$buildConfig, _config$buildConfig2, _config$buildConfig3, _config$buildConfig4, _config$buildConfig5, _config$buildConfig6;
34
+ const configPath = path.join(ROOT_DIR, "config.ts");
35
+ await fs.access(configPath, fs.constants.F_OK);
36
+ const config = (await import(`file://${configPath}`)).default;
37
+ state.srcDir = buildPath(((_config$buildConfig = config.buildConfig) === null || _config$buildConfig === void 0 ? void 0 : _config$buildConfig.srcDir) || "src");
38
+ state.distDir = buildPath(((_config$buildConfig2 = config.buildConfig) === null || _config$buildConfig2 === void 0 ? void 0 : _config$buildConfig2.distDir) || "dist");
39
+ state.outputDir = buildPath(((_config$buildConfig3 = config.buildConfig) === null || _config$buildConfig3 === void 0 ? void 0 : _config$buildConfig3.outputDir) || "build");
40
+ state.i18nDir = buildPath(((_config$buildConfig4 = config.buildConfig) === null || _config$buildConfig4 === void 0 ? void 0 : _config$buildConfig4.i18nDir) || "i18n");
41
+ state.resourcesDir = buildPath(((_config$buildConfig5 = config.buildConfig) === null || _config$buildConfig5 === void 0 ? void 0 : _config$buildConfig5.resourcesDir) || "resources");
42
+ state.isIsolateMode = ((_config$buildConfig6 = config.buildConfig) === null || _config$buildConfig6 === void 0 ? void 0 : _config$buildConfig6.isIsolateMode) || false;
43
+ if (state.isIsolateMode) {
44
+ var _config$buildConfig7, _config$buildConfig8;
45
+ state.mainEntry = buildPath(((_config$buildConfig7 = config.buildConfig) === null || _config$buildConfig7 === void 0 ? void 0 : _config$buildConfig7.mainEntry) || path.join(state.srcDir, "main/index.ts"));
46
+ state.isolatePreloadEntry = buildPath(((_config$buildConfig8 = config.buildConfig) === null || _config$buildConfig8 === void 0 ? void 0 : _config$buildConfig8.isolatePreloadEntry) || path.join(state.srcDir, "isolate-preload/index.ts"));
47
+ } else {
48
+ var _config$buildConfig9;
49
+ state.mainEntry = buildPath(((_config$buildConfig9 = config.buildConfig) === null || _config$buildConfig9 === void 0 ? void 0 : _config$buildConfig9.mainEntry) || path.join(state.srcDir, "index.ts"));
50
+ }
51
+ return config;
52
+ };
53
+ var loadEnvFile = async () => {
54
+ const envPath = path.join(ROOT_DIR, ".env");
55
+ let envContent;
56
+ try {
57
+ await fs.access(envPath, fs.constants.F_OK);
58
+ envContent = (await fs.readFile(envPath, "utf-8")).trim();
59
+ } catch {
60
+ return;
61
+ }
62
+ if (!envContent) return;
63
+ const lines = envContent.split("\n");
64
+ for (const line of lines) {
65
+ let [key, ...rest] = line.split("=");
66
+ key = key.trim();
67
+ if (key.startsWith("#") || key === "") continue;
68
+ process.env[key] = rest.join("=").trim();
69
+ }
70
+ };
71
+ var buildPackageName = (config) => {
72
+ return `${config.id}_v${config.version}.${EXTENSION.pkgExtName}`;
73
+ };
74
+ /**
75
+ * build code
76
+ */
77
+ var build$1 = async (config) => {
78
+ if (config.build) config.build.watch = null;
79
+ return build({
80
+ ...config,
81
+ configFile: false
82
+ }).then(() => {
83
+ return true;
84
+ }).catch((error) => {
85
+ console.log(error);
86
+ return false;
87
+ });
88
+ };
89
+ //#endregion
90
+ export { loadEnvFile as a, getConfig as i, build$1 as n, EXTENSION as o, buildPackageName as r, state as s, ROOT_DIR as t };
91
+
92
+ //# sourceMappingURL=utils-BN85b34y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-BN85b34y.js","names":[],"sources":["../src/state.ts","../src/constants.ts","../src/utils.ts"],"sourcesContent":["export const state = {\n srcDir: '',\n distDir: '',\n outputDir: '',\n i18nDir: '',\n resourcesDir: '',\n isIsolateMode: false,\n mainEntry: '',\n isolatePreloadEntry: '',\n}\n","export const EXTENSION = {\n pkgExtName: 'alix',\n mainifestName: 'manifest.json',\n signFileName: 'sig',\n extBundleFileName: 'ext.tgz',\n entryFileName: 'main.js',\n versionInfoName: 'version.json',\n}\n","import fs from 'node:fs/promises'\nimport path from 'node:path'\n\nimport { build as viteBuild, type UserConfig } from 'vite'\n\nimport { EXTENSION } from './constants'\nimport { state } from './state'\nimport type { ExtensionConfig } from './types/build'\n\nexport const ROOT_DIR = path.join(import.meta.dirname.split('node_modules')[0])\n\nconst buildPath = (subPath: string) => {\n if (path.isAbsolute(subPath)) return subPath\n return path.join(ROOT_DIR, subPath)\n}\n\nexport const getConfig = async () => {\n const configPath = path.join(ROOT_DIR, 'config.ts')\n await fs.access(configPath, fs.constants.F_OK)\n const config = ((await import(`file://${configPath}`)) as { default: ExtensionConfig }).default\n\n state.srcDir = buildPath(config.buildConfig?.srcDir || 'src')\n state.distDir = buildPath(config.buildConfig?.distDir || 'dist')\n state.outputDir = buildPath(config.buildConfig?.outputDir || 'build')\n state.i18nDir = buildPath(config.buildConfig?.i18nDir || 'i18n')\n state.resourcesDir = buildPath(config.buildConfig?.resourcesDir || 'resources')\n state.isIsolateMode = config.buildConfig?.isIsolateMode || false\n if (state.isIsolateMode) {\n state.mainEntry = buildPath(config.buildConfig?.mainEntry || path.join(state.srcDir, 'main/index.ts'))\n state.isolatePreloadEntry = buildPath(\n config.buildConfig?.isolatePreloadEntry || path.join(state.srcDir, 'isolate-preload/index.ts')\n )\n } else {\n state.mainEntry = buildPath(config.buildConfig?.mainEntry || path.join(state.srcDir, 'index.ts'))\n }\n\n return config\n}\n\nexport const loadEnvFile = async () => {\n const envPath = path.join(ROOT_DIR, '.env')\n let envContent: string\n try {\n await fs.access(envPath, fs.constants.F_OK)\n envContent = (await fs.readFile(envPath, 'utf-8')).trim()\n } catch {\n return\n }\n if (!envContent) return\n const lines = envContent.split('\\n')\n for (const line of lines) {\n let [key, ...rest] = line.split('=')\n key = key.trim()\n if (key.startsWith('#') || key === '') continue\n process.env[key] = rest.join('=').trim()\n }\n}\n\nexport const buildPackageName = (config: ExtensionConfig) => {\n return `${config.id}_v${config.version}.${EXTENSION.pkgExtName}`\n}\n\n/**\n * build code\n */\nexport const build = async (config: UserConfig) => {\n if (config.build) config.build.watch = null\n return viteBuild({ ...config, configFile: false })\n .then(() => {\n // output\n // console.log(output)\n return true\n })\n .catch((error) => {\n console.log(error)\n return false\n })\n}\n"],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ import pluginJs from '@eslint/js'
2
+ // import { typescriptRule } from './eslintrc.base.mjs'
3
+ // import tseslint from "typescript-eslint";
4
+ import typescriptParser from '@typescript-eslint/parser'
5
+ import love from 'eslint-config-love'
6
+ import globals from 'globals'
7
+
8
+ export { typescriptParser }
9
+ export const baseRule = {
10
+ eqeqeq: 'off',
11
+ 'require-atomic-updates': ['error', { allowProperties: true }],
12
+ 'prefer-const': 'off',
13
+ 'no-else-return': 'error',
14
+ 'object-shorthand': ['error', 'always'],
15
+ 'prefer-arrow-callback': 'error',
16
+ 'prefer-object-spread': 'error',
17
+ 'prefer-template': 'error',
18
+ yoda: 'error',
19
+ 'no-console': 'off',
20
+ 'no-await-in-loop': 'off',
21
+ 'promise/avoid-new': 'off',
22
+ 'eslint-comments/no-unlimited-disable': 'off',
23
+ 'eslint-comments/require-description': 'off',
24
+ curly: ['error', 'multi-line'],
25
+ 'arrow-body-style': 'off',
26
+ 'max-nested-callbacks': 'off',
27
+ complexity: 'off',
28
+ 'max-lines': 'off',
29
+ 'no-param-reassign': 'off',
30
+ 'no-plusplus': 'off',
31
+ 'prefer-named-capture-group': 'off',
32
+ '@eslint-community/eslint-comments/require-description': 'off',
33
+ 'require-unicode-regexp': 'off',
34
+ radix: 'off',
35
+ }
36
+ export const typescriptRule = {
37
+ ...baseRule,
38
+ '@typescript-eslint/prefer-nullish-coalescing': 'off',
39
+ '@typescript-eslint/no-magic-numbers': 'off',
40
+ '@typescript-eslint/prefer-destructuring': 'off',
41
+ '@typescript-eslint/strict-boolean-expressions': 'off',
42
+ '@typescript-eslint/explicit-function-return-type': 'off',
43
+ '@typescript-eslint/init-declarations': 'off',
44
+ '@typescript-eslint/no-unsafe-type-assertion': 'off',
45
+ '@typescript-eslint/no-non-null-assertion': 'off',
46
+ '@typescript-eslint/require-await': 'off',
47
+ '@typescript-eslint/no-unsafe-call': 'off',
48
+ '@typescript-eslint/use-unknown-in-catch-callback-variable': 'off',
49
+ '@typescript-eslint/await-thenable': 'off',
50
+ '@typescript-eslint/no-empty-function': 'off',
51
+ '@typescript-eslint/no-misused-promises': 'off',
52
+ '@typescript-eslint/no-unsafe-assignment': 'off',
53
+ '@typescript-eslint/no-unnecessary-type-conversion': 'off',
54
+ '@typescript-eslint/no-explicit-any': 'warn',
55
+ '@typescript-eslint/strict-void-return': 'off',
56
+ '@typescript-eslint/no-unnecessary-condition': 'off',
57
+
58
+ '@typescript-eslint/no-confusing-void-expression': [
59
+ 'error',
60
+ {
61
+ ignoreVoidReturningFunctions: true,
62
+ },
63
+ ],
64
+ '@typescript-eslint/no-unnecessary-type-parameters': 'off',
65
+ '@typescript-eslint/return-await': ['error', 'in-try-catch'],
66
+ '@typescript-eslint/ban-ts-comment': 'off',
67
+ '@typescript-eslint/max-params': [
68
+ 'error',
69
+ {
70
+ max: 6,
71
+ },
72
+ ],
73
+ }
74
+
75
+ /** @type {import('eslint').Linter.Config} */
76
+ export const js = {
77
+ files: ['**/*.{js,mjs,cjs}'],
78
+ ...pluginJs.configs.recommended,
79
+ rules: {
80
+ ...pluginJs.configs.recommended.rules,
81
+ ...baseRule,
82
+ },
83
+ }
84
+
85
+ /** @type {import('eslint').Linter.Config} */
86
+ export const jsNode = {
87
+ ...js,
88
+ languageOptions: {
89
+ globals: globals.node,
90
+ },
91
+ }
92
+
93
+ /** @type {import('eslint').Linter.Config} */
94
+ export const jsBrowser = {
95
+ ...js,
96
+ languageOptions: {
97
+ globals: globals.browser,
98
+ },
99
+ }
100
+
101
+ /** @type {import('eslint').Linter.Config} */
102
+ export const typescript = {
103
+ ...love,
104
+ // files: ['**/*.{ts}'],
105
+ files: ['**/*.ts'],
106
+ rules: {
107
+ ...love.rules,
108
+ ...typescriptRule,
109
+ },
110
+ }
111
+
112
+ /** @type {import('eslint').Linter.Config[]} */
113
+ export default [
114
+ js,
115
+ typescript,
116
+ {
117
+ languageOptions: {
118
+ parserOptions: {
119
+ parser: typescriptParser,
120
+ },
121
+ },
122
+ },
123
+ ]
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "@any-listen/extension-kit",
3
+ "version": "0.1.0",
4
+ "keywords": [
5
+ "any-listen",
6
+ "any-listen-extension"
7
+ ],
8
+ "homepage": "https://github.com/any-listen/extension-kit#readme",
9
+ "bugs": {
10
+ "url": "https://github.com/any-listen/extension-kit/issues"
11
+ },
12
+ "license": "Apache-2.0",
13
+ "author": {
14
+ "name": "lyswhut",
15
+ "email": "lyswhut@qq.com"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/any-listen/extension-kit.git"
20
+ },
21
+ "bin": "dist/bin.js",
22
+ "files": [
23
+ "dist",
24
+ "types",
25
+ "tsconfigs",
26
+ "eslint",
27
+ "src",
28
+ "LICENSE",
29
+ "README.md",
30
+ "package.json"
31
+ ],
32
+ "type": "module",
33
+ "types": "./types/app/index.d.ts",
34
+ "exports": {
35
+ ".": {
36
+ "types": "./types/app/index.d.ts"
37
+ },
38
+ "./config": {
39
+ "types": "./types/build.d.ts"
40
+ },
41
+ "./isolate": {
42
+ "types": "./types/isolate.d.ts"
43
+ },
44
+ "./tsconfig.app.json": {
45
+ "default": "./tsconfigs/tsconfig.app.json"
46
+ },
47
+ "./tsconfig.node.json": {
48
+ "default": "./tsconfigs/tsconfig.node.json"
49
+ },
50
+ "./tsconfig.isolate.json": {
51
+ "default": "./tsconfigs/tsconfig.isolate.json"
52
+ },
53
+ "./eslint.config.js": {
54
+ "default": "./eslint/eslint.config.js"
55
+ }
56
+ },
57
+ "scripts": {
58
+ "build": "vite build"
59
+ },
60
+ "dependencies": {
61
+ "@eslint/js": "^9.39.4",
62
+ "@tsconfig/node24": "^24.0.4",
63
+ "@tsconfig/recommended": "^1.0.13",
64
+ "@typescript-eslint/eslint-plugin": "^8.58.1",
65
+ "@typescript-eslint/parser": "^8.58.1",
66
+ "eslint-config-love": "^152.0.0",
67
+ "globals": "^17.5.0",
68
+ "tar": "^7.5.13",
69
+ "vite": "^8.0.8"
70
+ },
71
+ "devDependencies": {
72
+ "@types/node": "^25.6.0",
73
+ "eslint": "^9.39.4",
74
+ "oxfmt": "^0.44.0",
75
+ "typescript": "^5.9.3"
76
+ },
77
+ "peerDependencies": {
78
+ "eslint": "^9.39.4"
79
+ },
80
+ "packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319"
81
+ }
package/src/build.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { cpResources } from './cpResources'
2
+ import { createMainifest } from './mainifest'
3
+ import { pack } from './pack'
4
+ import { state } from './state'
5
+ import { build, getConfig, loadEnvFile } from './utils'
6
+ import createConfigs from './vite.config'
7
+
8
+ const run = async () => {
9
+ await loadEnvFile()
10
+ const config = await getConfig()
11
+ const appConfigs = createConfigs(state.isIsolateMode)
12
+ await Promise.all(appConfigs.map(async (appConfig) => build(appConfig)))
13
+ await Promise.all([cpResources(), createMainifest(config)])
14
+ await pack(config)
15
+ }
16
+
17
+ void run()
@@ -0,0 +1,8 @@
1
+ export const EXTENSION = {
2
+ pkgExtName: 'alix',
3
+ mainifestName: 'manifest.json',
4
+ signFileName: 'sig',
5
+ extBundleFileName: 'ext.tgz',
6
+ entryFileName: 'main.js',
7
+ versionInfoName: 'version.json',
8
+ }
@@ -0,0 +1,16 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+
4
+ import { state } from './state'
5
+
6
+ export const cpResources = async () => {
7
+ const sourcePath = state.resourcesDir
8
+ const targetPath = path.join(state.distDir, 'resources')
9
+ const sourceI18nPath = state.i18nDir
10
+ const targetI18nPath = path.join(state.distDir, 'i18n')
11
+
12
+ await Promise.all([
13
+ fs.promises.cp(sourcePath, targetPath, { recursive: true }),
14
+ fs.promises.cp(sourceI18nPath, targetI18nPath, { recursive: true }),
15
+ ])
16
+ }
package/src/index.ts ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { argv } from 'node:process'
4
+ import { parseArgs } from 'node:util'
5
+
6
+ const { values } = parseArgs({
7
+ args: argv.slice(2),
8
+ options: {
9
+ build: {
10
+ type: 'boolean',
11
+ },
12
+ publish: {
13
+ type: 'boolean',
14
+ },
15
+ },
16
+ })
17
+
18
+ if (values.build) {
19
+ void import('./build')
20
+ } else if (values.publish) {
21
+ void import('./publish')
22
+ } else {
23
+ console.log('Please specify a command: build or publish')
24
+ }
@@ -0,0 +1,27 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+
4
+ import { EXTENSION } from './constants'
5
+ import { state } from './state'
6
+ import type { ExtensionConfig } from './types/build'
7
+
8
+ export const createMainifest = async (config: ExtensionConfig) => {
9
+ const mainifest = {
10
+ id: config.id,
11
+ name: config.name,
12
+ description: config.description,
13
+ icon: config.icon,
14
+ version: config.version,
15
+ target_engine: config.target_engine,
16
+ author: config.author,
17
+ homepage: config.homepage,
18
+ license: config.license,
19
+ categories: config.categories,
20
+ tags: config.tags,
21
+ grant: config.grant,
22
+ contributes: config.contributes,
23
+ main: EXTENSION.entryFileName,
24
+ }
25
+
26
+ await fs.promises.writeFile(path.join(state.distDir, EXTENSION.mainifestName), JSON.stringify(mainifest, null, 2), 'utf8')
27
+ }
package/src/pack.ts ADDED
@@ -0,0 +1,80 @@
1
+ import crypto from 'node:crypto'
2
+ import fs from 'node:fs'
3
+ import path from 'node:path'
4
+
5
+ import { EXTENSION } from './constants'
6
+ import { state } from './state'
7
+ import type { ExtensionConfig } from './types/build'
8
+ import { buildPackageName } from './utils'
9
+
10
+ const buildPublicKey = (publicKey: string) => {
11
+ if (!publicKey.includes('-----BEGIN PUBLIC KEY-----')) {
12
+ return `-----BEGIN PUBLIC KEY-----\n${publicKey}\n-----END PUBLIC KEY-----`
13
+ }
14
+ return publicKey
15
+ }
16
+
17
+ const signData = (data: Buffer, privateKey: string) => {
18
+ const sign = crypto.createSign('SHA256')
19
+ sign.update(data)
20
+ sign.end()
21
+ const signature = sign.sign(privateKey, 'hex')
22
+ return signature
23
+ }
24
+ const verifySignature = (data: Buffer, publicKey: string, signature: string) => {
25
+ const verify = crypto.createVerify('SHA256')
26
+ verify.update(data)
27
+ verify.end()
28
+ const isValid = verify.verify(publicKey, signature, 'hex')
29
+ return isValid
30
+ }
31
+
32
+ const packFile = async ({ gzip, cwd, files, dist }: { gzip: boolean; cwd: string; files: string[]; dist: string }) => {
33
+ const { c } = await import('tar')
34
+ return new Promise<void>((resolve, reject) => {
35
+ c(
36
+ {
37
+ gzip,
38
+ cwd,
39
+ },
40
+ files
41
+ )
42
+ .pipe(fs.createWriteStream(dist))
43
+ .on('finish', () => {
44
+ resolve()
45
+ })
46
+ .on('error', reject)
47
+ })
48
+ }
49
+
50
+ export const pack = async (config: ExtensionConfig) => {
51
+ let privateKey = process.env.PRI_KEY?.trim()
52
+ let publicKey = process.env.PUB_KEY?.trim()
53
+ if (!privateKey || !publicKey) throw new Error('Missing private key or public key')
54
+ if (!privateKey.includes('-----BEGIN PRIVATE KEY-----')) {
55
+ privateKey = `-----BEGIN PRIVATE KEY-----\n${privateKey}\n-----END PRIVATE KEY-----`
56
+ }
57
+
58
+ const unpackedDir = path.join(state.outputDir, 'unpacked')
59
+ await fs.promises.rm(unpackedDir, { recursive: true }).catch(() => {})
60
+ await fs.promises.mkdir(unpackedDir, { recursive: true }).catch(() => {})
61
+ const extBundleFilePath = path.join(unpackedDir, EXTENSION.extBundleFileName)
62
+ await packFile({
63
+ gzip: true,
64
+ cwd: state.distDir,
65
+ files: [EXTENSION.entryFileName, EXTENSION.mainifestName, 'resources', 'i18n'],
66
+ dist: extBundleFilePath,
67
+ })
68
+ const buf = await fs.promises.readFile(extBundleFilePath)
69
+ const signature = signData(buf, privateKey)
70
+ if (!verifySignature(buf, buildPublicKey(publicKey), signature)) {
71
+ throw new Error('Signature is valid, please check your public key')
72
+ }
73
+ await fs.promises.writeFile(path.join(unpackedDir, EXTENSION.signFileName), `${signature}\n${publicKey}`)
74
+ await packFile({
75
+ gzip: true,
76
+ cwd: unpackedDir,
77
+ files: [EXTENSION.extBundleFileName, EXTENSION.signFileName],
78
+ dist: path.join(state.outputDir, buildPackageName(config)),
79
+ })
80
+ }
package/src/publish.ts ADDED
@@ -0,0 +1,43 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+
4
+ import type { VersionInfo } from './types/build'
5
+ import { buildPackageName, getConfig, ROOT_DIR } from './utils'
6
+
7
+ export const run = async () => {
8
+ const config = await getConfig()
9
+ const filePath = path.join(ROOT_DIR, 'publish/version.json')
10
+ let versionInfo = await fs.promises
11
+ .readFile(filePath, 'utf-8')
12
+ .then((d) => JSON.parse(d) as VersionInfo)
13
+ .catch(() => null)
14
+ if (versionInfo) {
15
+ if (versionInfo.version === config.version) {
16
+ console.warn(`Version (v${config.version}) already published`)
17
+ process.exit(1)
18
+ }
19
+ versionInfo.history ||= []
20
+ versionInfo.history.push({
21
+ version: versionInfo.version,
22
+ download_url: versionInfo.download_url,
23
+ log: versionInfo.log,
24
+ date: versionInfo.date,
25
+ })
26
+ } else {
27
+ versionInfo = { version: '', download_url: '', log: '', date: new Date().toISOString() }
28
+ }
29
+ versionInfo.version = config.version
30
+ if (config.download_url_template) {
31
+ versionInfo.download_url = `${config.download_url_template.replaceAll('{version}', config.version)}/${buildPackageName(config)}`
32
+ }
33
+ versionInfo.log = await fs.promises
34
+ .readFile(path.join(ROOT_DIR, 'publish/changeLog.md'), 'utf-8')
35
+ .then((d) => d.toString().trim())
36
+ .catch(() => '')
37
+ versionInfo.date = new Date().toISOString()
38
+
39
+ await fs.promises.rm(filePath, { recursive: true, force: true })
40
+ await fs.promises.writeFile(filePath, JSON.stringify(versionInfo))
41
+ }
42
+
43
+ void run()
package/src/state.ts ADDED
@@ -0,0 +1,10 @@
1
+ export const state = {
2
+ srcDir: '',
3
+ distDir: '',
4
+ outputDir: '',
5
+ i18nDir: '',
6
+ resourcesDir: '',
7
+ isIsolateMode: false,
8
+ mainEntry: '',
9
+ isolatePreloadEntry: '',
10
+ }
@@ -0,0 +1,24 @@
1
+ import type { Manifest } from './extension_config.js'
2
+
3
+ export interface BuildConfig {
4
+ distDir?: string
5
+ outputDir?: string
6
+ i18nDir?: string
7
+ resourcesDir?: string
8
+ srcDir?: string
9
+ isIsolateMode?: boolean
10
+ mainEntry?: string
11
+ isolatePreloadEntry?: string
12
+ }
13
+
14
+ export interface ExtensionConfig extends Manifest {
15
+ buildConfig?: BuildConfig
16
+ }
17
+
18
+ export interface VersionInfo {
19
+ version: string
20
+ download_url: string
21
+ log: string
22
+ date: string
23
+ history?: VersionInfo[]
24
+ }