@neuxnet/neux-cli 0.2.3
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.
- package/README.md +438 -0
- package/README.zh-CN.md +554 -0
- package/assets/container/assets/index.css +1 -0
- package/assets/container/assets/index.js +137 -0
- package/assets/container/assets/pageFrame.css +1 -0
- package/assets/container/assets/pageFrame.js +56 -0
- package/assets/container/assets/service.js +6 -0
- package/assets/container/assets/vconsole.js +931 -0
- package/assets/container/favicon.ico +0 -0
- package/assets/container/images/icon-arrow.png +0 -0
- package/assets/container/images/mini-action-white.png +0 -0
- package/assets/container/images/mini-action.png +0 -0
- package/assets/container/images/mini-arrow-left-white.png +0 -0
- package/assets/container/images/mini-arrow-left.jpg +0 -0
- package/assets/container/images/mini-arrow-left.png +0 -0
- package/assets/container/images/mini-close-white.png +0 -0
- package/assets/container/images/mini-close.png +0 -0
- package/assets/container/images/more.png +0 -0
- package/assets/container/images/search.jpg +0 -0
- package/assets/container/index.html +1 -0
- package/assets/container/pageFrame.html +1 -0
- package/assets/init/tabbar/home-active.png +0 -0
- package/assets/init/tabbar/home.png +0 -0
- package/assets/init/tabbar/list-active.png +0 -0
- package/assets/init/tabbar/list.png +0 -0
- package/assets/init/types/neux-api.d.ts +1402 -0
- package/package.json +68 -0
- package/scripts/generate-init-types.js +210 -0
- package/scripts/sync-compiler.js +22 -0
- package/scripts/sync-web-container.js +34 -0
- package/src/bin/cli.js +646 -0
- package/src/core/brand.js +11 -0
- package/src/core/compiler.js +305 -0
- package/src/core/defaults.js +12 -0
- package/src/core/dev.js +15 -0
- package/src/core/errors.js +17 -0
- package/src/core/fs.js +66 -0
- package/src/core/i18n.js +37 -0
- package/src/core/init.js +866 -0
- package/src/core/lifecycle.js +32 -0
- package/src/core/manifest.js +72 -0
- package/src/core/pack.js +156 -0
- package/src/core/package-info.js +27 -0
- package/src/core/preview-server.js +123 -0
- package/src/core/project.js +101 -0
- package/src/core/prompts.js +71 -0
- package/src/core/proxy-security.js +141 -0
- package/src/core/proxy.js +156 -0
- package/src/core/qr.js +41 -0
- package/src/core/terminal-qr.js +72 -0
- package/src/core/update.js +278 -0
- package/src/core/watch.js +113 -0
- package/src/core/web.js +649 -0
- package/src/core/zip.js +120 -0
- package/src/index.js +20 -0
- package/src/providers/service-client.js +149 -0
- package/src/providers/service-config.js +264 -0
- package/src/providers/service.js +146 -0
- package/src/providers/upload.js +112 -0
- package/vendor/dimina-compiler/bin/index.cjs +265 -0
- package/vendor/dimina-compiler/bin/index.js +263 -0
- package/vendor/dimina-compiler/compatibility-B-DoZtUX.cjs +395 -0
- package/vendor/dimina-compiler/compatibility-Cl3-DO6V.js +366 -0
- package/vendor/dimina-compiler/core/logic-compiler.cjs +378 -0
- package/vendor/dimina-compiler/core/logic-compiler.js +374 -0
- package/vendor/dimina-compiler/core/style-compiler.cjs +392 -0
- package/vendor/dimina-compiler/core/style-compiler.js +377 -0
- package/vendor/dimina-compiler/core/view-compiler.cjs +1601 -0
- package/vendor/dimina-compiler/core/view-compiler.js +1582 -0
- package/vendor/dimina-compiler/index.cjs +762 -0
- package/vendor/dimina-compiler/index.js +751 -0
- package/vendor/dimina-compiler/sourcemap-BgtIgqkC.cjs +1377 -0
- package/vendor/dimina-compiler/sourcemap-CKjhV9h7.js +1135 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import fsp from 'node:fs/promises'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { pathToFileURL } from 'node:url'
|
|
4
|
+
import { DiminaCliError } from '../core/errors.js'
|
|
5
|
+
import { createServiceProvider } from './service.js'
|
|
6
|
+
|
|
7
|
+
function unsupported(command) {
|
|
8
|
+
throw new DiminaCliError(
|
|
9
|
+
'DIMINA_PROVIDER_UNSUPPORTED',
|
|
10
|
+
`${command} is reserved for provider-backed integrations and is not implemented in v1.`,
|
|
11
|
+
{ command },
|
|
12
|
+
)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function providerFunction(provider, command) {
|
|
16
|
+
if (command === 'submit') return provider.submit || provider.audit
|
|
17
|
+
if (command === 'audit') return provider.audit || provider.submit
|
|
18
|
+
if (command === 'login') return provider.login
|
|
19
|
+
if (command === 'debug-preview') return provider.debugPreview
|
|
20
|
+
if (command === 'service-preview') return provider.servicePreview || provider.preview
|
|
21
|
+
if (command === 'submit-audit') return provider.submitAudit || provider.submit || provider.audit
|
|
22
|
+
if (command === 'audit-status') return provider.auditStatus
|
|
23
|
+
return provider[command]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function createUploadProvider(provider = {}) {
|
|
27
|
+
return {
|
|
28
|
+
login: provider.login || (async () => unsupported('login')),
|
|
29
|
+
upload: provider.upload || (async () => unsupported('upload')),
|
|
30
|
+
debugPreview: provider.debugPreview || (async () => unsupported('debug-preview')),
|
|
31
|
+
servicePreview: provider.servicePreview || provider.preview || (async () => unsupported('service-preview')),
|
|
32
|
+
version: provider.version || (async () => unsupported('version')),
|
|
33
|
+
auditStatus: provider.auditStatus || (async () => unsupported('audit-status')),
|
|
34
|
+
submitAudit: provider.submitAudit || provider.submit || provider.audit || (async () => unsupported('submit-audit')),
|
|
35
|
+
audit: provider.audit || provider.submit || (async () => unsupported('audit')),
|
|
36
|
+
submit: provider.submit || provider.audit || (async () => unsupported('submit')),
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function createLocalFileProvider(options = {}) {
|
|
41
|
+
const recordDir = path.resolve(options.providerOut || path.join(options.out || 'artifacts', 'provider-records'))
|
|
42
|
+
|
|
43
|
+
async function writeRecord(command, payload) {
|
|
44
|
+
const payloadOptions = payload.options || {}
|
|
45
|
+
await fsp.mkdir(recordDir, { recursive: true })
|
|
46
|
+
const record = {
|
|
47
|
+
ok: true,
|
|
48
|
+
command,
|
|
49
|
+
provider: 'local-file',
|
|
50
|
+
recordPath: path.join(recordDir, `${command}.json`),
|
|
51
|
+
artifact: payload.artifact,
|
|
52
|
+
project: payload.project,
|
|
53
|
+
versionCode: payloadOptions.versionCode,
|
|
54
|
+
versionName: payloadOptions.versionName,
|
|
55
|
+
}
|
|
56
|
+
await fsp.writeFile(record.recordPath, `${JSON.stringify(record, null, 2)}\n`)
|
|
57
|
+
return record
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return createUploadProvider({
|
|
61
|
+
login: payload => writeRecord('login', payload),
|
|
62
|
+
upload: payload => writeRecord('upload', payload),
|
|
63
|
+
audit: payload => writeRecord('audit', payload),
|
|
64
|
+
submit: payload => writeRecord('submit', payload),
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function resolveProviderModule(specifier) {
|
|
69
|
+
if (path.isAbsolute(specifier) || specifier.startsWith('.') || specifier.startsWith('..')) {
|
|
70
|
+
return pathToFileURL(path.resolve(process.cwd(), specifier)).href
|
|
71
|
+
}
|
|
72
|
+
return specifier
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export async function loadUploadProvider(specifier, options = {}) {
|
|
76
|
+
if (!specifier || specifier === 'service') return createUploadProvider(createServiceProvider(options))
|
|
77
|
+
if (specifier === 'local-file') return createLocalFileProvider(options)
|
|
78
|
+
|
|
79
|
+
let mod
|
|
80
|
+
try {
|
|
81
|
+
mod = await import(resolveProviderModule(specifier))
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
throw new DiminaCliError('DIMINA_PROVIDER_LOAD_FAILED', `Unable to load provider module: ${specifier}`, {
|
|
85
|
+
provider: specifier,
|
|
86
|
+
cause: error.message,
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const factory = mod.createProvider || mod.default
|
|
91
|
+
const provider = typeof factory === 'function'
|
|
92
|
+
? await factory(options)
|
|
93
|
+
: mod.provider || mod.default || mod
|
|
94
|
+
return createUploadProvider(provider)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export async function runProviderCommand(command, options, payload) {
|
|
98
|
+
const provider = await loadUploadProvider(options.provider, options)
|
|
99
|
+
const action = providerFunction(provider, command)
|
|
100
|
+
if (typeof action !== 'function') return await unsupported(command)
|
|
101
|
+
const result = await action({ command, ...payload, options })
|
|
102
|
+
return {
|
|
103
|
+
ok: true,
|
|
104
|
+
command,
|
|
105
|
+
provider: options.provider,
|
|
106
|
+
...result,
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export async function unsupportedProviderCommand(command) {
|
|
111
|
+
return await unsupported(command)
|
|
112
|
+
}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const require_sourcemap = require("../sourcemap-BgtIgqkC.cjs");
|
|
3
|
+
const require_index = require("../index.cjs");
|
|
4
|
+
let node_path = require("node:path");
|
|
5
|
+
node_path = require_sourcemap.__toESM(node_path, 1);
|
|
6
|
+
let node_process = require("node:process");
|
|
7
|
+
node_process = require_sourcemap.__toESM(node_process, 1);
|
|
8
|
+
let chokidar = require("chokidar");
|
|
9
|
+
chokidar = require_sourcemap.__toESM(chokidar, 1);
|
|
10
|
+
let commander = require("commander");
|
|
11
|
+
var package_default = {
|
|
12
|
+
name: "@dimina/compiler",
|
|
13
|
+
version: "1.1.0",
|
|
14
|
+
description: "星河编译工具",
|
|
15
|
+
main: "./dist/index.cjs",
|
|
16
|
+
module: "./dist/index.js",
|
|
17
|
+
type: "module",
|
|
18
|
+
files: ["dist"],
|
|
19
|
+
exports: {
|
|
20
|
+
".": {
|
|
21
|
+
"import": "./dist/index.js",
|
|
22
|
+
"require": "./dist/index.cjs"
|
|
23
|
+
},
|
|
24
|
+
"./view-compiler": {
|
|
25
|
+
"import": "./dist/core/view-compiler.js",
|
|
26
|
+
"require": "./dist/core/view-compiler.cjs"
|
|
27
|
+
},
|
|
28
|
+
"./logic-compiler": {
|
|
29
|
+
"import": "./dist/core/logic-compiler.mjs",
|
|
30
|
+
"require": "./dist/core/logic-compiler.js"
|
|
31
|
+
},
|
|
32
|
+
"./style-compiler": {
|
|
33
|
+
"import": "./dist/core/style-compiler.js",
|
|
34
|
+
"require": "./dist/core/style-compiler.cjs"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
bin: { "dmcc": "dist/bin/index.js" },
|
|
38
|
+
scripts: {
|
|
39
|
+
"prebuild": "node scripts/sync-compatibility-reference.js",
|
|
40
|
+
"build": "vite build",
|
|
41
|
+
"sync:compat": "node scripts/sync-compatibility-reference.js",
|
|
42
|
+
"pretest": "node scripts/sync-compatibility-reference.js",
|
|
43
|
+
"test": "vitest run",
|
|
44
|
+
"test:dev": "vitest",
|
|
45
|
+
"coverage": "vitest run --coverage",
|
|
46
|
+
"prepack": "npm run build",
|
|
47
|
+
"release:beta": "npm version prerelease --preid=beta && npm publish --tag beta",
|
|
48
|
+
"release": "npm version patch && npm publish"
|
|
49
|
+
},
|
|
50
|
+
author: "doslin",
|
|
51
|
+
license: "Apache-2.0",
|
|
52
|
+
engines: { "node": ">=20" },
|
|
53
|
+
keywords: [
|
|
54
|
+
"dimina",
|
|
55
|
+
"compiler",
|
|
56
|
+
"miniapp",
|
|
57
|
+
"小程序"
|
|
58
|
+
],
|
|
59
|
+
dependencies: {
|
|
60
|
+
"@vue/compiler-sfc": "^3.5.39",
|
|
61
|
+
"@vue/shared": "^3.5.39",
|
|
62
|
+
"autoprefixer": "^10.5.3",
|
|
63
|
+
"cheerio": "^1.2.0",
|
|
64
|
+
"chokidar": "^4.0.3",
|
|
65
|
+
"commander": "^14.0.3",
|
|
66
|
+
"cssnano": "^8.0.2",
|
|
67
|
+
"esbuild": "^0.28.1",
|
|
68
|
+
"htmlparser2": "^12.0.0",
|
|
69
|
+
"less": "^4.6.7",
|
|
70
|
+
"listr2": "^9.0.5",
|
|
71
|
+
"magic-string": "^0.30.21",
|
|
72
|
+
"oxc-parser": "^0.140.0",
|
|
73
|
+
"oxc-walker": "^1.0.0",
|
|
74
|
+
"postcss": "^8.5.19",
|
|
75
|
+
"postcss-selector-parser": "^7.1.4",
|
|
76
|
+
"sass": "^1.101.0",
|
|
77
|
+
"source-map-js": "^1.2.1"
|
|
78
|
+
},
|
|
79
|
+
publishConfig: {
|
|
80
|
+
"registry": "https://registry.npmjs.org/",
|
|
81
|
+
"access": "public"
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
//#endregion
|
|
85
|
+
//#region src/common/compile-stages.js
|
|
86
|
+
var COMPILE_STAGE_ORDER = [
|
|
87
|
+
"view",
|
|
88
|
+
"logic",
|
|
89
|
+
"style"
|
|
90
|
+
];
|
|
91
|
+
var COMPILE_STAGE_SET = new Set(COMPILE_STAGE_ORDER);
|
|
92
|
+
function getCompileStagesForFiles(dependencyGraph, filePaths) {
|
|
93
|
+
const selected = /* @__PURE__ */ new Set();
|
|
94
|
+
const unknownKinds = /* @__PURE__ */ new Set();
|
|
95
|
+
for (const filePath of filePaths) for (const kind of dependencyGraph.getFileKinds(filePath)) if (COMPILE_STAGE_SET.has(kind)) selected.add(kind);
|
|
96
|
+
else if (kind !== "config") unknownKinds.add(kind);
|
|
97
|
+
return {
|
|
98
|
+
stages: COMPILE_STAGE_ORDER.filter((stage) => selected.has(stage)),
|
|
99
|
+
unknownKinds: [...unknownKinds].sort()
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region src/bin/watch.js
|
|
104
|
+
var WATCH_FILE_EVENTS = /* @__PURE__ */ new Set([
|
|
105
|
+
"add",
|
|
106
|
+
"change",
|
|
107
|
+
"unlink"
|
|
108
|
+
]);
|
|
109
|
+
function createWatchRebuildScheduler({ rebuild, onRebuild = () => {}, onError = () => {} }) {
|
|
110
|
+
let pendingChange;
|
|
111
|
+
let running = false;
|
|
112
|
+
let idlePromise = Promise.resolve();
|
|
113
|
+
let resolveIdle;
|
|
114
|
+
const drain = async () => {
|
|
115
|
+
while (pendingChange) {
|
|
116
|
+
const change = pendingChange;
|
|
117
|
+
pendingChange = void 0;
|
|
118
|
+
try {
|
|
119
|
+
onRebuild(change);
|
|
120
|
+
await rebuild(change);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
onError(error, change);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
running = false;
|
|
126
|
+
resolveIdle?.();
|
|
127
|
+
resolveIdle = void 0;
|
|
128
|
+
};
|
|
129
|
+
return {
|
|
130
|
+
schedule(event, filePath) {
|
|
131
|
+
if (!WATCH_FILE_EVENTS.has(event)) return false;
|
|
132
|
+
pendingChange = {
|
|
133
|
+
event,
|
|
134
|
+
filePath,
|
|
135
|
+
count: (pendingChange?.count || 0) + 1
|
|
136
|
+
};
|
|
137
|
+
if (!running) {
|
|
138
|
+
running = true;
|
|
139
|
+
idlePromise = new Promise((resolve) => {
|
|
140
|
+
resolveIdle = resolve;
|
|
141
|
+
});
|
|
142
|
+
drain();
|
|
143
|
+
}
|
|
144
|
+
return true;
|
|
145
|
+
},
|
|
146
|
+
waitForIdle() {
|
|
147
|
+
return idlePromise;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function getPublishedOutputPath(targetPath, useAppIdDir, appId) {
|
|
152
|
+
return node_path.default.resolve(targetPath, useAppIdDir ? appId : ".");
|
|
153
|
+
}
|
|
154
|
+
function createWatchBuildPlan({ event, filePath, count = 1, dependencyGraph, publishedPath }) {
|
|
155
|
+
if (count > 1 || event !== "change" || node_path.default.extname(filePath).toLowerCase() === ".json") return {
|
|
156
|
+
skip: false,
|
|
157
|
+
incremental: false,
|
|
158
|
+
options: {}
|
|
159
|
+
};
|
|
160
|
+
if (!dependencyGraph.hasFile(filePath)) return {
|
|
161
|
+
skip: true,
|
|
162
|
+
incremental: false,
|
|
163
|
+
options: {}
|
|
164
|
+
};
|
|
165
|
+
const affectedEntries = dependencyGraph.getAffectedEntries(filePath);
|
|
166
|
+
if (affectedEntries.length === 0) return {
|
|
167
|
+
skip: true,
|
|
168
|
+
incremental: false,
|
|
169
|
+
options: {}
|
|
170
|
+
};
|
|
171
|
+
const { stages, unknownKinds } = getCompileStagesForFiles(dependencyGraph, [filePath]);
|
|
172
|
+
if (unknownKinds.length > 0) return {
|
|
173
|
+
skip: false,
|
|
174
|
+
incremental: false,
|
|
175
|
+
options: {}
|
|
176
|
+
};
|
|
177
|
+
return {
|
|
178
|
+
skip: false,
|
|
179
|
+
incremental: true,
|
|
180
|
+
options: {
|
|
181
|
+
affectedEntries,
|
|
182
|
+
stages,
|
|
183
|
+
seedPath: publishedPath,
|
|
184
|
+
dependencyGraph: dependencyGraph.toJSON()
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function isSameOrDescendantPath(candidatePath, directoryPath) {
|
|
189
|
+
const relativePath = node_path.default.relative(directoryPath, candidatePath);
|
|
190
|
+
return relativePath === "" || !relativePath.startsWith(`..${node_path.default.sep}`) && relativePath !== ".." && !node_path.default.isAbsolute(relativePath);
|
|
191
|
+
}
|
|
192
|
+
function createIgnoredPathMatcher(ignoredPaths) {
|
|
193
|
+
return (watchedPath) => {
|
|
194
|
+
const absolutePath = node_path.default.resolve(watchedPath);
|
|
195
|
+
for (const ignoredPath of ignoredPaths) if (isSameOrDescendantPath(absolutePath, ignoredPath)) return true;
|
|
196
|
+
return false;
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
//#endregion
|
|
200
|
+
//#region src/bin/index.js
|
|
201
|
+
commander.program.command("build").option("-c, --work-path <path>", "编译工作目录").option("-s, --target-path <path>", "编译产物存放路径").option("-w, --watch", "启用监听文件改动").option("--no-app-id-dir", "产物根目录不包含appId").option("--sourcemap", "生成 sourcemap 文件用于调试").action(async (options) => {
|
|
202
|
+
const workPath = options.workPath ? node_path.default.resolve(options.workPath) : node_process.default.cwd();
|
|
203
|
+
const targetPath = options.targetPath ? node_path.default.resolve(options.targetPath) : node_process.default.cwd();
|
|
204
|
+
const useAppIdDir = options.appIdDir !== false;
|
|
205
|
+
const sourcemap = !!options.sourcemap;
|
|
206
|
+
let buildResult;
|
|
207
|
+
try {
|
|
208
|
+
buildResult = await require_index.default(targetPath, workPath, useAppIdDir, { sourcemap });
|
|
209
|
+
} catch (error) {
|
|
210
|
+
throw new Error(`${workPath} 编译出错: ${error.message}`, { cause: error });
|
|
211
|
+
}
|
|
212
|
+
if (options.watch) {
|
|
213
|
+
let dependencyGraph = new require_sourcemap.DependencyGraph(buildResult.dependencyGraph);
|
|
214
|
+
const ignoredOutputPaths = /* @__PURE__ */ new Set([getPublishedOutputPath(targetPath, useAppIdDir, buildResult.appId)]);
|
|
215
|
+
const eventLabels = {
|
|
216
|
+
add: "新增",
|
|
217
|
+
change: "改动",
|
|
218
|
+
unlink: "删除"
|
|
219
|
+
};
|
|
220
|
+
const scheduler = createWatchRebuildScheduler({
|
|
221
|
+
rebuild: async (change) => {
|
|
222
|
+
const publishedPath = getPublishedOutputPath(targetPath, useAppIdDir, buildResult.appId);
|
|
223
|
+
const plan = createWatchBuildPlan({
|
|
224
|
+
...change,
|
|
225
|
+
dependencyGraph,
|
|
226
|
+
publishedPath
|
|
227
|
+
});
|
|
228
|
+
if (plan.skip) return;
|
|
229
|
+
const result = await require_index.default(targetPath, workPath, useAppIdDir, {
|
|
230
|
+
sourcemap,
|
|
231
|
+
...plan.options
|
|
232
|
+
});
|
|
233
|
+
buildResult = result;
|
|
234
|
+
dependencyGraph = new require_sourcemap.DependencyGraph(result.dependencyGraph);
|
|
235
|
+
ignoredOutputPaths.add(getPublishedOutputPath(targetPath, useAppIdDir, result.appId));
|
|
236
|
+
},
|
|
237
|
+
onRebuild: ({ event, filePath, count }) => {
|
|
238
|
+
const merged = count > 1 ? `(合并 ${count} 个文件事件)` : "";
|
|
239
|
+
console.log(`${filePath} ${eventLabels[event]},重新编译${merged}`);
|
|
240
|
+
},
|
|
241
|
+
onError: (error) => {
|
|
242
|
+
console.error(`${workPath} 编译出错: ${error.message}`);
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
chokidar.default.watch(workPath, {
|
|
246
|
+
persistent: true,
|
|
247
|
+
ignoreInitial: true,
|
|
248
|
+
ignored: createIgnoredPathMatcher(ignoredOutputPaths)
|
|
249
|
+
}).on("all", (event, filePath) => {
|
|
250
|
+
if (createWatchBuildPlan({
|
|
251
|
+
event,
|
|
252
|
+
filePath,
|
|
253
|
+
dependencyGraph,
|
|
254
|
+
publishedPath: getPublishedOutputPath(targetPath, useAppIdDir, buildResult.appId)
|
|
255
|
+
}).skip) return;
|
|
256
|
+
scheduler.schedule(event, filePath);
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
commander.program.name("dmcc").version(package_default.version);
|
|
261
|
+
commander.program.parseAsync(node_process.default.argv).catch((error) => {
|
|
262
|
+
console.error(error.stack || error.message);
|
|
263
|
+
node_process.default.exitCode = 1;
|
|
264
|
+
});
|
|
265
|
+
//#endregion
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { F as DependencyGraph } from "../sourcemap-CKjhV9h7.js";
|
|
3
|
+
import build from "../index.js";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import process from "node:process";
|
|
6
|
+
import chokidar from "chokidar";
|
|
7
|
+
import { program } from "commander";
|
|
8
|
+
var package_default = {
|
|
9
|
+
name: "@dimina/compiler",
|
|
10
|
+
version: "1.1.0",
|
|
11
|
+
description: "星河编译工具",
|
|
12
|
+
main: "./dist/index.cjs",
|
|
13
|
+
module: "./dist/index.js",
|
|
14
|
+
type: "module",
|
|
15
|
+
files: ["dist"],
|
|
16
|
+
exports: {
|
|
17
|
+
".": {
|
|
18
|
+
"import": "./dist/index.js",
|
|
19
|
+
"require": "./dist/index.cjs"
|
|
20
|
+
},
|
|
21
|
+
"./view-compiler": {
|
|
22
|
+
"import": "./dist/core/view-compiler.js",
|
|
23
|
+
"require": "./dist/core/view-compiler.cjs"
|
|
24
|
+
},
|
|
25
|
+
"./logic-compiler": {
|
|
26
|
+
"import": "./dist/core/logic-compiler.mjs",
|
|
27
|
+
"require": "./dist/core/logic-compiler.js"
|
|
28
|
+
},
|
|
29
|
+
"./style-compiler": {
|
|
30
|
+
"import": "./dist/core/style-compiler.js",
|
|
31
|
+
"require": "./dist/core/style-compiler.cjs"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
bin: { "dmcc": "dist/bin/index.js" },
|
|
35
|
+
scripts: {
|
|
36
|
+
"prebuild": "node scripts/sync-compatibility-reference.js",
|
|
37
|
+
"build": "vite build",
|
|
38
|
+
"sync:compat": "node scripts/sync-compatibility-reference.js",
|
|
39
|
+
"pretest": "node scripts/sync-compatibility-reference.js",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"test:dev": "vitest",
|
|
42
|
+
"coverage": "vitest run --coverage",
|
|
43
|
+
"prepack": "npm run build",
|
|
44
|
+
"release:beta": "npm version prerelease --preid=beta && npm publish --tag beta",
|
|
45
|
+
"release": "npm version patch && npm publish"
|
|
46
|
+
},
|
|
47
|
+
author: "doslin",
|
|
48
|
+
license: "Apache-2.0",
|
|
49
|
+
engines: { "node": ">=20" },
|
|
50
|
+
keywords: [
|
|
51
|
+
"dimina",
|
|
52
|
+
"compiler",
|
|
53
|
+
"miniapp",
|
|
54
|
+
"小程序"
|
|
55
|
+
],
|
|
56
|
+
dependencies: {
|
|
57
|
+
"@vue/compiler-sfc": "^3.5.39",
|
|
58
|
+
"@vue/shared": "^3.5.39",
|
|
59
|
+
"autoprefixer": "^10.5.3",
|
|
60
|
+
"cheerio": "^1.2.0",
|
|
61
|
+
"chokidar": "^4.0.3",
|
|
62
|
+
"commander": "^14.0.3",
|
|
63
|
+
"cssnano": "^8.0.2",
|
|
64
|
+
"esbuild": "^0.28.1",
|
|
65
|
+
"htmlparser2": "^12.0.0",
|
|
66
|
+
"less": "^4.6.7",
|
|
67
|
+
"listr2": "^9.0.5",
|
|
68
|
+
"magic-string": "^0.30.21",
|
|
69
|
+
"oxc-parser": "^0.140.0",
|
|
70
|
+
"oxc-walker": "^1.0.0",
|
|
71
|
+
"postcss": "^8.5.19",
|
|
72
|
+
"postcss-selector-parser": "^7.1.4",
|
|
73
|
+
"sass": "^1.101.0",
|
|
74
|
+
"source-map-js": "^1.2.1"
|
|
75
|
+
},
|
|
76
|
+
publishConfig: {
|
|
77
|
+
"registry": "https://registry.npmjs.org/",
|
|
78
|
+
"access": "public"
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/common/compile-stages.js
|
|
83
|
+
var COMPILE_STAGE_ORDER = [
|
|
84
|
+
"view",
|
|
85
|
+
"logic",
|
|
86
|
+
"style"
|
|
87
|
+
];
|
|
88
|
+
var COMPILE_STAGE_SET = new Set(COMPILE_STAGE_ORDER);
|
|
89
|
+
function getCompileStagesForFiles(dependencyGraph, filePaths) {
|
|
90
|
+
const selected = /* @__PURE__ */ new Set();
|
|
91
|
+
const unknownKinds = /* @__PURE__ */ new Set();
|
|
92
|
+
for (const filePath of filePaths) for (const kind of dependencyGraph.getFileKinds(filePath)) if (COMPILE_STAGE_SET.has(kind)) selected.add(kind);
|
|
93
|
+
else if (kind !== "config") unknownKinds.add(kind);
|
|
94
|
+
return {
|
|
95
|
+
stages: COMPILE_STAGE_ORDER.filter((stage) => selected.has(stage)),
|
|
96
|
+
unknownKinds: [...unknownKinds].sort()
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/bin/watch.js
|
|
101
|
+
var WATCH_FILE_EVENTS = /* @__PURE__ */ new Set([
|
|
102
|
+
"add",
|
|
103
|
+
"change",
|
|
104
|
+
"unlink"
|
|
105
|
+
]);
|
|
106
|
+
function createWatchRebuildScheduler({ rebuild, onRebuild = () => {}, onError = () => {} }) {
|
|
107
|
+
let pendingChange;
|
|
108
|
+
let running = false;
|
|
109
|
+
let idlePromise = Promise.resolve();
|
|
110
|
+
let resolveIdle;
|
|
111
|
+
const drain = async () => {
|
|
112
|
+
while (pendingChange) {
|
|
113
|
+
const change = pendingChange;
|
|
114
|
+
pendingChange = void 0;
|
|
115
|
+
try {
|
|
116
|
+
onRebuild(change);
|
|
117
|
+
await rebuild(change);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
onError(error, change);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
running = false;
|
|
123
|
+
resolveIdle?.();
|
|
124
|
+
resolveIdle = void 0;
|
|
125
|
+
};
|
|
126
|
+
return {
|
|
127
|
+
schedule(event, filePath) {
|
|
128
|
+
if (!WATCH_FILE_EVENTS.has(event)) return false;
|
|
129
|
+
pendingChange = {
|
|
130
|
+
event,
|
|
131
|
+
filePath,
|
|
132
|
+
count: (pendingChange?.count || 0) + 1
|
|
133
|
+
};
|
|
134
|
+
if (!running) {
|
|
135
|
+
running = true;
|
|
136
|
+
idlePromise = new Promise((resolve) => {
|
|
137
|
+
resolveIdle = resolve;
|
|
138
|
+
});
|
|
139
|
+
drain();
|
|
140
|
+
}
|
|
141
|
+
return true;
|
|
142
|
+
},
|
|
143
|
+
waitForIdle() {
|
|
144
|
+
return idlePromise;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function getPublishedOutputPath(targetPath, useAppIdDir, appId) {
|
|
149
|
+
return path.resolve(targetPath, useAppIdDir ? appId : ".");
|
|
150
|
+
}
|
|
151
|
+
function createWatchBuildPlan({ event, filePath, count = 1, dependencyGraph, publishedPath }) {
|
|
152
|
+
if (count > 1 || event !== "change" || path.extname(filePath).toLowerCase() === ".json") return {
|
|
153
|
+
skip: false,
|
|
154
|
+
incremental: false,
|
|
155
|
+
options: {}
|
|
156
|
+
};
|
|
157
|
+
if (!dependencyGraph.hasFile(filePath)) return {
|
|
158
|
+
skip: true,
|
|
159
|
+
incremental: false,
|
|
160
|
+
options: {}
|
|
161
|
+
};
|
|
162
|
+
const affectedEntries = dependencyGraph.getAffectedEntries(filePath);
|
|
163
|
+
if (affectedEntries.length === 0) return {
|
|
164
|
+
skip: true,
|
|
165
|
+
incremental: false,
|
|
166
|
+
options: {}
|
|
167
|
+
};
|
|
168
|
+
const { stages, unknownKinds } = getCompileStagesForFiles(dependencyGraph, [filePath]);
|
|
169
|
+
if (unknownKinds.length > 0) return {
|
|
170
|
+
skip: false,
|
|
171
|
+
incremental: false,
|
|
172
|
+
options: {}
|
|
173
|
+
};
|
|
174
|
+
return {
|
|
175
|
+
skip: false,
|
|
176
|
+
incremental: true,
|
|
177
|
+
options: {
|
|
178
|
+
affectedEntries,
|
|
179
|
+
stages,
|
|
180
|
+
seedPath: publishedPath,
|
|
181
|
+
dependencyGraph: dependencyGraph.toJSON()
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function isSameOrDescendantPath(candidatePath, directoryPath) {
|
|
186
|
+
const relativePath = path.relative(directoryPath, candidatePath);
|
|
187
|
+
return relativePath === "" || !relativePath.startsWith(`..${path.sep}`) && relativePath !== ".." && !path.isAbsolute(relativePath);
|
|
188
|
+
}
|
|
189
|
+
function createIgnoredPathMatcher(ignoredPaths) {
|
|
190
|
+
return (watchedPath) => {
|
|
191
|
+
const absolutePath = path.resolve(watchedPath);
|
|
192
|
+
for (const ignoredPath of ignoredPaths) if (isSameOrDescendantPath(absolutePath, ignoredPath)) return true;
|
|
193
|
+
return false;
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
//#endregion
|
|
197
|
+
//#region src/bin/index.js
|
|
198
|
+
program.command("build").option("-c, --work-path <path>", "编译工作目录").option("-s, --target-path <path>", "编译产物存放路径").option("-w, --watch", "启用监听文件改动").option("--no-app-id-dir", "产物根目录不包含appId").option("--sourcemap", "生成 sourcemap 文件用于调试").action(async (options) => {
|
|
199
|
+
const workPath = options.workPath ? path.resolve(options.workPath) : process.cwd();
|
|
200
|
+
const targetPath = options.targetPath ? path.resolve(options.targetPath) : process.cwd();
|
|
201
|
+
const useAppIdDir = options.appIdDir !== false;
|
|
202
|
+
const sourcemap = !!options.sourcemap;
|
|
203
|
+
let buildResult;
|
|
204
|
+
try {
|
|
205
|
+
buildResult = await build(targetPath, workPath, useAppIdDir, { sourcemap });
|
|
206
|
+
} catch (error) {
|
|
207
|
+
throw new Error(`${workPath} 编译出错: ${error.message}`, { cause: error });
|
|
208
|
+
}
|
|
209
|
+
if (options.watch) {
|
|
210
|
+
let dependencyGraph = new DependencyGraph(buildResult.dependencyGraph);
|
|
211
|
+
const ignoredOutputPaths = /* @__PURE__ */ new Set([getPublishedOutputPath(targetPath, useAppIdDir, buildResult.appId)]);
|
|
212
|
+
const eventLabels = {
|
|
213
|
+
add: "新增",
|
|
214
|
+
change: "改动",
|
|
215
|
+
unlink: "删除"
|
|
216
|
+
};
|
|
217
|
+
const scheduler = createWatchRebuildScheduler({
|
|
218
|
+
rebuild: async (change) => {
|
|
219
|
+
const publishedPath = getPublishedOutputPath(targetPath, useAppIdDir, buildResult.appId);
|
|
220
|
+
const plan = createWatchBuildPlan({
|
|
221
|
+
...change,
|
|
222
|
+
dependencyGraph,
|
|
223
|
+
publishedPath
|
|
224
|
+
});
|
|
225
|
+
if (plan.skip) return;
|
|
226
|
+
const result = await build(targetPath, workPath, useAppIdDir, {
|
|
227
|
+
sourcemap,
|
|
228
|
+
...plan.options
|
|
229
|
+
});
|
|
230
|
+
buildResult = result;
|
|
231
|
+
dependencyGraph = new DependencyGraph(result.dependencyGraph);
|
|
232
|
+
ignoredOutputPaths.add(getPublishedOutputPath(targetPath, useAppIdDir, result.appId));
|
|
233
|
+
},
|
|
234
|
+
onRebuild: ({ event, filePath, count }) => {
|
|
235
|
+
const merged = count > 1 ? `(合并 ${count} 个文件事件)` : "";
|
|
236
|
+
console.log(`${filePath} ${eventLabels[event]},重新编译${merged}`);
|
|
237
|
+
},
|
|
238
|
+
onError: (error) => {
|
|
239
|
+
console.error(`${workPath} 编译出错: ${error.message}`);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
chokidar.watch(workPath, {
|
|
243
|
+
persistent: true,
|
|
244
|
+
ignoreInitial: true,
|
|
245
|
+
ignored: createIgnoredPathMatcher(ignoredOutputPaths)
|
|
246
|
+
}).on("all", (event, filePath) => {
|
|
247
|
+
if (createWatchBuildPlan({
|
|
248
|
+
event,
|
|
249
|
+
filePath,
|
|
250
|
+
dependencyGraph,
|
|
251
|
+
publishedPath: getPublishedOutputPath(targetPath, useAppIdDir, buildResult.appId)
|
|
252
|
+
}).skip) return;
|
|
253
|
+
scheduler.schedule(event, filePath);
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
program.name("dmcc").version(package_default.version);
|
|
258
|
+
program.parseAsync(process.argv).catch((error) => {
|
|
259
|
+
console.error(error.stack || error.message);
|
|
260
|
+
process.exitCode = 1;
|
|
261
|
+
});
|
|
262
|
+
//#endregion
|
|
263
|
+
export {};
|