@neuxnet/neux-cli 0.2.4 → 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/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 +4 -3
- 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 +56 -7
- 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": {
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"smoke:init-types:registry": "node ./scripts/smoke-init-types.mjs --registry",
|
|
29
29
|
"test": "node --test",
|
|
30
30
|
"smoke:help": "node ./src/bin/cli.js --help",
|
|
31
|
-
"pack:dry": "npm pack --dry-run"
|
|
31
|
+
"pack:dry": "npm pack --dry-run",
|
|
32
|
+
"verify:schemas": "node ./scripts/verify-json-schemas.mjs"
|
|
32
33
|
},
|
|
33
34
|
"engines": {
|
|
34
35
|
"node": ">=20"
|
|
@@ -63,7 +64,7 @@
|
|
|
63
64
|
"neux": {
|
|
64
65
|
"typesPackage": {
|
|
65
66
|
"name": "@neuxnet/neux-miniapp-types",
|
|
66
|
-
"versionRange": "^0.1.
|
|
67
|
+
"versionRange": "^0.1.8"
|
|
67
68
|
}
|
|
68
69
|
},
|
|
69
70
|
"publishConfig": {
|
|
@@ -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'))
|
package/src/core/init.js
CHANGED
|
@@ -139,6 +139,25 @@ async function mergeJsonFile(filePath, generated) {
|
|
|
139
139
|
...(existing['files.associations'] || {}),
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
|
+
if (generated?.['json.schemas'] || existing?.['json.schemas']) {
|
|
143
|
+
const generatedSchemas = Array.isArray(generated?.['json.schemas']) ? generated['json.schemas'] : []
|
|
144
|
+
const existingSchemas = Array.isArray(existing?.['json.schemas']) ? existing['json.schemas'] : []
|
|
145
|
+
const keys = new Set()
|
|
146
|
+
merged['json.schemas'] = [...generatedSchemas, ...existingSchemas].filter(schema => {
|
|
147
|
+
const key = `${schema?.url || ''}|${JSON.stringify(schema?.fileMatch || [])}`
|
|
148
|
+
if (keys.has(key)) return false
|
|
149
|
+
keys.add(key)
|
|
150
|
+
return true
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
if (generated?.['html.customData'] || existing?.['html.customData']) {
|
|
154
|
+
merged['html.customData'] = [
|
|
155
|
+
...new Set([
|
|
156
|
+
...(Array.isArray(generated?.['html.customData']) ? generated['html.customData'] : []),
|
|
157
|
+
...(Array.isArray(existing?.['html.customData']) ? existing['html.customData'] : []),
|
|
158
|
+
]),
|
|
159
|
+
]
|
|
160
|
+
}
|
|
142
161
|
if (filePath.endsWith('neux.code-snippets')) {
|
|
143
162
|
Object.assign(merged, generated || {}, existing || {})
|
|
144
163
|
}
|
|
@@ -277,8 +296,21 @@ function createTemplateFiles({
|
|
|
277
296
|
'*.nxml': 'html',
|
|
278
297
|
'*.nxss': 'css',
|
|
279
298
|
},
|
|
299
|
+
'json.schemas': createJsonSchemaSettings(),
|
|
300
|
+
'html.customData': ['./.vscode/neux-html-data.json'],
|
|
280
301
|
},
|
|
281
302
|
},
|
|
303
|
+
{
|
|
304
|
+
path: '.vscode/neux-html-data.json',
|
|
305
|
+
kind: 'asset',
|
|
306
|
+
source: 'neux-html-data.json',
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
path: '.vscode/neux-components.code-snippets',
|
|
310
|
+
kind: 'asset',
|
|
311
|
+
source: 'neux-components.code-snippets',
|
|
312
|
+
},
|
|
313
|
+
...createJsonSchemaFiles(),
|
|
282
314
|
{
|
|
283
315
|
path: '.vscode/neux.code-snippets',
|
|
284
316
|
kind: 'merge-json',
|
|
@@ -545,6 +577,30 @@ function createTemplateFiles({
|
|
|
545
577
|
]
|
|
546
578
|
}
|
|
547
579
|
|
|
580
|
+
function createJsonSchemaSettings() {
|
|
581
|
+
return [
|
|
582
|
+
{ fileMatch: ['/app.json'], url: './.vscode/neux-json-schemas/app.schema.json' },
|
|
583
|
+
{ fileMatch: ['/pages/**/*.json', '/components/**/*.json'], url: './.vscode/neux-json-schemas/page.schema.json' },
|
|
584
|
+
{ fileMatch: ['/project.config.json'], url: './.vscode/neux-json-schemas/project-config.schema.json' },
|
|
585
|
+
{ fileMatch: ['/project.private.config.json'], url: './.vscode/neux-json-schemas/project-private-config.schema.json' },
|
|
586
|
+
{ fileMatch: ['/neux.config.json'], url: './.vscode/neux-json-schemas/neux-config.schema.json' },
|
|
587
|
+
]
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
function createJsonSchemaFiles() {
|
|
591
|
+
return [
|
|
592
|
+
'app.schema.json',
|
|
593
|
+
'page.schema.json',
|
|
594
|
+
'project-config.schema.json',
|
|
595
|
+
'project-private-config.schema.json',
|
|
596
|
+
'neux-config.schema.json',
|
|
597
|
+
].map(name => ({
|
|
598
|
+
path: `.vscode/neux-json-schemas/${name}`,
|
|
599
|
+
kind: 'asset',
|
|
600
|
+
source: `schemas/${name}`,
|
|
601
|
+
}))
|
|
602
|
+
}
|
|
603
|
+
|
|
548
604
|
function escapeJsString(value) {
|
|
549
605
|
return String(value).replaceAll('\\', '\\\\').replaceAll("'", "\\'")
|
|
550
606
|
}
|
|
@@ -782,13 +838,6 @@ function createNeuxCodeSnippets() {
|
|
|
782
838
|
body: ['<view nx:if="{{${1:visible}}}">', ' ${0}', '</view>'],
|
|
783
839
|
description: 'Render a view conditionally',
|
|
784
840
|
},
|
|
785
|
-
'Tap Button': {
|
|
786
|
-
prefix: 'nxbutton',
|
|
787
|
-
scope: 'html',
|
|
788
|
-
include: ['**/*.nxml'],
|
|
789
|
-
body: ['<button bindtap="${1:handleTap}">${2:Button}</button>$0'],
|
|
790
|
-
description: 'Insert a button with a tap handler',
|
|
791
|
-
},
|
|
792
841
|
'Page View': {
|
|
793
842
|
prefix: 'nxview',
|
|
794
843
|
scope: 'html',
|