@tokamakdev/tok 0.1.1-beta.126 → 0.1.1-beta.128
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/plugin-manifest.d.mts +0 -12
- package/dist/plugin-manifest.mjs +3 -33
- package/dist/worker-contract.d.mts +6 -3
- package/dist/worker-contract.mjs +31 -23
- package/dist/worker-graph.mjs +2 -8
- package/package.json +13 -13
|
@@ -4,16 +4,6 @@ export interface ModuleExport {
|
|
|
4
4
|
module: string;
|
|
5
5
|
export: string;
|
|
6
6
|
}
|
|
7
|
-
/** Where an operation runs, and what it needs there. */
|
|
8
|
-
export interface Operation {
|
|
9
|
-
/** The native platforms that implement it, with any minimum OS version. */
|
|
10
|
-
platforms: {
|
|
11
|
-
name: NativePlatform;
|
|
12
|
-
minimum?: string;
|
|
13
|
-
}[];
|
|
14
|
-
/** The native platforms where it needs the app in the foreground, to show UI. */
|
|
15
|
-
foreground: NativePlatform[];
|
|
16
|
-
}
|
|
17
7
|
export interface PluginDefinition {
|
|
18
8
|
id: string;
|
|
19
9
|
package: string;
|
|
@@ -24,8 +14,6 @@ export interface PluginDefinition {
|
|
|
24
14
|
client: string;
|
|
25
15
|
/** The native platforms the plugin builds for. */
|
|
26
16
|
platforms: NativePlatform[];
|
|
27
|
-
/** Each operation the manifest describes; others run on every platform the plugin builds for. */
|
|
28
|
-
operations: Record<string, Operation>;
|
|
29
17
|
}
|
|
30
18
|
/** Installed direct dependencies select the application's plugin services. */
|
|
31
19
|
export declare function discoverPlugins(root: string): PluginDefinition[];
|
package/dist/plugin-manifest.mjs
CHANGED
|
@@ -35,6 +35,9 @@ export function discoverPlugins(root) {
|
|
|
35
35
|
const reserved = reservedIds.find(word => data.id === word || data.id.startsWith(`${word}-`));
|
|
36
36
|
if (reserved)
|
|
37
37
|
throw new Error(`${manifest}: plugin id must not start with '${reserved}', which Tokamak's options use.`);
|
|
38
|
+
if (data.operations !== undefined) {
|
|
39
|
+
throw new Error(`${manifest}: operations is no longer read; tag a method that only some platforms implement with @platforms in its doc comment.`);
|
|
40
|
+
}
|
|
38
41
|
const api = moduleExport(directory, data.api, "api");
|
|
39
42
|
if (plugins.has(data.id))
|
|
40
43
|
throw new Error(`Duplicate Tokamak plugin id ${data.id}.`);
|
|
@@ -45,7 +48,6 @@ export function discoverPlugins(root) {
|
|
|
45
48
|
binding: `TOKAMAK_${data.id.toUpperCase().replaceAll("-", "_")}`,
|
|
46
49
|
client: `${name}/client`,
|
|
47
50
|
platforms,
|
|
48
|
-
operations: operations(manifest, data.operations ?? {}, platforms),
|
|
49
51
|
});
|
|
50
52
|
}
|
|
51
53
|
return [...plugins.values()].sort((left, right) => left.id.localeCompare(right.id));
|
|
@@ -62,35 +64,3 @@ function moduleExport(root, reference, field) {
|
|
|
62
64
|
}
|
|
63
65
|
return { module: module.split(path.sep).join("/"), export: value.export };
|
|
64
66
|
}
|
|
65
|
-
/** The manifest's `operations`, each on platforms the plugin builds for. */
|
|
66
|
-
function operations(manifest, value, built) {
|
|
67
|
-
const fail = (message) => { throw new Error(`${manifest}: ${message}`); };
|
|
68
|
-
const platform = (name, field) => built.includes(name) ? name : fail(`${field} names ${name}, which the plugin does not build for.`);
|
|
69
|
-
if (!isRecord(value))
|
|
70
|
-
return fail("operations must be an object.");
|
|
71
|
-
const result = {};
|
|
72
|
-
for (const [name, entry] of Object.entries(value)) {
|
|
73
|
-
const field = `operations.${name}`;
|
|
74
|
-
if (!isRecord(entry))
|
|
75
|
-
return fail(`${field} must be an object.`);
|
|
76
|
-
const { platforms, foreground = false, ...unknown } = entry;
|
|
77
|
-
if (Object.keys(unknown).length)
|
|
78
|
-
fail(`${field} has unknown keys: ${Object.keys(unknown).join(", ")}.`);
|
|
79
|
-
if (platforms !== undefined && (!isRecord(platforms) ||
|
|
80
|
-
!Object.values(platforms).every(version => typeof version === "string" || version === true))) {
|
|
81
|
-
fail(`${field}.platforms must map platforms to a minimum OS version, or true for the app's minimum.`);
|
|
82
|
-
}
|
|
83
|
-
if (typeof foreground !== "boolean" && !(Array.isArray(foreground) && foreground.every(name => typeof name === "string"))) {
|
|
84
|
-
fail(`${field}.foreground must be true or a list of platforms.`);
|
|
85
|
-
}
|
|
86
|
-
const implemented = platforms === undefined
|
|
87
|
-
? built.map(name => ({ name }))
|
|
88
|
-
: Object.entries(platforms).map(([name, minimum]) => ({ name: platform(name, `${field}.platforms`), minimum: minimum === true ? undefined : minimum }));
|
|
89
|
-
const needs = foreground === true ? implemented.map(({ name }) => name) : foreground === false ? [] : foreground;
|
|
90
|
-
result[name] = { platforms: implemented, foreground: needs.map(name => platform(name, `${field}.foreground`)) };
|
|
91
|
-
}
|
|
92
|
-
return result;
|
|
93
|
-
}
|
|
94
|
-
function isRecord(value) {
|
|
95
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
96
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PluginDefinition } from "./plugin-manifest.mjs";
|
|
1
|
+
import type { NativePlatform, PluginDefinition } from "./plugin-manifest.mjs";
|
|
2
2
|
/** The callable prototype methods and source dependencies of a Worker entrypoint. */
|
|
3
3
|
export interface WorkerContract {
|
|
4
4
|
methods: string[];
|
|
@@ -8,8 +8,11 @@ export interface WorkerContract {
|
|
|
8
8
|
export interface PluginContract extends WorkerContract {
|
|
9
9
|
definition: PluginDefinition;
|
|
10
10
|
webMethods: string[];
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* The native platforms that implement each operation of the native SDK, including those only the
|
|
13
|
+
* Tokamak worker can call.
|
|
14
|
+
*/
|
|
15
|
+
operations: Record<string, NativePlatform[]>;
|
|
13
16
|
}
|
|
14
17
|
/** The contract of a Tokamak worker without a module. */
|
|
15
18
|
export declare function emptyContract(): WorkerContract;
|
package/dist/worker-contract.mjs
CHANGED
|
@@ -123,7 +123,7 @@ function pluginContract(module, definition, validate) {
|
|
|
123
123
|
}
|
|
124
124
|
const reference = nativeSdkExport(program, checker, module.entry, "NativeReference", "@tokamakdev/plugin");
|
|
125
125
|
const methods = [];
|
|
126
|
-
const operations =
|
|
126
|
+
const operations = {};
|
|
127
127
|
for (const property of api.getProperties()) {
|
|
128
128
|
if (privateProperty(property))
|
|
129
129
|
continue;
|
|
@@ -137,7 +137,7 @@ function pluginContract(module, definition, validate) {
|
|
|
137
137
|
if (!method.getCallSignatures().length || String(property.escapedName).startsWith("__@")) {
|
|
138
138
|
throw new Error(`Plugin ${definition.id}.${property.name} must be a method.`);
|
|
139
139
|
}
|
|
140
|
-
operations.
|
|
140
|
+
operations[property.name] = implementedOn(property, definition);
|
|
141
141
|
try {
|
|
142
142
|
checkRpcMethod(checker, method, `${definition.id}.${property.name}`, reference);
|
|
143
143
|
}
|
|
@@ -148,39 +148,45 @@ function pluginContract(module, definition, validate) {
|
|
|
148
148
|
if (validate)
|
|
149
149
|
throw error;
|
|
150
150
|
}
|
|
151
|
-
|
|
151
|
+
// Its `@platforms` tag becomes the availability line the documentation ends with.
|
|
152
|
+
methods.push(methodDeclaration(checker, property, method, ["platforms"]));
|
|
152
153
|
}
|
|
153
154
|
methods.sort(byName);
|
|
154
|
-
const unknown = Object.keys(definition.operations).find(name => !operations.includes(name));
|
|
155
|
-
if (unknown)
|
|
156
|
-
throw new Error(`${definition.manifest}: operations.${unknown} names no method of ${definition.api.export}.`);
|
|
157
155
|
const webMethods = browserMethods(module, definition, methods, validate);
|
|
158
156
|
for (const method of methods) {
|
|
159
|
-
method.documentation = [method.documentation, availability(
|
|
157
|
+
method.documentation = [method.documentation, availability(operations[method.name], webMethods.includes(method.name))]
|
|
160
158
|
.filter(Boolean).join("\n\n");
|
|
161
159
|
}
|
|
162
160
|
return {
|
|
163
161
|
definition, methods: methods.map(method => method.name), files: [...module.files, definition.manifest],
|
|
164
|
-
webMethods, operations: operations.sort(),
|
|
162
|
+
webMethods, operations: Object.fromEntries(Object.entries(operations).sort(([left], [right]) => left.localeCompare(right))),
|
|
165
163
|
declarations: serviceTypes(`ReturnType<typeof import(${JSON.stringify(definition.api.module)}, { with: { "resolution-mode": "import" } })[${JSON.stringify(definition.api.export)}]>`, methods),
|
|
166
164
|
};
|
|
167
165
|
}
|
|
168
166
|
const platformNames = {
|
|
169
167
|
ios: "iOS", macos: "macOS", android: "Android", windows: "Windows", linux: "Linux",
|
|
170
168
|
};
|
|
171
|
-
/** Where
|
|
172
|
-
function availability(
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
169
|
+
/** Where an operation is implemented, for editor documentation. */
|
|
170
|
+
function availability(platforms, web) {
|
|
171
|
+
const native = platforms.map(platform => platformNames[platform]).join(", ") || "none";
|
|
172
|
+
return `Native: ${native}. Web: ${web ? "browser implementation" : "not supported"}.`;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The native platforms that implement the plugin method `property`: those the `@platforms` tag of
|
|
176
|
+
* its doc comment names, or every one the plugin builds for.
|
|
177
|
+
*/
|
|
178
|
+
function implementedOn(property, definition) {
|
|
179
|
+
const tag = property.declarations?.flatMap(node => ts.getJSDocTags(node)).find(({ tagName }) => tagName.text === "platforms");
|
|
180
|
+
if (!tag)
|
|
181
|
+
return definition.platforms;
|
|
182
|
+
const method = `Plugin ${definition.id}.${property.name}`;
|
|
183
|
+
const names = (ts.getTextOfJSDocComment(tag.comment) ?? "").split(/\s+/).filter(Boolean);
|
|
184
|
+
if (!names.length)
|
|
185
|
+
throw new Error(`${method}: @platforms names no platform.`);
|
|
186
|
+
const unknown = names.find(name => !definition.platforms.includes(name));
|
|
187
|
+
if (unknown)
|
|
188
|
+
throw new Error(`${method}: @platforms names ${unknown}, which the plugin does not build for (${definition.platforms.join(", ")}).`);
|
|
189
|
+
return names;
|
|
184
190
|
}
|
|
185
191
|
function browserMethods(project, definition, methods, validate) {
|
|
186
192
|
if (!definition.web)
|
|
@@ -258,13 +264,15 @@ function classContract(module, name, native, validate) {
|
|
|
258
264
|
function byName(left, right) {
|
|
259
265
|
return left.name < right.name ? -1 : left.name > right.name ? 1 : 0;
|
|
260
266
|
}
|
|
261
|
-
|
|
267
|
+
/** `property`'s declaration in generated service types, with its documentation apart from `consumed` tags. */
|
|
268
|
+
function methodDeclaration(checker, property, type, consumed = []) {
|
|
262
269
|
return {
|
|
263
270
|
name: property.name,
|
|
264
271
|
overloads: type.getCallSignatures().length,
|
|
265
272
|
documentation: [
|
|
266
273
|
ts.displayPartsToString(property.getDocumentationComment(checker)),
|
|
267
|
-
...property.getJsDocTags(checker).
|
|
274
|
+
...property.getJsDocTags(checker).filter(tag => !consumed.includes(tag.name))
|
|
275
|
+
.map(tag => `@${tag.name} ${ts.displayPartsToString(tag.text)}`.trim()),
|
|
268
276
|
].filter(Boolean).join("\n"),
|
|
269
277
|
};
|
|
270
278
|
}
|
package/dist/worker-graph.mjs
CHANGED
|
@@ -257,15 +257,9 @@ function nativeConnectionModule(relay) {
|
|
|
257
257
|
return `import { connectDevice } from ${JSON.stringify(NATIVE_CALLS)};
|
|
258
258
|
export const connect = ctx => connectDevice(${JSON.stringify(relay)}, ctx);`;
|
|
259
259
|
}
|
|
260
|
-
/**
|
|
260
|
+
/** The native platforms of each plugin operation. */
|
|
261
261
|
function availability(plugins) {
|
|
262
|
-
return Object.fromEntries(plugins.map(({ definition, operations }) => [
|
|
263
|
-
definition.id,
|
|
264
|
-
Object.fromEntries(operations.map(operation => [
|
|
265
|
-
operation,
|
|
266
|
-
definition.operations[operation]?.platforms.map(({ name }) => name) ?? definition.platforms,
|
|
267
|
-
])),
|
|
268
|
-
]));
|
|
262
|
+
return Object.fromEntries(plugins.map(({ definition, operations }) => [definition.id, operations]));
|
|
269
263
|
}
|
|
270
264
|
function serviceEntrypoint(entry, services) {
|
|
271
265
|
const sdk = normalizePath(fileURLToPath(import.meta.resolve("@tokamakdev/plugin/worker")));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokamakdev/tok",
|
|
3
|
-
"version": "0.1.1-beta.
|
|
3
|
+
"version": "0.1.1-beta.128",
|
|
4
4
|
"description": "The tokamak CLI, Vite plugin and app API: build native apps from a Cloudflare Workers codebase",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"node": ">=18"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@tokamakdev/plugin": "0.1.0-beta.
|
|
46
|
+
"@tokamakdev/plugin": "0.1.0-beta.128",
|
|
47
47
|
"typescript": "5.9.3",
|
|
48
48
|
"ws": "^8.22.0"
|
|
49
49
|
},
|
|
@@ -75,17 +75,17 @@
|
|
|
75
75
|
"wrangler": "4.147.0"
|
|
76
76
|
},
|
|
77
77
|
"optionalDependencies": {
|
|
78
|
-
"@tokamakdev/platform-android-arm64": "0.1.1-beta.
|
|
79
|
-
"@tokamakdev/platform-ios-arm64": "0.1.1-beta.
|
|
80
|
-
"@tokamakdev/platform-ios-simulator-arm64": "0.1.1-beta.
|
|
81
|
-
"@tokamakdev/platform-ios-simulator-x64": "0.1.1-beta.
|
|
82
|
-
"@tokamakdev/platform-macos-arm64": "0.1.1-beta.
|
|
83
|
-
"@tokamakdev/platform-macos-x64": "0.1.1-beta.
|
|
84
|
-
"@tokamakdev/platform-windows-x64": "0.1.1-beta.
|
|
85
|
-
"@tokamakdev/tok-darwin-arm64": "0.1.1-beta.
|
|
86
|
-
"@tokamakdev/tok-darwin-x64": "0.1.1-beta.
|
|
87
|
-
"@tokamakdev/tok-linux-x64": "0.1.1-beta.
|
|
88
|
-
"@tokamakdev/tok-win32-x64": "0.1.1-beta.
|
|
78
|
+
"@tokamakdev/platform-android-arm64": "0.1.1-beta.128",
|
|
79
|
+
"@tokamakdev/platform-ios-arm64": "0.1.1-beta.128",
|
|
80
|
+
"@tokamakdev/platform-ios-simulator-arm64": "0.1.1-beta.128",
|
|
81
|
+
"@tokamakdev/platform-ios-simulator-x64": "0.1.1-beta.128",
|
|
82
|
+
"@tokamakdev/platform-macos-arm64": "0.1.1-beta.128",
|
|
83
|
+
"@tokamakdev/platform-macos-x64": "0.1.1-beta.128",
|
|
84
|
+
"@tokamakdev/platform-windows-x64": "0.1.1-beta.128",
|
|
85
|
+
"@tokamakdev/tok-darwin-arm64": "0.1.1-beta.128",
|
|
86
|
+
"@tokamakdev/tok-darwin-x64": "0.1.1-beta.128",
|
|
87
|
+
"@tokamakdev/tok-linux-x64": "0.1.1-beta.128",
|
|
88
|
+
"@tokamakdev/tok-win32-x64": "0.1.1-beta.128"
|
|
89
89
|
},
|
|
90
90
|
"publishConfig": {
|
|
91
91
|
"access": "public"
|