@neuxnet/neux-cli 0.2.3 → 0.2.5
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 +10 -0
- package/README.zh-CN.md +10 -0
- package/assets/container/assets/pageFrame.js +6 -6
- package/assets/container/assets/service.js +2 -2
- package/assets/init/neux-components.code-snippets +756 -0
- package/assets/init/neux-html-data.json +3345 -0
- package/assets/init/schemas/app.schema.json +63 -0
- package/assets/init/schemas/neux-config.schema.json +18 -0
- package/assets/init/schemas/page.schema.json +20 -0
- package/assets/init/schemas/project-config.schema.json +23 -0
- package/assets/init/schemas/project-private-config.schema.json +161 -0
- package/package.json +11 -2
- package/scripts/smoke-init-types.mjs +114 -0
- package/scripts/verify-json-schemas.mjs +40 -0
- package/src/bin/cli.js +12 -0
- package/src/core/compiler.js +11 -0
- package/src/core/init.js +88 -16
- package/src/core/package-info.js +1 -0
- package/src/core/project.js +138 -1
- package/src/index.js +1 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://neuxnet.com/schemas/neux/app.schema.json",
|
|
4
|
+
"title": "Neux app configuration",
|
|
5
|
+
"description": "Application-level configuration consumed by the Neux mini program compiler.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"pages": { "type": "array", "description": "Page entry paths, relative to miniprogramRoot.", "items": { "type": "string", "minLength": 1 } },
|
|
9
|
+
"entryPagePath": { "type": "string", "description": "Optional initial page path." },
|
|
10
|
+
"window": { "$ref": "#/definitions/window" },
|
|
11
|
+
"tabBar": { "$ref": "#/definitions/tabBar" },
|
|
12
|
+
"subPackages": { "$ref": "#/definitions/subPackages" },
|
|
13
|
+
"subpackages": { "$ref": "#/definitions/subPackages" },
|
|
14
|
+
"preloadRule": { "type": "object", "description": "Page preload configuration.", "additionalProperties": { "type": "object" } },
|
|
15
|
+
"networkTimeout": { "type": "object", "properties": { "request": { "type": "number", "minimum": 0 }, "connectSocket": { "type": "number", "minimum": 0 }, "uploadFile": { "type": "number", "minimum": 0 }, "downloadFile": { "type": "number", "minimum": 0 } }, "additionalProperties": true },
|
|
16
|
+
"permission": { "type": "object", "description": "Permission declarations used by the host runtime.", "additionalProperties": true },
|
|
17
|
+
"usingComponents": { "$ref": "#/definitions/usingComponents" },
|
|
18
|
+
"style": { "type": "string" },
|
|
19
|
+
"sitemapLocation": { "type": "string" }
|
|
20
|
+
},
|
|
21
|
+
"additionalProperties": true,
|
|
22
|
+
"definitions": {
|
|
23
|
+
"window": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"properties": {
|
|
26
|
+
"navigationBarTitleText": { "type": "string" },
|
|
27
|
+
"navigationBarBackgroundColor": { "type": "string", "pattern": "^#?[0-9a-fA-F]{3,8}$" },
|
|
28
|
+
"navigationBarTextStyle": { "type": "string", "enum": ["black", "white"] },
|
|
29
|
+
"backgroundColor": { "type": "string", "pattern": "^#?[0-9a-fA-F]{3,8}$" },
|
|
30
|
+
"backgroundTextStyle": { "type": "string", "enum": ["dark", "light"] },
|
|
31
|
+
"enablePullDownRefresh": { "type": "boolean" },
|
|
32
|
+
"onReachBottomDistance": { "type": "number", "minimum": 0 },
|
|
33
|
+
"pageOrientation": { "type": "string" }
|
|
34
|
+
},
|
|
35
|
+
"additionalProperties": true
|
|
36
|
+
},
|
|
37
|
+
"tabBar": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"properties": {
|
|
40
|
+
"color": { "type": "string" },
|
|
41
|
+
"selectedColor": { "type": "string" },
|
|
42
|
+
"backgroundColor": { "type": "string" },
|
|
43
|
+
"borderStyle": { "type": "string", "enum": ["black", "white"] },
|
|
44
|
+
"position": { "type": "string", "enum": ["bottom", "top"] },
|
|
45
|
+
"custom": { "type": "boolean" },
|
|
46
|
+
"list": { "type": "array", "minItems": 1, "maxItems": 5, "items": { "$ref": "#/definitions/tabBarItem" } }
|
|
47
|
+
},
|
|
48
|
+
"required": ["list"],
|
|
49
|
+
"additionalProperties": true
|
|
50
|
+
},
|
|
51
|
+
"tabBarItem": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"properties": { "pagePath": { "type": "string" }, "text": { "type": "string" }, "iconPath": { "type": "string" }, "selectedIconPath": { "type": "string" } },
|
|
54
|
+
"required": ["pagePath", "text"],
|
|
55
|
+
"additionalProperties": true
|
|
56
|
+
},
|
|
57
|
+
"subPackages": {
|
|
58
|
+
"type": "array",
|
|
59
|
+
"items": { "type": "object", "properties": { "root": { "type": "string" }, "pages": { "type": "array", "items": { "type": "string" } }, "independent": { "type": "boolean" } }, "required": ["root", "pages"], "additionalProperties": true }
|
|
60
|
+
},
|
|
61
|
+
"usingComponents": { "type": "object", "description": "Maps component names to component files or package names.", "additionalProperties": { "type": "string", "minLength": 1 } }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://neuxnet.com/schemas/neux/neux-config.schema.json",
|
|
4
|
+
"title": "Neux CLI project configuration",
|
|
5
|
+
"description": "Non-secret project settings read by the Neux CLI. Never put CLI keys in this file.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"serverUrl": { "type": "string", "format": "uri", "description": "Signed service base URL." },
|
|
9
|
+
"appId": { "type": "string" },
|
|
10
|
+
"appid": { "type": "string" },
|
|
11
|
+
"profile": { "type": "string" },
|
|
12
|
+
"version": { "type": "string" },
|
|
13
|
+
"versionName": { "type": "string" },
|
|
14
|
+
"versionCode": { "type": "integer", "minimum": 1 }
|
|
15
|
+
},
|
|
16
|
+
"not": { "anyOf": [ { "required": ["key"] }, { "required": ["cliKey"] }, { "required": ["neuxCliKey"] } ] },
|
|
17
|
+
"additionalProperties": true
|
|
18
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://neuxnet.com/schemas/neux/page.schema.json",
|
|
4
|
+
"title": "Neux page configuration",
|
|
5
|
+
"description": "Page-level configuration consumed by the Neux mini program compiler.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"navigationBarTitleText": { "type": "string" },
|
|
9
|
+
"navigationBarBackgroundColor": { "type": "string" },
|
|
10
|
+
"navigationBarTextStyle": { "type": "string", "enum": ["black", "white"] },
|
|
11
|
+
"backgroundColor": { "type": "string" },
|
|
12
|
+
"backgroundTextStyle": { "type": "string", "enum": ["dark", "light"] },
|
|
13
|
+
"enablePullDownRefresh": { "type": "boolean" },
|
|
14
|
+
"onReachBottomDistance": { "type": "number", "minimum": 0 },
|
|
15
|
+
"usingComponents": { "type": "object", "additionalProperties": { "type": "string", "minLength": 1 } },
|
|
16
|
+
"disableScroll": { "type": "boolean" },
|
|
17
|
+
"pageOrientation": { "type": "string" }
|
|
18
|
+
},
|
|
19
|
+
"additionalProperties": true
|
|
20
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://neuxnet.com/schemas/neux/project-config.schema.json",
|
|
4
|
+
"title": "Neux project configuration",
|
|
5
|
+
"description": "Project and compiler settings consumed by neux and the Neux compiler.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"description": { "type": "string" }, "appid": { "type": "string" }, "appId": { "type": "string" },
|
|
9
|
+
"projectname": { "type": "string" }, "projectName": { "type": "string" },
|
|
10
|
+
"compileType": { "type": "string", "enum": ["miniprogram"] }, "libVersion": { "type": "string" },
|
|
11
|
+
"miniprogramRoot": { "type": "string" }, "versionName": { "type": "string" }, "version": { "type": "string" }, "versionCode": { "type": "integer", "minimum": 1 },
|
|
12
|
+
"setting": { "$ref": "#/definitions/setting" }, "condition": { "type": "object", "additionalProperties": true },
|
|
13
|
+
"packOptions": { "$ref": "#/definitions/packOptions" }, "editorSetting": { "$ref": "#/definitions/editorSetting" },
|
|
14
|
+
"neux": { "$ref": "#/definitions/neux" }, "neuxCli": { "$ref": "#/definitions/neux" }
|
|
15
|
+
},
|
|
16
|
+
"additionalProperties": true,
|
|
17
|
+
"definitions": {
|
|
18
|
+
"setting": { "type": "object", "properties": { "urlCheck": { "type": "boolean" }, "es6": { "type": "boolean" }, "postcss": { "type": "boolean" }, "minified": { "type": "boolean" }, "newFeature": { "type": "boolean" }, "babelSetting": { "type": "object", "properties": { "ignore": { "type": "array", "items": { "type": "string" } }, "disablePlugins": { "type": "array", "items": { "type": "string" } }, "outputPath": { "type": "string" } }, "additionalProperties": true } }, "additionalProperties": true },
|
|
19
|
+
"packOptions": { "type": "object", "properties": { "ignore": { "type": "array", "items": { "type": "string" } }, "include": { "type": "array", "items": { "type": "string" } } }, "additionalProperties": true },
|
|
20
|
+
"editorSetting": { "type": "object", "properties": { "tabIndent": { "type": "string", "enum": ["insertSpaces", "indexSize"] }, "tabSize": { "type": "integer", "minimum": 1 } }, "additionalProperties": true },
|
|
21
|
+
"neux": { "type": "object", "properties": { "serverUrl": { "type": "string", "format": "uri" }, "appId": { "type": "string" }, "profile": { "type": "string" } }, "additionalProperties": true }
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://neuxnet.com/schemas/neux/project-private-config.schema.json",
|
|
4
|
+
"title": "Neux private project configuration",
|
|
5
|
+
"description": "Optional local overrides for project.config.json. All fields are optional.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"description": {
|
|
9
|
+
"type": "string"
|
|
10
|
+
},
|
|
11
|
+
"appid": {
|
|
12
|
+
"type": "string"
|
|
13
|
+
},
|
|
14
|
+
"appId": {
|
|
15
|
+
"type": "string"
|
|
16
|
+
},
|
|
17
|
+
"projectname": {
|
|
18
|
+
"type": "string"
|
|
19
|
+
},
|
|
20
|
+
"projectName": {
|
|
21
|
+
"type": "string"
|
|
22
|
+
},
|
|
23
|
+
"compileType": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"enum": [
|
|
26
|
+
"miniprogram"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"libVersion": {
|
|
30
|
+
"type": "string"
|
|
31
|
+
},
|
|
32
|
+
"miniprogramRoot": {
|
|
33
|
+
"type": "string"
|
|
34
|
+
},
|
|
35
|
+
"versionName": {
|
|
36
|
+
"type": "string"
|
|
37
|
+
},
|
|
38
|
+
"version": {
|
|
39
|
+
"type": "string"
|
|
40
|
+
},
|
|
41
|
+
"versionCode": {
|
|
42
|
+
"type": "integer",
|
|
43
|
+
"minimum": 1
|
|
44
|
+
},
|
|
45
|
+
"setting": {
|
|
46
|
+
"$ref": "#/definitions/setting"
|
|
47
|
+
},
|
|
48
|
+
"condition": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"additionalProperties": true
|
|
51
|
+
},
|
|
52
|
+
"packOptions": {
|
|
53
|
+
"$ref": "#/definitions/packOptions"
|
|
54
|
+
},
|
|
55
|
+
"editorSetting": {
|
|
56
|
+
"$ref": "#/definitions/editorSetting"
|
|
57
|
+
},
|
|
58
|
+
"neux": {
|
|
59
|
+
"$ref": "#/definitions/neux"
|
|
60
|
+
},
|
|
61
|
+
"neuxCli": {
|
|
62
|
+
"$ref": "#/definitions/neux"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"additionalProperties": true,
|
|
66
|
+
"definitions": {
|
|
67
|
+
"setting": {
|
|
68
|
+
"type": "object",
|
|
69
|
+
"properties": {
|
|
70
|
+
"urlCheck": {
|
|
71
|
+
"type": "boolean"
|
|
72
|
+
},
|
|
73
|
+
"es6": {
|
|
74
|
+
"type": "boolean"
|
|
75
|
+
},
|
|
76
|
+
"postcss": {
|
|
77
|
+
"type": "boolean"
|
|
78
|
+
},
|
|
79
|
+
"minified": {
|
|
80
|
+
"type": "boolean"
|
|
81
|
+
},
|
|
82
|
+
"newFeature": {
|
|
83
|
+
"type": "boolean"
|
|
84
|
+
},
|
|
85
|
+
"babelSetting": {
|
|
86
|
+
"type": "object",
|
|
87
|
+
"properties": {
|
|
88
|
+
"ignore": {
|
|
89
|
+
"type": "array",
|
|
90
|
+
"items": {
|
|
91
|
+
"type": "string"
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"disablePlugins": {
|
|
95
|
+
"type": "array",
|
|
96
|
+
"items": {
|
|
97
|
+
"type": "string"
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"outputPath": {
|
|
101
|
+
"type": "string"
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"additionalProperties": true
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"additionalProperties": true
|
|
108
|
+
},
|
|
109
|
+
"packOptions": {
|
|
110
|
+
"type": "object",
|
|
111
|
+
"properties": {
|
|
112
|
+
"ignore": {
|
|
113
|
+
"type": "array",
|
|
114
|
+
"items": {
|
|
115
|
+
"type": "string"
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"include": {
|
|
119
|
+
"type": "array",
|
|
120
|
+
"items": {
|
|
121
|
+
"type": "string"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"additionalProperties": true
|
|
126
|
+
},
|
|
127
|
+
"editorSetting": {
|
|
128
|
+
"type": "object",
|
|
129
|
+
"properties": {
|
|
130
|
+
"tabIndent": {
|
|
131
|
+
"type": "string",
|
|
132
|
+
"enum": [
|
|
133
|
+
"insertSpaces",
|
|
134
|
+
"indexSize"
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
"tabSize": {
|
|
138
|
+
"type": "integer",
|
|
139
|
+
"minimum": 1
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"additionalProperties": true
|
|
143
|
+
},
|
|
144
|
+
"neux": {
|
|
145
|
+
"type": "object",
|
|
146
|
+
"properties": {
|
|
147
|
+
"serverUrl": {
|
|
148
|
+
"type": "string",
|
|
149
|
+
"format": "uri"
|
|
150
|
+
},
|
|
151
|
+
"appId": {
|
|
152
|
+
"type": "string"
|
|
153
|
+
},
|
|
154
|
+
"profile": {
|
|
155
|
+
"type": "string"
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"additionalProperties": true
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neuxnet/neux-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Standalone CLI and Node API for Neux mini program build, pack, preview, and CI automation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -24,9 +24,12 @@
|
|
|
24
24
|
"sync:compiler": "node ./scripts/sync-compiler.js",
|
|
25
25
|
"prepare:publish": "npm run sync:compiler && npm run sync:container",
|
|
26
26
|
"generate:init-types": "node ./scripts/generate-init-types.js",
|
|
27
|
+
"smoke:init-types": "node ./scripts/smoke-init-types.mjs",
|
|
28
|
+
"smoke:init-types:registry": "node ./scripts/smoke-init-types.mjs --registry",
|
|
27
29
|
"test": "node --test",
|
|
28
30
|
"smoke:help": "node ./src/bin/cli.js --help",
|
|
29
|
-
"pack:dry": "npm pack --dry-run"
|
|
31
|
+
"pack:dry": "npm pack --dry-run",
|
|
32
|
+
"verify:schemas": "node ./scripts/verify-json-schemas.mjs"
|
|
30
33
|
},
|
|
31
34
|
"engines": {
|
|
32
35
|
"node": ">=20"
|
|
@@ -58,6 +61,12 @@
|
|
|
58
61
|
"preview"
|
|
59
62
|
],
|
|
60
63
|
"license": "Apache-2.0",
|
|
64
|
+
"neux": {
|
|
65
|
+
"typesPackage": {
|
|
66
|
+
"name": "@neuxnet/neux-miniapp-types",
|
|
67
|
+
"versionRange": "^0.1.8"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
61
70
|
"publishConfig": {
|
|
62
71
|
"access": "public"
|
|
63
72
|
},
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import fs from 'node:fs/promises'
|
|
2
|
+
import os from 'node:os'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { execFile } from 'node:child_process'
|
|
5
|
+
import { promisify } from 'node:util'
|
|
6
|
+
import { initProject } from '../src/core/init.js'
|
|
7
|
+
|
|
8
|
+
const execFileAsync = promisify(execFile)
|
|
9
|
+
const cliRoot = path.resolve(import.meta.dirname, '..')
|
|
10
|
+
const repoRoot = path.resolve(cliRoot, '..')
|
|
11
|
+
const typesRoot = path.join(repoRoot, 'neux-miniapp-types')
|
|
12
|
+
const tscPath = path.join(repoRoot, 'fe', 'node_modules', '.bin', 'tsc')
|
|
13
|
+
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'neux-cli-types-smoke-'))
|
|
14
|
+
const registryMode = process.argv.includes('--registry')
|
|
15
|
+
|
|
16
|
+
async function pack(directory, destination) {
|
|
17
|
+
const { stdout } = await execFileAsync('npm', [
|
|
18
|
+
'pack',
|
|
19
|
+
'--pack-destination',
|
|
20
|
+
destination,
|
|
21
|
+
'--json',
|
|
22
|
+
], { cwd: directory })
|
|
23
|
+
const result = JSON.parse(stdout)
|
|
24
|
+
return path.join(destination, result[0].filename)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const project = path.join(tempRoot, 'starter-app')
|
|
29
|
+
await initProject({
|
|
30
|
+
_: [project],
|
|
31
|
+
appId: 'wxlocaltypes123',
|
|
32
|
+
name: 'Local Types Smoke',
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const packageJsonPath = path.join(project, 'package.json')
|
|
36
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'))
|
|
37
|
+
const typesPackage = packageJson.devDependencies['@neuxnet/neux-miniapp-types']
|
|
38
|
+
const cliPackage = JSON.parse(await fs.readFile(
|
|
39
|
+
path.join(cliRoot, 'package.json'),
|
|
40
|
+
'utf8',
|
|
41
|
+
))
|
|
42
|
+
const expectedTypesRange = cliPackage.neux?.typesPackage?.versionRange
|
|
43
|
+
if (typesPackage !== expectedTypesRange) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Unexpected generated types dependency: ${typesPackage}; ` +
|
|
46
|
+
`expected ${expectedTypesRange}`,
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!registryMode) {
|
|
51
|
+
const typesTarball = await pack(typesRoot, tempRoot)
|
|
52
|
+
const cliTarball = await pack(cliRoot, tempRoot)
|
|
53
|
+
packageJson.devDependencies['@neuxnet/neux-cli'] = `file:${cliTarball}`
|
|
54
|
+
packageJson.devDependencies['@neuxnet/neux-miniapp-types'] = `file:${typesTarball}`
|
|
55
|
+
}
|
|
56
|
+
await fs.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf8')
|
|
57
|
+
|
|
58
|
+
await fs.writeFile(path.join(project, 'types', 'consumer.ts'), [
|
|
59
|
+
'Page({',
|
|
60
|
+
' data: { count: 0 },',
|
|
61
|
+
' onLoad(query) {',
|
|
62
|
+
' const id: string | undefined = query.id',
|
|
63
|
+
' this.setData({ count: this.data.count + 1, dynamicallyAdded: true })',
|
|
64
|
+
' void id',
|
|
65
|
+
' },',
|
|
66
|
+
'})',
|
|
67
|
+
'',
|
|
68
|
+
'wx.request({',
|
|
69
|
+
" url: '/api/profile',",
|
|
70
|
+
" method: 'GET',",
|
|
71
|
+
' success(result) { result }',
|
|
72
|
+
'})',
|
|
73
|
+
'',
|
|
74
|
+
"Component({ properties: { title: String }, methods: { emitChange() {",
|
|
75
|
+
" this.triggerEvent<{ value: string }>('change', { value: this.properties.title })",
|
|
76
|
+
'} } })',
|
|
77
|
+
'',
|
|
78
|
+
].join('\n'), 'utf8')
|
|
79
|
+
|
|
80
|
+
const installArgs = [
|
|
81
|
+
'install',
|
|
82
|
+
'--ignore-scripts',
|
|
83
|
+
'--no-package-lock',
|
|
84
|
+
]
|
|
85
|
+
if (registryMode) {
|
|
86
|
+
installArgs.push('--registry=https://registry.npmjs.org/')
|
|
87
|
+
}
|
|
88
|
+
await execFileAsync('npm', installArgs, {
|
|
89
|
+
cwd: project,
|
|
90
|
+
maxBuffer: 1024 * 1024,
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
await execFileAsync(tscPath, [
|
|
94
|
+
'-p',
|
|
95
|
+
path.join(project, 'jsconfig.json'),
|
|
96
|
+
'--noEmit',
|
|
97
|
+
], { cwd: project, maxBuffer: 1024 * 1024 })
|
|
98
|
+
|
|
99
|
+
const installedTypesPackage = JSON.parse(await fs.readFile(
|
|
100
|
+
path.join(project, 'node_modules', '@neuxnet', 'neux-miniapp-types', 'package.json'),
|
|
101
|
+
'utf8',
|
|
102
|
+
))
|
|
103
|
+
if (installedTypesPackage.name !== '@neuxnet/neux-miniapp-types') {
|
|
104
|
+
throw new Error('Installed types package has an unexpected name')
|
|
105
|
+
}
|
|
106
|
+
if (installedTypesPackage.types !== './index.d.ts') {
|
|
107
|
+
throw new Error('Installed types package does not expose index.d.ts')
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
console.log(`Passed: neux init -> ${registryMode ? 'registry' : 'local'} npm install -> TypeScript consumer check.`)
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
await fs.rm(tempRoot, { recursive: true, force: true })
|
|
114
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import fs from 'node:fs/promises'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
|
|
5
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
|
6
|
+
const schemaDir = path.join(root, 'assets', 'init', 'schemas')
|
|
7
|
+
const initSource = await fs.readFile(path.join(root, 'src', 'core', 'init.js'), 'utf8')
|
|
8
|
+
const projectSource = await fs.readFile(path.join(root, 'src', 'core', 'project.js'), 'utf8')
|
|
9
|
+
const serviceSource = await fs.readFile(path.join(root, 'src', 'providers', 'service-config.js'), 'utf8')
|
|
10
|
+
|
|
11
|
+
const manifest = {
|
|
12
|
+
'app.schema.json': { fields: ['pages', 'entryPagePath', 'window', 'tabBar', 'subPackages', 'subpackages', 'preloadRule', 'networkTimeout', 'permission', 'usingComponents'] },
|
|
13
|
+
'page.schema.json': { fields: ['navigationBarTitleText', 'navigationBarBackgroundColor', 'navigationBarTextStyle', 'backgroundColor', 'backgroundTextStyle', 'enablePullDownRefresh', 'onReachBottomDistance', 'usingComponents', 'disableScroll', 'pageOrientation'] },
|
|
14
|
+
'project-config.schema.json': { fields: ['appid', 'projectname', 'compileType', 'libVersion', 'miniprogramRoot', 'versionName', 'versionCode', 'setting', 'condition', 'packOptions', 'editorSetting', 'neuxCli'] },
|
|
15
|
+
'project-private-config.schema.json': { fields: ['appid', 'projectname', 'versionName', 'versionCode', 'setting', 'packOptions', 'neuxCli'] },
|
|
16
|
+
'neux-config.schema.json': { fields: ['serverUrl', 'appId', 'appid', 'profile', 'version', 'versionName', 'versionCode'] },
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const errors = []
|
|
20
|
+
for (const [name, entry] of Object.entries(manifest)) {
|
|
21
|
+
const file = path.join(schemaDir, name)
|
|
22
|
+
let schema
|
|
23
|
+
try { schema = JSON.parse(await fs.readFile(file, 'utf8')) } catch (error) { errors.push(`${name}: invalid JSON (${error.message})`); continue }
|
|
24
|
+
if (schema.$schema !== 'http://json-schema.org/draft-07/schema#') errors.push(`${name}: missing draft-07 $schema`)
|
|
25
|
+
if (!schema.title || !schema.description) errors.push(`${name}: title and description are required`)
|
|
26
|
+
const serialized = JSON.stringify(schema)
|
|
27
|
+
for (const field of entry.fields) if (!serialized.includes(`"${field}"`)) errors.push(`${name}: source field is missing from schema: ${field}`)
|
|
28
|
+
if (name === 'neux-config.schema.json') {
|
|
29
|
+
for (const secret of ['key', 'cliKey', 'neuxCliKey']) if (schema.properties?.[secret]) errors.push(`${name}: secret field must not be declared: ${secret}`)
|
|
30
|
+
if (!schema.not?.anyOf?.some(rule => rule.required?.includes('key'))) errors.push(`${name}: must reject key`)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const settings = initSource.match(/function createJsonSchemaSettings\(\)\s*\{([\s\S]*?)\n\}/)?.[1] || ''
|
|
34
|
+
for (const name of Object.keys(manifest)) {
|
|
35
|
+
if (!settings.includes(name)) errors.push(`init.js: schema is not registered: ${name}`)
|
|
36
|
+
try { await fs.access(path.join(schemaDir, name)) } catch { errors.push(`missing schema asset: ${name}`) }
|
|
37
|
+
}
|
|
38
|
+
if (!projectSource.includes('readProjectCliConfig') || !serviceSource.includes('assertNoKey')) errors.push('source guard: expected configuration readers were not found')
|
|
39
|
+
if (errors.length) { console.error(['JSON Schema verification failed:', ...errors.map(error => `- ${error}`)].join('\n')); process.exitCode = 1 }
|
|
40
|
+
else console.log(`JSON Schema verification passed (${Object.keys(manifest).length} schemas, ${Object.values(manifest).reduce((n, item) => n + item.fields.length, 0)} source-backed fields).`)
|
package/src/bin/cli.js
CHANGED
|
@@ -307,6 +307,12 @@ async function writeResult(result, rawOptions) {
|
|
|
307
307
|
process.stdout.write(`key: ${result.key?.present ? 'configured' : 'missing'}\n`)
|
|
308
308
|
if (result.missing?.length) process.stdout.write(`missing: ${result.missing.join(', ')}\n`)
|
|
309
309
|
}
|
|
310
|
+
if (Array.isArray(result.diagnostics) && result.diagnostics.length > 0) {
|
|
311
|
+
process.stdout.write(`diagnostics: ${result.diagnostics.length}\n`)
|
|
312
|
+
for (const diagnostic of result.diagnostics) {
|
|
313
|
+
process.stdout.write(` [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}\n`)
|
|
314
|
+
}
|
|
315
|
+
}
|
|
310
316
|
if (result.qrPayload && qrFormat === 'terminal') {
|
|
311
317
|
process.stdout.write('\n')
|
|
312
318
|
process.stdout.write(await renderTerminalQr(result.qrPayload))
|
|
@@ -315,6 +321,12 @@ async function writeResult(result, rawOptions) {
|
|
|
315
321
|
|
|
316
322
|
function formatErrorPayload(payload, locale = 'en') {
|
|
317
323
|
const lines = [`${payload.code}: ${payload.message}`]
|
|
324
|
+
if (payload.details?.diagnostics?.length) {
|
|
325
|
+
lines.push('', 'Diagnostics:')
|
|
326
|
+
for (const diagnostic of payload.details.diagnostics) {
|
|
327
|
+
lines.push(` [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`)
|
|
328
|
+
}
|
|
329
|
+
}
|
|
318
330
|
const suggestions = payload.details?.suggestions
|
|
319
331
|
if (payload.code === 'NEUX_CLI_CONFIG_MISSING' && Array.isArray(suggestions) && suggestions.length > 0) {
|
|
320
332
|
lines.push('', translate(locale, 'suggestedFixes'))
|
package/src/core/compiler.js
CHANGED
|
@@ -49,6 +49,7 @@ async function loadCompiler(moduleSpecifier) {
|
|
|
49
49
|
|
|
50
50
|
export async function buildProject(options = {}) {
|
|
51
51
|
const projectInfo = await inspectProject(options)
|
|
52
|
+
assertProjectConfiguration(projectInfo, options)
|
|
52
53
|
const out = resolvePath(options.out || options.output || defaultOut('build'))
|
|
53
54
|
const compilerModule = options.compiler || await loadCompiler(options.compilerModule || process.env.DIMINA_COMPILER_MODULE)
|
|
54
55
|
const build = compilerModule.default || compilerModule.build || compilerModule
|
|
@@ -92,12 +93,22 @@ export async function buildProject(options = {}) {
|
|
|
92
93
|
compilerInputCreated: compilerInput.created,
|
|
93
94
|
outputPath: out,
|
|
94
95
|
appId: projectInfo.appId,
|
|
96
|
+
diagnostics: projectInfo.diagnostics,
|
|
95
97
|
compilerResult,
|
|
96
98
|
logs,
|
|
97
99
|
errors,
|
|
98
100
|
}
|
|
99
101
|
}
|
|
100
102
|
|
|
103
|
+
function assertProjectConfiguration(projectInfo, options = {}) {
|
|
104
|
+
if (options.validate === false || projectInfo.ok) return
|
|
105
|
+
throw new DiminaCliError(
|
|
106
|
+
'NEUX_PROJECT_CONFIG_INVALID',
|
|
107
|
+
`Project configuration validation failed with ${projectInfo.diagnostics.length} error(s).`,
|
|
108
|
+
{ diagnostics: projectInfo.diagnostics },
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
101
112
|
export async function buildStyleOnlyProject(options = {}) {
|
|
102
113
|
const projectInfo = await inspectProject(options)
|
|
103
114
|
const out = resolvePath(options.out || options.output || defaultOut('build'))
|