@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.
Files changed (73) hide show
  1. package/README.md +438 -0
  2. package/README.zh-CN.md +554 -0
  3. package/assets/container/assets/index.css +1 -0
  4. package/assets/container/assets/index.js +137 -0
  5. package/assets/container/assets/pageFrame.css +1 -0
  6. package/assets/container/assets/pageFrame.js +56 -0
  7. package/assets/container/assets/service.js +6 -0
  8. package/assets/container/assets/vconsole.js +931 -0
  9. package/assets/container/favicon.ico +0 -0
  10. package/assets/container/images/icon-arrow.png +0 -0
  11. package/assets/container/images/mini-action-white.png +0 -0
  12. package/assets/container/images/mini-action.png +0 -0
  13. package/assets/container/images/mini-arrow-left-white.png +0 -0
  14. package/assets/container/images/mini-arrow-left.jpg +0 -0
  15. package/assets/container/images/mini-arrow-left.png +0 -0
  16. package/assets/container/images/mini-close-white.png +0 -0
  17. package/assets/container/images/mini-close.png +0 -0
  18. package/assets/container/images/more.png +0 -0
  19. package/assets/container/images/search.jpg +0 -0
  20. package/assets/container/index.html +1 -0
  21. package/assets/container/pageFrame.html +1 -0
  22. package/assets/init/tabbar/home-active.png +0 -0
  23. package/assets/init/tabbar/home.png +0 -0
  24. package/assets/init/tabbar/list-active.png +0 -0
  25. package/assets/init/tabbar/list.png +0 -0
  26. package/assets/init/types/neux-api.d.ts +1402 -0
  27. package/package.json +68 -0
  28. package/scripts/generate-init-types.js +210 -0
  29. package/scripts/sync-compiler.js +22 -0
  30. package/scripts/sync-web-container.js +34 -0
  31. package/src/bin/cli.js +646 -0
  32. package/src/core/brand.js +11 -0
  33. package/src/core/compiler.js +305 -0
  34. package/src/core/defaults.js +12 -0
  35. package/src/core/dev.js +15 -0
  36. package/src/core/errors.js +17 -0
  37. package/src/core/fs.js +66 -0
  38. package/src/core/i18n.js +37 -0
  39. package/src/core/init.js +866 -0
  40. package/src/core/lifecycle.js +32 -0
  41. package/src/core/manifest.js +72 -0
  42. package/src/core/pack.js +156 -0
  43. package/src/core/package-info.js +27 -0
  44. package/src/core/preview-server.js +123 -0
  45. package/src/core/project.js +101 -0
  46. package/src/core/prompts.js +71 -0
  47. package/src/core/proxy-security.js +141 -0
  48. package/src/core/proxy.js +156 -0
  49. package/src/core/qr.js +41 -0
  50. package/src/core/terminal-qr.js +72 -0
  51. package/src/core/update.js +278 -0
  52. package/src/core/watch.js +113 -0
  53. package/src/core/web.js +649 -0
  54. package/src/core/zip.js +120 -0
  55. package/src/index.js +20 -0
  56. package/src/providers/service-client.js +149 -0
  57. package/src/providers/service-config.js +264 -0
  58. package/src/providers/service.js +146 -0
  59. package/src/providers/upload.js +112 -0
  60. package/vendor/dimina-compiler/bin/index.cjs +265 -0
  61. package/vendor/dimina-compiler/bin/index.js +263 -0
  62. package/vendor/dimina-compiler/compatibility-B-DoZtUX.cjs +395 -0
  63. package/vendor/dimina-compiler/compatibility-Cl3-DO6V.js +366 -0
  64. package/vendor/dimina-compiler/core/logic-compiler.cjs +378 -0
  65. package/vendor/dimina-compiler/core/logic-compiler.js +374 -0
  66. package/vendor/dimina-compiler/core/style-compiler.cjs +392 -0
  67. package/vendor/dimina-compiler/core/style-compiler.js +377 -0
  68. package/vendor/dimina-compiler/core/view-compiler.cjs +1601 -0
  69. package/vendor/dimina-compiler/core/view-compiler.js +1582 -0
  70. package/vendor/dimina-compiler/index.cjs +762 -0
  71. package/vendor/dimina-compiler/index.js +751 -0
  72. package/vendor/dimina-compiler/sourcemap-BgtIgqkC.cjs +1377 -0
  73. package/vendor/dimina-compiler/sourcemap-CKjhV9h7.js +1135 -0
