craft-native 0.0.86 → 0.0.88
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 +71 -0
- package/dist/api/window.d.ts +14 -1
- package/dist/cli.js +75 -3
- package/dist/index.cjs +386 -102
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +374 -90
- package/dist/ios/src/index.d.ts +74 -0
- package/dist/ios/src/index.js +73 -1
- package/dist/ios/templates/CraftApp.swift +510 -112
- package/dist/ios/templates/project.yml.template +1 -0
- package/dist/types.d.ts +22 -0
- package/dist/updater/index.d.ts +104 -1
- package/dist/updater/macos-bundle.d.ts +153 -0
- package/package.json +2 -2
package/dist/ios/src/index.d.ts
CHANGED
|
@@ -80,12 +80,32 @@ export interface InitOptions {
|
|
|
80
80
|
teamId?: string;
|
|
81
81
|
output: string;
|
|
82
82
|
config?: Partial<CraftConfig>;
|
|
83
|
+
/**
|
|
84
|
+
* Where the Zig runtime archives live, overriding `CRAFT_IOS_RUNTIME`.
|
|
85
|
+
*
|
|
86
|
+
* `null` means "no runtime, whatever the environment says" — the shape
|
|
87
|
+
* `AppConfig.craftPath` has for `CRAFT_BIN`, and the reason it exists here
|
|
88
|
+
* is the same: a caller that does not opt in should not be steered by an
|
|
89
|
+
* ambient variable. Without it this package's own tests inherited whatever
|
|
90
|
+
* the developer's shell exported, and went from 12 passing to 8 passing and
|
|
91
|
+
* 4 failing when `CRAFT_IOS_RUNTIME` happened to be set.
|
|
92
|
+
*
|
|
93
|
+
* Omitted (`undefined`) keeps the environment lookup, which is what the
|
|
94
|
+
* monorepo dev loop uses.
|
|
95
|
+
*/
|
|
96
|
+
runtimeDir?: string | null;
|
|
83
97
|
}
|
|
84
98
|
export interface BuildOptions {
|
|
85
99
|
htmlPath?: string;
|
|
86
100
|
devServer?: string;
|
|
87
101
|
output: string;
|
|
88
102
|
generateProject?: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Where to re-read the Zig runtime archives from, overriding
|
|
105
|
+
* `CRAFT_IOS_RUNTIME`. Same meaning as `InitOptions.runtimeDir`; `null`
|
|
106
|
+
* leaves whatever `init` installed exactly as it is.
|
|
107
|
+
*/
|
|
108
|
+
runtimeDir?: string | null;
|
|
89
109
|
}
|
|
90
110
|
export interface OpenOptions {
|
|
91
111
|
output: string;
|
|
@@ -101,12 +121,66 @@ export declare function renderUrlTypes(config: CraftConfig): string;
|
|
|
101
121
|
export declare function renderBackgroundModes(config: CraftConfig): string;
|
|
102
122
|
export declare function renderEntitlements(config: CraftConfig): string;
|
|
103
123
|
export declare function renderWatchEntitlements(config: CraftConfig): string;
|
|
124
|
+
/**
|
|
125
|
+
* The build settings that link the Zig runtime into the app target.
|
|
126
|
+
*
|
|
127
|
+
* Two things are load-bearing here:
|
|
128
|
+
*
|
|
129
|
+
* `LIBRARY_SEARCH_PATHS` is written twice, once per SDK, so `-lcraft-ios`
|
|
130
|
+
* resolves to the device archive for a device build and the simulator archive
|
|
131
|
+
* for a simulator one without the flag itself changing. Xcode applies the
|
|
132
|
+
* `[sdk=...]` condition; xcodegen passes these keys through verbatim.
|
|
133
|
+
*
|
|
134
|
+
* The four `-u` flags are the reason anything works at all. Nothing in the
|
|
135
|
+
* Swift source *references* these symbols — `CraftZigRuntime` and
|
|
136
|
+
* `CraftSwiftShim` both find them with `dlsym` at runtime — so a static
|
|
137
|
+
* archive contributes no objects for them and the linker drops the entire
|
|
138
|
+
* runtime as unreachable. `-u` names them as undefined so the objects are
|
|
139
|
+
* pulled in and the symbols end up in the binary for `dlsym` to find.
|
|
140
|
+
*
|
|
141
|
+
* `-u` rather than `-force_load`: forcing the whole archive would pull in
|
|
142
|
+
* every object whether reachable or not, and these four entry points already
|
|
143
|
+
* reach everything the bridge actually uses.
|
|
144
|
+
*/
|
|
145
|
+
export declare function renderRuntimeSettings(): string;
|
|
104
146
|
export declare function renderPrivacyManifest(config: CraftConfig): string;
|
|
105
147
|
/** Replace the bundled web application atomically so removed assets cannot linger. */
|
|
106
148
|
export declare function syncWebAssets(source: string, output: string): void;
|
|
107
149
|
/**
|
|
108
150
|
* Initialize a new iOS project
|
|
109
151
|
*/
|
|
152
|
+
/**
|
|
153
|
+
* Where the Zig runtime archives live, or null when this build has none.
|
|
154
|
+
*
|
|
155
|
+
* `CRAFT_IOS_RUNTIME` points at a directory holding the archives `zig build
|
|
156
|
+
* build-ios-all` produces. It is opt-in and there is deliberately no fallback
|
|
157
|
+
* search: a generated project with no runtime is the shipping default today,
|
|
158
|
+
* and it works — `CraftZigRuntime.offer` is a `dlsym` miss, every action
|
|
159
|
+
* answers false, and the Swift switch serves the whole surface exactly as it
|
|
160
|
+
* always has. Guessing at a path would turn "no runtime" into "some runtime,
|
|
161
|
+
* from somewhere", which is the failure mode the pantry contract exists to
|
|
162
|
+
* rule out.
|
|
163
|
+
*
|
|
164
|
+
* This is the same shape as `CRAFT_BIN`: an explicit override for the monorepo
|
|
165
|
+
* dev loop, not a lookup path. Shipping the runtime to real apps means putting
|
|
166
|
+
* these archives in the pantry package beside the `craft` binary, which is a
|
|
167
|
+
* distribution decision this function does not make.
|
|
168
|
+
*
|
|
169
|
+
* `override` is what `InitOptions.runtimeDir` passes: a path to use instead of
|
|
170
|
+
* the variable, or `null` to declare there is no runtime regardless of what the
|
|
171
|
+
* environment says. `undefined` falls through to `CRAFT_IOS_RUNTIME`.
|
|
172
|
+
*/
|
|
173
|
+
export declare function resolveRuntimeDir(override?: string | null): string | null;
|
|
174
|
+
/**
|
|
175
|
+
* Copy the Zig archives into the generated project as `Runtime/<sdk>/libcraft-ios.a`.
|
|
176
|
+
*
|
|
177
|
+
* One name for both SDKs, in two directories, because that is what lets a
|
|
178
|
+
* single `-lcraft-ios` in OTHER_LDFLAGS work for device and simulator builds:
|
|
179
|
+
* Xcode picks the directory by SDK and the flag never changes.
|
|
180
|
+
*
|
|
181
|
+
* Returns true when a runtime was installed.
|
|
182
|
+
*/
|
|
183
|
+
export declare function installRuntime(output: string, runtimeDir: string): Promise<boolean>;
|
|
110
184
|
export declare function init(options: InitOptions): Promise<void>;
|
|
111
185
|
/**
|
|
112
186
|
* Build web assets and generate Xcode project
|
package/dist/ios/src/index.js
CHANGED
|
@@ -176,6 +176,14 @@ ${appGroups}</dict>
|
|
|
176
176
|
</plist>
|
|
177
177
|
`;
|
|
178
178
|
}
|
|
179
|
+
function renderRuntimeSettings() {
|
|
180
|
+
return [
|
|
181
|
+
' LIBRARY_SEARCH_PATHS[sdk=iphoneos*]: "$(PROJECT_DIR)/Runtime/device"',
|
|
182
|
+
' LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]: "$(PROJECT_DIR)/Runtime/simulator"',
|
|
183
|
+
' OTHER_LDFLAGS: "-lcraft-ios -Wl,-u,_craft_ios_handle_action -Wl,-u,_craft_ios_set_webview ' + '-Wl,-u,_craft_ios_deliver_result -Wl,-u,_craft_ios_deliver_error"'
|
|
184
|
+
].join(`
|
|
185
|
+
`);
|
|
186
|
+
}
|
|
179
187
|
function renderPrivacyManifest(config) {
|
|
180
188
|
const privacy = config.privacy ?? {};
|
|
181
189
|
const collected = privacy.collectedDataTypes ?? [];
|
|
@@ -279,6 +287,59 @@ function syncWebAssets(source, output) {
|
|
|
279
287
|
throw new Error(`Web asset directory must contain index.html: ${source}`);
|
|
280
288
|
}
|
|
281
289
|
}
|
|
290
|
+
function resolveRuntimeDir(override) {
|
|
291
|
+
if (override === null)
|
|
292
|
+
return null;
|
|
293
|
+
const dir = override ?? process.env.CRAFT_IOS_RUNTIME;
|
|
294
|
+
if (!dir)
|
|
295
|
+
return null;
|
|
296
|
+
if (!existsSync(dir)) {
|
|
297
|
+
const source = override === undefined ? "CRAFT_IOS_RUNTIME points at" : "runtimeDir is";
|
|
298
|
+
throw new Error(`${source} ${dir}, which does not exist.`);
|
|
299
|
+
}
|
|
300
|
+
return dir;
|
|
301
|
+
}
|
|
302
|
+
var RUNTIME_ARCHIVES = {
|
|
303
|
+
device: ["libcraft-ios.a"],
|
|
304
|
+
simulator: ["libcraft-ios-simulator-arm64.a", "libcraft-ios-simulator-x64.a"]
|
|
305
|
+
};
|
|
306
|
+
async function installRuntime(output, runtimeDir) {
|
|
307
|
+
const resolved = Object.entries(RUNTIME_ARCHIVES).map(([sdk, archives]) => {
|
|
308
|
+
const present = archives.filter((a) => existsSync(join(runtimeDir, a)));
|
|
309
|
+
if (present.length === 0) {
|
|
310
|
+
throw new Error(`${runtimeDir} has none of ${archives.join(", ")}. ` + `Run \`zig build build-ios-all\` in packages/zig and point at its zig-out/lib.`);
|
|
311
|
+
}
|
|
312
|
+
return { sdk, archives, present };
|
|
313
|
+
});
|
|
314
|
+
const dest = join(output, "Runtime");
|
|
315
|
+
rmSync(dest, { recursive: true, force: true });
|
|
316
|
+
for (const { sdk, archives, present } of resolved) {
|
|
317
|
+
const sdkDir = join(dest, sdk);
|
|
318
|
+
mkdirSync(sdkDir, { recursive: true });
|
|
319
|
+
const target = join(sdkDir, "libcraft-ios.a");
|
|
320
|
+
if (present.length === 1) {
|
|
321
|
+
const missing = archives.filter((a) => !present.includes(a));
|
|
322
|
+
if (missing.length > 0) {
|
|
323
|
+
console.warn(` \u26A0 ${sdk}: only ${present[0]} was found; ${missing.join(", ")} is missing. ` + `The generated project will not link on the other architecture.`);
|
|
324
|
+
}
|
|
325
|
+
cpSync(join(runtimeDir, present[0]), target);
|
|
326
|
+
} else {
|
|
327
|
+
await $`lipo -create ${present.map((a) => join(runtimeDir, a))} -output ${target}`.quiet();
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
async function refreshRuntime(output, override) {
|
|
333
|
+
if (!existsSync(join(output, "Runtime")))
|
|
334
|
+
return;
|
|
335
|
+
const dir = resolveRuntimeDir(override);
|
|
336
|
+
if (!dir) {
|
|
337
|
+
console.log(" Keeping the Zig runtime installed at init (no runtime directory configured)");
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
await installRuntime(output, dir);
|
|
341
|
+
console.log(" Refreshed the Zig runtime from", dir);
|
|
342
|
+
}
|
|
282
343
|
async function init(options) {
|
|
283
344
|
const { name, bundleId, teamId, output } = options;
|
|
284
345
|
console.log(`
|
|
@@ -351,7 +412,14 @@ async function init(options) {
|
|
|
351
412
|
SWIFT_VERSION: "5.0"
|
|
352
413
|
SKIP_INSTALL: YES`);
|
|
353
414
|
}
|
|
354
|
-
const
|
|
415
|
+
const runtimeDir = resolveRuntimeDir(options.runtimeDir);
|
|
416
|
+
const hasRuntime = runtimeDir ? await installRuntime(output, runtimeDir) : false;
|
|
417
|
+
if (hasRuntime) {
|
|
418
|
+
console.log(" Linked the Zig runtime from", runtimeDir);
|
|
419
|
+
} else {
|
|
420
|
+
rmSync(join(output, "Runtime"), { recursive: true, force: true });
|
|
421
|
+
}
|
|
422
|
+
const projectYml = projectYmlTemplate.replace(/\{\{CRAFT_RUNTIME_SETTINGS\}\}/g, hasRuntime ? renderRuntimeSettings() : "").replace(/\{\{APP_NAME\}\}/g, name).replace(/\{\{BUNDLE_ID\}\}/g, finalBundleId).replace(/\{\{BUNDLE_ID_PREFIX\}\}/g, bundleIdPrefix).replace(/\{\{VERSION\}\}/g, config.version || "1.0.0").replace(/\{\{BUILD_NUMBER\}\}/g, config.buildNumber || "1").replace(/\{\{IOS_VERSION\}\}/g, config.iosVersion || "15.0").replace(/\{\{DEVICE_FAMILIES\}\}/g, renderDeviceFamilies(config)).replace(/\{\{TEAM_ID\}\}/g, teamId || "").replace(/\{\{NATIVE_DEPENDENCIES\}\}/g, nativeDependencies.length ? ` dependencies:
|
|
355
423
|
${nativeDependencies.join(`
|
|
356
424
|
`)}` : "").replace(/\{\{NATIVE_TARGETS\}\}/g, nativeTargets.join(`
|
|
357
425
|
`));
|
|
@@ -442,6 +510,7 @@ async function build(options) {
|
|
|
442
510
|
syncWebAssets(htmlPath, output);
|
|
443
511
|
console.log(` Synced: ${htmlPath} \u2192 dist/`);
|
|
444
512
|
}
|
|
513
|
+
await refreshRuntime(output, options.runtimeDir);
|
|
445
514
|
if (!generateProject)
|
|
446
515
|
return;
|
|
447
516
|
try {
|
|
@@ -567,9 +636,11 @@ export {
|
|
|
567
636
|
syncWebAssets,
|
|
568
637
|
showSimulator,
|
|
569
638
|
run,
|
|
639
|
+
resolveRuntimeDir,
|
|
570
640
|
renderWatchEntitlements,
|
|
571
641
|
renderUsageDescriptions,
|
|
572
642
|
renderUrlTypes,
|
|
643
|
+
renderRuntimeSettings,
|
|
573
644
|
renderPrivacyManifest,
|
|
574
645
|
renderOrientations,
|
|
575
646
|
renderEntitlements,
|
|
@@ -578,6 +649,7 @@ export {
|
|
|
578
649
|
pickSimulator,
|
|
579
650
|
orderSimulators,
|
|
580
651
|
open,
|
|
652
|
+
installRuntime,
|
|
581
653
|
init,
|
|
582
654
|
build,
|
|
583
655
|
bootSimulator
|