@lizardon386/sdk-tools 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/doctor.d.ts +4 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +58 -2
- package/dist/cli/doctor.js.map +1 -1
- package/package.json +3 -3
- package/src/cli/doctor.ts +67 -2
- package/templates/scripts/build.mjs +27 -1
package/dist/cli/doctor.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { GameReferenceSpec } from '@lizardon386/core-abi';
|
|
1
2
|
export interface HostInfo {
|
|
2
3
|
platform?: string;
|
|
3
4
|
packFormats?: unknown;
|
|
@@ -16,6 +17,9 @@ export interface DoctorTarget {
|
|
|
16
17
|
format: number;
|
|
17
18
|
mode: string;
|
|
18
19
|
apiVersion: number;
|
|
20
|
+
reference?: GameReferenceSpec;
|
|
21
|
+
/** 资料文档原文;源目录与包都用它跑同一份 parseGameReference。 */
|
|
22
|
+
referenceText?: string;
|
|
19
23
|
}
|
|
20
24
|
export interface DoctorCheck {
|
|
21
25
|
ok: boolean;
|
package/dist/cli/doctor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,8CAA8C;IAC9C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AA+DD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAI7D;AAUD,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,GAAG,WAAW,EAAE,CAoB7E;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAiBnE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,EAAE,CAiD/D;AAED,wBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAQpF"}
|
package/dist/cli/doctor.js
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
2
|
import { join, resolve } from 'node:path';
|
|
3
|
-
import { API_VERSION, DEFAULT_MODE } from '@lizardon386/core-abi';
|
|
3
|
+
import { API_VERSION, DEFAULT_MODE, isValidGameReferenceEntry, parseGameReference, } from '@lizardon386/core-abi';
|
|
4
4
|
import { PACK_FORMAT, readPack, readPackSource } from '@lizardon386/pack-format';
|
|
5
|
+
function readDeclaredReference(value) {
|
|
6
|
+
if (value === undefined)
|
|
7
|
+
return undefined;
|
|
8
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
9
|
+
throw new Error('bpmap.json 的 reference 必须是对象');
|
|
10
|
+
}
|
|
11
|
+
const entry = value.entry;
|
|
12
|
+
if (typeof entry !== 'string' || !isValidGameReferenceEntry(entry)) {
|
|
13
|
+
throw new Error('bpmap.json 的 reference.entry 必须是包内 .json 相对路径');
|
|
14
|
+
}
|
|
15
|
+
return { entry };
|
|
16
|
+
}
|
|
5
17
|
function readSourceTarget(dir) {
|
|
6
18
|
const rawPath = join(dir, 'bpmap.json');
|
|
7
19
|
let raw;
|
|
@@ -15,6 +27,7 @@ function readSourceTarget(dir) {
|
|
|
15
27
|
throw new Error(`读不到或解析不了源清单:${rawPath}(${error instanceof Error ? error.message : String(error)})`);
|
|
16
28
|
}
|
|
17
29
|
const source = readPackSource(dir);
|
|
30
|
+
const reference = readDeclaredReference(raw.reference);
|
|
18
31
|
return {
|
|
19
32
|
kind: 'source',
|
|
20
33
|
path: dir,
|
|
@@ -27,10 +40,15 @@ function readSourceTarget(dir) {
|
|
|
27
40
|
apiVersion: typeof raw.apiVersion === 'number' && Number.isSafeInteger(raw.apiVersion) && raw.apiVersion > 0
|
|
28
41
|
? raw.apiVersion
|
|
29
42
|
: API_VERSION,
|
|
43
|
+
...(reference ? { reference } : {}),
|
|
30
44
|
};
|
|
31
45
|
}
|
|
32
46
|
function readPackTarget(file) {
|
|
33
47
|
const pack = readPack(file);
|
|
48
|
+
const reference = pack.manifest.reference;
|
|
49
|
+
const document = reference
|
|
50
|
+
? pack.files.find((entry) => entry.path.toLowerCase() === reference.entry.toLowerCase())
|
|
51
|
+
: undefined;
|
|
34
52
|
return {
|
|
35
53
|
kind: 'pack',
|
|
36
54
|
path: file,
|
|
@@ -41,6 +59,8 @@ function readPackTarget(file) {
|
|
|
41
59
|
format: pack.manifest.format,
|
|
42
60
|
mode: pack.manifest.mode,
|
|
43
61
|
apiVersion: pack.manifest.apiVersion,
|
|
62
|
+
...(reference ? { reference } : {}),
|
|
63
|
+
...(document ? { referenceText: document.bytes.toString('utf8') } : {}),
|
|
44
64
|
};
|
|
45
65
|
}
|
|
46
66
|
export function readDoctorTarget(target) {
|
|
@@ -106,12 +126,48 @@ export function localChecks(target) {
|
|
|
106
126
|
];
|
|
107
127
|
if (target.client)
|
|
108
128
|
checks.push({ ok: existsSync(join(dir, target.client)), label: `客户端入口 ${target.client}` });
|
|
129
|
+
if (target.reference) {
|
|
130
|
+
const entry = target.reference.entry;
|
|
131
|
+
const valid = isValidGameReferenceEntry(entry);
|
|
132
|
+
checks.push({
|
|
133
|
+
ok: valid,
|
|
134
|
+
label: `资料文档入口 ${entry}`,
|
|
135
|
+
...(valid ? {} : { detail: '必须是包内 .json 相对路径' }),
|
|
136
|
+
});
|
|
137
|
+
if (valid) {
|
|
138
|
+
const absolute = join(dir, ...entry.split('/'));
|
|
139
|
+
const exists = existsSync(absolute);
|
|
140
|
+
checks.push({ ok: exists, label: `资料文档 ${entry}` });
|
|
141
|
+
if (exists) {
|
|
142
|
+
const parsed = parseGameReference(readFileSync(absolute, 'utf8'));
|
|
143
|
+
checks.push({
|
|
144
|
+
ok: parsed.ok,
|
|
145
|
+
label: '资料文档格式',
|
|
146
|
+
...(parsed.ok ? {} : { detail: parsed.error }),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
109
151
|
return checks;
|
|
110
152
|
}
|
|
111
|
-
|
|
153
|
+
const checks = [
|
|
112
154
|
{ ok: target.format === PACK_FORMAT, label: `包格式 ${target.format}` },
|
|
113
155
|
{ ok: Boolean(target.server), label: `服务端入口 ${target.server}` },
|
|
114
156
|
];
|
|
157
|
+
if (target.reference) {
|
|
158
|
+
const entry = target.reference.entry;
|
|
159
|
+
const inPack = target.referenceText !== undefined;
|
|
160
|
+
checks.push({ ok: inPack, label: `资料文档 ${entry} 在包清单里` });
|
|
161
|
+
if (inPack) {
|
|
162
|
+
const parsed = parseGameReference(target.referenceText);
|
|
163
|
+
checks.push({
|
|
164
|
+
ok: parsed.ok,
|
|
165
|
+
label: '资料文档格式',
|
|
166
|
+
...(parsed.ok ? {} : { detail: parsed.error }),
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return checks;
|
|
115
171
|
}
|
|
116
172
|
export async function doctor(target, hostUrl) {
|
|
117
173
|
const info = readDoctorTarget(target);
|
package/dist/cli/doctor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lizardon386/sdk-tools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "3178 SDK 工具:bpmap CLI、doctor 和游戏工程脚本模板",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "3178-battle-platform contributors",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"src"
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@lizardon386/core-abi": "^0.
|
|
36
|
-
"@lizardon386/pack-format": "^0.
|
|
35
|
+
"@lizardon386/core-abi": "^0.3.0",
|
|
36
|
+
"@lizardon386/pack-format": "^0.3.0"
|
|
37
37
|
},
|
|
38
38
|
"publishConfig": {
|
|
39
39
|
"access": "public"
|
package/src/cli/doctor.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
2
|
import { join, resolve } from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
API_VERSION,
|
|
5
|
+
DEFAULT_MODE,
|
|
6
|
+
isValidGameReferenceEntry,
|
|
7
|
+
parseGameReference,
|
|
8
|
+
} from '@lizardon386/core-abi';
|
|
9
|
+
import type { GameReferenceSpec } from '@lizardon386/core-abi';
|
|
4
10
|
import { PACK_FORMAT, readPack, readPackSource } from '@lizardon386/pack-format';
|
|
5
11
|
|
|
6
12
|
export interface HostInfo {
|
|
@@ -22,6 +28,9 @@ export interface DoctorTarget {
|
|
|
22
28
|
format: number;
|
|
23
29
|
mode: string;
|
|
24
30
|
apiVersion: number;
|
|
31
|
+
reference?: GameReferenceSpec;
|
|
32
|
+
/** 资料文档原文;源目录与包都用它跑同一份 parseGameReference。 */
|
|
33
|
+
referenceText?: string;
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
export interface DoctorCheck {
|
|
@@ -35,6 +44,18 @@ export interface DoctorReport {
|
|
|
35
44
|
checks: DoctorCheck[];
|
|
36
45
|
}
|
|
37
46
|
|
|
47
|
+
function readDeclaredReference(value: unknown): GameReferenceSpec | undefined {
|
|
48
|
+
if (value === undefined) return undefined;
|
|
49
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
50
|
+
throw new Error('bpmap.json 的 reference 必须是对象');
|
|
51
|
+
}
|
|
52
|
+
const entry = (value as Record<string, unknown>).entry;
|
|
53
|
+
if (typeof entry !== 'string' || !isValidGameReferenceEntry(entry)) {
|
|
54
|
+
throw new Error('bpmap.json 的 reference.entry 必须是包内 .json 相对路径');
|
|
55
|
+
}
|
|
56
|
+
return { entry };
|
|
57
|
+
}
|
|
58
|
+
|
|
38
59
|
function readSourceTarget(dir: string): DoctorTarget {
|
|
39
60
|
const rawPath = join(dir, 'bpmap.json');
|
|
40
61
|
let raw: Record<string, unknown>;
|
|
@@ -46,6 +67,7 @@ function readSourceTarget(dir: string): DoctorTarget {
|
|
|
46
67
|
throw new Error(`读不到或解析不了源清单:${rawPath}(${error instanceof Error ? error.message : String(error)})`);
|
|
47
68
|
}
|
|
48
69
|
const source = readPackSource(dir);
|
|
70
|
+
const reference = readDeclaredReference(raw.reference);
|
|
49
71
|
return {
|
|
50
72
|
kind: 'source',
|
|
51
73
|
path: dir,
|
|
@@ -58,11 +80,16 @@ function readSourceTarget(dir: string): DoctorTarget {
|
|
|
58
80
|
apiVersion: typeof raw.apiVersion === 'number' && Number.isSafeInteger(raw.apiVersion) && raw.apiVersion > 0
|
|
59
81
|
? raw.apiVersion
|
|
60
82
|
: API_VERSION,
|
|
83
|
+
...(reference ? { reference } : {}),
|
|
61
84
|
};
|
|
62
85
|
}
|
|
63
86
|
|
|
64
87
|
function readPackTarget(file: string): DoctorTarget {
|
|
65
88
|
const pack = readPack(file);
|
|
89
|
+
const reference = pack.manifest.reference;
|
|
90
|
+
const document = reference
|
|
91
|
+
? pack.files.find((entry) => entry.path.toLowerCase() === reference.entry.toLowerCase())
|
|
92
|
+
: undefined;
|
|
66
93
|
return {
|
|
67
94
|
kind: 'pack',
|
|
68
95
|
path: file,
|
|
@@ -73,6 +100,8 @@ function readPackTarget(file: string): DoctorTarget {
|
|
|
73
100
|
format: pack.manifest.format,
|
|
74
101
|
mode: pack.manifest.mode,
|
|
75
102
|
apiVersion: pack.manifest.apiVersion,
|
|
103
|
+
...(reference ? { reference } : {}),
|
|
104
|
+
...(document ? { referenceText: document.bytes.toString('utf8') } : {}),
|
|
76
105
|
};
|
|
77
106
|
}
|
|
78
107
|
|
|
@@ -138,12 +167,48 @@ export function localChecks(target: DoctorTarget): DoctorCheck[] {
|
|
|
138
167
|
{ ok: existsSync(join(dir, target.server)), label: `服务端入口 ${target.server}` },
|
|
139
168
|
];
|
|
140
169
|
if (target.client) checks.push({ ok: existsSync(join(dir, target.client)), label: `客户端入口 ${target.client}` });
|
|
170
|
+
if (target.reference) {
|
|
171
|
+
const entry = target.reference.entry;
|
|
172
|
+
const valid = isValidGameReferenceEntry(entry);
|
|
173
|
+
checks.push({
|
|
174
|
+
ok: valid,
|
|
175
|
+
label: `资料文档入口 ${entry}`,
|
|
176
|
+
...(valid ? {} : { detail: '必须是包内 .json 相对路径' }),
|
|
177
|
+
});
|
|
178
|
+
if (valid) {
|
|
179
|
+
const absolute = join(dir, ...entry.split('/'));
|
|
180
|
+
const exists = existsSync(absolute);
|
|
181
|
+
checks.push({ ok: exists, label: `资料文档 ${entry}` });
|
|
182
|
+
if (exists) {
|
|
183
|
+
const parsed = parseGameReference(readFileSync(absolute, 'utf8'));
|
|
184
|
+
checks.push({
|
|
185
|
+
ok: parsed.ok,
|
|
186
|
+
label: '资料文档格式',
|
|
187
|
+
...(parsed.ok ? {} : { detail: parsed.error }),
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
141
192
|
return checks;
|
|
142
193
|
}
|
|
143
|
-
|
|
194
|
+
const checks: DoctorCheck[] = [
|
|
144
195
|
{ ok: target.format === PACK_FORMAT, label: `包格式 ${target.format}` },
|
|
145
196
|
{ ok: Boolean(target.server), label: `服务端入口 ${target.server}` },
|
|
146
197
|
];
|
|
198
|
+
if (target.reference) {
|
|
199
|
+
const entry = target.reference.entry;
|
|
200
|
+
const inPack = target.referenceText !== undefined;
|
|
201
|
+
checks.push({ ok: inPack, label: `资料文档 ${entry} 在包清单里` });
|
|
202
|
+
if (inPack) {
|
|
203
|
+
const parsed = parseGameReference(target.referenceText);
|
|
204
|
+
checks.push({
|
|
205
|
+
ok: parsed.ok,
|
|
206
|
+
label: '资料文档格式',
|
|
207
|
+
...(parsed.ok ? {} : { detail: parsed.error }),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return checks;
|
|
147
212
|
}
|
|
148
213
|
|
|
149
214
|
export async function doctor(target: string, hostUrl?: string): Promise<DoctorReport> {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* --platform 复制到平台的 games/,--start 启动宿主,--host 调 bpmap doctor。
|
|
7
7
|
*/
|
|
8
8
|
import { createRequire } from 'node:module';
|
|
9
|
-
import { copyFileSync, cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
9
|
+
import { copyFileSync, cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
10
10
|
import { dirname, isAbsolute, join, resolve, sep } from 'node:path';
|
|
11
11
|
import { spawnSync } from 'node:child_process';
|
|
12
12
|
import { build } from 'esbuild';
|
|
@@ -84,6 +84,31 @@ if (hasClient) {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
// 资料文档与图片:src/reference/ 里的内容按原样铺到包根,也可只放一个 src/reference.json。
|
|
88
|
+
let referenceEntry = null;
|
|
89
|
+
const referenceDir = join(gameRoot, 'src', 'reference');
|
|
90
|
+
const singleReference = join(gameRoot, 'src', 'reference.json');
|
|
91
|
+
if (existsSync(referenceDir)) {
|
|
92
|
+
for (const item of readdirSync(referenceDir)) {
|
|
93
|
+
cpSync(join(referenceDir, item), join(outDir, item), { recursive: true });
|
|
94
|
+
}
|
|
95
|
+
referenceEntry = typeof pkg.bp?.reference === 'string' ? pkg.bp.reference : 'reference.json';
|
|
96
|
+
if (referenceEntry.includes('..') || isAbsolute(referenceEntry) || referenceEntry.includes('\\')) {
|
|
97
|
+
fail(`package.json 的 bp.reference 必须是包内相对路径:${referenceEntry}`);
|
|
98
|
+
}
|
|
99
|
+
if (!existsSync(join(outDir, ...referenceEntry.split('/')))) {
|
|
100
|
+
fail(`reference 入口不存在:src/reference/${referenceEntry}`);
|
|
101
|
+
}
|
|
102
|
+
} else if (existsSync(singleReference)) {
|
|
103
|
+
if (pkg.bp?.reference !== undefined && pkg.bp.reference !== 'reference.json') {
|
|
104
|
+
fail(`bp.reference 指向 ${pkg.bp.reference},但只找到 src/reference.json`);
|
|
105
|
+
}
|
|
106
|
+
referenceEntry = 'reference.json';
|
|
107
|
+
copyFileSync(singleReference, join(outDir, referenceEntry));
|
|
108
|
+
} else if (pkg.bp?.reference !== undefined) {
|
|
109
|
+
fail('package.json 声明了 bp.reference,但 src/reference/ 与 src/reference.json 都不存在');
|
|
110
|
+
}
|
|
111
|
+
|
|
87
112
|
const manifest = {
|
|
88
113
|
id,
|
|
89
114
|
version,
|
|
@@ -91,6 +116,7 @@ const manifest = {
|
|
|
91
116
|
apiVersion: pkg.bp?.apiVersion ?? API_VERSION,
|
|
92
117
|
server: 'server.js',
|
|
93
118
|
...(hasClient ? { client: entry } : {}),
|
|
119
|
+
...(referenceEntry ? { reference: { entry: referenceEntry } } : {}),
|
|
94
120
|
};
|
|
95
121
|
writeFileSync(join(outDir, 'bpmap.json'), JSON.stringify(manifest, null, 2) + '\n');
|
|
96
122
|
|