pixifact-cli 0.3.0 → 0.5.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/README.md +32 -1
- package/editor/assets/browserAll-CdyZj0BN.js +1 -0
- package/editor/assets/index-CAe9Mkmr.js +1130 -0
- package/editor/assets/index-CVrKIfXK.css +1 -0
- package/editor/assets/init-C32NAhsC.js +1 -0
- package/editor/assets/webworkerAll-BEmxAAYf.js +1 -0
- package/editor/index.html +13 -0
- package/package.json +5 -3
- package/src/automation.ts +16 -7
- package/src/editorServer.ts +375 -0
- package/src/editorSession.ts +490 -0
- package/src/pixifact-cli.ts +127 -47
- package/src/wechatTarget.ts +578 -0
- package/src/liveBridge.ts +0 -28
- package/src/liveBridgeServer.ts +0 -163
package/src/pixifact-cli.ts
CHANGED
|
@@ -3,16 +3,23 @@ import { createPixifactAutomation } from './automation';
|
|
|
3
3
|
import { hintForCommandError } from 'pixifact';
|
|
4
4
|
import { CompileSceneError, compileScenes } from 'pixifact/compiler-node';
|
|
5
5
|
import type { SceneValidationDiagnostic } from 'pixifact/compiler';
|
|
6
|
-
import {
|
|
6
|
+
import { startEditorServer } from './editorServer';
|
|
7
|
+
import { queryEditorContext } from './editorSession';
|
|
8
|
+
import {
|
|
9
|
+
buildWechatTarget,
|
|
10
|
+
devWechatTarget,
|
|
11
|
+
validateWechatTarget,
|
|
12
|
+
type WechatDevEvent,
|
|
13
|
+
WechatTargetError,
|
|
14
|
+
} from './wechatTarget';
|
|
7
15
|
|
|
8
16
|
type Automation = ReturnType<typeof createPixifactAutomation>;
|
|
9
|
-
type LiveBridge = Pick<ReturnType<typeof createLiveBridgeServer>, 'connected' | 'callAction' | 'stop'> & {
|
|
10
|
-
waitForConnection?: (timeoutMs?: number) => Promise<void>;
|
|
11
|
-
};
|
|
12
17
|
|
|
13
18
|
interface CliOptions {
|
|
14
19
|
automation?: Automation;
|
|
15
|
-
|
|
20
|
+
onWechatDevEvent?: (event: WechatDevEvent) => void;
|
|
21
|
+
readEditorContext?: typeof queryEditorContext;
|
|
22
|
+
startEditor?: typeof startEditorServer;
|
|
16
23
|
}
|
|
17
24
|
|
|
18
25
|
interface CliResult {
|
|
@@ -88,6 +95,15 @@ function isFailedResult(value: unknown): value is CliJsonResult {
|
|
|
88
95
|
function compileScenesFailure(error: unknown): CliJsonResult {
|
|
89
96
|
const message = error instanceof Error ? error.message : String(error);
|
|
90
97
|
if (error instanceof CompileSceneError) {
|
|
98
|
+
if (error.diagnostics) {
|
|
99
|
+
return {
|
|
100
|
+
ok: false,
|
|
101
|
+
scene: error.scene,
|
|
102
|
+
error: 'Scene compile failed.',
|
|
103
|
+
diagnostics: error.diagnostics,
|
|
104
|
+
hint: 'Fix the listed diagnostics, then run compile-scenes again.',
|
|
105
|
+
};
|
|
106
|
+
}
|
|
91
107
|
const sourceDiagnostic = sourceDiagnosticFromMessage(error.source ?? '', message);
|
|
92
108
|
if (sourceDiagnostic) {
|
|
93
109
|
return {
|
|
@@ -205,10 +221,99 @@ function sourcePositionFromMessage(source: string, message: string) {
|
|
|
205
221
|
};
|
|
206
222
|
}
|
|
207
223
|
|
|
208
|
-
async function executeFileCommand(
|
|
224
|
+
async function executeFileCommand(
|
|
225
|
+
positionals: string[],
|
|
226
|
+
flags: Record<string, string | true>,
|
|
227
|
+
automation: Automation,
|
|
228
|
+
onWechatDevEvent?: (event: WechatDevEvent) => void,
|
|
229
|
+
startEditor: typeof startEditorServer = startEditorServer,
|
|
230
|
+
readEditorContext: typeof queryEditorContext = queryEditorContext,
|
|
231
|
+
) {
|
|
209
232
|
const [area, action] = positionals;
|
|
210
233
|
const projectRoot = projectRootFlag(flags);
|
|
211
234
|
|
|
235
|
+
if (area === 'editor' && action === undefined) {
|
|
236
|
+
const session = await startEditor({ projectRoot });
|
|
237
|
+
return {
|
|
238
|
+
ok: true,
|
|
239
|
+
projectRoot,
|
|
240
|
+
url: session.url,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (area === 'editor' && action === 'context') {
|
|
245
|
+
return readEditorContext({ projectRoot });
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if ((area === 'build' || area === 'dev' || area === 'validate') && action === undefined) {
|
|
249
|
+
const target = requireFlag(flags, 'target');
|
|
250
|
+
if (target !== 'wechat') {
|
|
251
|
+
throw new Error(`Unknown Pixifact target "${target}".`);
|
|
252
|
+
}
|
|
253
|
+
if (area === 'validate') {
|
|
254
|
+
const result = await validateWechatTarget(projectRoot);
|
|
255
|
+
return result.diagnostics.length > 0
|
|
256
|
+
? {
|
|
257
|
+
ok: false,
|
|
258
|
+
target,
|
|
259
|
+
diagnostics: result.diagnostics,
|
|
260
|
+
hint: 'Fix the listed WeChat target diagnostics, then validate again.',
|
|
261
|
+
}
|
|
262
|
+
: { ok: true, projectRoot, target };
|
|
263
|
+
}
|
|
264
|
+
if (area === 'dev') {
|
|
265
|
+
if (flags.mode !== undefined) {
|
|
266
|
+
throw new Error('dev --target wechat always uses development mode; remove --mode.');
|
|
267
|
+
}
|
|
268
|
+
try {
|
|
269
|
+
const session = await devWechatTarget(projectRoot, onWechatDevEvent);
|
|
270
|
+
return {
|
|
271
|
+
ok: true,
|
|
272
|
+
projectRoot,
|
|
273
|
+
target,
|
|
274
|
+
mode: 'development',
|
|
275
|
+
watching: true,
|
|
276
|
+
report: session.initialReport,
|
|
277
|
+
};
|
|
278
|
+
} catch (error) {
|
|
279
|
+
if (error instanceof WechatTargetError) {
|
|
280
|
+
return {
|
|
281
|
+
ok: false,
|
|
282
|
+
target,
|
|
283
|
+
error: error.message,
|
|
284
|
+
diagnostics: error.diagnostics,
|
|
285
|
+
hint: 'Fix the listed WeChat target diagnostics, then start dev again.',
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
throw error;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
const mode = flags.mode === undefined ? 'production' : requireFlag(flags, 'mode');
|
|
292
|
+
if (mode !== 'development' && mode !== 'production') {
|
|
293
|
+
throw new Error('--mode must be development or production.');
|
|
294
|
+
}
|
|
295
|
+
try {
|
|
296
|
+
return {
|
|
297
|
+
ok: true,
|
|
298
|
+
projectRoot,
|
|
299
|
+
target,
|
|
300
|
+
mode,
|
|
301
|
+
report: await buildWechatTarget(projectRoot, mode),
|
|
302
|
+
};
|
|
303
|
+
} catch (error) {
|
|
304
|
+
if (error instanceof WechatTargetError) {
|
|
305
|
+
return {
|
|
306
|
+
ok: false,
|
|
307
|
+
target,
|
|
308
|
+
error: error.message,
|
|
309
|
+
diagnostics: error.diagnostics,
|
|
310
|
+
hint: 'Fix the listed WeChat target diagnostics, then build again.',
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
throw error;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
212
317
|
if (area === 'compile-scenes' && action === undefined) {
|
|
213
318
|
try {
|
|
214
319
|
await compileScenes({ projectRoot });
|
|
@@ -268,32 +373,7 @@ async function executeFileCommand(positionals: string[], flags: Record<string, s
|
|
|
268
373
|
throw new Error(`Unknown Pixifact CLI command "${positionals.join(' ')}".`);
|
|
269
374
|
}
|
|
270
375
|
|
|
271
|
-
async function executeLiveCommand(positionals: string[], flags: Record<string, string | true>, bridge: LiveBridge) {
|
|
272
|
-
if (!bridge.connected && bridge.waitForConnection) {
|
|
273
|
-
await bridge.waitForConnection();
|
|
274
|
-
}
|
|
275
|
-
if (!bridge.connected) {
|
|
276
|
-
throw new Error('No live Pixifact editor is connected.');
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const [area, action] = positionals;
|
|
280
|
-
if (area === 'summary' && action === undefined) {
|
|
281
|
-
return bridge.callAction('summary', {});
|
|
282
|
-
}
|
|
283
|
-
if (area === 'scene' && action === 'get') {
|
|
284
|
-
return bridge.callAction('scene.get', {});
|
|
285
|
-
}
|
|
286
|
-
if (area === 'node' && action === 'inspect') {
|
|
287
|
-
return bridge.callAction('node.inspect', {
|
|
288
|
-
node: requireFlag(flags, 'node'),
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
throw new Error(`Unknown Pixifact live command "${positionals.join(' ')}".`);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
376
|
export async function executePixifactCli(argv: string[], options: CliOptions = {}): Promise<CliResult> {
|
|
296
|
-
let ownedBridge: ReturnType<typeof createLiveBridgeServer> | undefined;
|
|
297
377
|
try {
|
|
298
378
|
const parsed = parseArgs(argv);
|
|
299
379
|
if (parsed.flags.help === true) {
|
|
@@ -305,19 +385,19 @@ export async function executePixifactCli(argv: string[], options: CliOptions = {
|
|
|
305
385
|
'scene inspect --scene <scene-path>',
|
|
306
386
|
'scene validate --scene <scene-path>',
|
|
307
387
|
'compile-scenes',
|
|
388
|
+
'validate --target wechat',
|
|
389
|
+
'build --target wechat',
|
|
390
|
+
'dev --target wechat',
|
|
308
391
|
],
|
|
309
392
|
aiValidationAlternatives: [
|
|
310
393
|
'scene validate --all',
|
|
311
394
|
],
|
|
312
395
|
auxiliaryCommands: [
|
|
396
|
+
'editor',
|
|
397
|
+
'editor context',
|
|
313
398
|
'scene create --scene <scene-path> --name <SceneName>',
|
|
314
399
|
'node inspect --scene <scene-path> --node <locator>',
|
|
315
400
|
],
|
|
316
|
-
liveContextCommands: [
|
|
317
|
-
'live summary',
|
|
318
|
-
'live scene get',
|
|
319
|
-
'live node inspect --node <locator>',
|
|
320
|
-
],
|
|
321
401
|
defaults: {
|
|
322
402
|
projectRoot: 'current working directory',
|
|
323
403
|
},
|
|
@@ -327,14 +407,14 @@ export async function executePixifactCli(argv: string[], options: CliOptions = {
|
|
|
327
407
|
}
|
|
328
408
|
|
|
329
409
|
const automation = options.automation ?? createPixifactAutomation();
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
410
|
+
const result = await executeFileCommand(
|
|
411
|
+
parsed.positionals,
|
|
412
|
+
parsed.flags,
|
|
413
|
+
automation,
|
|
414
|
+
options.onWechatDevEvent,
|
|
415
|
+
options.startEditor,
|
|
416
|
+
options.readEditorContext,
|
|
417
|
+
);
|
|
338
418
|
if (isFailedResult(result)) {
|
|
339
419
|
return {
|
|
340
420
|
exitCode: 1,
|
|
@@ -357,13 +437,13 @@ export async function executePixifactCli(argv: string[], options: CliOptions = {
|
|
|
357
437
|
hint: hintForCommandError(error instanceof Error ? error.message : String(error)),
|
|
358
438
|
}),
|
|
359
439
|
};
|
|
360
|
-
} finally {
|
|
361
|
-
ownedBridge?.stop();
|
|
362
440
|
}
|
|
363
441
|
}
|
|
364
442
|
|
|
365
443
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
366
|
-
const result = await executePixifactCli(process.argv.slice(2)
|
|
444
|
+
const result = await executePixifactCli(process.argv.slice(2), {
|
|
445
|
+
onWechatDevEvent: (event) => process.stdout.write(jsonLine(event)),
|
|
446
|
+
});
|
|
367
447
|
process.stdout.write(result.stdout);
|
|
368
448
|
process.stderr.write(result.stderr);
|
|
369
449
|
process.exitCode = result.exitCode;
|