pixifact 0.6.1 → 0.7.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.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -29
  3. package/dist/client.d.ts +23 -0
  4. package/dist/compiler/compileScenes.js +13 -4
  5. package/dist/compiler/typescriptCompiler.js +2 -2
  6. package/dist/compiler-node/vite.d.ts +16 -6
  7. package/dist/compiler-node/vite.js +417 -32
  8. package/dist/errors.d.ts +1 -1
  9. package/dist/errors.js +6 -0
  10. package/dist/platform/{wechat → minigame}/adapter.d.ts +7 -6
  11. package/dist/platform/{wechat → minigame}/adapter.js +10 -8
  12. package/dist/platform/minigame/application.d.ts +4 -0
  13. package/dist/platform/minigame/application.js +53 -0
  14. package/dist/platform/minigame/fetch.d.ts +2 -0
  15. package/dist/platform/{wechat → minigame}/fetch.js +13 -15
  16. package/dist/platform/minigame/index.d.ts +8 -0
  17. package/dist/platform/minigame/index.js +8 -0
  18. package/dist/platform/minigame/input.d.ts +16 -0
  19. package/dist/platform/{wechat → minigame}/input.js +18 -19
  20. package/dist/platform/minigame/lifecycle.d.ts +15 -0
  21. package/dist/platform/{wechat → minigame}/lifecycle.js +5 -7
  22. package/dist/platform/{wechat → minigame}/runtime.d.ts +5 -5
  23. package/dist/platform/{wechat → minigame}/runtime.js +14 -20
  24. package/dist/platform/minigame/subpackage.d.ts +3 -0
  25. package/dist/platform/minigame/subpackage.js +36 -0
  26. package/dist/platform/{wechat → minigame}/types.d.ts +24 -21
  27. package/dist/platform/minigame/types.js +1 -0
  28. package/dist/platform/web/index.d.ts +2 -0
  29. package/dist/platform/web/index.js +6 -0
  30. package/dist/project/index.d.ts +5 -24
  31. package/dist/project/index.js +45 -59
  32. package/dist/scene/index.d.ts +0 -1
  33. package/dist/scene/index.js +0 -1
  34. package/package.json +16 -7
  35. package/dist/platform/wechat/application.d.ts +0 -32
  36. package/dist/platform/wechat/application.js +0 -79
  37. package/dist/platform/wechat/fetch.d.ts +0 -1
  38. package/dist/platform/wechat/index.d.ts +0 -4
  39. package/dist/platform/wechat/index.js +0 -3
  40. package/dist/platform/wechat/input.d.ts +0 -12
  41. package/dist/platform/wechat/lifecycle.d.ts +0 -14
  42. package/dist/platform/wechat/subpackage.d.ts +0 -1
  43. package/dist/platform/wechat/subpackage.js +0 -27
  44. package/dist/platform/wechat/types.js +0 -3
  45. package/dist/scene/sceneAssetRuntime.d.ts +0 -11
  46. package/dist/scene/sceneAssetRuntime.js +0 -43
@@ -49,13 +49,6 @@ function normalizeRunCwd(value) {
49
49
  }
50
50
  return normalizeProjectPath(input, 'run.cwd');
51
51
  }
