craft-native 0.0.499 → 0.0.502
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/android/src/index.d.ts +6 -0
- package/dist/android/src/index.js +2 -0
- package/dist/android/templates/CraftNativeFlatList.kt.template +59 -4
- package/dist/android/templates/CraftNativeShell.kt.template +110 -2
- package/dist/android/templates/MainActivityNative.kt.template +180 -47
- package/dist/api/process.d.ts +23 -28
- package/dist/bridge/core.d.ts +30 -6
- package/dist/cli.js +39 -19
- package/dist/components/index.d.ts +1 -1
- package/dist/index.cjs +90 -99
- package/dist/index.js +90 -99
- package/dist/ios/templates/CraftApp.swift +17 -0
- package/dist/ios/templates/CraftHybrid.swift +16 -0
- package/dist/ios/templates/CraftNativeFiles.swift +152 -7
- package/dist/ios/templates/CraftNativeFlatList.swift +43 -6
- package/dist/ios/templates/CraftNativeScreen.swift +286 -86
- package/dist/ios/templates/CraftScheduledWorkouts.swift +11 -4
- package/dist/ios/templates/CraftWebAudio.swift +20 -1
- package/dist/package.d.ts +22 -0
- package/package.json +1 -1
package/dist/api/process.d.ts
CHANGED
|
@@ -60,7 +60,6 @@ export declare function exec(command: string, options?: ExecOptions): Promise<Ex
|
|
|
60
60
|
*/
|
|
61
61
|
export interface SpawnOptions {
|
|
62
62
|
cwd?: string;
|
|
63
|
-
env?: Record<string, string>;
|
|
64
63
|
/**
|
|
65
64
|
* Run `command` as a command line through a shell (cmd.exe on Windows,
|
|
66
65
|
* /bin/sh elsewhere) instead of executing it directly.
|
|
@@ -74,45 +73,41 @@ export interface SpawnOptions {
|
|
|
74
73
|
*/
|
|
75
74
|
shell?: boolean;
|
|
76
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* A process started through the native bridge.
|
|
78
|
+
*
|
|
79
|
+
* What native `shell.spawn` does, and so all this class offers: start a
|
|
80
|
+
* program, and kill it. The child inherits Craft's own standard output and
|
|
81
|
+
* error. Nothing it writes is delivered to the page, and its exit is not
|
|
82
|
+
* reported.
|
|
83
|
+
*
|
|
84
|
+
* `onStdout`, `onStderr`, `onExit` and `write` used to be declared here. No
|
|
85
|
+
* native bridge ever emitted the events behind them or accepted input, so a
|
|
86
|
+
* handler registered with them was never called. They are removed rather than
|
|
87
|
+
* left as methods that accept a callback and stay silent. To read a child's
|
|
88
|
+
* output, run it in your app's backend process and send the result to the
|
|
89
|
+
* page; `exec()` covers a command that finishes and returns its output whole.
|
|
90
|
+
*
|
|
91
|
+
* Windows and Linux desktop builds do not serve the `shell` namespace at all:
|
|
92
|
+
* there `start()` rejects.
|
|
93
|
+
*/
|
|
77
94
|
export declare class ChildProcess {
|
|
78
95
|
private command;
|
|
79
96
|
private args;
|
|
80
97
|
private options;
|
|
81
98
|
private processId;
|
|
82
|
-
private onStdoutHandlers;
|
|
83
|
-
private onStderrHandlers;
|
|
84
|
-
private onExitHandlers;
|
|
85
|
-
private domListeners;
|
|
86
|
-
private exited;
|
|
87
99
|
constructor(command: string, args?: string[], options?: SpawnOptions);
|
|
88
|
-
|
|
89
|
-
private removeDomListeners;
|
|
90
|
-
/** Pid assigned by the native bridge, or null before start(). */
|
|
100
|
+
/** Identifier this process is registered under, or null before start(). */
|
|
91
101
|
get pid(): string | null;
|
|
92
102
|
/**
|
|
93
|
-
* Start the process
|
|
103
|
+
* Start the process. Resolves once native has started it.
|
|
94
104
|
*/
|
|
95
105
|
start(): Promise<void>;
|
|
96
106
|
/**
|
|
97
|
-
*
|
|
98
|
-
|
|
99
|
-
write(data: string): Promise<void>;
|
|
100
|
-
/**
|
|
101
|
-
* Kill the process
|
|
102
|
-
*/
|
|
103
|
-
kill(signal?: string): Promise<void>;
|
|
104
|
-
/**
|
|
105
|
-
* Listen for stdout data
|
|
106
|
-
*/
|
|
107
|
-
onStdout(handler: (data: string) => void): () => void;
|
|
108
|
-
/**
|
|
109
|
-
* Listen for stderr data
|
|
110
|
-
*/
|
|
111
|
-
onStderr(handler: (data: string) => void): () => void;
|
|
112
|
-
/**
|
|
113
|
-
* Listen for exit
|
|
107
|
+
* Kill the process. Native sends the platform's default termination; there
|
|
108
|
+
* is no signal to choose.
|
|
114
109
|
*/
|
|
115
|
-
|
|
110
|
+
kill(): Promise<void>;
|
|
116
111
|
}
|
|
117
112
|
/**
|
|
118
113
|
* Spawn a child process
|
package/dist/bridge/core.d.ts
CHANGED
|
@@ -46,6 +46,12 @@ export declare const BridgeErrorCodes: {
|
|
|
46
46
|
readonly PROTOCOL_MISMATCH: -8;
|
|
47
47
|
/** Bridge transitioned from connected to disconnected with requests in flight */
|
|
48
48
|
readonly DISCONNECTED: -9;
|
|
49
|
+
/**
|
|
50
|
+
* The native side received the request and refused or failed it. Not
|
|
51
|
+
* retried: asking again gets the same answer. `data.nativeCode` carries
|
|
52
|
+
* the bridge's own string code when it sent one.
|
|
53
|
+
*/
|
|
54
|
+
readonly NATIVE_ERROR: -10;
|
|
49
55
|
};
|
|
50
56
|
export type BridgeErrorCode = typeof BridgeErrorCodes[keyof typeof BridgeErrorCodes];
|
|
51
57
|
/**
|
|
@@ -136,12 +142,12 @@ export declare class NativeBridge extends EventEmitter {
|
|
|
136
142
|
* BridgeError(PROTOCOL_MISMATCH) if the native side reports a version we
|
|
137
143
|
* don't speak.
|
|
138
144
|
*
|
|
139
|
-
* This is **opt-in** — you must call it explicitly
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
+
* This is **opt-in** — you must call it explicitly, and only against a
|
|
146
|
+
* host of your own that answers a `_handshake` request. Craft's own
|
|
147
|
+
* webview hosts do not: inside one, requests go through
|
|
148
|
+
* `window.craft.invoke`, which takes `namespace.action` names, and this
|
|
149
|
+
* call is rejected immediately instead of negotiating anything. Use
|
|
150
|
+
* `window.craft.capabilities` to ask a Craft host what it serves.
|
|
145
151
|
*/
|
|
146
152
|
handshake(): Promise<{
|
|
147
153
|
nativeVersion: number;
|
|
@@ -203,6 +209,24 @@ export declare class NativeBridge extends EventEmitter {
|
|
|
203
209
|
* use that to fail fast instead of waiting for the request timeout.
|
|
204
210
|
*/
|
|
205
211
|
private send;
|
|
212
|
+
/**
|
|
213
|
+
* Hand a request to `window.craft.invoke`, the dispatcher that
|
|
214
|
+
* `craft-bridge.js` injects into every Craft webview, and settle the
|
|
215
|
+
* pending entry with what native answers.
|
|
216
|
+
*
|
|
217
|
+
* This is the only path by which `request()` reaches native code. The
|
|
218
|
+
* `{id, type: 'request', method, params}` envelope this class builds is not
|
|
219
|
+
* something any Craft host parses: posted raw to the `craft` message
|
|
220
|
+
* handler it was dropped, and every `request()` waited out its timeout and
|
|
221
|
+
* its retries. The method name is used as written, `namespace.action`, so
|
|
222
|
+
* it has to be one the native bridge serves (`fs.readFile`,
|
|
223
|
+
* `shell.openUrl`, `dialog.openFile`); one it does not serve is rejected
|
|
224
|
+
* with `NATIVE_ERROR` straight away.
|
|
225
|
+
*
|
|
226
|
+
* Returns false when the injected bridge is not present, so the older
|
|
227
|
+
* transports below still get their turn in a host that provides one.
|
|
228
|
+
*/
|
|
229
|
+
private sendThroughInjectedBridge;
|
|
206
230
|
/**
|
|
207
231
|
* Reject the pending entry corresponding to `message.id` with `error`,
|
|
208
232
|
* if any. Used by `send()` when serialization or transport throws so
|
package/dist/cli.js
CHANGED
|
@@ -1395,6 +1395,33 @@ Description: ${description || opts.name}
|
|
|
1395
1395
|
}
|
|
1396
1396
|
});
|
|
1397
1397
|
}
|
|
1398
|
+
function rpmSpec(options) {
|
|
1399
|
+
return [
|
|
1400
|
+
"%global debug_package %{nil}",
|
|
1401
|
+
"%global _build_id_links none",
|
|
1402
|
+
"%global __strip /bin/true",
|
|
1403
|
+
"%global __os_install_post %{nil}",
|
|
1404
|
+
`Name: ${options.name}`,
|
|
1405
|
+
`Version: ${options.version}`,
|
|
1406
|
+
"Release: 1",
|
|
1407
|
+
`Summary: ${options.summary}`,
|
|
1408
|
+
"License: MIT",
|
|
1409
|
+
`Source0: ${options.name}`,
|
|
1410
|
+
...options.requires ? [`Requires: ${options.requires}`] : [],
|
|
1411
|
+
"",
|
|
1412
|
+
"%description",
|
|
1413
|
+
options.description,
|
|
1414
|
+
"",
|
|
1415
|
+
"%install",
|
|
1416
|
+
"mkdir -p %{buildroot}/usr/bin",
|
|
1417
|
+
`install -m 755 %{SOURCE0} %{buildroot}/usr/bin/${options.name}`,
|
|
1418
|
+
"",
|
|
1419
|
+
"%files",
|
|
1420
|
+
`/usr/bin/${options.name}`,
|
|
1421
|
+
""
|
|
1422
|
+
].join(`
|
|
1423
|
+
`);
|
|
1424
|
+
}
|
|
1398
1425
|
async function createRPM(opts) {
|
|
1399
1426
|
return new Promise((resolve) => {
|
|
1400
1427
|
try {
|
|
@@ -1427,26 +1454,17 @@ async function createRPM(opts) {
|
|
|
1427
1454
|
return r;
|
|
1428
1455
|
}).join(", ");
|
|
1429
1456
|
copyFileSync(opts.binaryPath, join3(sourcesDir, sanitizedName));
|
|
1430
|
-
const specContent =
|
|
1431
|
-
Version: ${opts.version}
|
|
1432
|
-
Release: 1%{?dist}
|
|
1433
|
-
Summary: ${summary}
|
|
1434
|
-
License: MIT
|
|
1435
|
-
Requires: ${requires}
|
|
1436
|
-
|
|
1437
|
-
%description
|
|
1438
|
-
${description}
|
|
1439
|
-
|
|
1440
|
-
%install
|
|
1441
|
-
mkdir -p %{buildroot}/usr/bin
|
|
1442
|
-
install -m 755 %{SOURCE0} %{buildroot}/usr/bin/${sanitizedName}
|
|
1443
|
-
|
|
1444
|
-
%files
|
|
1445
|
-
/usr/bin/${sanitizedName}
|
|
1446
|
-
`;
|
|
1457
|
+
const specContent = rpmSpec({ name: sanitizedName, version: opts.version, summary, description, requires });
|
|
1447
1458
|
const specPath = join3(specDir, `${opts.name.toLowerCase()}.spec`);
|
|
1448
1459
|
writeFileSync4(specPath, specContent);
|
|
1449
1460
|
const proc = spawn("rpmbuild", ["-bb", specPath]);
|
|
1461
|
+
let said = "";
|
|
1462
|
+
proc.stdout?.on("data", (chunk) => {
|
|
1463
|
+
said += chunk.toString();
|
|
1464
|
+
});
|
|
1465
|
+
proc.stderr?.on("data", (chunk) => {
|
|
1466
|
+
said += chunk.toString();
|
|
1467
|
+
});
|
|
1450
1468
|
proc.on("close", (code) => {
|
|
1451
1469
|
if (code === 0) {
|
|
1452
1470
|
const rpmName = `${opts.name.toLowerCase()}-${opts.version}-1.x86_64.rpm`;
|
|
@@ -1458,7 +1476,9 @@ install -m 755 %{SOURCE0} %{buildroot}/usr/bin/${sanitizedName}
|
|
|
1458
1476
|
resolve({ success: false, error: "Failed to copy built RPM" });
|
|
1459
1477
|
}
|
|
1460
1478
|
} else {
|
|
1461
|
-
resolve({ success: false, error: `rpmbuild exited with code ${code}
|
|
1479
|
+
resolve({ success: false, error: `rpmbuild exited with code ${code}: ${said.trim().split(`
|
|
1480
|
+
`).slice(-12).join(`
|
|
1481
|
+
`)}` });
|
|
1462
1482
|
}
|
|
1463
1483
|
});
|
|
1464
1484
|
proc.on("error", (err) => {
|
|
@@ -3246,7 +3266,7 @@ function pinCraftNativeDependency(packagePath, craftVersion) {
|
|
|
3246
3266
|
`);
|
|
3247
3267
|
}
|
|
3248
3268
|
// package.json
|
|
3249
|
-
var version = "0.0.
|
|
3269
|
+
var version = "0.0.502";
|
|
3250
3270
|
|
|
3251
3271
|
// bin/cli.ts
|
|
3252
3272
|
var spawnedFrom = process6.env[CRAFT_CLI_SPAWN_MARKER];
|
|
@@ -801,7 +801,7 @@ export interface TextInputProps extends BaseProps {
|
|
|
801
801
|
autoCapitalize?: 'none' | 'sentences' | 'words' | 'characters';
|
|
802
802
|
/** Auto correct */
|
|
803
803
|
autoCorrect?: boolean;
|
|
804
|
-
/**
|
|
804
|
+
/** Focus the input when it mounts, or when this turns on; not on each render. */
|
|
805
805
|
autoFocus?: boolean;
|
|
806
806
|
/** Secure text entry (password) */
|
|
807
807
|
secureTextEntry?: boolean;
|
package/dist/index.cjs
CHANGED
|
@@ -376,7 +376,7 @@ function craftBinaryNotFoundMessage(triedPath) {
|
|
|
376
376
|
`);
|
|
377
377
|
}
|
|
378
378
|
// package.json
|
|
379
|
-
var version = "0.0.
|
|
379
|
+
var version = "0.0.502";
|
|
380
380
|
|
|
381
381
|
// src/sdk-version.ts
|
|
382
382
|
var SDK_VERSION = version;
|
|
@@ -1764,6 +1764,33 @@ Description: ${description || opts.name}
|
|
|
1764
1764
|
}
|
|
1765
1765
|
});
|
|
1766
1766
|
}
|
|
1767
|
+
function rpmSpec(options) {
|
|
1768
|
+
return [
|
|
1769
|
+
"%global debug_package %{nil}",
|
|
1770
|
+
"%global _build_id_links none",
|
|
1771
|
+
"%global __strip /bin/true",
|
|
1772
|
+
"%global __os_install_post %{nil}",
|
|
1773
|
+
`Name: ${options.name}`,
|
|
1774
|
+
`Version: ${options.version}`,
|
|
1775
|
+
"Release: 1",
|
|
1776
|
+
`Summary: ${options.summary}`,
|
|
1777
|
+
"License: MIT",
|
|
1778
|
+
`Source0: ${options.name}`,
|
|
1779
|
+
...options.requires ? [`Requires: ${options.requires}`] : [],
|
|
1780
|
+
"",
|
|
1781
|
+
"%description",
|
|
1782
|
+
options.description,
|
|
1783
|
+
"",
|
|
1784
|
+
"%install",
|
|
1785
|
+
"mkdir -p %{buildroot}/usr/bin",
|
|
1786
|
+
`install -m 755 %{SOURCE0} %{buildroot}/usr/bin/${options.name}`,
|
|
1787
|
+
"",
|
|
1788
|
+
"%files",
|
|
1789
|
+
`/usr/bin/${options.name}`,
|
|
1790
|
+
""
|
|
1791
|
+
].join(`
|
|
1792
|
+
`);
|
|
1793
|
+
}
|
|
1767
1794
|
async function createRPM(opts) {
|
|
1768
1795
|
return new Promise((resolve) => {
|
|
1769
1796
|
try {
|
|
@@ -1796,26 +1823,17 @@ async function createRPM(opts) {
|
|
|
1796
1823
|
return r;
|
|
1797
1824
|
}).join(", ");
|
|
1798
1825
|
import_fs.copyFileSync(opts.binaryPath, import_path.join(sourcesDir, sanitizedName));
|
|
1799
|
-
const specContent =
|
|
1800
|
-
Version: ${opts.version}
|
|
1801
|
-
Release: 1%{?dist}
|
|
1802
|
-
Summary: ${summary}
|
|
1803
|
-
License: MIT
|
|
1804
|
-
Requires: ${requires}
|
|
1805
|
-
|
|
1806
|
-
%description
|
|
1807
|
-
${description}
|
|
1808
|
-
|
|
1809
|
-
%install
|
|
1810
|
-
mkdir -p %{buildroot}/usr/bin
|
|
1811
|
-
install -m 755 %{SOURCE0} %{buildroot}/usr/bin/${sanitizedName}
|
|
1812
|
-
|
|
1813
|
-
%files
|
|
1814
|
-
/usr/bin/${sanitizedName}
|
|
1815
|
-
`;
|
|
1826
|
+
const specContent = rpmSpec({ name: sanitizedName, version: opts.version, summary, description, requires });
|
|
1816
1827
|
const specPath = import_path.join(specDir, `${opts.name.toLowerCase()}.spec`);
|
|
1817
1828
|
import_fs.writeFileSync(specPath, specContent);
|
|
1818
1829
|
const proc = import_child_process.spawn("rpmbuild", ["-bb", specPath]);
|
|
1830
|
+
let said = "";
|
|
1831
|
+
proc.stdout?.on("data", (chunk) => {
|
|
1832
|
+
said += chunk.toString();
|
|
1833
|
+
});
|
|
1834
|
+
proc.stderr?.on("data", (chunk) => {
|
|
1835
|
+
said += chunk.toString();
|
|
1836
|
+
});
|
|
1819
1837
|
proc.on("close", (code) => {
|
|
1820
1838
|
if (code === 0) {
|
|
1821
1839
|
const rpmName = `${opts.name.toLowerCase()}-${opts.version}-1.x86_64.rpm`;
|
|
@@ -1827,7 +1845,9 @@ install -m 755 %{SOURCE0} %{buildroot}/usr/bin/${sanitizedName}
|
|
|
1827
1845
|
resolve({ success: false, error: "Failed to copy built RPM" });
|
|
1828
1846
|
}
|
|
1829
1847
|
} else {
|
|
1830
|
-
resolve({ success: false, error: `rpmbuild exited with code ${code}
|
|
1848
|
+
resolve({ success: false, error: `rpmbuild exited with code ${code}: ${said.trim().split(`
|
|
1849
|
+
`).slice(-12).join(`
|
|
1850
|
+
`)}` });
|
|
1831
1851
|
}
|
|
1832
1852
|
});
|
|
1833
1853
|
proc.on("error", (err) => {
|
|
@@ -2364,7 +2384,8 @@ var BridgeErrorCodes = {
|
|
|
2364
2384
|
BRIDGE_DESTROYED: -6,
|
|
2365
2385
|
BUSY: -7,
|
|
2366
2386
|
PROTOCOL_MISMATCH: -8,
|
|
2367
|
-
DISCONNECTED: -9
|
|
2387
|
+
DISCONNECTED: -9,
|
|
2388
|
+
NATIVE_ERROR: -10
|
|
2368
2389
|
};
|
|
2369
2390
|
var BRIDGE_PROTOCOL_VERSION = 1;
|
|
2370
2391
|
function buildMessageId(prefix, counter) {
|
|
@@ -2772,6 +2793,9 @@ class NativeBridge extends import_events.EventEmitter {
|
|
|
2772
2793
|
}
|
|
2773
2794
|
try {
|
|
2774
2795
|
if (typeof window !== "undefined") {
|
|
2796
|
+
if (message.type === "request" && this.sendThroughInjectedBridge(message)) {
|
|
2797
|
+
return true;
|
|
2798
|
+
}
|
|
2775
2799
|
if (window.webkit?.messageHandlers?.craft) {
|
|
2776
2800
|
window.webkit.messageHandlers.craft.postMessage(message);
|
|
2777
2801
|
return true;
|
|
@@ -2799,6 +2823,31 @@ class NativeBridge extends import_events.EventEmitter {
|
|
|
2799
2823
|
return false;
|
|
2800
2824
|
}
|
|
2801
2825
|
}
|
|
2826
|
+
sendThroughInjectedBridge(message) {
|
|
2827
|
+
const injected = window.craft;
|
|
2828
|
+
if (!injected || typeof injected.invoke !== "function" || typeof message.method !== "string")
|
|
2829
|
+
return false;
|
|
2830
|
+
let call;
|
|
2831
|
+
try {
|
|
2832
|
+
call = Promise.resolve(injected.invoke(message.method, message.params));
|
|
2833
|
+
} catch (e) {
|
|
2834
|
+
call = Promise.reject(e);
|
|
2835
|
+
}
|
|
2836
|
+
call.then((result) => this.handleResponse({ id: message.id, type: "response", result }), (error) => {
|
|
2837
|
+
const detail = error ?? {};
|
|
2838
|
+
const text = typeof detail.message === "string" && detail.message.length > 0 ? detail.message : `Native bridge refused ${message.method}`;
|
|
2839
|
+
this.handleResponse({
|
|
2840
|
+
id: message.id,
|
|
2841
|
+
type: "response",
|
|
2842
|
+
error: {
|
|
2843
|
+
code: BridgeErrorCodes.NATIVE_ERROR,
|
|
2844
|
+
message: text,
|
|
2845
|
+
data: { nativeCode: typeof detail.code === "string" ? detail.code : undefined, method: message.method }
|
|
2846
|
+
}
|
|
2847
|
+
});
|
|
2848
|
+
});
|
|
2849
|
+
return true;
|
|
2850
|
+
}
|
|
2802
2851
|
failPendingForMessage(message, error) {
|
|
2803
2852
|
const pending = this.pendingRequests.get(message.id);
|
|
2804
2853
|
if (!pending)
|
|
@@ -5109,7 +5158,7 @@ async function getSystemInfo() {
|
|
|
5109
5158
|
}
|
|
5110
5159
|
async function exec(command, options) {
|
|
5111
5160
|
if (typeof window !== "undefined" && window.craft) {
|
|
5112
|
-
return callBridge3("
|
|
5161
|
+
return callBridge3("shell.exec", { command, cwd: options?.cwd });
|
|
5113
5162
|
}
|
|
5114
5163
|
const { exec: nodeExec } = await import("node:child_process");
|
|
5115
5164
|
const { promisify } = await import("node:util");
|
|
@@ -5130,107 +5179,46 @@ async function exec(command, options) {
|
|
|
5130
5179
|
};
|
|
5131
5180
|
}
|
|
5132
5181
|
}
|
|
5182
|
+
var nextProcessId = 0;
|
|
5183
|
+
function shellFacade() {
|
|
5184
|
+
return window.craft?.shell;
|
|
5185
|
+
}
|
|
5133
5186
|
|
|
5134
5187
|
class ChildProcess {
|
|
5135
5188
|
command;
|
|
5136
5189
|
args;
|
|
5137
5190
|
options;
|
|
5138
5191
|
processId = null;
|
|
5139
|
-
onStdoutHandlers = [];
|
|
5140
|
-
onStderrHandlers = [];
|
|
5141
|
-
onExitHandlers = [];
|
|
5142
|
-
domListeners = [];
|
|
5143
|
-
exited = false;
|
|
5144
5192
|
constructor(command, args = [], options = {}) {
|
|
5145
5193
|
this.command = command;
|
|
5146
5194
|
this.args = args;
|
|
5147
5195
|
this.options = options;
|
|
5148
5196
|
}
|
|
5149
|
-
addDomListener(type, handler) {
|
|
5150
|
-
if (typeof window === "undefined")
|
|
5151
|
-
return;
|
|
5152
|
-
window.addEventListener(type, handler);
|
|
5153
|
-
this.domListeners.push({ type, handler });
|
|
5154
|
-
}
|
|
5155
|
-
removeDomListeners() {
|
|
5156
|
-
if (typeof window === "undefined")
|
|
5157
|
-
return;
|
|
5158
|
-
for (const { type, handler } of this.domListeners) {
|
|
5159
|
-
window.removeEventListener(type, handler);
|
|
5160
|
-
}
|
|
5161
|
-
this.domListeners = [];
|
|
5162
|
-
}
|
|
5163
5197
|
get pid() {
|
|
5164
5198
|
return this.processId;
|
|
5165
5199
|
}
|
|
5166
5200
|
async start() {
|
|
5167
5201
|
if (typeof window !== "undefined" && window.craft) {
|
|
5168
|
-
|
|
5202
|
+
nextProcessId += 1;
|
|
5203
|
+
const id = `sdk-${Date.now().toString(36)}-${nextProcessId}`;
|
|
5204
|
+
await callBridge3("shell.spawn", {
|
|
5205
|
+
id,
|
|
5169
5206
|
command: this.command,
|
|
5170
5207
|
args: this.args,
|
|
5171
|
-
|
|
5208
|
+
cwd: this.options.cwd,
|
|
5209
|
+
shell: this.options.shell
|
|
5172
5210
|
});
|
|
5173
|
-
this.processId =
|
|
5174
|
-
const stdoutHandler = (event) => {
|
|
5175
|
-
if (event.detail.pid === this.processId) {
|
|
5176
|
-
this.onStdoutHandlers.forEach((h) => h(event.detail.data));
|
|
5177
|
-
}
|
|
5178
|
-
};
|
|
5179
|
-
const stderrHandler = (event) => {
|
|
5180
|
-
if (event.detail.pid === this.processId) {
|
|
5181
|
-
this.onStderrHandlers.forEach((h) => h(event.detail.data));
|
|
5182
|
-
}
|
|
5183
|
-
};
|
|
5184
|
-
const exitHandler = (event) => {
|
|
5185
|
-
if (event.detail.pid === this.processId) {
|
|
5186
|
-
this.exited = true;
|
|
5187
|
-
this.onExitHandlers.forEach((h) => h(event.detail.code));
|
|
5188
|
-
this.removeDomListeners();
|
|
5189
|
-
}
|
|
5190
|
-
};
|
|
5191
|
-
this.addDomListener("craft:process:stdout", stdoutHandler);
|
|
5192
|
-
this.addDomListener("craft:process:stderr", stderrHandler);
|
|
5193
|
-
this.addDomListener("craft:process:exit", exitHandler);
|
|
5211
|
+
this.processId = id;
|
|
5194
5212
|
return;
|
|
5195
5213
|
}
|
|
5196
5214
|
throw new Error("spawn() requires Craft environment");
|
|
5197
5215
|
}
|
|
5198
|
-
async
|
|
5216
|
+
async kill() {
|
|
5199
5217
|
if (typeof window !== "undefined" && window.craft && this.processId) {
|
|
5200
|
-
await
|
|
5218
|
+
await shellFacade()?.kill?.(this.processId);
|
|
5219
|
+
this.processId = null;
|
|
5201
5220
|
}
|
|
5202
5221
|
}
|
|
5203
|
-
async kill(signal = "SIGTERM") {
|
|
5204
|
-
if (typeof window !== "undefined" && window.craft && this.processId) {
|
|
5205
|
-
await callBridge3("process.kill", { pid: this.processId, signal });
|
|
5206
|
-
if (this.exited)
|
|
5207
|
-
this.removeDomListeners();
|
|
5208
|
-
}
|
|
5209
|
-
}
|
|
5210
|
-
onStdout(handler) {
|
|
5211
|
-
this.onStdoutHandlers.push(handler);
|
|
5212
|
-
return () => {
|
|
5213
|
-
const idx = this.onStdoutHandlers.indexOf(handler);
|
|
5214
|
-
if (idx >= 0)
|
|
5215
|
-
this.onStdoutHandlers.splice(idx, 1);
|
|
5216
|
-
};
|
|
5217
|
-
}
|
|
5218
|
-
onStderr(handler) {
|
|
5219
|
-
this.onStderrHandlers.push(handler);
|
|
5220
|
-
return () => {
|
|
5221
|
-
const idx = this.onStderrHandlers.indexOf(handler);
|
|
5222
|
-
if (idx >= 0)
|
|
5223
|
-
this.onStderrHandlers.splice(idx, 1);
|
|
5224
|
-
};
|
|
5225
|
-
}
|
|
5226
|
-
onExit(handler) {
|
|
5227
|
-
this.onExitHandlers.push(handler);
|
|
5228
|
-
return () => {
|
|
5229
|
-
const idx = this.onExitHandlers.indexOf(handler);
|
|
5230
|
-
if (idx >= 0)
|
|
5231
|
-
this.onExitHandlers.splice(idx, 1);
|
|
5232
|
-
};
|
|
5233
|
-
}
|
|
5234
5222
|
}
|
|
5235
5223
|
function spawn2(command, args, options) {
|
|
5236
5224
|
return new ChildProcess(command, args, options);
|
|
@@ -5243,7 +5231,7 @@ function cwd() {
|
|
|
5243
5231
|
}
|
|
5244
5232
|
async function homeDir() {
|
|
5245
5233
|
if (typeof window !== "undefined" && window.craft) {
|
|
5246
|
-
return callBridge3("
|
|
5234
|
+
return (await callBridge3("fs.getHomeDir"))?.path || "/";
|
|
5247
5235
|
}
|
|
5248
5236
|
if (typeof process !== "undefined") {
|
|
5249
5237
|
const os = await import("node:os");
|
|
@@ -5253,7 +5241,7 @@ async function homeDir() {
|
|
|
5253
5241
|
}
|
|
5254
5242
|
async function tempDir() {
|
|
5255
5243
|
if (typeof window !== "undefined" && window.craft) {
|
|
5256
|
-
return callBridge3("
|
|
5244
|
+
return (await callBridge3("fs.getTempDir"))?.path || "/tmp";
|
|
5257
5245
|
}
|
|
5258
5246
|
if (typeof process !== "undefined") {
|
|
5259
5247
|
const os = await import("node:os");
|
|
@@ -5281,7 +5269,10 @@ function argv() {
|
|
|
5281
5269
|
}
|
|
5282
5270
|
async function open(target) {
|
|
5283
5271
|
if (typeof window !== "undefined" && window.craft) {
|
|
5284
|
-
|
|
5272
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(target) && !/^[a-z]:[\\/]/i.test(target))
|
|
5273
|
+
await callBridge3("shell.openUrl", { url: target });
|
|
5274
|
+
else
|
|
5275
|
+
await shellFacade()?.openPath?.(target);
|
|
5285
5276
|
return;
|
|
5286
5277
|
}
|
|
5287
5278
|
const platform = getPlatform();
|