@idosgames/module-sdk 0.2.1 → 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/index.cjs +1 -1
- package/dist/index.d.cts +75 -1
- package/dist/index.d.ts +75 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var
|
|
1
|
+
'use strict';var S=/^[a-z0-9][a-z0-9-]*:[a-z0-9][a-z0-9-]*@[1-9]\d*$/;function x(e){return typeof e=="string"&&S.test(e)}function M(e){let t=e.indexOf(":");return t<0?"":e.slice(0,t)}var l=/^(string|number|boolean)(\[\])?(\?)?$/;function u(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function c(e,t){return e==="number"?typeof t=="number"&&Number.isFinite(t):typeof t===e}function f(e,t,r){if(!u(t))return `${r||"payload"} must be an object`;for(let[n,o]of Object.entries(e)){let i=r?`${r}.${n}`:n,a=t[n];if(typeof o!="string"){let p=f(o,a,i);if(p)return p;continue}let d=l.exec(o);if(!d)return `${i}: invalid descriptor "${o}"`;let[,s="",g,m]=d;if(a===void 0){if(m)continue;return `${i} is missing`}if(g){if(!Array.isArray(a))return `${i} must be ${s}[]`;if(!a.every(p=>c(s,p)))return `${i} must contain only ${s} values`;continue}if(!c(s,a))return `${i} must be a ${s}`}return null}function y(e,t){for(let[r,n]of Object.entries(e)){let o=t?`${t}.${r}`:r;if(typeof n=="string"){if(!l.test(n))throw new Error(`shape(): field "${o}" has invalid type "${n}" \u2014 use "string" | "number" | "boolean", optionally with "[]" and/or a trailing "?"`)}else if(u(n))y(n,o);else throw new Error(`shape(): field "${o}" must be a type string or an object`)}}function h(e){return y(e,""),{descriptor:e,check:t=>f(e,t,"")}}function v(e,t){if(!x(e))throw new Error(`defineTopic(): "${e}" is not a valid topic name \u2014 expected "<module-id>:<event>@<major>", e.g. "idle-rpg:character-upgraded@1"`);return {name:e,shape:t}}var E={modeChanged:v("host:mode-changed@1",h({from:"string?",to:"string"}))};var T=["currency-bar","wallet","status","account"];function $(e){return typeof e=="string"&&T.includes(e)}function D(e){return e}exports.SHARED_UI_ROLES=T;exports.TOPIC_NAME_RE=S;exports.defineModule=D;exports.defineTopic=v;exports.hostTopics=E;exports.isSharedUiRole=$;exports.isTopicName=x;exports.shape=h;exports.topicNamespace=M;
|
package/dist/index.d.cts
CHANGED
|
@@ -132,6 +132,70 @@ interface SharedUiContext {
|
|
|
132
132
|
}
|
|
133
133
|
declare function isSharedUiRole(value: unknown): value is SharedUiRole;
|
|
134
134
|
|
|
135
|
+
/** Bytes of one file. Strings are UTF-8 encoded (JSON saves are the common case). */
|
|
136
|
+
type ContentFileData = Blob | ArrayBuffer | Uint8Array | string;
|
|
137
|
+
/** Something local the player can publish (a saved world, a level they built). */
|
|
138
|
+
interface LocalContentItem {
|
|
139
|
+
id: string;
|
|
140
|
+
name: string;
|
|
141
|
+
/** Epoch ms of the last change — lists are shown newest first. */
|
|
142
|
+
updatedAt?: number;
|
|
143
|
+
/** One line under the name ("recipe world · 256×256"). */
|
|
144
|
+
subtitle?: string;
|
|
145
|
+
}
|
|
146
|
+
/** What `capture` hands to the Workshop to publish. Roles and MIME types must fit the title's content type config. */
|
|
147
|
+
interface CapturedContent {
|
|
148
|
+
files: Array<{
|
|
149
|
+
role: string;
|
|
150
|
+
contentType: string;
|
|
151
|
+
data: ContentFileData;
|
|
152
|
+
}>;
|
|
153
|
+
thumbnail?: {
|
|
154
|
+
contentType: "image/png" | "image/jpeg" | "image/webp";
|
|
155
|
+
data: ContentFileData;
|
|
156
|
+
};
|
|
157
|
+
suggestedTitle?: string;
|
|
158
|
+
suggestedDescription?: string;
|
|
159
|
+
tags?: string[];
|
|
160
|
+
metadata?: Record<string, string>;
|
|
161
|
+
}
|
|
162
|
+
/** What the Workshop hands to `open` after the player got access. */
|
|
163
|
+
interface DownloadedContent {
|
|
164
|
+
contentID: string;
|
|
165
|
+
title?: string | null;
|
|
166
|
+
/** Revision of the publication — lets a game tell an update from a first download. */
|
|
167
|
+
revision?: number | null;
|
|
168
|
+
files: Array<{
|
|
169
|
+
role: string;
|
|
170
|
+
contentType: string;
|
|
171
|
+
data: ArrayBuffer;
|
|
172
|
+
}>;
|
|
173
|
+
}
|
|
174
|
+
interface ContentTypeHandler {
|
|
175
|
+
/** Must equal a key of `Workshop.ContentTypes` in the title config (e.g. "voxelcraft.world"). */
|
|
176
|
+
type: string;
|
|
177
|
+
/** Shown in the Workshop's type filter and publish wizard. */
|
|
178
|
+
label: string;
|
|
179
|
+
icon?: string;
|
|
180
|
+
/** Mode (route id) to switch to after `open` — the game that plays this content. */
|
|
181
|
+
modeId?: string;
|
|
182
|
+
/** Local items the player can publish. Omit when the type cannot be published from the game. */
|
|
183
|
+
listLocal?(): Promise<LocalContentItem[]>;
|
|
184
|
+
/** Serialize one local item for publishing. */
|
|
185
|
+
capture?(localId: string): Promise<CapturedContent>;
|
|
186
|
+
/** Load downloaded content into the game (import a world, start a level). */
|
|
187
|
+
open?(content: DownloadedContent): Promise<void>;
|
|
188
|
+
}
|
|
189
|
+
/** `ctx.content` — the host's registry of content types, shared by every module of the session. */
|
|
190
|
+
interface ContentRegistry {
|
|
191
|
+
/** Register (or replace) the handler of a type. Returns an unregister function. */
|
|
192
|
+
registerType(handler: ContentTypeHandler): () => void;
|
|
193
|
+
getType(type: string): ContentTypeHandler | undefined;
|
|
194
|
+
listTypes(): ContentTypeHandler[];
|
|
195
|
+
/** Called when a type is registered or removed (a UI re-renders its type list). */
|
|
196
|
+
subscribe(listener: () => void): () => void;
|
|
197
|
+
}
|
|
198
|
+
|
|
135
199
|
/** What a module is, for catalog/UI purposes. Not every module is a game. */
|
|
136
200
|
type ModuleType = "game" | "app" | "ai-app";
|
|
137
201
|
/**
|
|
@@ -257,6 +321,16 @@ interface ModuleContext {
|
|
|
257
321
|
registerPanel(panel: UiPanel): void;
|
|
258
322
|
/** Register a nav / mode entry so the player can switch to this module. */
|
|
259
323
|
registerRoute(entry: RouteEntry): void;
|
|
324
|
+
/**
|
|
325
|
+
* Content types other modules can publish and open (see `ContentTypeHandler`). A game registers
|
|
326
|
+
* its type here; the Workshop module reads the registry — neither imports the other.
|
|
327
|
+
*/
|
|
328
|
+
content: ContentRegistry;
|
|
329
|
+
/**
|
|
330
|
+
* Switch the host to another mode (a route id registered by any module) — e.g. the Workshop opens a
|
|
331
|
+
* world and hands the screen to the game. Unknown ids are ignored.
|
|
332
|
+
*/
|
|
333
|
+
navigate(modeId: string): void;
|
|
260
334
|
/**
|
|
261
335
|
* Publish a debug surface for the AI Coder's agent — what the module IS and what it can be told
|
|
262
336
|
* to DO. Optional: a module without it simply stays opaque to the agent.
|
|
@@ -371,4 +445,4 @@ interface SharedEventBus<Events extends Record<string, unknown> = Record<string,
|
|
|
371
445
|
/** Identity helper that pins a module literal to the `Module` type for editor help and errors. */
|
|
372
446
|
declare function defineModule(module: Module): Module;
|
|
373
447
|
|
|
374
|
-
export { type EngineScene, type InferShape, type Module, type ModuleAgentApi, type ModuleAuthor, type ModuleContext, type ModuleEngine, type ModuleEventEmit, type ModuleEventListen, type ModuleEvents, type ModuleEventsManifest, type ModuleManifest, type ModuleMedia, type ModuleMeta, type ModuleSharedUi, type ModuleType, type PanelSlot, type RouteEntry, SHARED_UI_ROLES, type SceneMountContext, type Shape, type ShapeDescriptor, type ShapeLeaf, type ShapeLeafSpec, type SharedEventBus, type SharedUiContext, type SharedUiRole, type SurfaceAllocator, type SurfaceHandle, type SurfaceKind, TOPIC_NAME_RE, type Topic, type TopicName, type TopicPayload, type UiPanel, defineModule, defineTopic, hostTopics, isSharedUiRole, isTopicName, shape, topicNamespace };
|
|
448
|
+
export { type CapturedContent, type ContentFileData, type ContentRegistry, type ContentTypeHandler, type DownloadedContent, type EngineScene, type InferShape, type LocalContentItem, type Module, type ModuleAgentApi, type ModuleAuthor, type ModuleContext, type ModuleEngine, type ModuleEventEmit, type ModuleEventListen, type ModuleEvents, type ModuleEventsManifest, type ModuleManifest, type ModuleMedia, type ModuleMeta, type ModuleSharedUi, type ModuleType, type PanelSlot, type RouteEntry, SHARED_UI_ROLES, type SceneMountContext, type Shape, type ShapeDescriptor, type ShapeLeaf, type ShapeLeafSpec, type SharedEventBus, type SharedUiContext, type SharedUiRole, type SurfaceAllocator, type SurfaceHandle, type SurfaceKind, TOPIC_NAME_RE, type Topic, type TopicName, type TopicPayload, type UiPanel, defineModule, defineTopic, hostTopics, isSharedUiRole, isTopicName, shape, topicNamespace };
|
package/dist/index.d.ts
CHANGED
|
@@ -132,6 +132,70 @@ interface SharedUiContext {
|
|
|
132
132
|
}
|
|
133
133
|
declare function isSharedUiRole(value: unknown): value is SharedUiRole;
|
|
134
134
|
|
|
135
|
+
/** Bytes of one file. Strings are UTF-8 encoded (JSON saves are the common case). */
|
|
136
|
+
type ContentFileData = Blob | ArrayBuffer | Uint8Array | string;
|
|
137
|
+
/** Something local the player can publish (a saved world, a level they built). */
|
|
138
|
+
interface LocalContentItem {
|
|
139
|
+
id: string;
|
|
140
|
+
name: string;
|
|
141
|
+
/** Epoch ms of the last change — lists are shown newest first. */
|
|
142
|
+
updatedAt?: number;
|
|
143
|
+
/** One line under the name ("recipe world · 256×256"). */
|
|
144
|
+
subtitle?: string;
|
|
145
|
+
}
|
|
146
|
+
/** What `capture` hands to the Workshop to publish. Roles and MIME types must fit the title's content type config. */
|
|
147
|
+
interface CapturedContent {
|
|
148
|
+
files: Array<{
|
|
149
|
+
role: string;
|
|
150
|
+
contentType: string;
|
|
151
|
+
data: ContentFileData;
|
|
152
|
+
}>;
|
|
153
|
+
thumbnail?: {
|
|
154
|
+
contentType: "image/png" | "image/jpeg" | "image/webp";
|
|
155
|
+
data: ContentFileData;
|
|
156
|
+
};
|
|
157
|
+
suggestedTitle?: string;
|
|
158
|
+
suggestedDescription?: string;
|
|
159
|
+
tags?: string[];
|
|
160
|
+
metadata?: Record<string, string>;
|
|
161
|
+
}
|
|
162
|
+
/** What the Workshop hands to `open` after the player got access. */
|
|
163
|
+
interface DownloadedContent {
|
|
164
|
+
contentID: string;
|
|
165
|
+
title?: string | null;
|
|
166
|
+
/** Revision of the publication — lets a game tell an update from a first download. */
|
|
167
|
+
revision?: number | null;
|
|
168
|
+
files: Array<{
|
|
169
|
+
role: string;
|
|
170
|
+
contentType: string;
|
|
171
|
+
data: ArrayBuffer;
|
|
172
|
+
}>;
|
|
173
|
+
}
|
|
174
|
+
interface ContentTypeHandler {
|
|
175
|
+
/** Must equal a key of `Workshop.ContentTypes` in the title config (e.g. "voxelcraft.world"). */
|
|
176
|
+
type: string;
|
|
177
|
+
/** Shown in the Workshop's type filter and publish wizard. */
|
|
178
|
+
label: string;
|
|
179
|
+
icon?: string;
|
|
180
|
+
/** Mode (route id) to switch to after `open` — the game that plays this content. */
|
|
181
|
+
modeId?: string;
|
|
182
|
+
/** Local items the player can publish. Omit when the type cannot be published from the game. */
|
|
183
|
+
listLocal?(): Promise<LocalContentItem[]>;
|
|
184
|
+
/** Serialize one local item for publishing. */
|
|
185
|
+
capture?(localId: string): Promise<CapturedContent>;
|
|
186
|
+
/** Load downloaded content into the game (import a world, start a level). */
|
|
187
|
+
open?(content: DownloadedContent): Promise<void>;
|
|
188
|
+
}
|
|
189
|
+
/** `ctx.content` — the host's registry of content types, shared by every module of the session. */
|
|
190
|
+
interface ContentRegistry {
|
|
191
|
+
/** Register (or replace) the handler of a type. Returns an unregister function. */
|
|
192
|
+
registerType(handler: ContentTypeHandler): () => void;
|
|
193
|
+
getType(type: string): ContentTypeHandler | undefined;
|
|
194
|
+
listTypes(): ContentTypeHandler[];
|
|
195
|
+
/** Called when a type is registered or removed (a UI re-renders its type list). */
|
|
196
|
+
subscribe(listener: () => void): () => void;
|
|
197
|
+
}
|
|
198
|
+
|
|
135
199
|
/** What a module is, for catalog/UI purposes. Not every module is a game. */
|
|
136
200
|
type ModuleType = "game" | "app" | "ai-app";
|
|
137
201
|
/**
|
|
@@ -257,6 +321,16 @@ interface ModuleContext {
|
|
|
257
321
|
registerPanel(panel: UiPanel): void;
|
|
258
322
|
/** Register a nav / mode entry so the player can switch to this module. */
|
|
259
323
|
registerRoute(entry: RouteEntry): void;
|
|
324
|
+
/**
|
|
325
|
+
* Content types other modules can publish and open (see `ContentTypeHandler`). A game registers
|
|
326
|
+
* its type here; the Workshop module reads the registry — neither imports the other.
|
|
327
|
+
*/
|
|
328
|
+
content: ContentRegistry;
|
|
329
|
+
/**
|
|
330
|
+
* Switch the host to another mode (a route id registered by any module) — e.g. the Workshop opens a
|
|
331
|
+
* world and hands the screen to the game. Unknown ids are ignored.
|
|
332
|
+
*/
|
|
333
|
+
navigate(modeId: string): void;
|
|
260
334
|
/**
|
|
261
335
|
* Publish a debug surface for the AI Coder's agent — what the module IS and what it can be told
|
|
262
336
|
* to DO. Optional: a module without it simply stays opaque to the agent.
|
|
@@ -371,4 +445,4 @@ interface SharedEventBus<Events extends Record<string, unknown> = Record<string,
|
|
|
371
445
|
/** Identity helper that pins a module literal to the `Module` type for editor help and errors. */
|
|
372
446
|
declare function defineModule(module: Module): Module;
|
|
373
447
|
|
|
374
|
-
export { type EngineScene, type InferShape, type Module, type ModuleAgentApi, type ModuleAuthor, type ModuleContext, type ModuleEngine, type ModuleEventEmit, type ModuleEventListen, type ModuleEvents, type ModuleEventsManifest, type ModuleManifest, type ModuleMedia, type ModuleMeta, type ModuleSharedUi, type ModuleType, type PanelSlot, type RouteEntry, SHARED_UI_ROLES, type SceneMountContext, type Shape, type ShapeDescriptor, type ShapeLeaf, type ShapeLeafSpec, type SharedEventBus, type SharedUiContext, type SharedUiRole, type SurfaceAllocator, type SurfaceHandle, type SurfaceKind, TOPIC_NAME_RE, type Topic, type TopicName, type TopicPayload, type UiPanel, defineModule, defineTopic, hostTopics, isSharedUiRole, isTopicName, shape, topicNamespace };
|
|
448
|
+
export { type CapturedContent, type ContentFileData, type ContentRegistry, type ContentTypeHandler, type DownloadedContent, type EngineScene, type InferShape, type LocalContentItem, type Module, type ModuleAgentApi, type ModuleAuthor, type ModuleContext, type ModuleEngine, type ModuleEventEmit, type ModuleEventListen, type ModuleEvents, type ModuleEventsManifest, type ModuleManifest, type ModuleMedia, type ModuleMeta, type ModuleSharedUi, type ModuleType, type PanelSlot, type RouteEntry, SHARED_UI_ROLES, type SceneMountContext, type Shape, type ShapeDescriptor, type ShapeLeaf, type ShapeLeafSpec, type SharedEventBus, type SharedUiContext, type SharedUiRole, type SurfaceAllocator, type SurfaceHandle, type SurfaceKind, TOPIC_NAME_RE, type Topic, type TopicName, type TopicPayload, type UiPanel, defineModule, defineTopic, hostTopics, isSharedUiRole, isTopicName, shape, topicNamespace };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var S=/^[a-z0-9][a-z0-9-]*:[a-z0-9][a-z0-9-]*@[1-9]\d*$/;function x(e){return typeof e=="string"&&S.test(e)}function M(e){let t=e.indexOf(":");return t<0?"":e.slice(0,t)}var l=/^(string|number|boolean)(\[\])?(\?)?$/;function u(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function c(e,t){return e==="number"?typeof t=="number"&&Number.isFinite(t):typeof t===e}function f(e,t,r){if(!u(t))return `${r||"payload"} must be an object`;for(let[n,o]of Object.entries(e)){let i=r?`${r}.${n}`:n,a=t[n];if(typeof o!="string"){let p=f(o,a,i);if(p)return p;continue}let d=l.exec(o);if(!d)return `${i}: invalid descriptor "${o}"`;let[,s="",g,m]=d;if(a===void 0){if(m)continue;return `${i} is missing`}if(g){if(!Array.isArray(a))return `${i} must be ${s}[]`;if(!a.every(p=>c(s,p)))return `${i} must contain only ${s} values`;continue}if(!c(s,a))return `${i} must be a ${s}`}return null}function y(e,t){for(let[r,n]of Object.entries(e)){let o=t?`${t}.${r}`:r;if(typeof n=="string"){if(!l.test(n))throw new Error(`shape(): field "${o}" has invalid type "${n}" \u2014 use "string" | "number" | "boolean", optionally with "[]" and/or a trailing "?"`)}else if(u(n))y(n,o);else throw new Error(`shape(): field "${o}" must be a type string or an object`)}}function h(e){return y(e,""),{descriptor:e,check:t=>f(e,t,"")}}function v(e,t){if(!x(e))throw new Error(`defineTopic(): "${e}" is not a valid topic name \u2014 expected "<module-id>:<event>@<major>", e.g. "idle-rpg:character-upgraded@1"`);return {name:e,shape:t}}var E={modeChanged:v("host:mode-changed@1",h({from:"string?",to:"string"}))};var T=["currency-bar","wallet","status","account"];function $(e){return typeof e=="string"&&T.includes(e)}function D(e){return e}export{T as SHARED_UI_ROLES,S as TOPIC_NAME_RE,D as defineModule,v as defineTopic,E as hostTopics,$ as isSharedUiRole,x as isTopicName,h as shape,M as topicNamespace};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idosgames/module-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "The composable-module contract for the iDosGames host shell: Module / ModuleContext types plus tiny authoring helpers. Framework-neutral at runtime — a module can be a game (Three/Phaser), a plain app, or an AI app.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"//": "@idosgames/core is a real range, not '*': a published contract must name the version of core whose IDosGamesClient/SdkEvents shapes it references. Bump in step with core (see RELEASING.md). react is an OPTIONAL peer — the contract references React's ComponentType type only (a UI panel is a React component), which is erased at build, so a runtime-only module needs no React.",
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@idosgames/core": "^0.
|
|
49
|
+
"@idosgames/core": "^0.14.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"react": "^18.3.1 || ^19.0.0"
|