@tokamakdev/tok 0.1.1-beta.80 → 0.1.1-beta.82
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 +6 -3
- package/dist/index.d.mts +3 -3
- package/dist/vite.d.mts +12 -5
- package/dist/vite.mjs +47 -101
- package/package.json +12 -12
package/README.md
CHANGED
|
@@ -11,18 +11,21 @@ npx tok targets
|
|
|
11
11
|
|
|
12
12
|
| Entry | Contents |
|
|
13
13
|
| --- | --- |
|
|
14
|
-
| `@tokamakdev/tok` | The `Config` type of
|
|
14
|
+
| `@tokamakdev/tok` | The `Config` type of the Vite plugin's options |
|
|
15
15
|
| `@tokamakdev/tok/vite` | The Vite plugin, `tokamak()` |
|
|
16
16
|
| `tok` | The CLI |
|
|
17
17
|
|
|
18
|
-
The Vite plugin goes next to Cloudflare's
|
|
18
|
+
The Vite plugin goes next to Cloudflare's, and its options are the app's
|
|
19
|
+
tokamak configuration:
|
|
19
20
|
|
|
20
21
|
```ts
|
|
21
22
|
import { cloudflare } from "@cloudflare/vite-plugin";
|
|
22
23
|
import { tokamak } from "@tokamakdev/tok/vite";
|
|
23
24
|
import { defineConfig } from "vite";
|
|
24
25
|
|
|
25
|
-
export default defineConfig({
|
|
26
|
+
export default defineConfig({
|
|
27
|
+
plugins: [cloudflare(), tokamak({ name: "My App", version: "1.0.0" })],
|
|
28
|
+
});
|
|
26
29
|
```
|
|
27
30
|
|
|
28
31
|
It does nothing unless `tok` runs the build or development command.
|
package/dist/index.d.mts
CHANGED
|
@@ -6,18 +6,18 @@ export interface PlatformConfig {
|
|
|
6
6
|
name?: string;
|
|
7
7
|
/** Application identifier. */
|
|
8
8
|
identifier?: string;
|
|
9
|
-
/** Icon in the platform's format, relative to the
|
|
9
|
+
/** Icon in the platform's format, relative to the Vite root. */
|
|
10
10
|
icon?: string;
|
|
11
11
|
/** A setting the platform pack declares; `tok` validates it. */
|
|
12
12
|
[key: string]: Value | undefined;
|
|
13
13
|
}
|
|
14
|
-
/** The app's tokamak configuration
|
|
14
|
+
/** The app's tokamak configuration: the tokamak Vite plugin's options other than `module`. */
|
|
15
15
|
export interface Config {
|
|
16
16
|
/** Display name for every platform. */
|
|
17
17
|
name?: string;
|
|
18
18
|
/** Application identifier for every platform. */
|
|
19
19
|
identifier?: string;
|
|
20
|
-
/** Icon for every platform, relative to the
|
|
20
|
+
/** Icon for every platform, relative to the Vite root. */
|
|
21
21
|
icon?: string;
|
|
22
22
|
/** App version. */
|
|
23
23
|
version?: string;
|
package/dist/vite.d.mts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { type Plugin } from "vite";
|
|
2
|
+
import type { Config } from "./index.mjs";
|
|
2
3
|
/**
|
|
3
|
-
* Reports the
|
|
4
|
-
* address and Worker name, to `tok`, and makes the entry
|
|
5
|
-
*
|
|
6
|
-
* no hooks.
|
|
4
|
+
* Reports the app's tokamak configuration, and the development server's
|
|
5
|
+
* address, HTTPS certificate and Worker name, to `tok`, and makes the entry
|
|
6
|
+
* Worker import `module`. Without `TOKAMAK_VITE_OUTPUT`, which `tok` sets, it
|
|
7
|
+
* adds no hooks.
|
|
7
8
|
*/
|
|
8
|
-
export declare function tokamak(
|
|
9
|
+
export declare function tokamak({ module, ...config }?: Config & {
|
|
10
|
+
/**
|
|
11
|
+
* The module the entry Worker imports, relative to the Vite root; by
|
|
12
|
+
* default `src/tokamak.ts`, then `src/tokamak.js`, when one exists.
|
|
13
|
+
*/
|
|
14
|
+
module?: string;
|
|
15
|
+
}): Plugin[];
|
package/dist/vite.mjs
CHANGED
|
@@ -1,57 +1,53 @@
|
|
|
1
|
+
import { X509Certificate } from "node:crypto";
|
|
1
2
|
import fs from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
|
-
import { normalizePath
|
|
4
|
-
/**
|
|
5
|
-
const
|
|
4
|
+
import { normalizePath } from "vite";
|
|
5
|
+
/** Modules tried in order when the options name none. */
|
|
6
|
+
const DEFAULT_MODULES = ["src/tokamak.ts", "src/tokamak.js"];
|
|
6
7
|
/** Wrangler configuration files Cloudflare's plugin tries in order. */
|
|
7
8
|
const WRANGLER_FILES = ["wrangler.jsonc", "wrangler.json", "wrangler.toml"];
|
|
8
|
-
|
|
9
|
-
const written = new Map();
|
|
9
|
+
const MIDDLEWARE_MODE_ERROR = "Vite is running in middleware mode, so tokamak cannot find the development server's address; tok dev needs Vite's own dev server";
|
|
10
10
|
/**
|
|
11
|
-
* Reports the
|
|
12
|
-
* address and Worker name, to `tok`, and makes the entry
|
|
13
|
-
*
|
|
14
|
-
* no hooks.
|
|
11
|
+
* Reports the app's tokamak configuration, and the development server's
|
|
12
|
+
* address, HTTPS certificate and Worker name, to `tok`, and makes the entry
|
|
13
|
+
* Worker import `module`. Without `TOKAMAK_VITE_OUTPUT`, which `tok` sets, it
|
|
14
|
+
* adds no hooks.
|
|
15
15
|
*/
|
|
16
|
-
export function tokamak() {
|
|
16
|
+
export function tokamak({ module, ...config } = {}) {
|
|
17
17
|
const output = process.env.TOKAMAK_VITE_OUTPUT;
|
|
18
18
|
if (!output) {
|
|
19
19
|
return [];
|
|
20
20
|
}
|
|
21
|
-
let config;
|
|
22
21
|
let file;
|
|
23
22
|
/** The module IDs of each entry environment's inputs. */
|
|
24
23
|
const entryIds = new Map();
|
|
25
|
-
/** The entry environments whose input imports the
|
|
24
|
+
/** The entry environments whose input imports the module. */
|
|
26
25
|
const importing = new Set();
|
|
27
|
-
const write = () => {
|
|
28
|
-
const files = writeConfig(output, file, config);
|
|
29
|
-
// A file that fails to load stays watched, so fixing it rewrites `config.json`.
|
|
30
|
-
written.set(output, files.catch(() => (file ? [file] : [])));
|
|
31
|
-
return files;
|
|
32
|
-
};
|
|
33
26
|
return [
|
|
34
27
|
{
|
|
35
28
|
name: "tokamak",
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
await (written.has(output) ? written.get(output) : write());
|
|
40
|
-
},
|
|
41
|
-
async watchChange(id) {
|
|
42
|
-
if ((await written.get(output))?.includes(id)) {
|
|
43
|
-
await write();
|
|
44
|
-
}
|
|
29
|
+
configResolved({ root }) {
|
|
30
|
+
file = findModule(root, module);
|
|
31
|
+
writeJson(output, "config.json", { root, config });
|
|
45
32
|
},
|
|
46
33
|
async configureServer(server) {
|
|
47
34
|
const httpServer = server.httpServer;
|
|
35
|
+
// A middleware-mode server beside a reported one, such as the server
|
|
36
|
+
// Astro syncs content with, leaves the report in place.
|
|
48
37
|
if (!httpServer) {
|
|
38
|
+
if (!fs.existsSync(path.join(output, "server.json"))) {
|
|
39
|
+
writeJson(output, "server.json", { error: MIDDLEWARE_MODE_ERROR });
|
|
40
|
+
}
|
|
49
41
|
return;
|
|
50
42
|
}
|
|
51
43
|
const workerName = await readWorkerName(server.config.root);
|
|
52
44
|
httpServer.on("listening", () => {
|
|
53
45
|
const urls = server.resolvedUrls;
|
|
54
|
-
writeJson(output, "server.json", {
|
|
46
|
+
writeJson(output, "server.json", {
|
|
47
|
+
url: urls?.local[0] ?? urls?.network[0],
|
|
48
|
+
workerName,
|
|
49
|
+
certificates: endEntityCertificates(server.config.server.https),
|
|
50
|
+
});
|
|
55
51
|
});
|
|
56
52
|
},
|
|
57
53
|
async buildApp(builder) {
|
|
@@ -65,9 +61,6 @@ export function tokamak() {
|
|
|
65
61
|
name: "tokamak:entry",
|
|
66
62
|
applyToEnvironment: ({ config }) => file !== undefined && buildsEntryWorker(config),
|
|
67
63
|
async transform(code, id) {
|
|
68
|
-
if (id === file) {
|
|
69
|
-
return withoutConfig(this, code);
|
|
70
|
-
}
|
|
71
64
|
const environment = this.environment;
|
|
72
65
|
const ids = entryIds.get(environment.name) ??
|
|
73
66
|
Promise.all(inputs(environment.config.build).map(async (input) => (await this.resolve(input))?.id));
|
|
@@ -88,33 +81,14 @@ export function tokamak() {
|
|
|
88
81
|
},
|
|
89
82
|
];
|
|
90
83
|
}
|
|
91
|
-
/** The
|
|
92
|
-
function
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
return normalizePath(path.resolve(named));
|
|
84
|
+
/** The module `name` under `root`, or else the first default under `root` that exists. */
|
|
85
|
+
function findModule(root, name) {
|
|
86
|
+
const candidates = (name ? [name] : DEFAULT_MODULES).map((candidate) => normalizePath(path.resolve(root, candidate)));
|
|
87
|
+
const file = candidates.find((candidate) => fs.existsSync(candidate));
|
|
88
|
+
if (name && !file) {
|
|
89
|
+
throw new Error(`tokamak module not found: ${candidates[0]}`);
|
|
99
90
|
}
|
|
100
|
-
|
|
101
|
-
return file && normalizePath(file);
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Writes the file's `config` export, with the file's path, to `config.json`,
|
|
105
|
-
* returning the files it was read from.
|
|
106
|
-
*/
|
|
107
|
-
async function writeConfig(output, file, config) {
|
|
108
|
-
if (!file) {
|
|
109
|
-
writeJson(output, "config.json", { config: {} });
|
|
110
|
-
return [];
|
|
111
|
-
}
|
|
112
|
-
const { module, dependencies } = await runnerImport(file, {
|
|
113
|
-
root: config.root,
|
|
114
|
-
resolve: { alias: config.resolve.alias, tsconfigPaths: config.resolve.tsconfigPaths },
|
|
115
|
-
});
|
|
116
|
-
writeJson(output, "config.json", { file, config: module.config ?? {} });
|
|
117
|
-
return [file, ...dependencies.map(normalizePath)];
|
|
91
|
+
return file;
|
|
118
92
|
}
|
|
119
93
|
/**
|
|
120
94
|
* The name of the Worker in the Wrangler configuration file in `root`, found
|
|
@@ -130,6 +104,22 @@ async function readWorkerName(root) {
|
|
|
130
104
|
const worker = unstable_readConfig({ config: file, env: process.env.CLOUDFLARE_ENV }, { hideWarnings: true });
|
|
131
105
|
return worker.topLevelName ?? worker.name;
|
|
132
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* The PEM of the end-entity certificate of each chain in `https.cert`, which
|
|
109
|
+
* Vite reads from a file when a string names one.
|
|
110
|
+
*/
|
|
111
|
+
function endEntityCertificates(https) {
|
|
112
|
+
const cert = typeof https?.cert === "string" ? readFileIfExists(https.cert) : https?.cert;
|
|
113
|
+
return cert && [cert].flat().map((chain) => new X509Certificate(chain).toString()).join("");
|
|
114
|
+
}
|
|
115
|
+
function readFileIfExists(file) {
|
|
116
|
+
try {
|
|
117
|
+
return fs.readFileSync(path.resolve(file));
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return file;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
133
123
|
/**
|
|
134
124
|
* Whether an environment builds from the entry Worker: Cloudflare's plugin
|
|
135
125
|
* gives a manifest to its entry and prerender Workers, and Astro to its server
|
|
@@ -143,50 +133,6 @@ function inputs(build) {
|
|
|
143
133
|
const { input } = build.rollupOptions;
|
|
144
134
|
return typeof input === "string" ? [input] : Object.values(input ?? {});
|
|
145
135
|
}
|
|
146
|
-
/**
|
|
147
|
-
* `code` without its `config` export: the `export const config = ...`
|
|
148
|
-
* statement is blanked, or only its `export` keyword while other statements
|
|
149
|
-
* mention `config`, so that every other position, and so the source map, is
|
|
150
|
-
* unchanged.
|
|
151
|
-
*/
|
|
152
|
-
function withoutConfig(context, code) {
|
|
153
|
-
const statements = context.parse(code).body;
|
|
154
|
-
const statement = statements.find(exportsConfig);
|
|
155
|
-
if (!statement) {
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
const declaration = statement.declaration;
|
|
159
|
-
if (declaration?.declarations?.length !== 1) {
|
|
160
|
-
return context.error("declare config in its own `export const config = ...` statement");
|
|
161
|
-
}
|
|
162
|
-
const mentioned = statements.some((other) => other !== statement && mentions(other, "config"));
|
|
163
|
-
const end = mentioned ? declaration.start : statement.end;
|
|
164
|
-
const blank = code.slice(statement.start, end).replace(/[^\n]/g, " ");
|
|
165
|
-
return { code: code.slice(0, statement.start) + blank + code.slice(end), map: null };
|
|
166
|
-
}
|
|
167
|
-
/** Whether `node` contains an identifier named `name`, property names included. */
|
|
168
|
-
function mentions(node, name) {
|
|
169
|
-
if (typeof node !== "object" || node === null) {
|
|
170
|
-
return false;
|
|
171
|
-
}
|
|
172
|
-
const identifier = node;
|
|
173
|
-
if (identifier.type === "Identifier" && identifier.name === name) {
|
|
174
|
-
return true;
|
|
175
|
-
}
|
|
176
|
-
return Object.values(node).some((child) => mentions(child, name));
|
|
177
|
-
}
|
|
178
|
-
function exportsConfig(statement) {
|
|
179
|
-
if (statement.type !== "ExportNamedDeclaration") {
|
|
180
|
-
return false;
|
|
181
|
-
}
|
|
182
|
-
const declaration = statement.declaration;
|
|
183
|
-
const names = [
|
|
184
|
-
declaration?.id?.name,
|
|
185
|
-
...(declaration?.declarations ?? []).map((declarator) => declarator.id.name),
|
|
186
|
-
...(statement.specifiers ?? []).map((specifier) => specifier.exported.name),
|
|
187
|
-
];
|
|
188
|
-
return names.includes("config");
|
|
189
|
-
}
|
|
190
136
|
/** Writes `value` to `name` whole, as `tok` reads the file as soon as it exists. */
|
|
191
137
|
function writeJson(output, name, value) {
|
|
192
138
|
const file = path.join(output, name);
|
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.82",
|
|
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",
|
|
@@ -55,17 +55,17 @@
|
|
|
55
55
|
"wrangler": "4.147.0"
|
|
56
56
|
},
|
|
57
57
|
"optionalDependencies": {
|
|
58
|
-
"@tokamakdev/platform-android-arm64": "0.1.1-beta.
|
|
59
|
-
"@tokamakdev/platform-ios-arm64": "0.1.1-beta.
|
|
60
|
-
"@tokamakdev/platform-ios-simulator-arm64": "0.1.1-beta.
|
|
61
|
-
"@tokamakdev/platform-ios-simulator-x64": "0.1.1-beta.
|
|
62
|
-
"@tokamakdev/platform-macos-arm64": "0.1.1-beta.
|
|
63
|
-
"@tokamakdev/platform-macos-x64": "0.1.1-beta.
|
|
64
|
-
"@tokamakdev/platform-windows-x64": "0.1.1-beta.
|
|
65
|
-
"@tokamakdev/tok-darwin-arm64": "0.1.1-beta.
|
|
66
|
-
"@tokamakdev/tok-darwin-x64": "0.1.1-beta.
|
|
67
|
-
"@tokamakdev/tok-linux-x64": "0.1.1-beta.
|
|
68
|
-
"@tokamakdev/tok-win32-x64": "0.1.1-beta.
|
|
58
|
+
"@tokamakdev/platform-android-arm64": "0.1.1-beta.82",
|
|
59
|
+
"@tokamakdev/platform-ios-arm64": "0.1.1-beta.82",
|
|
60
|
+
"@tokamakdev/platform-ios-simulator-arm64": "0.1.1-beta.82",
|
|
61
|
+
"@tokamakdev/platform-ios-simulator-x64": "0.1.1-beta.82",
|
|
62
|
+
"@tokamakdev/platform-macos-arm64": "0.1.1-beta.82",
|
|
63
|
+
"@tokamakdev/platform-macos-x64": "0.1.1-beta.82",
|
|
64
|
+
"@tokamakdev/platform-windows-x64": "0.1.1-beta.82",
|
|
65
|
+
"@tokamakdev/tok-darwin-arm64": "0.1.1-beta.82",
|
|
66
|
+
"@tokamakdev/tok-darwin-x64": "0.1.1-beta.82",
|
|
67
|
+
"@tokamakdev/tok-linux-x64": "0.1.1-beta.82",
|
|
68
|
+
"@tokamakdev/tok-win32-x64": "0.1.1-beta.82"
|
|
69
69
|
},
|
|
70
70
|
"publishConfig": {
|
|
71
71
|
"access": "public"
|