@@ -0,0 +1,305 @@
1
+ import path from 'node:path'
2
+ import fs from 'node:fs/promises'
3
+ import { pathToFileURL } from 'node:url'
4
+ import { DiminaCliError } from './errors.js'
5
+ import { inspectProject } from './project.js'
6
+ import { copyDir, pathExists, readJson, resolvePath, writeJson } from './fs.js'
7
+ import { defaultOut } from './defaults.js'
8
+ import { brand } from './brand.js'
9
+
10
+ const bundledCompilerPath = new URL('../../vendor/dimina-compiler/index.js', import.meta.url)
11
+ const NEUX_FILE_TYPES = {
12
+ template: ['.nxml'],
13
+ style: ['.nxss'],
14
+ }
15
+
16
+ function compilerOptions(options = {}, extra = {}) {
17
+ return {
18
+ ...extra,
19
+ fileTypes: {
20
+ ...NEUX_FILE_TYPES,
21
+ ...(options.fileTypes || {}),
22
+ template: [...new Set([...(NEUX_FILE_TYPES.template || []), ...(options.fileTypes?.template || [])])],
23
+ style: [...new Set([...(NEUX_FILE_TYPES.style || []), ...(options.fileTypes?.style || [])])],
24
+ },
25
+ sourcemap: !!options.sourcemap,
26
+ lang: options.lang || process.env.NEUX_CLI_LANG || 'en',
27
+ signal: options.signal,
28
+ }
29
+ }
30
+
31
+ async function loadCompiler(moduleSpecifier) {
32
+ try {
33
+ if (moduleSpecifier) {
34
+ const resolved = path.isAbsolute(moduleSpecifier)
35
+ ? pathToFileURL(moduleSpecifier).href
36
+ : pathToFileURL(path.resolve(process.cwd(), moduleSpecifier)).href
37
+ return await import(resolved)
38
+ }
39
+ return await import(bundledCompilerPath.href)
40
+ }
41
+ catch (error) {
42
+ throw new DiminaCliError(
43
+ 'DIMINA_COMPILER_NOT_FOUND',
44
+ `Unable to load bundled ${brand.compilerPackageName}. Run npm run sync:compiler before packing, or pass --compiler-module for a custom compiler.`,
45
+ { cause: error.message },
46
+ )
47
+ }
48
+ }
49
+
50
+ export async function buildProject(options = {}) {
51
+ const projectInfo = await inspectProject(options)
52
+ const out = resolvePath(options.out || options.output || defaultOut('build'))
53
+ const compilerModule = options.compiler || await loadCompiler(options.compilerModule || process.env.DIMINA_COMPILER_MODULE)
54
+ const build = compilerModule.default || compilerModule.build || compilerModule
55
+
56
+ if (typeof build !== 'function') {
57
+ throw new DiminaCliError('DIMINA_COMPILER_INVALID', `${brand.compilerPackageName} does not expose a callable build function`)
58
+ }
59
+
60
+ let compilerResult
61
+ const logs = []
62
+ const errors = []
63
+ const compilerInput = await prepareCompilerInput(projectInfo, out, options)
64
+ try {
65
+ compilerResult = await withCompilerLogCapture(options, logs, errors, () => build(
66
+ out,
67
+ compilerInput.projectPath,
68
+ options.appIdDir !== false,
69
+ compilerOptions(options),
70
+ ))
71
+ }
72
+ catch (error) {
73
+ errors.push(error.message)
74
+ throw new DiminaCliError('DIMINA_BUILD_FAILED', `Dimina compiler failed: ${error.message}`, {
75
+ cause: error.message,
76
+ compilerInputPath: compilerInput.projectPath,
77
+ })
78
+ }
79
+
80
+ if (compilerResult === undefined && options.strict !== false) {
81
+ throw new DiminaCliError('DIMINA_BUILD_FAILED', 'Dimina compiler finished without a build result', {
82
+ compilerInputPath: compilerInput.projectPath,
83
+ })
84
+ }
85
+
86
+ return {
87
+ ok: true,
88
+ command: 'build',
89
+ projectPath: projectInfo.projectPath,
90
+ sourceRoot: projectInfo.sourceRoot,
91
+ compilerInputPath: compilerInput.projectPath,
92
+ compilerInputCreated: compilerInput.created,
93
+ outputPath: out,
94
+ appId: projectInfo.appId,
95
+ compilerResult,
96
+ logs,
97
+ errors,
98
+ }
99
+ }
100
+
101
+ export async function buildStyleOnlyProject(options = {}) {
102
+ const projectInfo = await inspectProject(options)
103
+ const out = resolvePath(options.out || options.output || defaultOut('build'))
104
+ const compilerModule = options.compiler || await loadCompiler(options.compilerModule || process.env.DIMINA_COMPILER_MODULE)
105
+ const buildStyleOnly = compilerModule.buildStyleOnly
106
+
107
+ if (typeof buildStyleOnly !== 'function') {
108
+ throw new DiminaCliError('DIMINA_STYLE_BUILD_UNAVAILABLE', `${brand.compilerPackageName} does not expose buildStyleOnly`)
109
+ }
110
+
111
+ const logs = []
112
+ const errors = []
113
+ const compilerInput = await prepareCompilerInput(projectInfo, out, options)
114
+ let compilerResult
115
+ try {
116
+ compilerResult = await withCompilerLogCapture(options, logs, errors, () => buildStyleOnly(out, compilerInput.projectPath, options.appIdDir !== false, compilerOptions(options, {
117
+ changedPath: options.changedPath,
118
+ })))
119
+ }
120
+ catch (error) {
121
+ errors.push(error.message)
122
+ throw new DiminaCliError('DIMINA_STYLE_BUILD_FAILED', `Dimina style compiler failed: ${error.message}`, {
123
+ cause: error.message,
124
+ compilerInputPath: compilerInput.projectPath,
125
+ })
126
+ }
127
+
128
+ return {
129
+ ok: true,
130
+ command: 'build-style',
131
+ styleOnly: true,
132
+ projectPath: projectInfo.projectPath,
133
+ sourceRoot: projectInfo.sourceRoot,
134
+ compilerInputPath: compilerInput.projectPath,
135
+ compilerInputCreated: compilerInput.created,
136
+ outputPath: out,
137
+ appId: projectInfo.appId,
138
+ compilerResult,
139
+ logs,
140
+ errors,
141
+ ...compilerResult,
142
+ }
143
+ }
144
+
145
+ export async function buildViewOnlyProject(options = {}) {
146
+ const projectInfo = await inspectProject(options)
147
+ const out = resolvePath(options.out || options.output || defaultOut('build'))
148
+ const compilerModule = options.compiler || await loadCompiler(options.compilerModule || process.env.DIMINA_COMPILER_MODULE)
149
+ const buildViewOnly = compilerModule.buildViewOnly
150
+
151
+ if (typeof buildViewOnly !== 'function') {
152
+ throw new DiminaCliError('DIMINA_VIEW_BUILD_UNAVAILABLE', `${brand.compilerPackageName} does not expose buildViewOnly`)
153
+ }
154
+
155
+ const logs = []
156
+ const errors = []
157
+ const compilerInput = await prepareCompilerInput(projectInfo, out, options)
158
+ let compilerResult
159
+ try {
160
+ compilerResult = await withCompilerLogCapture(options, logs, errors, () => buildViewOnly(out, compilerInput.projectPath, options.appIdDir !== false, compilerOptions(options, {
161
+ changedPath: options.changedPath,
162
+ })))
163
+ }
164
+ catch (error) {
165
+ errors.push(error.message)
166
+ throw new DiminaCliError('DIMINA_VIEW_BUILD_FAILED', `Dimina view compiler failed: ${error.message}`, {
167
+ cause: error.message,
168
+ compilerInputPath: compilerInput.projectPath,
169
+ })
170
+ }
171
+
172
+ return {
173
+ ok: true,
174
+ command: 'build-view',
175
+ viewOnly: true,
176
+ projectPath: projectInfo.projectPath,
177
+ sourceRoot: projectInfo.sourceRoot,
178
+ compilerInputPath: compilerInput.projectPath,
179
+ compilerInputCreated: compilerInput.created,
180
+ outputPath: out,
181
+ appId: projectInfo.appId,
182
+ compilerResult,
183
+ logs,
184
+ errors,
185
+ ...compilerResult,
186
+ }
187
+ }
188
+
189
+ export async function buildLogicOnlyProject(options = {}) {
190
+ const projectInfo = await inspectProject(options)
191
+ const out = resolvePath(options.out || options.output || defaultOut('build'))
192
+ const compilerModule = options.compiler || await loadCompiler(options.compilerModule || process.env.DIMINA_COMPILER_MODULE)
193
+ const buildLogicOnly = compilerModule.buildLogicOnly
194
+
195
+ if (typeof buildLogicOnly !== 'function') {
196
+ throw new DiminaCliError('DIMINA_LOGIC_BUILD_UNAVAILABLE', `${brand.compilerPackageName} does not expose buildLogicOnly`)
197
+ }
198
+
199
+ const logs = []
200
+ const errors = []
201
+ const compilerInput = await prepareCompilerInput(projectInfo, out, options)
202
+ let compilerResult
203
+ try {
204
+ compilerResult = await withCompilerLogCapture(options, logs, errors, () => buildLogicOnly(out, compilerInput.projectPath, options.appIdDir !== false, compilerOptions(options, {
205
+ changedPath: options.changedPath,
206
+ })))
207
+ }
208
+ catch (error) {
209
+ errors.push(error.message)
210
+ throw new DiminaCliError('DIMINA_LOGIC_BUILD_FAILED', `Dimina logic compiler failed: ${error.message}`, {
211
+ cause: error.message,
212
+ compilerInputPath: compilerInput.projectPath,
213
+ })
214
+ }
215
+
216
+ return {
217
+ ok: true,
218
+ command: 'build-logic',
219
+ logicOnly: true,
220
+ projectPath: projectInfo.projectPath,
221
+ sourceRoot: projectInfo.sourceRoot,
222
+ compilerInputPath: compilerInput.projectPath,
223
+ compilerInputCreated: compilerInput.created,
224
+ outputPath: out,
225
+ appId: projectInfo.appId,
226
+ compilerResult,
227
+ logs,
228
+ errors,
229
+ ...compilerResult,
230
+ }
231
+ }
232
+
233
+ async function prepareCompilerInput(projectInfo, out, options) {
234
+ if (!projectInfo.miniprogramRoot || path.resolve(projectInfo.projectPath) === path.resolve(projectInfo.sourceRoot)) {
235
+ return {
236
+ projectPath: projectInfo.projectPath,
237
+ created: false,
238
+ }
239
+ }
240
+
241
+ const inputRoot = resolvePath(
242
+ options.compilerInputRoot,
243
+ path.join(path.dirname(out), `${path.basename(out)}.compiler-input`),
244
+ )
245
+ await fs.rm(inputRoot, { recursive: true, force: true })
246
+ await copyDir(projectInfo.sourceRoot, inputRoot)
247
+
248
+ const projectConfig = await readJson(projectInfo.projectConfigPath)
249
+ projectConfig.miniprogramRoot = ''
250
+ await writeJson(path.join(inputRoot, 'project.config.json'), projectConfig)
251
+
252
+ const privateConfigPath = path.join(projectInfo.projectPath, 'project.private.config.json')
253
+ if (await pathExists(privateConfigPath)) {
254
+ await fs.copyFile(privateConfigPath, path.join(inputRoot, 'project.private.config.json'))
255
+ }
256
+
257
+ return {
258
+ projectPath: inputRoot,
259
+ created: true,
260
+ }
261
+ }
262
+
263
+ async function withCompilerLogCapture(options, logs, errors, action) {
264
+ if (!options.captureLogs && typeof options.onLog !== 'function') {
265
+ return await action()
266
+ }
267
+
268
+ const restore = []
269
+ const capture = (stream, level) => {
270
+ const originalWrite = stream.write.bind(stream)
271
+ stream.write = (chunk, encoding, callback) => {
272
+ for (const message of normalizeLogLines(chunk)) {
273
+ const record = {
274
+ source: 'compiler',
275
+ level,
276
+ message,
277
+ timestamp: Date.now(),
278
+ }
279
+ logs.push(record)
280
+ if (level === 'error') errors.push(message)
281
+ options.onLog?.(record)
282
+ }
283
+ return originalWrite(chunk, encoding, callback)
284
+ }
285
+ restore.push(() => {
286
+ stream.write = originalWrite
287
+ })
288
+ }
289
+
290
+ capture(process.stdout, 'info')
291
+ capture(process.stderr, 'error')
292
+ try {
293
+ return await action()
294
+ }
295
+ finally {
296
+ for (const restoreWrite of restore.reverse()) restoreWrite()
297
+ }
298
+ }
299
+
300
+ function normalizeLogLines(chunk) {
301
+ return String(Buffer.isBuffer(chunk) ? chunk.toString('utf8') : chunk)
302
+ .split(/\r?\n/)
303
+ .map(line => line.trim())
304
+ .filter(Boolean)
305
+ }
@@ -0,0 +1,12 @@
1
+ export const defaultOutputDirs = {
2
+ build: 'dist/release',
3
+ compile: 'dist/build',
4
+ dev: 'dist/dev',
5
+ pack: 'dist/pack',
6
+ preview: 'dist/preview',
7
+ web: 'dist/web',
8
+ }
9
+
10
+ export function defaultOut(command) {
11
+ return defaultOutputDirs[command] || 'dist'
12
+ }
@@ -0,0 +1,15 @@
1
+ import { startWeb } from './web.js'
2
+
3
+ export async function startDev(options = {}) {
4
+ const session = await startWeb({
5
+ ...options,
6
+ command: 'dev',
7
+ watch: true,
8
+ })
9
+
10
+ return {
11
+ ...session,
12
+ command: 'dev',
13
+ watch: true,
14
+ }
15
+ }
@@ -0,0 +1,17 @@
1
+ export class DiminaCliError extends Error {
2
+ constructor(code, message, details = {}) {
3
+ super(message)
4
+ this.name = 'DiminaCliError'
5
+ this.code = code
6
+ this.details = details
7
+ }
8
+ }
9
+
10
+ export function toErrorPayload(error) {
11
+ return {
12
+ ok: false,
13
+ code: error?.code || 'DIMINA_UNKNOWN_ERROR',
14
+ message: error?.message || String(error),
15
+ details: error?.details || undefined,
16
+ }
17
+ }
package/src/core/fs.js ADDED
@@ -0,0 +1,66 @@
1
+ import fs from 'node:fs/promises'
2
+ import path from 'node:path'
3
+
4
+ export function resolvePath(value, fallback = process.cwd()) {
5
+ return path.resolve(value || fallback)
6
+ }
7
+
8
+ export async function pathExists(filePath) {
9
+ try {
10
+ await fs.access(filePath)
11
+ return true
12
+ }
13
+ catch {
14
+ return false
15
+ }
16
+ }
17
+
18
+ export async function readJson(filePath, fallback = null) {
19
+ try {
20
+ return JSON.parse(await fs.readFile(filePath, 'utf8'))
21
+ }
22
+ catch (error) {
23
+ if (fallback !== null && error.code === 'ENOENT') return fallback
24
+ throw error
25
+ }
26
+ }
27
+
28
+ export async function writeJson(filePath, value) {
29
+ await fs.mkdir(path.dirname(filePath), { recursive: true })
30
+ await fs.writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8')
31
+ }
32
+
33
+ export async function copyDir(sourceDir, targetDir) {
34
+ const entries = await fs.readdir(sourceDir, { withFileTypes: true })
35
+ await fs.mkdir(targetDir, { recursive: true })
36
+ for (const entry of entries) {
37
+ const sourcePath = path.join(sourceDir, entry.name)
38
+ const targetPath = path.join(targetDir, entry.name)
39
+ if (entry.isDirectory()) {
40
+ await copyDir(sourcePath, targetPath)
41
+ }
42
+ else if (entry.isFile()) {
43
+ await fs.copyFile(sourcePath, targetPath)
44
+ }
45
+ }
46
+ }
47
+
48
+ export async function listFiles(rootDir) {
49
+ const files = []
50
+
51
+ async function walk(currentDir) {
52
+ const entries = await fs.readdir(currentDir, { withFileTypes: true })
53
+ for (const entry of entries) {
54
+ const absolute = path.join(currentDir, entry.name)
55
+ if (entry.isDirectory()) {
56
+ await walk(absolute)
57
+ }
58
+ else if (entry.isFile()) {
59
+ files.push(absolute)
60
+ }
61
+ }
62
+ }
63
+
64
+ await walk(rootDir)
65
+ return files.sort()
66
+ }
@@ -0,0 +1,37 @@
1
+ const messages = {
2
+ en: {
3
+ usage: 'Usage',
4
+ commands: 'Commands',
5
+ commonOptions: 'Common options',
6
+ initOk: 'init ok',
7
+ outputPath: 'outputPath',
8
+ outputDir: 'outputDir',
9
+ packagePath: 'packagePath',
10
+ serverUrl: 'serverUrl',
11
+ suggestedFixes: 'Suggested fixes:',
12
+ },
13
+ 'zh-CN': {
14
+ usage: '用法',
15
+ commands: '命令',
16
+ commonOptions: '通用选项',
17
+ initOk: 'init 完成',
18
+ outputPath: '输出路径',
19
+ outputDir: '输出目录',
20
+ packagePath: '包路径',
21
+ serverUrl: '服务地址',
22
+ suggestedFixes: '建议处理方式:',
23
+ },
24
+ }
25
+
26
+ export function normalizeLocale(value) {
27
+ return String(value || '').toLowerCase().startsWith('zh') ? 'zh-CN' : 'en'
28
+ }
29
+
30
+ export function resolveLocale(options = {}) {
31
+ return normalizeLocale(options.lang || process.env.NEUX_CLI_LANG || 'en')
32
+ }
33
+
34
+ export function translate(locale, key) {
35
+ const dictionary = messages[normalizeLocale(locale)] || messages.en
36
+ return dictionary[key] || messages.en[key] || key
37
+ }