@swiftbrowser/cli 0.1.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 (45) hide show
  1. package/README.md +166 -0
  2. package/bin/swiftbrowser.js +11 -0
  3. package/dist/build.d.ts +36 -0
  4. package/dist/build.js +124 -0
  5. package/dist/build.js.map +1 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.js +137 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/commands/build.d.ts +8 -0
  10. package/dist/commands/build.js +33 -0
  11. package/dist/commands/build.js.map +1 -0
  12. package/dist/commands/check.d.ts +4 -0
  13. package/dist/commands/check.js +27 -0
  14. package/dist/commands/check.js.map +1 -0
  15. package/dist/commands/dev.d.ts +19 -0
  16. package/dist/commands/dev.js +83 -0
  17. package/dist/commands/dev.js.map +1 -0
  18. package/dist/commands/doctor.d.ts +12 -0
  19. package/dist/commands/doctor.js +66 -0
  20. package/dist/commands/doctor.js.map +1 -0
  21. package/dist/commands/shared.d.ts +23 -0
  22. package/dist/commands/shared.js +73 -0
  23. package/dist/commands/shared.js.map +1 -0
  24. package/dist/compat.d.ts +27 -0
  25. package/dist/compat.js +111 -0
  26. package/dist/compat.js.map +1 -0
  27. package/dist/config.d.ts +45 -0
  28. package/dist/config.js +70 -0
  29. package/dist/config.js.map +1 -0
  30. package/dist/icu.d.ts +94 -0
  31. package/dist/icu.js +368 -0
  32. package/dist/icu.js.map +1 -0
  33. package/dist/log.d.ts +16 -0
  34. package/dist/log.js +28 -0
  35. package/dist/log.js.map +1 -0
  36. package/dist/project.d.ts +56 -0
  37. package/dist/project.js +264 -0
  38. package/dist/project.js.map +1 -0
  39. package/dist/stage.d.ts +78 -0
  40. package/dist/stage.js +344 -0
  41. package/dist/stage.js.map +1 -0
  42. package/dist/toolchain.d.ts +42 -0
  43. package/dist/toolchain.js +159 -0
  44. package/dist/toolchain.js.map +1 -0
  45. package/package.json +37 -0
