@tokamakdev/tok 0.1.1-beta.65 → 0.1.1-beta.70

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/vite.d.mts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { type Plugin } from "vite";
2
2
  /**
3
- * Reports the build's tokamak configuration and development server address to
4
- * `tok`, and makes the entry Worker import the configuration file. Without
5
- * `TOKAMAK_VITE_OUTPUT`, which `tok` sets, it adds no hooks.
3
+ * Reports the build's tokamak configuration, and the development server's
4
+ * address and Worker name, to `tok`, and makes the entry Worker import the
5
+ * configuration file. Without `TOKAMAK_VITE_OUTPUT`, which `tok` sets, it adds
6
+ * no hooks.
6
7
  */
7
8
  export declare function tokamak(): Plugin[];
package/dist/vite.mjs CHANGED
@@ -3,12 +3,15 @@ import path from "node:path";
3
3
  import { normalizePath, runnerImport, } from "vite";
4
4
  /** Configuration files tried in order when `tok` names none. */
5
5
  const CONFIG_FILES = ["src/tokamak.ts", "src/tokamak.js"];
6
+ /** Wrangler configuration files Cloudflare's plugin tries in order. */
7
+ const WRANGLER_FILES = ["wrangler.jsonc", "wrangler.json", "wrangler.toml"];
6
8
  /** The files each output directory's `config.json` was read from, once written. */
7
9
  const written = new Map();
8
10
  /**
9
- * Reports the build's tokamak configuration and development server address to
10
- * `tok`, and makes the entry Worker import the configuration file. Without
11
- * `TOKAMAK_VITE_OUTPUT`, which `tok` sets, it adds no hooks.
11
+ * Reports the build's tokamak configuration, and the development server's
12
+ * address and Worker name, to `tok`, and makes the entry Worker import the
13
+ * configuration file. Without `TOKAMAK_VITE_OUTPUT`, which `tok` sets, it adds
14
+ * no hooks.
12
15
  */
13
16
  export function tokamak() {
14
17
  const output = process.env.TOKAMAK_VITE_OUTPUT;
@@ -40,19 +43,27 @@ export function tokamak() {
40
43
  await write();
41
44
  }
42
45
  },
