@swiftbrowser/cli 0.1.0 → 0.2.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/README.md +330 -64
- package/dist/assetSymbols.d.ts +25 -0
- package/dist/assetSymbols.js +218 -0
- package/dist/assetSymbols.js.map +1 -0
- package/dist/build.d.ts +17 -2
- package/dist/build.js +40 -13
- package/dist/build.js.map +1 -1
- package/dist/buildSettings.d.ts +15 -0
- package/dist/buildSettings.js +74 -0
- package/dist/buildSettings.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +60 -11
- package/dist/cli.js.map +1 -1
- package/dist/commands/build.js +6 -5
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/check.js +2 -2
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/dev.d.ts +5 -2
- package/dist/commands/dev.js +19 -13
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/init.d.ts +18 -0
- package/dist/commands/init.js +57 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/kit.d.ts +3 -0
- package/dist/commands/kit.js +21 -0
- package/dist/commands/kit.js.map +1 -0
- package/dist/commands/shared.d.ts +25 -4
- package/dist/commands/shared.js +104 -10
- package/dist/commands/shared.js.map +1 -1
- package/dist/compat.d.ts +44 -6
- package/dist/compat.js +64 -36
- package/dist/compat.js.map +1 -1
- package/dist/config.d.ts +48 -10
- package/dist/config.js +64 -8
- package/dist/config.js.map +1 -1
- package/dist/coreml.d.ts +194 -0
- package/dist/coreml.js +626 -0
- package/dist/coreml.js.map +1 -0
- package/dist/icu.d.ts +17 -4
- package/dist/icu.js +32 -18
- package/dist/icu.js.map +1 -1
- package/dist/kit.d.ts +133 -0
- package/dist/kit.js +403 -0
- package/dist/kit.js.map +1 -0
- package/dist/objc.d.ts +31 -0
- package/dist/objc.js +319 -0
- package/dist/objc.js.map +1 -0
- package/dist/packagePatches.d.ts +24 -0
- package/dist/packagePatches.js +107 -0
- package/dist/packagePatches.js.map +1 -0
- package/dist/packages.d.ts +59 -0
- package/dist/packages.js +149 -0
- package/dist/packages.js.map +1 -0
- package/dist/project.d.ts +45 -4
- package/dist/project.js +91 -18
- package/dist/project.js.map +1 -1
- package/dist/protobuf.d.ts +62 -0
- package/dist/protobuf.js +233 -0
- package/dist/protobuf.js.map +1 -0
- package/dist/stage.d.ts +155 -27
- package/dist/stage.js +483 -79
- package/dist/stage.js.map +1 -1
- package/dist/strings.d.ts +44 -0
- package/dist/strings.js +386 -0
- package/dist/strings.js.map +1 -0
- package/dist/template.d.ts +29 -0
- package/dist/template.js +438 -0
- package/dist/template.js.map +1 -0
- package/dist/threadStacks.d.ts +14 -0
- package/dist/threadStacks.js +78 -0
- package/dist/threadStacks.js.map +1 -0
- package/dist/toolchain.d.ts +7 -1
- package/dist/toolchain.js +8 -2
- package/dist/toolchain.js.map +1 -1
- package/dist/urlSchemes.d.ts +11 -0
- package/dist/urlSchemes.js +58 -0
- package/dist/urlSchemes.js.map +1 -0
- package/dist/vendor.d.ts +109 -0
- package/dist/vendor.js +440 -0
- package/dist/vendor.js.map +1 -0
- package/dist/wasm.d.ts +28 -0
- package/dist/wasm.js +84 -0
- package/dist/wasm.js.map +1 -0
- package/package.json +7 -6
package/dist/commands/shared.js
CHANGED
|
@@ -4,9 +4,12 @@ import path from 'node:path';
|
|
|
4
4
|
import { swiftPackagePath } from '@swiftbrowser/swift';
|
|
5
5
|
import { compatReport, rewrittenTo } from '../compat.js';
|
|
6
6
|
import { CliError, bad, bold, cyan, dim, info, ok, warn, yellow } from '../log.js';
|
|
7
|
+
import { packageDisplayName, packageModules, packageSource, planPackages } from '../packages.js';
|
|
8
|
+
import { ensureKit, kitEnabled, kitSwiftFlags } from '../kit.js';
|
|
7
9
|
import { resolveApp } from '../project.js';
|
|
8
10
|
import { stage } from '../stage.js';
|
|
9
11
|
import { SWIFT_VERSION, findToolchain, hasWasmSdk } from '../toolchain.js';
|
|
12
|
+
import { vendorPackages } from '../vendor.js';
|
|
10
13
|
import { SWIFT_INSTALL_HINT } from './doctor.js';
|
|
11
14
|
/** The required toolchain, or a CliError saying how to get it. */
|
|
12
15
|
export function requireToolchain(options) {
|
|
@@ -20,37 +23,89 @@ export function requireToolchain(options) {
|
|
|
20
23
|
}
|
|
21
24
|
return found.toolchain;
|
|
22
25
|
}
|
|
23
|
-
|
|
26
|
+
/**
|
|
27
|
+
* The shim as `build` and `dev` use it: the kit (the shim compiled once for
|
|
28
|
+
* this version, kit.ts), built first if there is none, or the shim's sources
|
|
29
|
+
* when there is no toolchain yet (the command stops after the report) or with
|
|
30
|
+
* SWIFTBROWSER_KIT=0.
|
|
31
|
+
*/
|
|
32
|
+
export async function wasmShim(options = {}) {
|
|
33
|
+
const source = { path: swiftPackagePath(), swiftFlags: [], kit: null };
|
|
34
|
+
const toolchain = findToolchain().toolchain;
|
|
35
|
+
if (!toolchain || !kitEnabled() || !hasWasmSdk(toolchain))
|
|
36
|
+
return source;
|
|
37
|
+
const started = Date.now();
|
|
38
|
+
let built = false;
|
|
39
|
+
const kit = await ensureKit(toolchain, source.path, {
|
|
40
|
+
onBuild: () => {
|
|
41
|
+
built = true;
|
|
42
|
+
info(dim(`compiling SwiftBrowser for WebAssembly, once for this version (a few minutes; later builds reuse it)…`));
|
|
43
|
+
},
|
|
44
|
+
onPackaged: (packaged) => info(ok(`SwiftBrowser's prebuilt modules ${dim(`(@swiftbrowser/kit, ${packaged.dir})`)}`)),
|
|
45
|
+
onPackagedRejected: (reason) => info(warn(`@swiftbrowser/kit's modules do not load with this toolchain (${reason}); compiling SwiftBrowser instead`)),
|
|
46
|
+
...(options.verbose ? { onOutput: (chunk) => process.stdout.write(chunk) } : {}),
|
|
47
|
+
});
|
|
48
|
+
if (built)
|
|
49
|
+
info(ok(`SwiftBrowser compiled ${dim(`(${((Date.now() - started) / 1000).toFixed(1)} s, ${kit.dir})`)}`));
|
|
50
|
+
return { path: kit.package, swiftFlags: kitSwiftFlags(kit), kit };
|
|
51
|
+
}
|
|
52
|
+
export async function prepare(input, options, shimPackage = swiftPackagePath()) {
|
|
24
53
|
const resolveOptions = {};
|
|
25
54
|
if (options.target)
|
|
26
55
|
resolveOptions.target = options.target;
|
|
27
56
|
if (options.config)
|
|
28
57
|
resolveOptions.configFile = options.config;
|
|
29
|
-
if (options.foundation)
|
|
30
|
-
resolveOptions.foundation = options.foundation;
|
|
31
58
|
const app = await resolveApp(input, resolveOptions);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
59
|
+
if (options.corsProxy)
|
|
60
|
+
app.corsProxy = options.corsProxy;
|
|
61
|
+
if (options.blockHosts?.length)
|
|
62
|
+
app.blockHosts = [...new Set([...(app.blockHosts ?? []), ...options.blockHosts])];
|
|
63
|
+
// Finding the packages that import SwiftUI takes SwiftPM; without the
|
|
64
|
+
// toolchain the command stops with how to get it once the report is out.
|
|
65
|
+
const toolchain = findToolchain().toolchain;
|
|
66
|
+
const vendored = toolchain ? await vendorPackages(app, toolchain, shimPackage) : new Map();
|
|
67
|
+
// The modules of every package built against the shim count as supported
|
|
68
|
+
// too: an app imports its local packages' dependencies (Nuke through its
|
|
69
|
+
// own DesignSystem package, say) without linking them itself.
|
|
70
|
+
const modules = packageModules(planPackages(app.packages));
|
|
71
|
+
for (const copy of vendored.values()) {
|
|
72
|
+
for (const module of copy.modules ?? [])
|
|
73
|
+
if (!modules.has(module))
|
|
74
|
+
modules.set(module, copy.name);
|
|
75
|
+
}
|
|
76
|
+
const report = compatReport(app.sources, modules);
|
|
77
|
+
const staged = stage(app, shimPackage, { vendored });
|
|
78
|
+
for (const warning of staged.localizationWarnings)
|
|
79
|
+
info(warn(`string tables: ${warning}`));
|
|
80
|
+
return { app, report, staged, vendored };
|
|
35
81
|
}
|
|
36
82
|
export function describeApp(app) {
|
|
37
83
|
const origin = app.origin.kind === 'xcodeproj'
|
|
38
84
|
? `${path.relative(process.cwd(), app.origin.project) || '.'} › target ${app.origin.target}`
|
|
39
85
|
: `${path.relative(process.cwd(), app.root) || '.'} (folder)`;
|
|
40
86
|
info(`${bold(app.displayName)} ${dim(`(${app.name})`)} from ${cyan(origin)}`);
|
|
41
|
-
|
|
87
|
+
const models = app.models?.length ?? 0;
|
|
88
|
+
const modelCount = models > 0 ? `, ${models} Core ML model${models === 1 ? '' : 's'}` : '';
|
|
89
|
+
const strings = app.localizations?.length ?? 0;
|
|
90
|
+
const stringCount = strings > 0 ? `, ${strings} string catalog${strings === 1 ? '' : 's'} or table${strings === 1 ? '' : 's'} (${app.locales.join(', ')})` : '';
|
|
91
|
+
info(dim(` ${app.sources.length} Swift file${app.sources.length === 1 ? '' : 's'}${modelCount}, ${app.catalogs.length} asset catalog${app.catalogs.length === 1 ? '' : 's'}${stringCount}, Swift ${app.swiftLanguageMode} mode`));
|
|
42
92
|
}
|
|
43
93
|
/** Prints the import report; returns whether anything is known to be unsupported. */
|
|
44
|
-
export function describeReport(report, app) {
|
|
94
|
+
export function describeReport(report, app, vendored = new Map()) {
|
|
45
95
|
let blocked = false;
|
|
46
96
|
for (const module of report.modules) {
|
|
47
97
|
const where = module.files.length === 1 ? path.basename(module.files[0]) : `${module.files.length} files`;
|
|
48
98
|
switch (module.status) {
|
|
49
99
|
case 'supported':
|
|
50
|
-
info(ok(`import ${module.module} ${dim(where)}`));
|
|
100
|
+
info(ok(`import ${module.module} ${dim(module.package ? `${where}; from package ${module.package}` : where)}`));
|
|
101
|
+
break;
|
|
102
|
+
case 'empty':
|
|
103
|
+
info(warn(`import ${module.module} ${dim(where)}`));
|
|
104
|
+
if (module.hint)
|
|
105
|
+
info(` ${yellow(module.hint)}`);
|
|
51
106
|
break;
|
|
52
107
|
case 'rewritten':
|
|
53
|
-
info(ok(`import ${module.module} ${dim(`→ ${rewrittenTo(module.module
|
|
108
|
+
info(ok(`import ${module.module} ${dim(`→ ${rewrittenTo(module.module)} (${where})`)}`));
|
|
54
109
|
break;
|
|
55
110
|
case 'unsupported':
|
|
56
111
|
blocked = true;
|
|
@@ -63,6 +118,37 @@ export function describeReport(report, app) {
|
|
|
63
118
|
break;
|
|
64
119
|
}
|
|
65
120
|
}
|
|
121
|
+
// The Xcode project's package dependencies, and which way each went (packages.ts).
|
|
122
|
+
for (const plan of planPackages(app.packages)) {
|
|
123
|
+
const name = `package ${packageDisplayName(plan.package)}`;
|
|
124
|
+
const source = packageSource(plan.package);
|
|
125
|
+
const from = source ? dim(` (${source})`) : '';
|
|
126
|
+
switch (plan.kind) {
|
|
127
|
+
case 'dependency': {
|
|
128
|
+
const copy = vendored.get(plan.identity);
|
|
129
|
+
const patched = copy?.patched ? `, with SwiftBrowser's patch (${copy.patched} edits, packagePatches.ts)` : '';
|
|
130
|
+
const how = copy ? `built against the shim (${shimTargets(copy)})${patched}` : 'a SwiftPM dependency of the build';
|
|
131
|
+
info(ok(`${name}${from}: ${dim(`${how} (${plan.package.products.join(', ')})`)}`));
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
case 'stand-in':
|
|
135
|
+
info(ok(`${name}${from}: ${dim(`SwiftBrowser's stand-in, not fetched (${plan.reason})`)}`));
|
|
136
|
+
break;
|
|
137
|
+
case 'unresolved':
|
|
138
|
+
info(warn(`${name}${from}: ${dim(`left out, ${plan.problem}`)}`));
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Packages deeper in the graph that import SwiftUI, built from a copy too.
|
|
143
|
+
const direct = new Set(app.packages.flatMap((entry) => (entry.reference ? [entry.reference.identity] : [])));
|
|
144
|
+
for (const copy of vendored.values()) {
|
|
145
|
+
if (direct.has(copy.identity))
|
|
146
|
+
continue;
|
|
147
|
+
const version = copy.version === 'unspecified' ? '' : ` ${copy.version}`;
|
|
148
|
+
const patched = copy.patched ? `, with SwiftBrowser's patch (${copy.patched} edits, packagePatches.ts)` : '';
|
|
149
|
+
const how = copy.standIn ? `SwiftBrowser's stand-in, not built (${copy.standIn})` : `built against the shim (${shimTargets(copy)})${patched}`;
|
|
150
|
+
info(ok(`package ${copy.name}${dim(`${version}, a dependency of a dependency: ${how}`)}`));
|
|
151
|
+
}
|
|
66
152
|
const previews = [...report.previews.values()].reduce((a, b) => a + b, 0);
|
|
67
153
|
if (previews > 0)
|
|
68
154
|
info(dim(` ${previews} #Preview block${previews === 1 ? '' : 's'} left out`));
|
|
@@ -70,4 +156,12 @@ export function describeReport(report, app) {
|
|
|
70
156
|
info(warn(`no @main App found among the sources of ${app.name}`));
|
|
71
157
|
return blocked;
|
|
72
158
|
}
|
|
159
|
+
/** `Shimmer imports SwiftUI`, for the report. */
|
|
160
|
+
function shimTargets(copy) {
|
|
161
|
+
if (copy.targets.length === 0)
|
|
162
|
+
return 'it depends on a package that imports SwiftUI';
|
|
163
|
+
return copy.targets
|
|
164
|
+
.map((target) => (target.imports.length > 0 ? `${target.name} imports ${target.imports.join(', ')}` : `${target.name} uses ${(target.uses ?? ['Objective-C selectors']).join(' and ')}`))
|
|
165
|
+
.join('; ');
|
|
166
|
+
}
|
|
73
167
|
//# sourceMappingURL=shared.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/commands/shared.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,iDAAiD;AAEjD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAqB,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/commands/shared.ts"],"names":[],"mappings":"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"}
|
package/dist/compat.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* `empty`: the shim has a module of that name with nothing in it, so an
|
|
3
|
+
* unused import compiles, and any use is a compile error (EMPTY_FRAMEWORKS;
|
|
4
|
+
* none today).
|
|
5
|
+
*/
|
|
6
|
+
export type ModuleStatus = 'supported' | 'rewritten' | 'empty' | 'unsupported' | 'unknown';
|
|
3
7
|
export interface ModuleReport {
|
|
4
8
|
module: string;
|
|
5
9
|
status: ModuleStatus;
|
|
@@ -7,6 +11,8 @@ export interface ModuleReport {
|
|
|
7
11
|
files: string[];
|
|
8
12
|
/** For unsupported modules: what to do. */
|
|
9
13
|
hint?: string;
|
|
14
|
+
/** For a module one of the project's Swift packages provides: the package. */
|
|
15
|
+
package?: string;
|
|
10
16
|
}
|
|
11
17
|
export interface CompatReport {
|
|
12
18
|
modules: ModuleReport[];
|
|
@@ -15,13 +21,45 @@ export interface CompatReport {
|
|
|
15
21
|
/** Whether some file declares `@main`. */
|
|
16
22
|
hasMain: boolean;
|
|
17
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Apple frameworks the shim stands in for, as far as apps commonly use them:
|
|
26
|
+
* StoreKit's `requestReview` (a no-op), Core Location's coordinate type, a
|
|
27
|
+
* LocalAuthentication `LAContext` that always succeeds, Core ML for the
|
|
28
|
+
* tabular models Create ML makes (coreml.ts), PhotosUI's `PhotosPicker` over
|
|
29
|
+
* the page's file chooser (with the `UTType`s of UniformTypeIdentifiers),
|
|
30
|
+
* Core Image's built-in filters and QR code generator (drawn by the page), and
|
|
31
|
+
* UserNotifications over the browser's Notification API; the frameworks under
|
|
32
|
+
* SwiftUI that packages build on (UIKit's images and colors, Core Graphics
|
|
33
|
+
* contexts and Image I/O sources over the shim's image recipes, CryptoKit's
|
|
34
|
+
* hashes and CommonCrypto's digest functions over them, os's locks and logs
|
|
35
|
+
* (and OSLog, which re-exports it),
|
|
36
|
+
* Combine (OpenCombine), MobileCoreServices' kUTType constants, Security's
|
|
37
|
+
* keychain items over a file in the app's home, zlib's inflate API, which
|
|
38
|
+
* re-exports Compression's, Core Text's font registration, MapKit's
|
|
39
|
+
* SwiftUI map, drawn without map data, and WeatherKit's service, whose
|
|
40
|
+
* requests throw); plus
|
|
41
|
+
* packages that cannot build for the browser (none today; see packages.ts).
|
|
42
|
+
* Each is a small module linked only into apps that import it (stage.ts).
|
|
43
|
+
*/
|
|
44
|
+
export declare const STAND_IN_FRAMEWORKS: readonly ["StoreKit", "CoreLocation", "LocalAuthentication", "CoreML", "PhotosUI", "UniformTypeIdentifiers", "CoreImage", "UserNotifications", "UIKit", "CoreGraphics", "ImageIO", "CryptoKit", "os", "Combine", "CommonCrypto", "MobileCoreServices", "OSLog", "Security", "Accelerate", "AppIntents", "CoreHaptics", "NaturalLanguage", "Compression", "Symbols", "AudioToolbox", "AuthenticationServices", "SafariServices", "WebKit", "CoreTransferable", "Photos", "LinkPresentation", "Translation", "FoundationModels", "AVFoundation", "AVKit", "QuickLook", "zlib", "CoreText", "MapKit", "WeatherKit"];
|
|
45
|
+
/**
|
|
46
|
+
* Frameworks the shim has as empty modules: an import compiles, a use does
|
|
47
|
+
* not. Linked like the stand-ins when a source imports them.
|
|
48
|
+
*/
|
|
49
|
+
export declare const EMPTY_FRAMEWORKS: Readonly<Record<string, string>>;
|
|
50
|
+
/** The modules the staging links when a source imports them: the stand-ins and the empty ones. */
|
|
51
|
+
export declare const LINKED_FRAMEWORKS: readonly string[];
|
|
18
52
|
/** The modules a Swift source imports (first path component of each import). */
|
|
19
53
|
export declare function importsOf(source: string): string[];
|
|
20
54
|
/** Number of `#Preview` macro uses in a source. */
|
|
21
55
|
export declare function previewCount(source: string): number;
|
|
22
|
-
export declare function classify(module: string
|
|
56
|
+
export declare function classify(module: string): ModuleStatus;
|
|
23
57
|
export declare function hintFor(module: string): string | undefined;
|
|
24
58
|
/** What a `rewritten` import becomes in the staging package. */
|
|
25
|
-
export declare function rewrittenTo(module: string
|
|
26
|
-
/**
|
|
27
|
-
|
|
59
|
+
export declare function rewrittenTo(module: string): string;
|
|
60
|
+
/**
|
|
61
|
+
* Scans `files` (absolute paths) and groups their imports. `packageModules`
|
|
62
|
+
* (module → package name) are the modules the project's Swift packages
|
|
63
|
+
* provide; they count as supported, the build fetches them.
|
|
64
|
+
*/
|
|
65
|
+
export declare function compatReport(files: readonly string[], packageModules?: ReadonlyMap<string, string>): CompatReport;
|
package/dist/compat.js
CHANGED
|
@@ -3,30 +3,53 @@
|
|
|
3
3
|
// a wall of unresolved-identifier errors.
|
|
4
4
|
import { readFileSync } from 'node:fs';
|
|
5
5
|
// The C libraries are usually behind `#if canImport(...)`; whichever branch the wasm build takes is fine.
|
|
6
|
-
const SUPPORTED = new Set(['SwiftUI', 'Swift', 'Observation', 'FoundationEssentials', '
|
|
6
|
+
const SUPPORTED = new Set(['SwiftUI', 'Swift', 'Observation', 'Foundation', 'FoundationEssentials', 'FoundationInternationalization', 'FoundationBridge', 'Charts', 'SwiftData', 'SwiftBrowser', 'WASILibc', 'Glibc', 'Musl', 'Darwin']);
|
|
7
|
+
/**
|
|
8
|
+
* Apple frameworks the shim stands in for, as far as apps commonly use them:
|
|
9
|
+
* StoreKit's `requestReview` (a no-op), Core Location's coordinate type, a
|
|
10
|
+
* LocalAuthentication `LAContext` that always succeeds, Core ML for the
|
|
11
|
+
* tabular models Create ML makes (coreml.ts), PhotosUI's `PhotosPicker` over
|
|
12
|
+
* the page's file chooser (with the `UTType`s of UniformTypeIdentifiers),
|
|
13
|
+
* Core Image's built-in filters and QR code generator (drawn by the page), and
|
|
14
|
+
* UserNotifications over the browser's Notification API; the frameworks under
|
|
15
|
+
* SwiftUI that packages build on (UIKit's images and colors, Core Graphics
|
|
16
|
+
* contexts and Image I/O sources over the shim's image recipes, CryptoKit's
|
|
17
|
+
* hashes and CommonCrypto's digest functions over them, os's locks and logs
|
|
18
|
+
* (and OSLog, which re-exports it),
|
|
19
|
+
* Combine (OpenCombine), MobileCoreServices' kUTType constants, Security's
|
|
20
|
+
* keychain items over a file in the app's home, zlib's inflate API, which
|
|
21
|
+
* re-exports Compression's, Core Text's font registration, MapKit's
|
|
22
|
+
* SwiftUI map, drawn without map data, and WeatherKit's service, whose
|
|
23
|
+
* requests throw); plus
|
|
24
|
+
* packages that cannot build for the browser (none today; see packages.ts).
|
|
25
|
+
* Each is a small module linked only into apps that import it (stage.ts).
|
|
26
|
+
*/
|
|
27
|
+
export const STAND_IN_FRAMEWORKS = [
|
|
28
|
+
'StoreKit', 'CoreLocation', 'LocalAuthentication', 'CoreML', 'PhotosUI', 'UniformTypeIdentifiers', 'CoreImage',
|
|
29
|
+
'UserNotifications', 'UIKit', 'CoreGraphics', 'ImageIO', 'CryptoKit', 'os', 'Combine',
|
|
30
|
+
'CommonCrypto', 'MobileCoreServices', 'OSLog', 'Security', 'Accelerate',
|
|
31
|
+
'AppIntents', 'CoreHaptics', 'NaturalLanguage', 'Compression',
|
|
32
|
+
'Symbols', 'AudioToolbox', 'AuthenticationServices', 'SafariServices', 'WebKit',
|
|
33
|
+
'CoreTransferable', 'Photos', 'LinkPresentation', 'Translation', 'FoundationModels',
|
|
34
|
+
'AVFoundation', 'AVKit', 'QuickLook', 'zlib', 'CoreText', 'MapKit', 'WeatherKit',
|
|
35
|
+
];
|
|
36
|
+
for (const framework of STAND_IN_FRAMEWORKS)
|
|
37
|
+
SUPPORTED.add(framework);
|
|
38
|
+
/**
|
|
39
|
+
* Frameworks the shim has as empty modules: an import compiles, a use does
|
|
40
|
+
* not. Linked like the stand-ins when a source imports them.
|
|
41
|
+
*/
|
|
42
|
+
export const EMPTY_FRAMEWORKS = {};
|
|
43
|
+
/** The modules the staging links when a source imports them: the stand-ins and the empty ones. */
|
|
44
|
+
export const LINKED_FRAMEWORKS = [...STAND_IN_FRAMEWORKS, ...Object.keys(EMPTY_FRAMEWORKS)];
|
|
7
45
|
/** Frameworks the browser has no counterpart for yet, with the usual way out. */
|
|
8
46
|
const UNSUPPORTED = {
|
|
9
|
-
UIKit: 'UIKit has no browser counterpart; keep UIKit code behind `#if !SWIFTBROWSER`',
|
|
10
47
|
AppKit: 'AppKit has no browser counterpart; keep it behind `#if !SWIFTBROWSER`',
|
|
11
|
-
Combine: 'Combine is not available (`Timer.publish` + `onReceive` work without the import); use async/await, `.task` and `@Observable` for the rest',
|
|
12
|
-
SwiftData: 'SwiftData is not available; keep models in an `@Observable` store behind `#if SWIFTBROWSER`',
|
|
13
48
|
CoreData: 'Core Data is not available; keep persistence behind `#if !SWIFTBROWSER`',
|
|
14
|
-
CoreML: 'Core ML is not available; stub the model behind `#if SWIFTBROWSER`',
|
|
15
49
|
CreateML: 'Create ML is not available',
|
|
16
50
|
Vision: 'Vision is not available',
|
|
17
|
-
MapKit: 'MapKit is not available yet; show a placeholder behind `#if SWIFTBROWSER`',
|
|
18
|
-
CoreLocation: 'Core Location is not available yet',
|
|
19
|
-
AVFoundation: 'AVFoundation is not available; audio and video need a browser-side counterpart first',
|
|
20
|
-
AVKit: 'AVKit is not available',
|
|
21
|
-
UserNotifications: 'UserNotifications is not available; guard it with `#if !SWIFTBROWSER`',
|
|
22
|
-
StoreKit: 'StoreKit is not available',
|
|
23
51
|
CloudKit: 'CloudKit is not available',
|
|
24
52
|
WidgetKit: 'WidgetKit extensions do not run in the browser',
|
|
25
|
-
PhotosUI: 'PhotosUI is not available yet',
|
|
26
|
-
Photos: 'Photos is not available',
|
|
27
|
-
WebKit: 'WebKit is not available (an inline web view would be a renderer feature)',
|
|
28
|
-
CoreImage: 'Core Image is not available',
|
|
29
|
-
CoreGraphics: 'Core Graphics is only partly available (CGFloat, CGPoint, CGSize, CGRect are in the shim); remove the import',
|
|
30
53
|
QuartzCore: 'QuartzCore is not available',
|
|
31
54
|
Metal: 'Metal is not available',
|
|
32
55
|
MetalKit: 'Metal is not available',
|
|
@@ -39,14 +62,10 @@ const UNSUPPORTED = {
|
|
|
39
62
|
EventKit: 'EventKit is not available',
|
|
40
63
|
Contacts: 'Contacts is not available',
|
|
41
64
|
MessageUI: 'MessageUI is not available',
|
|
42
|
-
|
|
43
|
-
LocalAuthentication: 'LocalAuthentication is not available',
|
|
44
|
-
Security: 'Security is not available',
|
|
45
|
-
Network: 'Network.framework is not available; use URLSession-free fetching through the host (planned)',
|
|
65
|
+
Network: 'Network.framework is not available; URLSession (over the browser\'s fetch) is',
|
|
46
66
|
TipKit: 'TipKit is not available',
|
|
47
|
-
CodeScanner: 'CodeScanner (a camera package) is not available; simulate the scan behind `#if SWIFTBROWSER`',
|
|
48
67
|
};
|
|
49
|
-
const IMPORT = /^\s*(?:@[A-Za-z_]+(?:\([^)]*\))?\s+)*import\s+(?:(?:struct|class|enum|protocol|typealias|func|let|var|actor)\s+)?([A-Za-z_][A-Za-z0-9_]*)/gm;
|
|
68
|
+
const IMPORT = /^\s*(?:@[A-Za-z_]+(?:\([^)]*\))?\s+)*(?:(?:public|package|internal|fileprivate|private)\s+)?import\s+(?:(?:struct|class|enum|protocol|typealias|func|let|var|actor)\s+)?([A-Za-z_][A-Za-z0-9_]*)/gm;
|
|
50
69
|
/** The modules a Swift source imports (first path component of each import). */
|
|
51
70
|
export function importsOf(source) {
|
|
52
71
|
const out = [];
|
|
@@ -58,30 +77,35 @@ export function importsOf(source) {
|
|
|
58
77
|
export function previewCount(source) {
|
|
59
78
|
return (source.match(/^\s*#Preview\b/gm) ?? []).length;
|
|
60
79
|
}
|
|
61
|
-
export function classify(module
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (module === 'FoundationLite')
|
|
65
|
-
return
|
|
80
|
+
export function classify(module) {
|
|
81
|
+
// Phase 14: FoundationLite (the lean mode's formatting layer) folded into
|
|
82
|
+
// Foundation; an old import of it becomes the bridge.
|
|
83
|
+
if (module === 'FoundationLite' || module === 'Dispatch')
|
|
84
|
+
return 'rewritten';
|
|
66
85
|
if (SUPPORTED.has(module))
|
|
67
86
|
return 'supported';
|
|
87
|
+
if (module in EMPTY_FRAMEWORKS)
|
|
88
|
+
return 'empty';
|
|
68
89
|
if (module in UNSUPPORTED)
|
|
69
90
|
return 'unsupported';
|
|
70
91
|
return 'unknown';
|
|
71
92
|
}
|
|
72
93
|
export function hintFor(module) {
|
|
73
|
-
return UNSUPPORTED[module];
|
|
94
|
+
return UNSUPPORTED[module] ?? EMPTY_FRAMEWORKS[module];
|
|
74
95
|
}
|
|
75
96
|
/** What a `rewritten` import becomes in the staging package. */
|
|
76
|
-
export function rewrittenTo(module
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (module === 'FoundationLite' && foundation === 'full')
|
|
97
|
+
export function rewrittenTo(module) {
|
|
98
|
+
// The SDK has no Dispatch on WASI; the bridge's queues stand in.
|
|
99
|
+
if (module === 'FoundationLite' || module === 'Dispatch')
|
|
80
100
|
return 'FoundationBridge';
|
|
81
101
|
return module;
|
|
82
102
|
}
|
|
83
|
-
/**
|
|
84
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Scans `files` (absolute paths) and groups their imports. `packageModules`
|
|
105
|
+
* (module → package name) are the modules the project's Swift packages
|
|
106
|
+
* provide; they count as supported, the build fetches them.
|
|
107
|
+
*/
|
|
108
|
+
export function compatReport(files, packageModules = new Map()) {
|
|
85
109
|
const byModule = new Map();
|
|
86
110
|
const previews = new Map();
|
|
87
111
|
let hasMain = false;
|
|
@@ -95,7 +119,11 @@ export function compatReport(files, foundation) {
|
|
|
95
119
|
for (const module of new Set(importsOf(source))) {
|
|
96
120
|
let report = byModule.get(module);
|
|
97
121
|
if (!report) {
|
|
98
|
-
|
|
122
|
+
const status = classify(module);
|
|
123
|
+
const fromPackage = status === 'unknown' ? packageModules.get(module) : undefined;
|
|
124
|
+
report = { module, status: fromPackage !== undefined ? 'supported' : status, files: [] };
|
|
125
|
+
if (fromPackage !== undefined)
|
|
126
|
+
report.package = fromPackage;
|
|
99
127
|
const hint = hintFor(module);
|
|
100
128
|
if (hint)
|
|
101
129
|
report.hint = hint;
|
|
@@ -104,7 +132,7 @@ export function compatReport(files, foundation) {
|
|
|
104
132
|
report.files.push(file);
|
|
105
133
|
}
|
|
106
134
|
}
|
|
107
|
-
const order = { unsupported: 0, unknown: 1,
|
|
135
|
+
const order = { unsupported: 0, unknown: 1, empty: 2, rewritten: 3, supported: 4 };
|
|
108
136
|
const modules = [...byModule.values()].sort((a, b) => order[a.status] - order[b.status] || a.module.localeCompare(b.module));
|
|
109
137
|
return { modules, previews, hasMain };
|
|
110
138
|
}
|
package/dist/compat.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compat.js","sourceRoot":"","sources":["../src/compat.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,6EAA6E;AAC7E,0CAA0C;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"compat.js","sourceRoot":"","sources":["../src/compat.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
|
-
export type FoundationMode = 'lean' | 'full';
|
|
2
1
|
export type SwiftLanguageMode = '5' | '6';
|
|
2
|
+
/**
|
|
3
|
+
* A Swift package the app depends on, for a folder of sources (an Xcode
|
|
4
|
+
* project lists its own): a remote `url` with one rule (`from`: up to the next
|
|
5
|
+
* major version, `exact`, `branch` or `revision`), or a local `path` (relative
|
|
6
|
+
* to the project), and the products the app imports.
|
|
7
|
+
*/
|
|
8
|
+
export interface ConfigPackage {
|
|
9
|
+
url?: string;
|
|
10
|
+
path?: string;
|
|
11
|
+
from?: string;
|
|
12
|
+
exact?: string;
|
|
13
|
+
branch?: string;
|
|
14
|
+
revision?: string;
|
|
15
|
+
products: string[];
|
|
16
|
+
}
|
|
3
17
|
export interface Config {
|
|
4
18
|
/** Module name of the app (letters, digits, `_`); defaults to the target or folder name. */
|
|
5
19
|
name?: string;
|
|
@@ -24,22 +38,46 @@ export interface Config {
|
|
|
24
38
|
/** Swift language mode the sources are compiled in (default 5, like Xcode's default for apps). */
|
|
25
39
|
swiftLanguageMode?: SwiftLanguageMode;
|
|
26
40
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* + FoundationLite, a smaller module (4.5 to 9 MB) with a smaller API.
|
|
41
|
+
* The languages whose ICU locale data stays in the module (`["en"]` by
|
|
42
|
+
* default; `["*"]` keeps everything). The viewer's language is chosen among
|
|
43
|
+
* them at launch. Each language adds roughly 100 to 300 kB, Chinese 1.7 MB.
|
|
31
44
|
*/
|
|
32
|
-
|
|
45
|
+
locales?: string[];
|
|
33
46
|
/**
|
|
34
|
-
*
|
|
35
|
-
* the
|
|
36
|
-
*
|
|
47
|
+
* Whether ICU's collation tables ship (default true). `false` saves 0.9 MB
|
|
48
|
+
* when the app never compares strings in a locale (`localizedCompare`,
|
|
49
|
+
* `localizedStandardCompare`, `.localizedStandard` sorting fall back to
|
|
50
|
+
* Unicode scalar order).
|
|
37
51
|
*/
|
|
38
|
-
|
|
52
|
+
collation?: boolean;
|
|
39
53
|
/** Extra `-D` compilation conditions (SWIFTBROWSER is always defined). */
|
|
40
54
|
defines?: string[];
|
|
55
|
+
/**
|
|
56
|
+
* The app's URL schemes, whose OAuth redirects come back through the page
|
|
57
|
+
* (docs/ops-protocol.md, "Signing in"); replaces those of the Info.plist's
|
|
58
|
+
* `CFBundleURLTypes`.
|
|
59
|
+
*/
|
|
60
|
+
urlSchemes?: string[];
|
|
61
|
+
/**
|
|
62
|
+
* A CORS proxy (packages/cors-proxy, deployed on Cloudflare): the page
|
|
63
|
+
* retries a cross-origin GET or HEAD the browser refused through
|
|
64
|
+
* `<corsProxy>?url=<target>`. For apps whose servers do not allow the page's
|
|
65
|
+
* origin (images, mostly), as in screenshots and demos. `--cors-proxy`
|
|
66
|
+
* overrides it.
|
|
67
|
+
*/
|
|
68
|
+
corsProxy?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Hosts (and their subdomains) the app's requests may not reach in the
|
|
71
|
+
* browser: they fail as a network error does. For a public deploy of an app
|
|
72
|
+
* whose analytics belong to someone else. `--block-host` adds to them.
|
|
73
|
+
*/
|
|
74
|
+
blockHosts?: string[];
|
|
75
|
+
/** Swift packages the app depends on, added to the Xcode target's (see `ConfigPackage`). */
|
|
76
|
+
packages?: ConfigPackage[];
|
|
41
77
|
}
|
|
42
78
|
export declare const CONFIG_FILE = "swiftbrowser.json";
|
|
43
79
|
/** Reads and validates `swiftbrowser.json` in `dir` (or the file at `file`); `{}` when absent. */
|
|
44
80
|
export declare function loadConfig(dir: string, file?: string): Config;
|
|
45
81
|
export declare function validateConfig(raw: unknown, source?: string): Config;
|
|
82
|
+
/** Whether `value` is an absolute http(s) URL (a CORS proxy's). */
|
|
83
|
+
export declare function isHTTPURL(value: string): boolean;
|
package/dist/config.js
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
// need no file at all.
|
|
4
4
|
import { existsSync, readFileSync } from 'node:fs';
|
|
5
5
|
import path from 'node:path';
|
|
6
|
-
import { CliError } from './log.js';
|
|
6
|
+
import { CliError, info, warn } from './log.js';
|
|
7
7
|
export const CONFIG_FILE = 'swiftbrowser.json';
|
|
8
|
-
const STRING_KEYS = ['name', 'displayName', 'target', 'icon'];
|
|
9
|
-
const LIST_KEYS = ['sources', 'exclude', 'catalogs', 'resources', 'defines', 'locales'];
|
|
8
|
+
const STRING_KEYS = ['name', 'displayName', 'target', 'icon', 'corsProxy'];
|
|
9
|
+
const LIST_KEYS = ['sources', 'exclude', 'catalogs', 'resources', 'defines', 'locales', 'urlSchemes', 'blockHosts'];
|
|
10
10
|
/** Reads and validates `swiftbrowser.json` in `dir` (or the file at `file`); `{}` when absent. */
|
|
11
11
|
export function loadConfig(dir, file) {
|
|
12
12
|
const configPath = file ?? path.join(dir, CONFIG_FILE);
|
|
@@ -45,26 +45,82 @@ export function validateConfig(raw, source = CONFIG_FILE) {
|
|
|
45
45
|
throw new CliError(`${source}: "${key}" must be an array of strings`);
|
|
46
46
|
config[key] = value;
|
|
47
47
|
}
|
|
48
|
+
if (record['collation'] !== undefined) {
|
|
49
|
+
if (typeof record['collation'] !== 'boolean')
|
|
50
|
+
throw new CliError(`${source}: "collation" must be true or false`);
|
|
51
|
+
config.collation = record['collation'];
|
|
52
|
+
}
|
|
48
53
|
if (record['swiftLanguageMode'] !== undefined) {
|
|
49
54
|
const mode = String(record['swiftLanguageMode']);
|
|
50
55
|
if (mode !== '5' && mode !== '6')
|
|
51
56
|
throw new CliError(`${source}: "swiftLanguageMode" must be "5" or "6"`);
|
|
52
57
|
config.swiftLanguageMode = mode;
|
|
53
58
|
}
|
|
59
|
+
if (record['packages'] !== undefined)
|
|
60
|
+
config.packages = validatePackages(record['packages'], source);
|
|
54
61
|
if (record['foundation'] !== undefined) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
62
|
+
// Phase 14: there is one Foundation now. Old files may still say "lean" or "full".
|
|
63
|
+
info(warn(`${source}: "foundation" is ignored; the real Foundation is always used (lean mode was removed)`));
|
|
64
|
+
}
|
|
65
|
+
if (config.corsProxy !== undefined && !isHTTPURL(config.corsProxy)) {
|
|
66
|
+
throw new CliError(`${source}: "corsProxy" must be an http(s) URL`);
|
|
59
67
|
}
|
|
60
68
|
if (config.name !== undefined && !/^[A-Za-z_][A-Za-z0-9_]*$/.test(config.name)) {
|
|
61
69
|
throw new CliError(`${source}: "name" must be a Swift module name (letters, digits, underscores)`);
|
|
62
70
|
}
|
|
63
71
|
for (const key of Object.keys(record)) {
|
|
64
|
-
if (!STRING_KEYS.includes(key) && !LIST_KEYS.includes(key) && key !== 'swiftLanguageMode' && key !== 'foundation' && key !== '$schema') {
|
|
72
|
+
if (!STRING_KEYS.includes(key) && !LIST_KEYS.includes(key) && key !== 'swiftLanguageMode' && key !== 'collation' && key !== 'packages' && key !== 'foundation' && key !== '$schema') {
|
|
65
73
|
throw new CliError(`${source}: unknown key "${key}"`);
|
|
66
74
|
}
|
|
67
75
|
}
|
|
68
76
|
return config;
|
|
69
77
|
}
|
|
78
|
+
const PACKAGE_KEYS = ['url', 'path', 'from', 'exact', 'branch', 'revision'];
|
|
79
|
+
const PACKAGE_RULES = ['from', 'exact', 'branch', 'revision'];
|
|
80
|
+
function validatePackages(value, source) {
|
|
81
|
+
if (!Array.isArray(value))
|
|
82
|
+
throw new CliError(`${source}: "packages" must be an array`);
|
|
83
|
+
return value.map((entry, index) => {
|
|
84
|
+
const where = `${source}: packages[${index}]`;
|
|
85
|
+
if (typeof entry !== 'object' || entry === null || Array.isArray(entry))
|
|
86
|
+
throw new CliError(`${where} must be an object`);
|
|
87
|
+
const record = entry;
|
|
88
|
+
const pkg = { products: [] };
|
|
89
|
+
for (const key of Object.keys(record)) {
|
|
90
|
+
if (!PACKAGE_KEYS.includes(key) && key !== 'products')
|
|
91
|
+
throw new CliError(`${where}: unknown key "${key}"`);
|
|
92
|
+
}
|
|
93
|
+
for (const key of PACKAGE_KEYS) {
|
|
94
|
+
const field = record[key];
|
|
95
|
+
if (field === undefined)
|
|
96
|
+
continue;
|
|
97
|
+
if (typeof field !== 'string' || field === '')
|
|
98
|
+
throw new CliError(`${where}: "${key}" must be a string`);
|
|
99
|
+
pkg[key] = field;
|
|
100
|
+
}
|
|
101
|
+
const products = record['products'];
|
|
102
|
+
if (!Array.isArray(products) || products.length === 0 || !products.every((p) => typeof p === 'string')) {
|
|
103
|
+
throw new CliError(`${where}: "products" must be a non-empty array of strings`);
|
|
104
|
+
}
|
|
105
|
+
pkg.products = products;
|
|
106
|
+
if (!pkg.url === !pkg.path)
|
|
107
|
+
throw new CliError(`${where}: give either "url" or "path"`);
|
|
108
|
+
const rules = PACKAGE_RULES.filter((key) => pkg[key] !== undefined);
|
|
109
|
+
if (pkg.url && rules.length !== 1)
|
|
110
|
+
throw new CliError(`${where}: a "url" needs one of "from", "exact", "branch" or "revision"`);
|
|
111
|
+
if (pkg.path && rules.length > 0)
|
|
112
|
+
throw new CliError(`${where}: a "path" takes no version rule`);
|
|
113
|
+
return pkg;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/** Whether `value` is an absolute http(s) URL (a CORS proxy's). */
|
|
117
|
+
export function isHTTPURL(value) {
|
|
118
|
+
try {
|
|
119
|
+
const url = new URL(value);
|
|
120
|
+
return url.protocol === 'http:' || url.protocol === 'https:';
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
70
126
|
//# sourceMappingURL=config.js.map
|