package/dist/stage.js ADDED
@@ -0,0 +1,344 @@
1
+ // The staging package: a SwiftPM package under `<project>/.swiftbrowser/<App>/`
2
+ // whose one executable target is a copy of the app's sources, adjusted for
3
+ // the shim, depending on the SwiftBrowser package by path. The user's project
4
+ // is never written to outside that folder.
5
+ import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs';
6
+ import path from 'node:path';
7
+ import { ICU_TARGET, icuAssembly } from './icu.js';
8
+ /** Where an app's staging package lives. */
9
+ export function stagingDir(app) {
10
+ return path.join(app.root, '.swiftbrowser', app.name);
11
+ }
12
+ /** The built module, optimized or not. */
13
+ export function wasmOutput(app) {
14
+ return path.join(stagingDir(app), `${app.name}.wasm`);
15
+ }
16
+ /**
17
+ * Adjusts one source for the shim without moving any line, so compiler
18
+ * diagnostics keep their line numbers:
19
+ * - `import SwiftUI` also imports the Foundation modules (lean: FoundationEssentials
20
+ * + FoundationLite; full: Foundation + FoundationBridge), as Apple's SwiftUI
21
+ * re-exports Foundation;
22
+ * - lean: `import Foundation` → `import FoundationEssentials; import FoundationLite`,
23
+ * which is what the SwiftBrowser examples import by hand; in both modes the
24
+ * line also imports Observation (Apple's Foundation re-exports it, so
25
+ * `@Observable` works in a file that imports Foundation alone);
26
+ * - full: `import FoundationLite` → `import FoundationBridge` (the examples'
27
+ * `#if canImport(FoundationEssentials)` branch, against the real Foundation);
28
+ * - `#Preview { … }` blocks (and `#Preview("name", traits: …) { … }`) become
29
+ * blank lines: the shim has no preview macro and previews are not part of
30
+ * the app.
31
+ */
32
+ export function transformSource(text, options) {
33
+ let foundationRewrites = 0;
34
+ let out = text;
35
+ // On Apple platforms `import SwiftUI` re-exports Foundation (UUID, JSON,
36
+ // Date, UserDefaults are in scope without an import); the shim's SwiftUI
37
+ // does not, so the same modules are imported next to it.
38
+ const companions = options.foundation === 'lean' ? 'import FoundationEssentials; import FoundationLite; import Observation' : 'import Foundation; import FoundationBridge; import Observation';
39
+ out = out.replace(/^([ \t]*)import SwiftUI[ \t]*(\r?)$/gm, (_, indent, cr) => `${indent}import SwiftUI; ${companions}${cr}`);
40
+ if (options.foundation === 'lean') {
41
+ out = out.replace(/^([ \t]*)import Foundation[ \t]*(\r?)$/gm, (_, indent, cr) => {
42
+ foundationRewrites += 1;
43
+ return `${indent}import FoundationEssentials; import FoundationLite; import Observation${cr}`;
44
+ });
45
+ }
46
+ else {
47
+ out = out.replace(/^([ \t]*)import Foundation[ \t]*(\r?)$/gm, (_, indent, cr) => `${indent}import Foundation; import Observation${cr}`);
48
+ out = out.replace(/^([ \t]*)import FoundationLite[ \t]*(\r?)$/gm, (_, indent, cr) => {
49
+ foundationRewrites += 1;
50
+ return `${indent}import FoundationBridge${cr}`;
51
+ });
52
+ }
53
+ const stripped = stripPreviews(out);
54
+ return { text: stripped.text, previewsStripped: stripped.count, foundationRewrites };
55
+ }
56
+ /** Replaces every `#Preview …{ … }` block with blank lines of the same count. */
57
+ export function stripPreviews(text) {
58
+ let count = 0;
59
+ let result = '';
60
+ let index = 0;
61
+ const pattern = /^[ \t]*#Preview\b/gm;
62
+ for (;;) {
63
+ pattern.lastIndex = index;
64
+ const match = pattern.exec(text);
65
+ if (!match)
66
+ break;
67
+ const start = match.index;
68
+ const open = text.indexOf('{', start);
69
+ if (open < 0)
70
+ break;
71
+ const close = matchingBrace(text, open);
72
+ if (close < 0)
73
+ break;
74
+ // Consume the rest of the line after the closing brace (usually nothing).
75
+ let end = close + 1;
76
+ while (end < text.length && (text[end] === ' ' || text[end] === '\t'))
77
+ end += 1;
78
+ result += text.slice(index, start);
79
+ const removed = text.slice(start, end);
80
+ result += removed.replace(/[^\n]/g, '');
81
+ count += 1;
82
+ index = end;
83
+ }
84
+ result += text.slice(index);
85
+ return { text: result, count };
86
+ }
87
+ /** Index of the `}` closing the `{` at `open`, skipping strings and comments; -1 when unbalanced. */
88
+ export function matchingBrace(text, open) {
89
+ let depth = 0;
90
+ let i = open;
91
+ while (i < text.length) {
92
+ const ch = text[i];
93
+ const next = text[i + 1];
94
+ if (ch === '/' && next === '/') {
95
+ i = text.indexOf('\n', i);
96
+ if (i < 0)
97
+ return -1;
98
+ continue;
99
+ }
100
+ if (ch === '/' && next === '*') {
101
+ const end = text.indexOf('*/', i + 2);
102
+ if (end < 0)
103
+ return -1;
104
+ i = end + 2;
105
+ continue;
106
+ }
107
+ if (ch === '"') {
108
+ i = skipString(text, i);
109
+ if (i < 0)
110
+ return -1;
111
+ continue;
112
+ }
113
+ if (ch === '{')
114
+ depth += 1;
115
+ if (ch === '}') {
116
+ depth -= 1;
117
+ if (depth === 0)
118
+ return i;
119
+ }
120
+ i += 1;
121
+ }
122
+ return -1;
123
+ }
124
+ /** Index just past a string literal starting at `start` (`"…"`, `"""…"""`, raw `#"…"#`), interpolations included; -1 when unterminated. */
125
+ function skipString(text, start) {
126
+ const triple = text.startsWith('"""', start);
127
+ const quote = triple ? '"""' : '"';
128
+ let i = start + quote.length;
129
+ while (i < text.length) {
130
+ if (text[i] === '\\') {
131
+ if (text[i + 1] === '(') {
132
+ // Interpolation: skip to its matching parenthesis.
133
+ let depth = 0;
134
+ let j = i + 1;
135
+ while (j < text.length) {
136
+ const c = text[j];
137
+ if (c === '"') {
138
+ j = skipString(text, j);
139
+ if (j < 0)
140
+ return -1;
141
+ continue;
142
+ }
143
+ if (c === '(')
144
+ depth += 1;
145
+ if (c === ')') {
146
+ depth -= 1;
147
+ if (depth === 0)
148
+ break;
149
+ }
150
+ j += 1;
151
+ }
152
+ i = j + 1;
153
+ continue;
154
+ }
155
+ i += 2;
156
+ continue;
157
+ }
158
+ if (text.startsWith(quote, i))
159
+ return i + quote.length;
160
+ i += 1;
161
+ }
162
+ return -1;
163
+ }
164
+ /** The Package.swift of the staging package. */
165
+ export function packageManifest(app, swiftPackagePath) {
166
+ const languageMode = app.swiftLanguageMode === '6' ? '.v6' : '.v5';
167
+ const defines = ['SWIFTBROWSER', ...app.defines].map((d) => `.define(${JSON.stringify(d)})`).join(', ');
168
+ const products = app.foundation === 'lean' ? ['SwiftUI', 'Charts', 'FoundationLite'] : ['SwiftUI', 'Charts', 'FoundationBridge'];
169
+ const deps = [
170
+ ...products.map((p) => `.product(name: ${JSON.stringify(p)}, package: "SwiftBrowser")`),
171
+ ...(app.foundation === 'full' ? [JSON.stringify(ICU_TARGET)] : []),
172
+ ].join(',\n ');
173
+ // Locale.current follows the host's choice (SB_LOCALE): the two functions
174
+ // that hard-code en_001 in swift-foundation are redirected to FoundationBridge.
175
+ const localeWrap = app.foundation === 'full'
176
+ ? `
177
+ // Full Foundation only: route swift-foundation's hard-coded current locale
178
+ // (and preferred languages) to FoundationBridge/Locale.swift.
179
+ + ["-Xlinker", "--wrap=$s20FoundationEssentials11LocaleCacheV11preferencesAA0C11PreferencesV_SbtyF",
180
+ "-Xlinker", "--wrap=$s20FoundationEssentials6LocaleV18preferredLanguagesSaySSGvgZ"]`
181
+ : '';
182
+ const icuTarget = app.foundation === 'full'
183
+ ? `
184
+ // Foundation's ICU reads its locale data from a symbol this target
185
+ // defines, trimmed to the app's languages, ahead of the SDK's 34 MB
186
+ // original (see @swiftbrowser/cli src/icu.ts).
187
+ .target(name: ${JSON.stringify(ICU_TARGET)}, path: ${JSON.stringify(ICU_TARGET)}),`
188
+ : '';
189
+ return `// swift-tools-version: 6.0
190
+ // Generated by @swiftbrowser/cli for ${app.displayName}. Do not edit: it is
191
+ // rewritten on every build. Sources/ holds the app's sources, adjusted for
192
+ // the shim (see stage.ts); the SwiftBrowser package is referenced by path.
193
+ import PackageDescription
194
+
195
+ // C-ABI entry points the browser renderer calls; the linker must keep them.
196
+ let wasmExports = ["sb_event", "sb_ops_ptr", "sb_ops_len", "sb_ops_clear",
197
+ "sb_alloc", "sb_event_json", "sb_state_ptr", "sb_state_len", "sb_run_jobs"]
198
+ .flatMap { ["-Xlinker", "--export=\\($0)"] }
199
+ // The reconciler recurses once per view; 8 MB of stack like a native thread.
200
+ + ["-Xlinker", "-z", "-Xlinker", "stack-size=8388608"]${localeWrap}
201
+
202
+ let package = Package(
203
+ name: ${JSON.stringify(app.name)},
204
+ platforms: [.macOS(.v14)],
205
+ products: [.executable(name: ${JSON.stringify(app.name)}, targets: [${JSON.stringify(app.name)}])],
206
+ dependencies: [.package(name: "SwiftBrowser", path: ${JSON.stringify(swiftPackagePath)})],
207
+ targets: [
208
+ .executableTarget(
209
+ name: ${JSON.stringify(app.name)},
210
+ dependencies: [
211
+ ${deps}
212
+ ],
213
+ path: "Sources",
214
+ swiftSettings: [${defines}, .swiftLanguageMode(${languageMode})],
215
+ linkerSettings: [.unsafeFlags(wasmExports, .when(platforms: [.wasi]))]
216
+ ),${icuTarget}
217
+ ]
218
+ )
219
+ `;
220
+ }
221
+ /** The staged file that settles names declared by both the shim and Foundation. */
222
+ export const FULL_FOUNDATION_FILE = '_SwiftBrowserFoundation.swift';
223
+ /**
224
+ * In full mode the app imports both the shim and the real Foundation, and
225
+ * both declare a few names (the shim cannot import Foundation itself, which
226
+ * would link it into every lean app; and a module does not shadow another's
227
+ * declarations, only the current module's do). A typealias in the app module
228
+ * does: these point the shared names at the shim's types (what its
229
+ * `frame(width:)` and friends take) and at FoundationBridge's `Timer` and
230
+ * `RunLoop`, which Foundation lacks on WASI (`RunLoop` is marked unavailable,
231
+ * its `Timer` needs CFRunLoop and does not link).
232
+ */
233
+ export function fullFoundationSource() {
234
+ return `// Generated by @swiftbrowser/cli; rewritten on every build.
235
+ // The shim and Foundation both declare these names. A typealias in the app
236
+ // module settles each in the shim's favor (SwiftUI's geometry) or on the
237
+ // bridge (Timer and RunLoop, which the SDK's Foundation does not have on WASI).
238
+ import SwiftUI
239
+ import Foundation
240
+ import FoundationBridge
241
+
242
+ // Public, so the app's own public API may use the names (a public method of
243
+ // a Layout returning CGSize, for one).
244
+ public typealias CGFloat = SwiftUI.CGFloat
245
+ public typealias CGPoint = SwiftUI.CGPoint
246
+ public typealias CGSize = SwiftUI.CGSize
247
+ public typealias CGRect = SwiftUI.CGRect
248
+ public typealias Timer = FoundationBridge.Timer
249
+ public typealias RunLoop = FoundationBridge.RunLoop
250
+ // UserDefaults persists through the browser; Bundle reads the app's resources.
251
+ // Foundation's own cannot persist on WASI, and its Bundle.main traps.
252
+ public typealias UserDefaults = FoundationBridge.UserDefaults
253
+ public typealias Bundle = FoundationBridge.Bundle
254
+ `;
255
+ }
256
+ /** The directory the staged sources keep their layout relative to. */
257
+ export function commonSourceBase(app) {
258
+ let base = path.dirname(app.sources[0]);
259
+ for (const file of app.sources) {
260
+ while (!file.startsWith(`${base}${path.sep}`) && base !== path.dirname(base))
261
+ base = path.dirname(base);
262
+ }
263
+ return base;
264
+ }
265
+ function writeIfChanged(file, content) {
266
+ if (existsSync(file) && readFileSync(file, 'utf8') === content)
267
+ return false;
268
+ mkdirSync(path.dirname(file), { recursive: true });
269
+ writeFileSync(file, content);
270
+ return true;
271
+ }
272
+ function listFiles(dir, out = []) {
273
+ if (!existsSync(dir))
274
+ return out;
275
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
276
+ const full = path.join(dir, entry.name);
277
+ if (entry.isDirectory())
278
+ listFiles(full, out);
279
+ else
280
+ out.push(full);
281
+ }
282
+ return out;
283
+ }
284
+ /**
285
+ * Writes (or refreshes) the staging package. Files are written only when
286
+ * their content changed, so SwiftPM's incremental build stays incremental;
287
+ * staged files whose source is gone are removed.
288
+ */
289
+ export function stage(app, swiftPackagePath, options = {}) {
290
+ const dir = stagingDir(app);
291
+ const sourcesDir = path.join(dir, 'Sources');
292
+ mkdirSync(sourcesDir, { recursive: true });
293
+ writeIfChanged(path.join(dir, 'Package.swift'), packageManifest(app, swiftPackagePath));
294
+ const icuDir = path.join(dir, ICU_TARGET);
295
+ if (app.foundation === 'full') {
296
+ writeIfChanged(path.join(icuDir, 'icudt.S'), icuAssembly(options.icu ?? null));
297
+ // SwiftPM insists on a public headers directory for a C target.
298
+ writeIfChanged(path.join(icuDir, 'include', `${ICU_TARGET}.h`), '// Nothing to include: the target holds data only.\n');
299
+ }
300
+ else {
301
+ rmSync(icuDir, { recursive: true, force: true });
302
+ }
303
+ const base = commonSourceBase(app);
304
+ const originals = new Map();
305
+ const keep = new Set();
306
+ let previewsStripped = 0;
307
+ for (const file of app.sources) {
308
+ const relative = path.relative(base, file);
309
+ const staged = path.join(sourcesDir, relative);
310
+ const transformed = transformSource(readFileSync(file, 'utf8'), { foundation: app.foundation });
311
+ previewsStripped += transformed.previewsStripped;
312
+ writeIfChanged(staged, transformed.text);
313
+ originals.set(staged, file);
314
+ keep.add(staged);
315
+ }
316
+ if (app.foundation === 'full') {
317
+ const generated = path.join(sourcesDir, FULL_FOUNDATION_FILE);
318
+ writeIfChanged(generated, fullFoundationSource());
319
+ keep.add(generated);
320
+ }
321
+ for (const stale of listFiles(sourcesDir)) {
322
+ if (!keep.has(stale))
323
+ rmSync(stale, { force: true });
324
+ }
325
+ // Drop directories left empty by removals.
326
+ pruneEmptyDirs(sourcesDir, sourcesDir);
327
+ return { dir, originals, previewsStripped };
328
+ }
329
+ function pruneEmptyDirs(dir, root) {
330
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
331
+ if (entry.isDirectory())
332
+ pruneEmptyDirs(path.join(dir, entry.name), root);
333
+ }
334
+ if (dir !== root && readdirSync(dir).length === 0 && statSync(dir).isDirectory())
335
+ rmSync(dir, { recursive: true });
336
+ }
337
+ /** Rewrites staged paths in compiler output back to the user's files. */
338
+ export function remapDiagnostics(output, staged) {
339
+ let result = output;
340
+ for (const [stagedPath, original] of staged.originals)
341
+ result = result.split(stagedPath).join(original);
342
+ return result;
343
+ }
344
+ //# sourceMappingURL=stage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stage.js","sourceRoot":"","sources":["../src/stage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /** The Swift release the shim is built and tested with; the wasm SDK must match it. */
2
+ export declare const SWIFT_VERSION = "6.4.0";
3
+ export declare const WASM_SDK = "swift-6.4.0-RELEASE_wasm";
4
+ export declare const WASM_SDK_URL = "https://download.swift.org/swift-6.4.0-release/wasm-sdk/swift-6.4.0-RELEASE/swift-6.4.0-RELEASE_wasm.artifactbundle.tar.gz";
5
+ export declare const WASM_SDK_CHECKSUM = "f07b7be3c586d92d7a07051fc6d303b87ebea67eadc40640ba59d5a8b79aa86d";
6
+ export declare const BINARYEN_VERSION = "version_123";
7
+ export interface Toolchain {
8
+ /** Path of the `swift` executable. */
9
+ swift: string;
10
+ /** Its `usr/bin` directory, prepended to PATH for child processes. */
11
+ bin: string;
12
+ /** `Swift version X.Y.Z` as reported by `swift --version`. */
13
+ version: string;
14
+ }
15
+ /** The CLI's cache (binaryen lives here). `$SWIFTBROWSER_CACHE` overrides. */
16
+ export declare function cacheDir(): string;
17
+ export declare function swiftVersionOf(swift: string): string | null;
18
+ /** True when `version` is the required release (patch digits may be omitted by the toolchain). */
19
+ export declare function isRequiredVersion(version: string): boolean;
20
+ /** Candidate `swift` executables, most specific first. */
21
+ export declare function swiftCandidates(env?: NodeJS.ProcessEnv): string[];
22
+ /** The first candidate that runs and reports the required version, else the first that runs at all (for diagnostics), else null. */
23
+ export declare function findToolchain(env?: NodeJS.ProcessEnv): {
24
+ toolchain: Toolchain | null;
25
+ fallback: Toolchain | null;
26
+ };
27
+ /** Environment for `swift` child processes: the toolchain first on PATH. */
28
+ export declare function toolchainEnv(toolchain: Toolchain, env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
29
+ /** Whether `swift sdk list` names the wasm SDK. */
30
+ export declare function hasWasmSdk(toolchain: Toolchain): boolean;
31
+ /** Installs the wasm SDK with `swift sdk install`; returns the command output. */
32
+ export declare function installWasmSdk(toolchain: Toolchain): {
33
+ ok: boolean;
34
+ output: string;
35
+ };
36
+ export declare function wasmOptVersionOf(wasmOpt: string): string | null;
37
+ /** The cached binaryen directory for the pinned version. */
38
+ export declare function binaryenDir(): string;
39
+ /** `$BINARYEN_BIN/wasm-opt`, the cached install, or one on PATH. */
40
+ export declare function findWasmOpt(env?: NodeJS.ProcessEnv): string | null;
41
+ /** Downloads the pinned binaryen release into the cache and returns the wasm-opt path. */
42
+ export declare function installBinaryen(): Promise<string>;
@@ -0,0 +1,159 @@
1
+ // Finding (and installing) what a build needs: a Swift toolchain of the
2
+ // release SwiftBrowser is built with, its Swift SDK for WebAssembly, and
3
+ // Binaryen's wasm-opt for optimized `build`s.
4
+ import { spawnSync } from 'node:child_process';
5
+ import { createHash } from 'node:crypto';
6
+ import { existsSync, mkdirSync, readdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';
7
+ import { homedir, tmpdir } from 'node:os';
8
+ import path from 'node:path';
9
+ /** The Swift release the shim is built and tested with; the wasm SDK must match it. */
10
+ export const SWIFT_VERSION = '6.4.0';
11
+ export const WASM_SDK = `swift-${SWIFT_VERSION}-RELEASE_wasm`;
12
+ export const WASM_SDK_URL = `https://download.swift.org/swift-${SWIFT_VERSION}-release/wasm-sdk/swift-${SWIFT_VERSION}-RELEASE/${WASM_SDK}.artifactbundle.tar.gz`;
13
+ export const WASM_SDK_CHECKSUM = 'f07b7be3c586d92d7a07051fc6d303b87ebea67eadc40640ba59d5a8b79aa86d';
14
+ export const BINARYEN_VERSION = 'version_123';
15
+ /** Pinned release tarballs, by `${process.platform}-${process.arch}`. */
16
+ const BINARYEN_BUILDS = {
17
+ 'linux-x64': { platform: 'x86_64-linux', sha256: 'e959f2170af4c20c552e9de3a0253704d6a9d2766e8fdb88e4d6ac4bae9388fe' },
18
+ 'linux-arm64': { platform: 'aarch64-linux', sha256: '4b6bd61ba6cd3b18c993b4657d93426c782f9b91b74be0d38018cd8be1319376' },
19
+ 'darwin-arm64': { platform: 'arm64-macos', sha256: '74428be348c1a09863e7b642a1fa948cabf8ec9561052233d8288e941951725b' },
20
+ 'darwin-x64': { platform: 'x86_64-macos', sha256: 'cc18b14d2b673d9c66bf54f31ff2b0ceb23ba5132455b893965ae2792f9e00dd' },
21
+ };
22
+ /** The CLI's cache (binaryen lives here). `$SWIFTBROWSER_CACHE` overrides. */
23
+ export function cacheDir() {
24
+ return process.env['SWIFTBROWSER_CACHE'] ?? path.join(process.env['XDG_CACHE_HOME'] ?? path.join(homedir(), '.cache'), 'swiftbrowser');
25
+ }
26
+ export function swiftVersionOf(swift) {
27
+ const result = spawnSync(swift, ['--version'], { encoding: 'utf8' });
28
+ if (result.status !== 0)
29
+ return null;
30
+ const match = /Swift version (\d+\.\d+(?:\.\d+)?)/.exec(`${result.stdout}\n${result.stderr}`);
31
+ return match?.[1] ?? null;
32
+ }
33
+ function versionTuple(version) {
34
+ return version.split('.').map((n) => Number(n) || 0);
35
+ }
36
+ /** True when `version` is the required release (patch digits may be omitted by the toolchain). */
37
+ export function isRequiredVersion(version) {
38
+ const [major, minor] = versionTuple(version);
39
+ const [wantMajor, wantMinor] = versionTuple(SWIFT_VERSION);
40
+ return major === wantMajor && minor === wantMinor;
41
+ }
42
+ /** Candidate `swift` executables, most specific first. */
43
+ export function swiftCandidates(env = process.env) {
44
+ const out = [];
45
+ if (env['SWIFT_TOOLCHAIN_BIN'])
46
+ out.push(path.join(env['SWIFT_TOOLCHAIN_BIN'], 'swift'));
47
+ const swiftly = path.join(env['SWIFTLY_HOME_DIR'] ?? path.join(homedir(), '.local', 'share', 'swiftly'), 'toolchains');
48
+ if (existsSync(swiftly)) {
49
+ for (const name of readdirSync(swiftly).sort().reverse()) {
50
+ if (name.startsWith(SWIFT_VERSION.split('.').slice(0, 2).join('.')))
51
+ out.push(path.join(swiftly, name, 'usr', 'bin', 'swift'));
52
+ }
53
+ }
54
+ // macOS toolchains installed from swift.org.
55
+ const library = '/Library/Developer/Toolchains';
56
+ if (existsSync(library)) {
57
+ for (const name of readdirSync(library).sort().reverse()) {
58
+ if (name.includes(SWIFT_VERSION))
59
+ out.push(path.join(library, name, 'usr', 'bin', 'swift'));
60
+ }
61
+ }
62
+ for (const dir of (env['PATH'] ?? '').split(path.delimiter)) {
63
+ if (dir)
64
+ out.push(path.join(dir, 'swift'));
65
+ }
66
+ return out;
67
+ }
68
+ /** The first candidate that runs and reports the required version, else the first that runs at all (for diagnostics), else null. */
69
+ export function findToolchain(env = process.env) {
70
+ let fallback = null;
71
+ const seen = new Set();
72
+ for (const swift of swiftCandidates(env)) {
73
+ if (seen.has(swift) || !existsSync(swift))
74
+ continue;
75
+ seen.add(swift);
76
+ const version = swiftVersionOf(swift);
77
+ if (!version)
78
+ continue;
79
+ const toolchain = { swift, bin: path.dirname(swift), version };
80
+ if (isRequiredVersion(version))
81
+ return { toolchain, fallback };
82
+ fallback ??= toolchain;
83
+ }
84
+ return { toolchain: null, fallback };
85
+ }
86
+ /** Environment for `swift` child processes: the toolchain first on PATH. */
87
+ export function toolchainEnv(toolchain, env = process.env) {
88
+ return { ...env, PATH: `${toolchain.bin}${path.delimiter}${env['PATH'] ?? ''}` };
89
+ }
90
+ /** Whether `swift sdk list` names the wasm SDK. */
91
+ export function hasWasmSdk(toolchain) {
92
+ const result = spawnSync(toolchain.swift, ['sdk', 'list'], { encoding: 'utf8', env: toolchainEnv(toolchain) });
93
+ return result.status === 0 && result.stdout.split('\n').some((line) => line.trim() === WASM_SDK);
94
+ }
95
+ /** Installs the wasm SDK with `swift sdk install`; returns the command output. */
96
+ export function installWasmSdk(toolchain) {
97
+ const result = spawnSync(toolchain.swift, ['sdk', 'install', WASM_SDK_URL, '--checksum', WASM_SDK_CHECKSUM], {
98
+ encoding: 'utf8',
99
+ env: toolchainEnv(toolchain),
100
+ stdio: ['ignore', 'pipe', 'pipe'],
101
+ });
102
+ return { ok: result.status === 0, output: `${result.stdout}${result.stderr}` };
103
+ }
104
+ export function wasmOptVersionOf(wasmOpt) {
105
+ const result = spawnSync(wasmOpt, ['--version'], { encoding: 'utf8' });
106
+ if (result.status !== 0)
107
+ return null;
108
+ return result.stdout.trim() || null;
109
+ }
110
+ /** The cached binaryen directory for the pinned version. */
111
+ export function binaryenDir() {
112
+ return path.join(cacheDir(), `binaryen-${BINARYEN_VERSION}`);
113
+ }
114
+ /** `$BINARYEN_BIN/wasm-opt`, the cached install, or one on PATH. */
115
+ export function findWasmOpt(env = process.env) {
116
+ const candidates = [];
117
+ if (env['BINARYEN_BIN'])
118
+ candidates.push(path.join(env['BINARYEN_BIN'], 'wasm-opt'));
119
+ candidates.push(path.join(binaryenDir(), 'bin', 'wasm-opt'));
120
+ for (const dir of (env['PATH'] ?? '').split(path.delimiter))
121
+ if (dir)
122
+ candidates.push(path.join(dir, 'wasm-opt'));
123
+ for (const candidate of candidates) {
124
+ if (existsSync(candidate) && wasmOptVersionOf(candidate))
125
+ return candidate;
126
+ }
127
+ return null;
128
+ }
129
+ /** Downloads the pinned binaryen release into the cache and returns the wasm-opt path. */
130
+ export async function installBinaryen() {
131
+ const key = `${process.platform}-${process.arch}`;
132
+ const build = BINARYEN_BUILDS[key];
133
+ if (!build) {
134
+ throw new Error(`no pinned binaryen build for ${key}; install wasm-opt yourself (https://github.com/WebAssembly/binaryen/releases) and set BINARYEN_BIN`);
135
+ }
136
+ const url = `https://github.com/WebAssembly/binaryen/releases/download/${BINARYEN_VERSION}/binaryen-${BINARYEN_VERSION}-${build.platform}.tar.gz`;
137
+ const response = await fetch(url);
138
+ if (!response.ok)
139
+ throw new Error(`downloading ${url}: HTTP ${response.status}`);
140
+ const bytes = Buffer.from(await response.arrayBuffer());
141
+ const digest = createHash('sha256').update(bytes).digest('hex');
142
+ if (digest !== build.sha256)
143
+ throw new Error(`binaryen download checksum mismatch: ${digest} (expected ${build.sha256})`);
144
+ const scratch = path.join(tmpdir(), `swiftbrowser-binaryen-${process.pid}`);
145
+ rmSync(scratch, { recursive: true, force: true });
146
+ mkdirSync(scratch, { recursive: true });
147
+ const tarball = path.join(scratch, 'binaryen.tar.gz');
148
+ writeFileSync(tarball, bytes);
149
+ const tar = spawnSync('tar', ['xzf', tarball, '-C', scratch], { encoding: 'utf8' });
150
+ if (tar.status !== 0)
151
+ throw new Error(`extracting binaryen: ${tar.stderr}`);
152
+ const dest = binaryenDir();
153
+ mkdirSync(path.dirname(dest), { recursive: true });
154
+ rmSync(dest, { recursive: true, force: true });
155
+ renameSync(path.join(scratch, `binaryen-${BINARYEN_VERSION}`), dest);
156
+ rmSync(scratch, { recursive: true, force: true });
157
+ return path.join(dest, 'bin', 'wasm-opt');
158
+ }
159
+ //# sourceMappingURL=toolchain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolchain.js","sourceRoot":"","sources":["../src/toolchain.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@swiftbrowser/cli",
3
+ "version": "0.1.0",
4
+ "description": "Run an iOS SwiftUI app in the browser: doctor, check, dev and build for an Xcode project or a folder of Swift sources.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/dabbott/SwiftBrowser.git",
8
+ "directory": "packages/cli"
9
+ },
10
+ "type": "module",
11
+ "bin": {
12
+ "swiftbrowser": "bin/swiftbrowser.js"
13
+ },
14
+ "files": [
15
+ "bin",
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "typecheck": "tsc --noEmit -p tsconfig.json",
21
+ "test:unit": "vitest run",
22
+ "build": "tsc -p tsconfig.build.json"
23
+ },
24
+ "dependencies": {
25
+ "@swiftbrowser/web": "0.1.0",
26
+ "@swiftbrowser/xcodeproj": "0.1.0",
27
+ "@swiftbrowser/swift": "0.1.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^26.6.4",
31
+ "typescript": "^5.9.2",
32
+ "vitest": "^5.0.3"
33
+ },
34
+ "engines": {
35
+ "node": ">=22"
36
+ }
37
+ }