43
- configureServer(server) {
44
- server.httpServer?.on("listening", () => {
46
+ async configureServer(server) {
47
+ const httpServer = server.httpServer;
48
+ if (!httpServer) {
49
+ return;
50
+ }
51
+ const workerName = await readWorkerName(server.config.root);
52
+ httpServer.on("listening", () => {
45
53
  const urls = server.resolvedUrls;
46
- writeJson(output, "server.json", { url: urls?.local[0] ?? urls?.network[0] });
54
+ writeJson(output, "server.json", { url: urls?.local[0] ?? urls?.network[0], workerName });
47
55
  });
48
56
  },
57
+ async buildApp(builder) {
58
+ const environments = Object.values(builder.environments);
59
+ if (file && !environments.some((environment) => buildsEntryWorker(environment.config))) {
60
+ throw new Error(`no environment builds the entry Worker to import ${file} into`);
61
+ }
62
+ },
49
63
  },
50
64
  {
51
65
  name: "tokamak:entry",
52
- // Server environments with a manifest are built from the entry Worker:
53
- // Cloudflare's plugin gives one to the entry and prerender Workers, and
54
- // Astro to its server and prerender environments.
55
- applyToEnvironment: ({ config }) => file !== undefined && config.consumer === "server" && Boolean(config.build.manifest),
66
+ applyToEnvironment: ({ config }) => file !== undefined && buildsEntryWorker(config),
56
67
  async transform(code, id) {
57
68
  if (id === file) {
58
69
  return withoutConfig(this, code);
@@ -105,14 +116,38 @@ async function writeConfig(output, file, config) {
105
116
  writeJson(output, "config.json", { file, config: module.config ?? {} });
106
117
  return [file, ...dependencies.map(normalizePath)];
107
118
  }
119
+ /**
120
+ * The name of the Worker in the Wrangler configuration file in `root`, found
121
+ * as Cloudflare's plugin finds it without `configPath`, without the suffix of
122
+ * the `CLOUDFLARE_ENV` environment.
123
+ */
124
+ async function readWorkerName(root) {
125
+ const file = WRANGLER_FILES.map((name) => path.join(root, name)).find((candidate) => fs.existsSync(candidate));
126
+ if (!file) {
127
+ return undefined;
128
+ }
129
+ const { unstable_readConfig } = await import("wrangler");
130
+ const worker = unstable_readConfig({ config: file, env: process.env.CLOUDFLARE_ENV }, { hideWarnings: true });
131
+ return worker.topLevelName ?? worker.name;
132
+ }
133
+ /**
134
+ * Whether an environment builds from the entry Worker: Cloudflare's plugin
135
+ * gives a manifest to its entry and prerender Workers, and Astro to its server
136
+ * and prerender environments.
137
+ */
138
+ function buildsEntryWorker(config) {
139
+ return config.consumer === "server" && Boolean(config.build.manifest);
140
+ }
108
141
  /** The modules an environment's build starts from. */
109
142
  function inputs(build) {
110
143
  const { input } = build.rollupOptions;
111
144
  return typeof input === "string" ? [input] : Object.values(input ?? {});
112
145
  }
113
146
  /**
114
- * `code` without its `export const config = ...` statement, which is blanked
115
- * so that every other position, and so the source map, is unchanged.
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.
116
151
  */
117
152
  function withoutConfig(context, code) {
118
153
  const statements = context.parse(code).body;
@@ -120,11 +155,25 @@ function withoutConfig(context, code) {
120
155
  if (!statement) {
121
156
  return;
122
157
  }
123
- if (statement.declaration?.declarations?.length !== 1) {
124
- context.error("declare config in its own `export const config = ...` statement");
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;
125
175
  }
126
- const blank = code.slice(statement.start, statement.end).replace(/[^\n]/g, " ");
127
- return { code: code.slice(0, statement.start) + blank + code.slice(statement.end), map: null };
176
+ return Object.values(node).some((child) => mentions(child, name));
128
177
  }
129
178
  function exportsConfig(statement) {
130
179
  if (statement.type !== "ExportNamedDeclaration") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokamakdev/tok",
3
- "version": "0.1.1-beta.65",
3
+ "version": "0.1.1-beta.70",
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",
@@ -36,31 +36,36 @@
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@cloudflare/vite-plugin": "^1.54.0",
39
- "vite": "^7.0.0 || ^8.0.0"
39
+ "vite": "^7.0.0 || ^8.0.0",
40
+ "wrangler": "^4.126.0"
40
41
  },
41
42
  "peerDependenciesMeta": {
42
43
  "@cloudflare/vite-plugin": {
43
44
  "optional": true
45
+ },
46
+ "wrangler": {
47
+ "optional": true
44
48
  }
45
49
  },
46
50
  "devDependencies": {
47
51
  "@cloudflare/vite-plugin": "1.62.5",
48
52
  "@types/node": "22.19.15",
49
53
  "typescript": "5.9.3",
50
- "vite": "8.3.2"
54
+ "vite": "8.3.2",
55
+ "wrangler": "4.147.0"
51
56
  },
52
57
  "optionalDependencies": {
53
- "@tokamakdev/platform-android-arm64": "0.1.1-beta.65",
54
- "@tokamakdev/platform-ios-arm64": "0.1.1-beta.65",
55
- "@tokamakdev/platform-ios-simulator-arm64": "0.1.1-beta.65",
56
- "@tokamakdev/platform-ios-simulator-x64": "0.1.1-beta.65",
57
- "@tokamakdev/platform-macos-arm64": "0.1.1-beta.65",
58
- "@tokamakdev/platform-macos-x64": "0.1.1-beta.65",
59
- "@tokamakdev/platform-windows-x64": "0.1.1-beta.65",
60
- "@tokamakdev/tok-darwin-arm64": "0.1.1-beta.65",
61
- "@tokamakdev/tok-darwin-x64": "0.1.1-beta.65",
62
- "@tokamakdev/tok-linux-x64": "0.1.1-beta.65",
63
- "@tokamakdev/tok-win32-x64": "0.1.1-beta.65"
58
+ "@tokamakdev/platform-android-arm64": "0.1.1-beta.70",
59
+ "@tokamakdev/platform-ios-arm64": "0.1.1-beta.70",
60
+ "@tokamakdev/platform-ios-simulator-arm64": "0.1.1-beta.70",
61
+ "@tokamakdev/platform-ios-simulator-x64": "0.1.1-beta.70",
62
+ "@tokamakdev/platform-macos-arm64": "0.1.1-beta.70",
63
+ "@tokamakdev/platform-macos-x64": "0.1.1-beta.70",
64
+ "@tokamakdev/platform-windows-x64": "0.1.1-beta.70",
65
+ "@tokamakdev/tok-darwin-arm64": "0.1.1-beta.70",
66
+ "@tokamakdev/tok-darwin-x64": "0.1.1-beta.70",
67
+ "@tokamakdev/tok-linux-x64": "0.1.1-beta.70",
68
+ "@tokamakdev/tok-win32-x64": "0.1.1-beta.70"
64
69
  },
65
70
  "publishConfig": {
66
71
  "access": "public"