52
- function normalizeProjectChildPath(value, name) {
53
- const input = normalizeProjectPath(value, name);
54
- if (input === '.') {
55
- throw new Error(`${name} must not be projectRoot.`);
56
- }
57
- return input;
58
- }
59
52
  function parseScenes(value) {
60
53
  const scenes = assertRecord(value, 'scenes');
61
54
  return Object.fromEntries(Object.entries(scenes).map(([key, scenePath]) => [
@@ -108,73 +101,66 @@ function parseResourcePacks(value) {
108
101
  if (value === undefined) {
109
102
  return undefined;
110
103
  }
111
- const packs = assertRecord(value, 'resourcePacks');
112
- return Object.fromEntries(Object.entries(packs).map(([name, packValue]) => {
113
- const pack = assertRecord(packValue, `resourcePacks.${name}`);
114
- return [assertString(name, 'resource pack name'), {
115
- root: normalizeProjectChildPath(pack.root, `resourcePacks.${name}.root`),
116
- }];
117
- }));
118
- }
119
- function parseWechatResourcePacks(value) {
120
- const packs = assertRecord(value, 'targets.wechat.resourcePacks');
121
- return Object.fromEntries(Object.entries(packs).map(([name, packValue]) => {
122
- const pack = assertRecord(packValue, `targets.wechat.resourcePacks.${name}`);
123
- const delivery = assertString(pack.delivery, `targets.wechat.resourcePacks.${name}.delivery`);
124
- if (delivery === 'subpackage') {
125
- return [name, {
126
- delivery,
127
- root: normalizeProjectChildPath(pack.root, `targets.wechat.resourcePacks.${name}.root`),
128
- }];
129
- }
130
- if (delivery === 'remote') {
131
- return [name, {
132
- delivery,
133
- baseUrl: assertString(pack.baseUrl, `targets.wechat.resourcePacks.${name}.baseUrl`).replace(/\/+$/, ''),
134
- }];
104
+ if (!Array.isArray(value) || !value.every((name) => typeof name === 'string')) {
105
+ throw new Error('resourcePacks must be an array of strings.');
106
+ }
107
+ const packs = value.map((name, index) => {
108
+ const normalized = normalizeProjectPath(name, `resourcePacks.${index}`);
109
+ if (normalized.includes('/')) {
110
+ throw new Error(`resourcePacks.${index} must be a directory name.`);
135
111
  }
136
- throw new Error(`targets.wechat.resourcePacks.${name}.delivery must be subpackage or remote.`);
137
- }));
112
+ return normalized;
113
+ });
114
+ if (new Set(packs).size !== packs.length) {
115
+ throw new Error('resourcePacks must not contain duplicate names.');
116
+ }
117
+ return packs;
138
118
  }
139
- function parseTargets(value) {
119
+ function parseRemoteResourcePacks(value, resourcePacks) {
140
120
  if (value === undefined) {
141
121
  return undefined;
142
122
  }
143
- const targets = assertRecord(value, 'targets');
144
- if (targets.wechat === undefined) {
145
- return {};
146
- }
147
- const wechat = assertRecord(targets.wechat, 'targets.wechat');
148
- const outDir = normalizeProjectChildPath(wechat.outDir, 'targets.wechat.outDir');
149
- return {
150
- wechat: {
151
- entry: normalizeProjectPath(wechat.entry, 'targets.wechat.entry'),
152
- configDir: normalizeProjectPath(wechat.configDir, 'targets.wechat.configDir'),
153
- outDir,
154
- resourcePacks: parseWechatResourcePacks(wechat.resourcePacks),
155
- },
156
- };
123
+ const packs = assertRecord(value, 'remoteResourcePacks');
124
+ return Object.fromEntries(Object.entries(packs).map(([rawName, rawBaseUrl]) => {
125
+ const name = assertString(rawName, 'remote resource pack name');
126
+ if (!resourcePacks?.includes(name)) {
127
+ throw new Error(`remoteResourcePacks.${name} must reference resourcePacks.`);
128
+ }
129
+ const baseUrl = assertString(rawBaseUrl, `remoteResourcePacks.${name}`).replace(/\/+$/, '');
130
+ let url;
131
+ try {
132
+ url = new URL(baseUrl);
133
+ }
134
+ catch {
135
+ throw new Error(`remoteResourcePacks.${name} must be an HTTPS URL.`);
136
+ }
137
+ if (url.protocol !== 'https:' || url.hostname === '') {
138
+ throw new Error(`remoteResourcePacks.${name} must be an HTTPS URL.`);
139
+ }
140
+ return [name, baseUrl];
141
+ }));
157
142
  }
158
143
  export function parsePixifactProjectConfig(value) {
159
144
  const config = assertRecord(value, 'pixifact.project.json');
160
- if (config.version !== 1) {
161
- throw new Error('pixifact.project.json version must be 1.');
145
+ if (config.version !== 2) {
146
+ throw new Error('pixifact.project.json version must be 2.');
162
147
  }
163
- const resourcePacks = parseResourcePacks(config.resourcePacks);
164
- const targets = parseTargets(config.targets);
165
- for (const name of Object.keys(targets?.wechat?.resourcePacks ?? {})) {
166
- if (!resourcePacks?.[name]) {
167
- throw new Error(`targets.wechat.resourcePacks.${name} must reference resourcePacks.${name}.`);
168
- }
148
+ if (config.targets !== undefined) {
149
+ throw new Error('targets is not supported in pixifact.project.json version 2.');
169
150
  }
151
+ if (config.defines !== undefined) {
152
+ throw new Error('defines is not supported in pixifact.project.json version 2.');
153
+ }
154
+ const resourcePacks = parseResourcePacks(config.resourcePacks);
155
+ const remoteResourcePacks = parseRemoteResourcePacks(config.remoteResourcePacks, resourcePacks);
170
156
  return {
171
- version: 1,
157
+ version: 2,
172
158
  name: assertString(config.name, 'name'),
173
159
  resolution: parseResolution(config.resolution),
174
160
  viewport: parseViewport(config.viewport),
175
161
  scenes: parseScenes(config.scenes),
176
162
  ...(resourcePacks === undefined ? {} : { resourcePacks }),
177
- ...(targets === undefined ? {} : { targets }),
163
+ ...(remoteResourcePacks === undefined ? {} : { remoteResourcePacks }),
178
164
  run: parseRun(config.run),
179
165
  };
180
166
  }
@@ -185,7 +171,7 @@ export function summarizePixifactProjectConfig(config) {
185
171
  viewport: config.viewport,
186
172
  scenes: config.scenes,
187
173
  ...(config.resourcePacks === undefined ? {} : { resourcePacks: config.resourcePacks }),
188
- ...(config.targets === undefined ? {} : { targets: config.targets }),
174
+ ...(config.remoteResourcePacks === undefined ? {} : { remoteResourcePacks: config.remoteResourcePacks }),
189
175
  ...(config.run === undefined ? {} : { run: config.run }),
190
176
  };
191
177
  }
@@ -1,6 +1,5 @@
1
1
  export * from './decorators.js';
2
2
  export * from './eventRuntime.js';
3
- export * from './sceneAssetRuntime.js';
4
3
  export * from './sceneBindingRuntime.js';
5
4
  export * from './sceneRuntime.js';
6
5
  export * from './slotRuntime.js';
@@ -1,6 +1,5 @@
1
1
  export * from './decorators.js';
2
2
  export * from './eventRuntime.js';
3
- export * from './sceneAssetRuntime.js';
4
3
  export * from './sceneBindingRuntime.js';
5
4
  export * from './sceneRuntime.js';
6
5
  export * from './slotRuntime.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixifact",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "Pixifact 2D UI 和轻量游戏 Scene 语义框架。",
5
5
  "packageManager": "bun@1.3.13",
6
6
  "main": "./dist/index.js",
@@ -26,7 +26,7 @@
26
26
  "author": "youxia <243802688@qq.com>",
27
27
  "license": "MIT",
28
28
  "scripts": {
29
- "build": "bun scripts/clean-dist.mjs && bunx --no-install tsc -p tsconfig.build.json && bun scripts/fix-dist-esm-imports.mjs"
29
+ "build": "bun scripts/clean-dist.mjs && bunx --no-install tsc -p tsconfig.build.json && cp src/client.d.ts dist/client.d.ts && bun scripts/fix-dist-esm-imports.mjs"
30
30
  },
31
31
  "publishConfig": {
32
32
  "registry": "https://registry.npmjs.org/"
@@ -62,14 +62,23 @@
62
62
  "import": "./dist/compiler-node/index.js",
63
63
  "require": "./dist/compiler-node/index.js"
64
64
  },
65
- "./platform/wechat": {
66
- "types": "./dist/platform/wechat/index.d.ts",
67
- "import": "./dist/platform/wechat/index.js",
68
- "require": "./dist/platform/wechat/index.js"
65
+ "./client": {
66
+ "types": "./dist/client.d.ts"
67
+ },
68
+ "./platform/web": {
69
+ "types": "./dist/platform/web/index.d.ts",
70
+ "import": "./dist/platform/web/index.js",
71
+ "require": "./dist/platform/web/index.js"
72
+ },
73
+ "./internal/minigame": {
74
+ "types": "./dist/platform/minigame/index.d.ts",
75
+ "import": "./dist/platform/minigame/index.js",
76
+ "require": "./dist/platform/minigame/index.js"
69
77
  }
70
78
  },
71
79
  "peerDependencies": {
72
- "pixi.js": ">=8.3.0"
80
+ "pixi.js": ">=8.3.0",
81
+ "vite": ">=6.0.0"
73
82
  },
74
83
  "dependencies": {
75
84
  "typescript": "^5.3.3"
@@ -1,32 +0,0 @@
1
- import 'pixi.js/unsafe-eval';
2
- import 'pixi.js/events';
3
- import { Container, Rectangle, Ticker, WebGLRenderer, type ColorSource, type EventSystemFeatures } from 'pixi.js';
4
- import { type WechatPointerBinding } from './input.js';
5
- import { type WechatLifecycleBinding } from './lifecycle.js';
6
- import { type WechatRuntime } from './runtime.js';
7
- import type { WechatCanvas } from './types.js';
8
- export interface WechatPixiApplicationOptions {
9
- antialias?: boolean;
10
- autoStart?: boolean;
11
- backgroundAlpha?: number;
12
- backgroundColor?: ColorSource;
13
- eventFeatures?: Partial<EventSystemFeatures>;
14
- onHide?(): void;
15
- onShow?(): void;
16
- resolution?: number;
17
- }
18
- export interface WechatPixiApplication {
19
- readonly canvas: WechatCanvas;
20
- destroy(): void;
21
- readonly input: WechatPointerBinding;
22
- readonly lifecycle: WechatLifecycleBinding;
23
- render(): void;
24
- readonly renderer: WebGLRenderer;
25
- readonly runtime: WechatRuntime;
26
- readonly screen: Rectangle;
27
- readonly stage: Container;
28
- start(): void;
29
- stop(): void;
30
- readonly ticker: Ticker;
31
- }
32
- export declare function createWechatPixiApplication(options?: WechatPixiApplicationOptions): Promise<WechatPixiApplication>;
@@ -1,79 +0,0 @@
1
- import 'pixi.js/unsafe-eval';
2
- import 'pixi.js/events';
3
- import { Container, DOMAdapter, loadTextures, Rectangle, Ticker, UPDATE_PRIORITY, WebGLRenderer, } from 'pixi.js';
4
- import { createWechatPixiAdapter } from './adapter.js';
5
- import { bindWechatPointerEvents } from './input.js';
6
- import { bindWechatLifecycle } from './lifecycle.js';
7
- import { createWechatRuntime } from './runtime.js';
8
- export async function createWechatPixiApplication(options = {}) {
9
- const runtime = createWechatRuntime();
10
- DOMAdapter.set(createWechatPixiAdapter(runtime));
11
- loadTextures.config.preferCreateImageBitmap = false;
12
- const renderer = new WebGLRenderer();
13
- await renderer.init({
14
- antialias: options.antialias ?? true,
15
- autoDensity: false,
16
- backgroundAlpha: options.backgroundAlpha ?? 1,
17
- backgroundColor: options.backgroundColor ?? 0x000000,
18
- canvas: runtime.canvas,
19
- context: runtime.context,
20
- eventFeatures: options.eventFeatures ?? {
21
- click: true,
22
- globalMove: true,
23
- move: true,
24
- wheel: false,
25
- },
26
- height: runtime.height,
27
- resolution: options.resolution ?? runtime.resolution,
28
- skipExtensionImports: true,
29
- width: runtime.width,
30
- });
31
- const stage = new Container();
32
- const screen = new Rectangle(0, 0, runtime.width, runtime.height);
33
- const ticker = new Ticker();
34
- const render = () => renderer.render(stage);
35
- const events = renderer.events;
36
- const sink = {
37
- pointerdown: (event) => events._onPointerDown(event),
38
- pointermove: (event) => events._onPointerMove(event),
39
- pointerup: (event) => events._onPointerUp(event),
40
- };
41
- const input = bindWechatPointerEvents(runtime.canvas, sink);
42
- const lifecycle = bindWechatLifecycle(ticker, {
43
- onHide: () => {
44
- input.cancelAll();
45
- options.onHide?.();
46
- },
47
- onShow: options.onShow,
48
- });
49
- let destroyed = false;
50
- ticker.add(render, undefined, UPDATE_PRIORITY.LOW);
51
- render();
52
- if (options.autoStart !== false) {
53
- ticker.start();
54
- }
55
- return {
56
- canvas: runtime.canvas,
57
- destroy() {
58
- if (destroyed) {
59
- return;
60
- }
61
- destroyed = true;
62
- lifecycle.dispose();
63
- input.dispose();
64
- ticker.destroy();
65
- stage.destroy({ children: true });
66
- renderer.destroy();
67
- },
68
- input,
69
- lifecycle,
70
- render,
71
- renderer,
72
- runtime,
73
- screen,
74
- stage,
75
- start: () => ticker.start(),
76
- stop: () => ticker.stop(),
77
- ticker,
78
- };
79
- }
@@ -1 +0,0 @@
1
- export declare function fetchWechatResource(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
@@ -1,4 +0,0 @@
1
- export * from './application.js';
2
- export * from './fetch.js';
3
- export * from './subpackage.js';
4
- export type { WechatCanvas, WechatMiniGameApi } from './types.js';
@@ -1,3 +0,0 @@
1
- export * from './application.js';
2
- export * from './fetch.js';
3
- export * from './subpackage.js';
@@ -1,12 +0,0 @@
1
- import { type WechatCanvas } from './types.js';
2
- export interface WechatPointerEventSink {
3
- pointerdown(event: Event): void;
4
- pointermove(event: Event): void;
5
- pointerup(event: Event): void;
6
- }
7
- export interface WechatPointerBinding {
8
- readonly activePointerCount: number;
9
- cancelAll(): void;
10
- dispose(): void;
11
- }
12
- export declare function bindWechatPointerEvents(canvas: WechatCanvas, sink: WechatPointerEventSink): WechatPointerBinding;
@@ -1,14 +0,0 @@
1
- interface LifecycleTarget {
2
- readonly started?: boolean;
3
- start(): void;
4
- stop(): void;
5
- }
6
- export interface WechatLifecycleBinding {
7
- dispose(): void;
8
- readonly hidden: boolean;
9
- }
10
- export declare function bindWechatLifecycle(target: LifecycleTarget, options?: {
11
- onHide?(): void;
12
- onShow?(): void;
13
- }): WechatLifecycleBinding;
14
- export {};
@@ -1 +0,0 @@
1
- export declare function loadWechatSubpackage(name: string): Promise<void>;
@@ -1,27 +0,0 @@
1
- import { wechatApi } from './types.js';
2
- const loaded = new Set();
3
- const loading = new Map();
4
- export function loadWechatSubpackage(name) {
5
- if (loaded.has(name)) {
6
- return Promise.resolve();
7
- }
8
- const existing = loading.get(name);
9
- if (existing) {
10
- return existing;
11
- }
12
- const pending = new Promise((resolve, reject) => {
13
- wechatApi().loadSubpackage({
14
- name,
15
- fail: (error) => reject(new Error(`Failed to load WeChat subpackage ${name}: ${error.errMsg}`)),
16
- success: resolve,
17
- });
18
- }).then(() => {
19
- loaded.add(name);
20
- loading.delete(name);
21
- }, (error) => {
22
- loading.delete(name);
23
- throw error;
24
- });
25
- loading.set(name, pending);
26
- return pending;
27
- }
@@ -1,3 +0,0 @@
1
- export function wechatApi() {
2
- return globalThis.wx;
3
- }
@@ -1,11 +0,0 @@
1
- import { type Texture } from 'pixi.js';
2
- export interface SceneAssetLocation {
3
- src: string;
4
- pack?: string;
5
- }
6
- export type SceneAssetManifest = Record<string, SceneAssetLocation>;
7
- export interface SceneAssetRuntimeOptions {
8
- loadPack?: (name: string) => Promise<void>;
9
- }
10
- export declare function configureSceneAssets(manifest: SceneAssetManifest, options?: SceneAssetRuntimeOptions): void;
11
- export declare function loadSceneTexture(id: string): Promise<Texture>;
@@ -1,43 +0,0 @@
1
- import { Assets } from 'pixi.js';
2
- let assetManifest = {};
3
- let loadPack;
4
- const loadedPacks = new Set();
5
- const loadingPacks = new Map();
6
- export function configureSceneAssets(manifest, options = {}) {
7
- assetManifest = manifest;
8
- loadPack = options.loadPack;
9
- loadedPacks.clear();
10
- loadingPacks.clear();
11
- }
12
- async function preparePack(name) {
13
- if (loadedPacks.has(name)) {
14
- return;
15
- }
16
- const existing = loadingPacks.get(name);
17
- if (existing) {
18
- return existing;
19
- }
20
- if (!loadPack) {
21
- throw new Error(`Scene asset pack "${name}" has no platform loader.`);
22
- }
23
- const pending = loadPack(name).then(() => {
24
- loadedPacks.add(name);
25
- loadingPacks.delete(name);
26
- }, (error) => {
27
- loadingPacks.delete(name);
28
- throw error;
29
- });
30
- loadingPacks.set(name, pending);
31
- return pending;
32
- }
33
- export async function loadSceneTexture(id) {
34
- const location = assetManifest[id];
35
- if (!location) {
36
- throw new Error(`Scene asset "${id}" is missing from the target manifest.`);
37
- }
38
- if (location.pack) {
39
- await preparePack(location.pack);
40
- }
41
- Assets.add({ alias: id, src: location.src });
42
- return Assets.load(id);
43
- }