elit 3.6.5 → 3.6.6
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 +6 -0
- package/dist/build.d.ts +4 -1
- package/dist/cli.cjs +502 -11
- package/dist/cli.mjs +502 -11
- package/dist/config.d.ts +8 -1
- package/dist/coverage.d.ts +4 -1
- package/dist/desktop-auto-render.cjs +5 -4
- package/dist/desktop-auto-render.d.ts +4 -1
- package/dist/desktop-auto-render.js +5 -4
- package/dist/desktop-auto-render.mjs +5 -4
- package/dist/dom.cjs +5 -4
- package/dist/dom.d.ts +2 -0
- package/dist/dom.js +5 -4
- package/dist/dom.mjs +5 -4
- package/dist/el.d.ts +2 -0
- package/dist/index.cjs +5 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -4
- package/dist/index.mjs +5 -4
- package/dist/native.cjs +5 -4
- package/dist/native.d.ts +2 -0
- package/dist/native.js +5 -4
- package/dist/native.mjs +5 -4
- package/dist/render-context.d.ts +4 -1
- package/dist/router.cjs +5 -4
- package/dist/router.d.ts +2 -0
- package/dist/router.js +5 -4
- package/dist/router.mjs +5 -4
- package/dist/{server-CcBFc2F5.d.ts → server-uMQvZAll.d.ts} +9 -0
- package/dist/server.cjs +146 -4
- package/dist/server.d.ts +4 -1
- package/dist/server.js +4494 -285
- package/dist/server.mjs +146 -4
- package/dist/smtp-server.cjs +115 -0
- package/dist/smtp-server.d.ts +41 -0
- package/dist/smtp-server.js +4186 -0
- package/dist/smtp-server.mjs +87 -0
- package/dist/state.cjs +5 -4
- package/dist/state.d.ts +2 -0
- package/dist/state.js +5 -4
- package/dist/state.mjs +5 -4
- package/dist/types.d.ts +34 -2
- package/dist/universal.d.ts +2 -0
- package/package.json +9 -1
package/dist/cli.mjs
CHANGED
|
@@ -60469,6 +60469,71 @@ function lookup(path) {
|
|
|
60469
60469
|
// src/server.ts
|
|
60470
60470
|
init_runtime();
|
|
60471
60471
|
|
|
60472
|
+
// src/smtp-server.ts
|
|
60473
|
+
import { SMTPServer } from "smtp-server";
|
|
60474
|
+
var DEFAULT_SMTP_PORT = 2525;
|
|
60475
|
+
var DEFAULT_SMTP_HOST = "127.0.0.1";
|
|
60476
|
+
function resolveSmtpServerConfig(config = {}) {
|
|
60477
|
+
const { port = DEFAULT_SMTP_PORT, host = DEFAULT_SMTP_HOST, label, ...serverOptions } = config;
|
|
60478
|
+
return {
|
|
60479
|
+
...serverOptions,
|
|
60480
|
+
port,
|
|
60481
|
+
host,
|
|
60482
|
+
label
|
|
60483
|
+
};
|
|
60484
|
+
}
|
|
60485
|
+
function normalizeSmtpServerConfigs(input) {
|
|
60486
|
+
const configs = Array.isArray(input) ? input : input ? [input] : [];
|
|
60487
|
+
return configs.map((config) => resolveSmtpServerConfig(config));
|
|
60488
|
+
}
|
|
60489
|
+
function closeSmtpServer(server) {
|
|
60490
|
+
return new Promise((resolve9, reject) => {
|
|
60491
|
+
let settled = false;
|
|
60492
|
+
const finish = (error) => {
|
|
60493
|
+
if (settled) {
|
|
60494
|
+
return;
|
|
60495
|
+
}
|
|
60496
|
+
settled = true;
|
|
60497
|
+
if (error) {
|
|
60498
|
+
reject(error);
|
|
60499
|
+
return;
|
|
60500
|
+
}
|
|
60501
|
+
resolve9();
|
|
60502
|
+
};
|
|
60503
|
+
const handleCloseError = (error) => {
|
|
60504
|
+
const errorCode = error.code;
|
|
60505
|
+
if (errorCode === "ERR_SERVER_NOT_RUNNING") {
|
|
60506
|
+
finish();
|
|
60507
|
+
return;
|
|
60508
|
+
}
|
|
60509
|
+
finish(error);
|
|
60510
|
+
};
|
|
60511
|
+
try {
|
|
60512
|
+
server.close(() => finish());
|
|
60513
|
+
} catch (error) {
|
|
60514
|
+
handleCloseError(error);
|
|
60515
|
+
}
|
|
60516
|
+
});
|
|
60517
|
+
}
|
|
60518
|
+
function createSmtpServer(config = {}) {
|
|
60519
|
+
const resolvedConfig = resolveSmtpServerConfig(config);
|
|
60520
|
+
const { port, host, label: _label, ...serverOptions } = resolvedConfig;
|
|
60521
|
+
const server = new SMTPServer(serverOptions);
|
|
60522
|
+
return {
|
|
60523
|
+
server,
|
|
60524
|
+
config: resolvedConfig,
|
|
60525
|
+
listen(callback) {
|
|
60526
|
+
return callback ? server.listen(port, host, callback) : server.listen(port, host);
|
|
60527
|
+
},
|
|
60528
|
+
address() {
|
|
60529
|
+
return server.server.address();
|
|
60530
|
+
},
|
|
60531
|
+
close() {
|
|
60532
|
+
return closeSmtpServer(server);
|
|
60533
|
+
}
|
|
60534
|
+
};
|
|
60535
|
+
}
|
|
60536
|
+
|
|
60472
60537
|
// src/render-context.ts
|
|
60473
60538
|
var RUNTIME_TARGET_KEY = "__ELIT_RUNTIME_TARGET__";
|
|
60474
60539
|
var CAPTURED_RENDER_KEY = "__ELIT_CAPTURED_RENDER__";
|
|
@@ -60922,6 +60987,7 @@ var DomNode = class {
|
|
|
60922
60987
|
html += `</${tagName}>${newLine}`;
|
|
60923
60988
|
return html;
|
|
60924
60989
|
}
|
|
60990
|
+
const isRawText = tagName === "script" || tagName === "style";
|
|
60925
60991
|
if (children && children.length > 0) {
|
|
60926
60992
|
const resolvedChildren = children.map((c) => {
|
|
60927
60993
|
const resolved = this.resolveStateValue(c);
|
|
@@ -60937,11 +61003,11 @@ var DomNode = class {
|
|
|
60937
61003
|
if (Array.isArray(child)) {
|
|
60938
61004
|
for (const c of child) {
|
|
60939
61005
|
if (!shouldSkipChild(c)) {
|
|
60940
|
-
html += this.renderToString(c, { pretty, indent: indent5 + 1 });
|
|
61006
|
+
html += isRawText && typeof c === "string" ? c : this.renderToString(c, { pretty, indent: indent5 + 1 });
|
|
60941
61007
|
}
|
|
60942
61008
|
}
|
|
60943
61009
|
} else {
|
|
60944
|
-
html += this.renderToString(child, { pretty, indent: indent5 + 1 });
|
|
61010
|
+
html += isRawText && typeof child === "string" ? child : this.renderToString(child, { pretty, indent: indent5 + 1 });
|
|
60945
61011
|
}
|
|
60946
61012
|
}
|
|
60947
61013
|
html += indentStr;
|
|
@@ -60951,11 +61017,11 @@ var DomNode = class {
|
|
|
60951
61017
|
if (Array.isArray(child)) {
|
|
60952
61018
|
for (const c of child) {
|
|
60953
61019
|
if (!shouldSkipChild(c)) {
|
|
60954
|
-
html += this.renderToString(c, { pretty: false, indent: 0 });
|
|
61020
|
+
html += isRawText && typeof c === "string" ? c : this.renderToString(c, { pretty: false, indent: 0 });
|
|
60955
61021
|
}
|
|
60956
61022
|
}
|
|
60957
61023
|
} else {
|
|
60958
|
-
html += this.renderToString(child, { pretty: false, indent: 0 });
|
|
61024
|
+
html += isRawText && typeof child === "string" ? child : this.renderToString(child, { pretty: false, indent: 0 });
|
|
60959
61025
|
}
|
|
60960
61026
|
}
|
|
60961
61027
|
}
|
|
@@ -61883,6 +61949,56 @@ var defaultOptions = {
|
|
|
61883
61949
|
worker: [],
|
|
61884
61950
|
mode: "dev"
|
|
61885
61951
|
};
|
|
61952
|
+
function createSmtpBindingKey(config) {
|
|
61953
|
+
return `${config.host}:${config.port}`;
|
|
61954
|
+
}
|
|
61955
|
+
function createSmtpServerLabel(config) {
|
|
61956
|
+
return config.label || createSmtpBindingKey(config);
|
|
61957
|
+
}
|
|
61958
|
+
function formatSmtpServerAddress(address, fallback) {
|
|
61959
|
+
if (typeof address === "string") {
|
|
61960
|
+
return address;
|
|
61961
|
+
}
|
|
61962
|
+
if (address) {
|
|
61963
|
+
return `${address.address}:${address.port}`;
|
|
61964
|
+
}
|
|
61965
|
+
return createSmtpBindingKey(fallback);
|
|
61966
|
+
}
|
|
61967
|
+
function collectSmtpServerConfigs(config, usesClientArray) {
|
|
61968
|
+
const modeLabel = config.mode || "dev";
|
|
61969
|
+
const smtpConfigs = normalizeSmtpServerConfigs(config.smtp).map((smtpConfig, index) => ({
|
|
61970
|
+
...smtpConfig,
|
|
61971
|
+
label: smtpConfig.label || `${modeLabel}.smtp[${index}]`
|
|
61972
|
+
}));
|
|
61973
|
+
if (!usesClientArray || !config.clients) {
|
|
61974
|
+
return smtpConfigs;
|
|
61975
|
+
}
|
|
61976
|
+
for (let clientIndex = 0; clientIndex < config.clients.length; clientIndex += 1) {
|
|
61977
|
+
const client = config.clients[clientIndex];
|
|
61978
|
+
const clientDescriptor = client.basePath || client.root;
|
|
61979
|
+
const clientPrefix = clientDescriptor ? `${modeLabel}.clients[${clientIndex}] (${clientDescriptor})` : `${modeLabel}.clients[${clientIndex}]`;
|
|
61980
|
+
smtpConfigs.push(...normalizeSmtpServerConfigs(client.smtp).map((smtpConfig, smtpIndex) => ({
|
|
61981
|
+
...smtpConfig,
|
|
61982
|
+
label: smtpConfig.label || `${clientPrefix}.smtp[${smtpIndex}]`
|
|
61983
|
+
})));
|
|
61984
|
+
}
|
|
61985
|
+
return smtpConfigs;
|
|
61986
|
+
}
|
|
61987
|
+
function assertUniqueSmtpServerBindings(configs) {
|
|
61988
|
+
const seenBindings = /* @__PURE__ */ new Map();
|
|
61989
|
+
for (const smtpConfig of configs) {
|
|
61990
|
+
if (smtpConfig.port === 0) {
|
|
61991
|
+
continue;
|
|
61992
|
+
}
|
|
61993
|
+
const bindingKey = createSmtpBindingKey(smtpConfig);
|
|
61994
|
+
const currentLabel = createSmtpServerLabel(smtpConfig);
|
|
61995
|
+
const previousLabel = seenBindings.get(bindingKey);
|
|
61996
|
+
if (previousLabel) {
|
|
61997
|
+
throw new Error(`Duplicate SMTP server binding "${bindingKey}" configured for ${previousLabel} and ${currentLabel}`);
|
|
61998
|
+
}
|
|
61999
|
+
seenBindings.set(bindingKey, currentLabel);
|
|
62000
|
+
}
|
|
62001
|
+
}
|
|
61886
62002
|
function shouldUseClientFallbackRoot(primaryRoot, fallbackRoot, indexPath) {
|
|
61887
62003
|
if (!fallbackRoot) {
|
|
61888
62004
|
return false;
|
|
@@ -62017,6 +62133,7 @@ function createDevServer(options) {
|
|
|
62017
62133
|
const globalWebSocketEndpoints = usesClientArray ? normalizeWebSocketEndpoints(config.ws) : [];
|
|
62018
62134
|
const normalizedWebSocketEndpoints = [...normalizedClients.flatMap((client) => client.ws), ...globalWebSocketEndpoints];
|
|
62019
62135
|
const seenWebSocketPaths = /* @__PURE__ */ new Set();
|
|
62136
|
+
const smtpServerConfigs = collectSmtpServerConfigs(config, usesClientArray);
|
|
62020
62137
|
for (const endpoint of normalizedWebSocketEndpoints) {
|
|
62021
62138
|
if (endpoint.path === ELIT_INTERNAL_WS_PATH) {
|
|
62022
62139
|
throw new Error(`WebSocket path "${ELIT_INTERNAL_WS_PATH}" is reserved for Elit internals`);
|
|
@@ -62026,6 +62143,21 @@ function createDevServer(options) {
|
|
|
62026
62143
|
}
|
|
62027
62144
|
seenWebSocketPaths.add(endpoint.path);
|
|
62028
62145
|
}
|
|
62146
|
+
assertUniqueSmtpServerBindings(smtpServerConfigs);
|
|
62147
|
+
const smtpServers = smtpServerConfigs.map((smtpConfig) => {
|
|
62148
|
+
const smtpServer = createSmtpServer(smtpConfig);
|
|
62149
|
+
const smtpLabel = createSmtpServerLabel(smtpServer.config);
|
|
62150
|
+
smtpServer.server.on("error", (error) => {
|
|
62151
|
+
console.error(`[SMTP] ${smtpLabel} error:`, error);
|
|
62152
|
+
});
|
|
62153
|
+
if (config.logging) {
|
|
62154
|
+
smtpServer.server.server.once("listening", () => {
|
|
62155
|
+
console.log(`[SMTP] ${smtpLabel} listening on ${formatSmtpServerAddress(smtpServer.address(), smtpServer.config)}`);
|
|
62156
|
+
});
|
|
62157
|
+
}
|
|
62158
|
+
smtpServer.listen();
|
|
62159
|
+
return smtpServer;
|
|
62160
|
+
});
|
|
62029
62161
|
const globalProxyHandler = config.proxy ? createProxyHandler(config.proxy) : null;
|
|
62030
62162
|
const server = createServer(async (req, res) => {
|
|
62031
62163
|
const originalUrl = req.url || "/";
|
|
@@ -62566,6 +62698,15 @@ ${elitImportMap}`;
|
|
|
62566
62698
|
if (config.logging) console.log("\n[Server] Shutting down...");
|
|
62567
62699
|
transformCache.clear();
|
|
62568
62700
|
if (watcher) await watcher.close();
|
|
62701
|
+
if (smtpServers.length > 0) {
|
|
62702
|
+
await Promise.all(smtpServers.map(async (smtpServer) => {
|
|
62703
|
+
try {
|
|
62704
|
+
await smtpServer.close();
|
|
62705
|
+
} catch (error) {
|
|
62706
|
+
console.error(`[SMTP] ${createSmtpServerLabel(smtpServer.config)} close error:`, error);
|
|
62707
|
+
}
|
|
62708
|
+
}));
|
|
62709
|
+
}
|
|
62569
62710
|
if (webSocketServers.length > 0) {
|
|
62570
62711
|
webSocketServers.forEach((wsServer) => wsServer.close());
|
|
62571
62712
|
wsClients.clear();
|
|
@@ -62582,6 +62723,7 @@ ${elitImportMap}`;
|
|
|
62582
62723
|
return {
|
|
62583
62724
|
server,
|
|
62584
62725
|
wss,
|
|
62726
|
+
smtpServers,
|
|
62585
62727
|
url: primaryUrl,
|
|
62586
62728
|
state: stateManager,
|
|
62587
62729
|
close
|
|
@@ -74461,7 +74603,7 @@ var WAPK_AUTH_TAG_LENGTH = 16;
|
|
|
74461
74603
|
var WAPK_SCRYPT_OPTIONS = { N: 16384, r: 8, p: 1 };
|
|
74462
74604
|
var DEFAULT_GOOGLE_DRIVE_TOKEN_ENV = "GOOGLE_DRIVE_ACCESS_TOKEN";
|
|
74463
74605
|
var DEFAULT_WAPK_ONLINE_URL_ENV = "ELIT_WAPK_ONLINE_URL";
|
|
74464
|
-
var DEFAULT_WAPK_ONLINE_URLS = ["
|
|
74606
|
+
var DEFAULT_WAPK_ONLINE_URLS = ["http://wapk.d-osc.com/"];
|
|
74465
74607
|
var WAPK_ONLINE_CREATE_PATH = "/api/shared-session/create";
|
|
74466
74608
|
var WAPK_ONLINE_READ_PATH = "/api/shared-session/read";
|
|
74467
74609
|
var WAPK_ONLINE_CLOSE_PATH = "/api/shared-session/close";
|
|
@@ -74499,6 +74641,113 @@ function normalizeNonEmptyString(value) {
|
|
|
74499
74641
|
const normalized = value.trim();
|
|
74500
74642
|
return normalized.length > 0 ? normalized : void 0;
|
|
74501
74643
|
}
|
|
74644
|
+
function normalizeGeneratedIdentifier(value) {
|
|
74645
|
+
const normalized = value.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
74646
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
74647
|
+
}
|
|
74648
|
+
function joinGeneratedIdentifier(...segments) {
|
|
74649
|
+
const normalizedSegments = segments.map((segment) => segment ? normalizeGeneratedIdentifier(segment) : void 0).filter((segment) => Boolean(segment));
|
|
74650
|
+
return normalizedSegments.length > 0 ? normalizedSegments.join(".") : void 0;
|
|
74651
|
+
}
|
|
74652
|
+
function parseScopedPackageName(value) {
|
|
74653
|
+
const normalizedValue = normalizeNonEmptyString(value);
|
|
74654
|
+
if (!normalizedValue) {
|
|
74655
|
+
return {};
|
|
74656
|
+
}
|
|
74657
|
+
if (!normalizedValue.startsWith("@")) {
|
|
74658
|
+
return {
|
|
74659
|
+
packageName: normalizedValue
|
|
74660
|
+
};
|
|
74661
|
+
}
|
|
74662
|
+
const scopeSeparatorIndex = normalizedValue.indexOf("/");
|
|
74663
|
+
if (scopeSeparatorIndex === -1) {
|
|
74664
|
+
return {
|
|
74665
|
+
packageName: normalizedValue
|
|
74666
|
+
};
|
|
74667
|
+
}
|
|
74668
|
+
return {
|
|
74669
|
+
scope: normalizedValue.slice(1, scopeSeparatorIndex),
|
|
74670
|
+
packageName: normalizedValue.slice(scopeSeparatorIndex + 1)
|
|
74671
|
+
};
|
|
74672
|
+
}
|
|
74673
|
+
function readPackageAuthorMetadata(value) {
|
|
74674
|
+
if (typeof value === "string") {
|
|
74675
|
+
const normalizedValue = value.trim();
|
|
74676
|
+
if (!normalizedValue) {
|
|
74677
|
+
return {};
|
|
74678
|
+
}
|
|
74679
|
+
const email = normalizedValue.match(/<([^>]+)>/)?.[1];
|
|
74680
|
+
const url = normalizedValue.match(/\(([^)]+)\)/)?.[1];
|
|
74681
|
+
const name = normalizedValue.replace(/<[^>]+>/g, " ").replace(/\([^)]+\)/g, " ").replace(/\s+/g, " ").trim();
|
|
74682
|
+
return {
|
|
74683
|
+
name: normalizeNonEmptyString(name),
|
|
74684
|
+
email: normalizeNonEmptyString(email),
|
|
74685
|
+
url: normalizeNonEmptyString(url)
|
|
74686
|
+
};
|
|
74687
|
+
}
|
|
74688
|
+
if (!isRecord(value)) {
|
|
74689
|
+
return {};
|
|
74690
|
+
}
|
|
74691
|
+
return {
|
|
74692
|
+
name: normalizeNonEmptyString(value.name),
|
|
74693
|
+
email: normalizeNonEmptyString(value.email),
|
|
74694
|
+
url: normalizeNonEmptyString(value.url)
|
|
74695
|
+
};
|
|
74696
|
+
}
|
|
74697
|
+
function extractPublisherIdFromRepository(value) {
|
|
74698
|
+
const repositoryUrl = typeof value === "string" ? value : isRecord(value) ? normalizeNonEmptyString(value.url) : void 0;
|
|
74699
|
+
const normalizedRepositoryUrl = normalizeNonEmptyString(repositoryUrl);
|
|
74700
|
+
if (!normalizedRepositoryUrl) {
|
|
74701
|
+
return void 0;
|
|
74702
|
+
}
|
|
74703
|
+
const shorthandMatch = normalizedRepositoryUrl.match(/^(?:github|gitlab|bitbucket):([^/]+)\/.+$/i);
|
|
74704
|
+
if (shorthandMatch?.[1]) {
|
|
74705
|
+
return normalizeGeneratedIdentifier(shorthandMatch[1]);
|
|
74706
|
+
}
|
|
74707
|
+
const sshMatch = normalizedRepositoryUrl.match(/^[^@]+@[^:]+:([^/]+)\/.+$/i);
|
|
74708
|
+
if (sshMatch?.[1]) {
|
|
74709
|
+
return normalizeGeneratedIdentifier(sshMatch[1]);
|
|
74710
|
+
}
|
|
74711
|
+
try {
|
|
74712
|
+
const parsed = new URL(normalizedRepositoryUrl.replace(/^git\+/, ""));
|
|
74713
|
+
const firstPathSegment = parsed.pathname.replace(/\.git$/i, "").split("/").filter(Boolean)[0];
|
|
74714
|
+
return normalizeGeneratedIdentifier(firstPathSegment ?? parsed.hostname.replace(/^www\./i, ""));
|
|
74715
|
+
} catch {
|
|
74716
|
+
return void 0;
|
|
74717
|
+
}
|
|
74718
|
+
}
|
|
74719
|
+
function extractPublisherIdFromUrl(value) {
|
|
74720
|
+
const normalizedValue = normalizeNonEmptyString(value);
|
|
74721
|
+
if (!normalizedValue) {
|
|
74722
|
+
return void 0;
|
|
74723
|
+
}
|
|
74724
|
+
try {
|
|
74725
|
+
const parsed = new URL(normalizedValue);
|
|
74726
|
+
return normalizeGeneratedIdentifier(parsed.hostname.replace(/^www\./i, ""));
|
|
74727
|
+
} catch {
|
|
74728
|
+
return void 0;
|
|
74729
|
+
}
|
|
74730
|
+
}
|
|
74731
|
+
function extractPublisherIdFromEmail(value) {
|
|
74732
|
+
const normalizedValue = normalizeNonEmptyString(value);
|
|
74733
|
+
if (!normalizedValue) {
|
|
74734
|
+
return void 0;
|
|
74735
|
+
}
|
|
74736
|
+
const domain = normalizedValue.split("@")[1];
|
|
74737
|
+
return domain ? normalizeGeneratedIdentifier(domain.replace(/^www\./i, "")) : void 0;
|
|
74738
|
+
}
|
|
74739
|
+
function resolveAutoGeneratedWapkAppId(packageName, fallbackName) {
|
|
74740
|
+
const scopedPackage = parseScopedPackageName(packageName);
|
|
74741
|
+
return joinGeneratedIdentifier(scopedPackage.scope, scopedPackage.packageName ?? fallbackName);
|
|
74742
|
+
}
|
|
74743
|
+
function resolveAutoGeneratedWapkPublisherId(packageJson, fallbackName) {
|
|
74744
|
+
const scopedPackage = parseScopedPackageName(typeof packageJson?.name === "string" ? packageJson.name : void 0);
|
|
74745
|
+
if (scopedPackage.scope) {
|
|
74746
|
+
return normalizeGeneratedIdentifier(scopedPackage.scope);
|
|
74747
|
+
}
|
|
74748
|
+
const author = readPackageAuthorMetadata(packageJson?.author);
|
|
74749
|
+
return extractPublisherIdFromRepository(packageJson?.repository) ?? extractPublisherIdFromUrl(packageJson?.homepage) ?? extractPublisherIdFromUrl(author.url) ?? extractPublisherIdFromEmail(author.email) ?? normalizeGeneratedIdentifier(author.name ?? fallbackName);
|
|
74750
|
+
}
|
|
74502
74751
|
function normalizeStringMap(value) {
|
|
74503
74752
|
if (!isRecord(value)) {
|
|
74504
74753
|
return void 0;
|
|
@@ -74538,6 +74787,8 @@ function normalizeWapkConfig(value) {
|
|
|
74538
74787
|
runtime: normalizeRuntime(value.runtime ?? value.engine),
|
|
74539
74788
|
entry: typeof value.entry === "string" ? value.entry : void 0,
|
|
74540
74789
|
scripts: normalizeStringMap(value.scripts ?? value.script),
|
|
74790
|
+
appId: normalizeNonEmptyString(value.appId),
|
|
74791
|
+
publisherId: normalizeNonEmptyString(value.publisherId),
|
|
74541
74792
|
port: normalizePort(value.port),
|
|
74542
74793
|
env: normalizeStringMap(value.env),
|
|
74543
74794
|
desktop: normalizeDesktopConfig(value.desktop),
|
|
@@ -74827,6 +75078,7 @@ async function readWapkProjectConfig(directory) {
|
|
|
74827
75078
|
const elitConfig = await loadConfig(directory);
|
|
74828
75079
|
const elitWapkConfig = normalizeWapkConfig(elitConfig?.wapk);
|
|
74829
75080
|
const packageJson = readJsonFile(packageJsonPath);
|
|
75081
|
+
const packageJsonWapk = isRecord(packageJson?.wapk) ? packageJson.wapk : void 0;
|
|
74830
75082
|
const packageScripts = normalizeStringMap(packageJson?.scripts) ?? {};
|
|
74831
75083
|
const selectedScripts = elitWapkConfig.scripts ?? packageScripts;
|
|
74832
75084
|
const inferred = inferRuntimeAndEntryFromScript(selectedScripts.start ?? packageScripts.start);
|
|
@@ -74850,12 +75102,16 @@ async function readWapkProjectConfig(directory) {
|
|
|
74850
75102
|
if (!existsSync2(entryPath) || !statSync2(entryPath).isFile()) {
|
|
74851
75103
|
throw new Error(`WAPK entry not found: ${entryPath}`);
|
|
74852
75104
|
}
|
|
75105
|
+
const appId = elitWapkConfig.appId ?? normalizeNonEmptyString(packageJson?.appId) ?? normalizeNonEmptyString(packageJsonWapk?.appId) ?? resolveAutoGeneratedWapkAppId(typeof packageJson?.name === "string" ? packageJson.name : void 0, name);
|
|
75106
|
+
const publisherId = elitWapkConfig.publisherId ?? normalizeNonEmptyString(packageJson?.publisherId) ?? normalizeNonEmptyString(packageJsonWapk?.publisherId) ?? resolveAutoGeneratedWapkPublisherId(packageJson, name);
|
|
74853
75107
|
return {
|
|
74854
75108
|
name,
|
|
74855
75109
|
version,
|
|
74856
75110
|
runtime: runtime2,
|
|
74857
75111
|
entry,
|
|
74858
75112
|
scripts: selectedScripts,
|
|
75113
|
+
appId,
|
|
75114
|
+
publisherId,
|
|
74859
75115
|
port: elitWapkConfig.port,
|
|
74860
75116
|
env: elitWapkConfig.env,
|
|
74861
75117
|
desktop: elitWapkConfig.desktop,
|
|
@@ -74865,11 +75121,14 @@ async function readWapkProjectConfig(directory) {
|
|
|
74865
75121
|
function readIgnorePatterns(directory) {
|
|
74866
75122
|
return readLineIgnorePatterns(join2(directory, ".wapkignore"));
|
|
74867
75123
|
}
|
|
75124
|
+
function parsePatternLines(content) {
|
|
75125
|
+
return content.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && (!line.startsWith("#") || line.startsWith("\\#")));
|
|
75126
|
+
}
|
|
74868
75127
|
function readLineIgnorePatterns(filePath) {
|
|
74869
75128
|
if (!existsSync2(filePath)) {
|
|
74870
75129
|
return [];
|
|
74871
75130
|
}
|
|
74872
|
-
return readFileSync2(filePath, "utf8")
|
|
75131
|
+
return parsePatternLines(readFileSync2(filePath, "utf8"));
|
|
74873
75132
|
}
|
|
74874
75133
|
function normalizePackageEntry(value) {
|
|
74875
75134
|
const normalized = normalizeNonEmptyString(value)?.replace(/^[.][\\/]/, "").split("\\").join("/");
|
|
@@ -75148,6 +75407,91 @@ function shouldIgnore(relativePath2, ignorePatterns, isDirectory) {
|
|
|
75148
75407
|
}
|
|
75149
75408
|
return ignored;
|
|
75150
75409
|
}
|
|
75410
|
+
function matchesPatchPattern(relativePath2, pattern) {
|
|
75411
|
+
const normalizedRule = normalizeIgnorePattern(pattern);
|
|
75412
|
+
if (!normalizedRule) {
|
|
75413
|
+
return false;
|
|
75414
|
+
}
|
|
75415
|
+
const normalizedPath = relativePath2.replace(/\\/g, "/");
|
|
75416
|
+
const subtreeSelector = normalizedRule.pattern.endsWith("/*") && !normalizedRule.pattern.slice(0, -2).includes("*") && !normalizedRule.pattern.slice(0, -2).includes("?");
|
|
75417
|
+
if (subtreeSelector) {
|
|
75418
|
+
const directoryPath = normalizedRule.pattern.slice(0, -2);
|
|
75419
|
+
return directoryPath.length > 0 && normalizedPath.startsWith(`${directoryPath}/`);
|
|
75420
|
+
}
|
|
75421
|
+
const hasGlob = /[*?]/.test(normalizedRule.pattern);
|
|
75422
|
+
if (!hasGlob) {
|
|
75423
|
+
if (normalizedRule.directoryOnly) {
|
|
75424
|
+
return normalizedPath === normalizedRule.pattern || normalizedPath.startsWith(`${normalizedRule.pattern}/`);
|
|
75425
|
+
}
|
|
75426
|
+
return normalizedPath === normalizedRule.pattern;
|
|
75427
|
+
}
|
|
75428
|
+
return globPatternToRegex(normalizedRule.pattern, {
|
|
75429
|
+
directoryOnly: normalizedRule.directoryOnly,
|
|
75430
|
+
matchSegmentsOnly: false
|
|
75431
|
+
}).test(normalizedPath);
|
|
75432
|
+
}
|
|
75433
|
+
function shouldPatchArchivePath(relativePath2, patchPatterns) {
|
|
75434
|
+
let selected = false;
|
|
75435
|
+
for (const pattern of patchPatterns) {
|
|
75436
|
+
const normalizedRule = normalizeIgnorePattern(pattern);
|
|
75437
|
+
if (!normalizedRule) {
|
|
75438
|
+
continue;
|
|
75439
|
+
}
|
|
75440
|
+
if (!matchesPatchPattern(relativePath2, pattern)) {
|
|
75441
|
+
continue;
|
|
75442
|
+
}
|
|
75443
|
+
selected = !normalizedRule.negate;
|
|
75444
|
+
}
|
|
75445
|
+
return selected;
|
|
75446
|
+
}
|
|
75447
|
+
function resolvePatchManifestPatterns(files) {
|
|
75448
|
+
const patchManifest = files.find((file) => file.path === ".wapkpatch");
|
|
75449
|
+
if (!patchManifest) {
|
|
75450
|
+
throw new Error("Patch archive must include a .wapkpatch manifest file.");
|
|
75451
|
+
}
|
|
75452
|
+
const patterns = parsePatternLines(patchManifest.content.toString("utf8"));
|
|
75453
|
+
if (patterns.length === 0) {
|
|
75454
|
+
throw new Error("Patch archive .wapkpatch must define at least one patch rule.");
|
|
75455
|
+
}
|
|
75456
|
+
return patterns;
|
|
75457
|
+
}
|
|
75458
|
+
function applyPatchEntriesToFiles(targetFiles, patchFiles) {
|
|
75459
|
+
const fileMap = new Map(targetFiles.map((file) => [file.path, file]));
|
|
75460
|
+
const fileOrder = targetFiles.map((file) => file.path);
|
|
75461
|
+
const addedPaths = [];
|
|
75462
|
+
const updatedPaths = [];
|
|
75463
|
+
const unchangedPaths = [];
|
|
75464
|
+
for (const patchFile of [...patchFiles].sort((left, right) => left.path.localeCompare(right.path))) {
|
|
75465
|
+
const existing = fileMap.get(patchFile.path);
|
|
75466
|
+
const nextEntry = {
|
|
75467
|
+
path: patchFile.path,
|
|
75468
|
+
content: Buffer.from(patchFile.content),
|
|
75469
|
+
mode: patchFile.mode
|
|
75470
|
+
};
|
|
75471
|
+
if (!existing) {
|
|
75472
|
+
addedPaths.push(patchFile.path);
|
|
75473
|
+
fileOrder.push(patchFile.path);
|
|
75474
|
+
} else if (existing.mode === patchFile.mode && existing.content.equals(patchFile.content)) {
|
|
75475
|
+
unchangedPaths.push(patchFile.path);
|
|
75476
|
+
} else {
|
|
75477
|
+
updatedPaths.push(patchFile.path);
|
|
75478
|
+
}
|
|
75479
|
+
fileMap.set(patchFile.path, nextEntry);
|
|
75480
|
+
}
|
|
75481
|
+
return {
|
|
75482
|
+
files: fileOrder.map((filePath) => {
|
|
75483
|
+
const file = fileMap.get(filePath);
|
|
75484
|
+
if (!file) {
|
|
75485
|
+
throw new Error(`Internal WAPK patch error: missing file entry for ${filePath}`);
|
|
75486
|
+
}
|
|
75487
|
+
return file;
|
|
75488
|
+
}),
|
|
75489
|
+
patchedPaths: [...updatedPaths, ...addedPaths],
|
|
75490
|
+
addedPaths,
|
|
75491
|
+
updatedPaths,
|
|
75492
|
+
unchangedPaths
|
|
75493
|
+
};
|
|
75494
|
+
}
|
|
75151
75495
|
function collectFiles(directory, baseDirectory, ignorePatterns) {
|
|
75152
75496
|
const files = [];
|
|
75153
75497
|
const entries = readdirSync2(directory, { withFileTypes: true });
|
|
@@ -75303,6 +75647,8 @@ function decodeWapkPayload(buffer) {
|
|
|
75303
75647
|
runtime: normalizeRuntime(rawHeader.runtime ?? rawHeader.engine) ?? "node",
|
|
75304
75648
|
entry: typeof rawHeader.entry === "string" ? rawHeader.entry : "index.js",
|
|
75305
75649
|
scripts: normalizeStringMap(rawHeader.scripts) ?? {},
|
|
75650
|
+
appId: normalizeNonEmptyString(rawHeader.appId),
|
|
75651
|
+
publisherId: normalizeNonEmptyString(rawHeader.publisherId),
|
|
75306
75652
|
port: normalizePort(rawHeader.port),
|
|
75307
75653
|
env: normalizeStringMap(rawHeader.env),
|
|
75308
75654
|
desktop: normalizeDesktopConfig(rawHeader.desktop),
|
|
@@ -75800,11 +76146,14 @@ function sanitizeOnlineArchiveFileName(label, fallback) {
|
|
|
75800
76146
|
const fileName = sanitized.length > 0 ? sanitized : "app.wapk";
|
|
75801
76147
|
return fileName.toLowerCase().endsWith(".wapk") ? fileName : `${fileName}.wapk`;
|
|
75802
76148
|
}
|
|
76149
|
+
var WAPK_ONLINE_JOIN_SOURCE_QUERY_PARAM = "launchSource";
|
|
76150
|
+
var WAPK_ONLINE_JOIN_SOURCE_QUERY_VALUE = "elit-wapk-online";
|
|
75803
76151
|
function buildOnlineJoinUrl(baseUrl, joinKey) {
|
|
75804
76152
|
const joinUrl = new URL(baseUrl.toString());
|
|
75805
76153
|
joinUrl.search = "";
|
|
75806
76154
|
joinUrl.hash = "";
|
|
75807
76155
|
joinUrl.searchParams.set("join", joinKey);
|
|
76156
|
+
joinUrl.searchParams.set(WAPK_ONLINE_JOIN_SOURCE_QUERY_PARAM, WAPK_ONLINE_JOIN_SOURCE_QUERY_VALUE);
|
|
75808
76157
|
return joinUrl.toString();
|
|
75809
76158
|
}
|
|
75810
76159
|
async function probeOnlineLauncherUrl(url) {
|
|
@@ -75985,11 +76334,16 @@ async function closeWapkOnlineSharedSession(launcherUrl, session) {
|
|
|
75985
76334
|
function isPmWapkOnlineShutdownEnabled() {
|
|
75986
76335
|
return process.env[WAPK_ONLINE_PM_SHUTDOWN_ENV] === "1" && Boolean(process.stdin) && !process.stdin.isTTY;
|
|
75987
76336
|
}
|
|
75988
|
-
|
|
76337
|
+
function getWapkOnlineProcessDetails() {
|
|
76338
|
+
return `pid ${process.pid}, ppid ${process.ppid}`;
|
|
76339
|
+
}
|
|
76340
|
+
async function waitForWapkOnlineSessionShutdown(launcherUrl, session, archiveHandle, lock, options = {}) {
|
|
75989
76341
|
let snapshotRevision = 0;
|
|
75990
76342
|
let snapshotSyncPending = false;
|
|
75991
76343
|
let snapshotSyncPromise = Promise.resolve();
|
|
75992
76344
|
let lastSnapshotSyncError = null;
|
|
76345
|
+
const allowSigtermClose = options.allowSigtermClose === true;
|
|
76346
|
+
const processDetails = getWapkOnlineProcessDetails();
|
|
75993
76347
|
const syncGuestSnapshotUpdates = () => {
|
|
75994
76348
|
if (snapshotSyncPending) {
|
|
75995
76349
|
return snapshotSyncPromise;
|
|
@@ -76023,6 +76377,7 @@ async function waitForWapkOnlineSessionShutdown(launcherUrl, session, archiveHan
|
|
|
76023
76377
|
void syncGuestSnapshotUpdates();
|
|
76024
76378
|
}, WAPK_ONLINE_KEEPALIVE_INTERVAL_MS);
|
|
76025
76379
|
const pmManaged = isPmWapkOnlineShutdownEnabled();
|
|
76380
|
+
let ignoredSigTermLogged = false;
|
|
76026
76381
|
let stdinBuffer = "";
|
|
76027
76382
|
const cleanup = () => {
|
|
76028
76383
|
clearInterval(keepAlive);
|
|
@@ -76041,7 +76396,17 @@ async function waitForWapkOnlineSessionShutdown(launcherUrl, session, archiveHan
|
|
|
76041
76396
|
finish({ kind: "signal", signal: "SIGINT" });
|
|
76042
76397
|
};
|
|
76043
76398
|
const onSigTerm = () => {
|
|
76044
|
-
|
|
76399
|
+
if (allowSigtermClose) {
|
|
76400
|
+
finish({ kind: "signal", signal: "SIGTERM" });
|
|
76401
|
+
return;
|
|
76402
|
+
}
|
|
76403
|
+
if (ignoredSigTermLogged) {
|
|
76404
|
+
return;
|
|
76405
|
+
}
|
|
76406
|
+
ignoredSigTermLogged = true;
|
|
76407
|
+
console.warn(
|
|
76408
|
+
pmManaged ? `[wapk] Ignoring SIGTERM while shared session ${session.joinKey} is active (${processDetails}). Use elit pm stop, restart, or delete to close the session.` : `[wapk] Ignoring SIGTERM while shared session ${session.joinKey} is active (${processDetails}). Press Ctrl+C to stop sharing, or pass --allow-sigterm-close to close on SIGTERM.`
|
|
76409
|
+
);
|
|
76045
76410
|
};
|
|
76046
76411
|
const onStdinData = (chunk) => {
|
|
76047
76412
|
stdinBuffer += typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
@@ -76066,9 +76431,12 @@ async function waitForWapkOnlineSessionShutdown(launcherUrl, session, archiveHan
|
|
|
76066
76431
|
if (shutdownTrigger.kind === "pm") {
|
|
76067
76432
|
console.log(`
|
|
76068
76433
|
[wapk] PM requested shutdown for shared session ${session.joinKey}...`);
|
|
76434
|
+
} else if (shutdownTrigger.signal === "SIGTERM") {
|
|
76435
|
+
console.log(`
|
|
76436
|
+
[wapk] Received SIGTERM for shared session ${session.joinKey} (${processDetails}); closing because --allow-sigterm-close is enabled...`);
|
|
76069
76437
|
} else {
|
|
76070
76438
|
console.log(`
|
|
76071
|
-
[wapk]
|
|
76439
|
+
[wapk] Received ${shutdownTrigger.signal}; closing shared session ${session.joinKey}...`);
|
|
76072
76440
|
}
|
|
76073
76441
|
try {
|
|
76074
76442
|
await closeWapkOnlineSharedSession(launcherUrl, session);
|
|
@@ -76108,7 +76476,9 @@ async function runWapkOnline(archiveSpecifier, options) {
|
|
|
76108
76476
|
process.exitCode = await waitForWapkOnlineSessionShutdown(launcherUrl, {
|
|
76109
76477
|
joinKey: response.joinKey,
|
|
76110
76478
|
adminToken: response.adminToken
|
|
76111
|
-
}, archiveHandle, onlineArchiveLock
|
|
76479
|
+
}, archiveHandle, onlineArchiveLock, {
|
|
76480
|
+
allowSigtermClose: options.allowSigtermClose
|
|
76481
|
+
});
|
|
76112
76482
|
}
|
|
76113
76483
|
async function writeWapkArchiveFromMemory(archiveHandle, header, files, lock) {
|
|
76114
76484
|
const updatedHeader = {
|
|
@@ -76365,6 +76735,8 @@ async function packWapkDirectory(directory, options = {}) {
|
|
|
76365
76735
|
runtime: config.runtime,
|
|
76366
76736
|
entry: config.entry,
|
|
76367
76737
|
scripts: config.scripts,
|
|
76738
|
+
appId: config.appId,
|
|
76739
|
+
publisherId: config.publisherId,
|
|
76368
76740
|
port: config.port,
|
|
76369
76741
|
env: config.env,
|
|
76370
76742
|
desktop: config.desktop,
|
|
@@ -76396,6 +76768,56 @@ function extractWapkArchive(wapkPath, outputDir = ".", options = {}) {
|
|
|
76396
76768
|
console.log(`Extracted ${archive.files.length} files to: ${extractDirectory}`);
|
|
76397
76769
|
return extractDirectory;
|
|
76398
76770
|
}
|
|
76771
|
+
async function patchWapkArchive(wapkPath, options) {
|
|
76772
|
+
const targetHandle = resolveArchiveHandle(wapkPath);
|
|
76773
|
+
const targetSnapshot = await targetHandle.readSnapshot();
|
|
76774
|
+
const targetEnvelope = parseWapkEnvelope(targetSnapshot.buffer);
|
|
76775
|
+
const targetArchive = decodeWapk(targetSnapshot.buffer, options);
|
|
76776
|
+
const targetLock = targetEnvelope.version === WAPK_LOCKED_VERSION ? resolveArchiveCredentials(options) : void 0;
|
|
76777
|
+
const patchArchive = readWapkArchive(options.from, {
|
|
76778
|
+
password: options.fromPassword ?? options.password
|
|
76779
|
+
});
|
|
76780
|
+
const patchPatterns = resolvePatchManifestPatterns(patchArchive.files);
|
|
76781
|
+
const selectedPatchFiles = patchArchive.files.filter((file) => file.path !== ".wapkpatch").filter((file) => shouldPatchArchivePath(file.path, patchPatterns));
|
|
76782
|
+
const patchResult = applyPatchEntriesToFiles(targetArchive.files, selectedPatchFiles);
|
|
76783
|
+
console.log(`[wapk] Target: ${targetSnapshot.label ?? targetHandle.label}`);
|
|
76784
|
+
console.log(`[wapk] Patch: ${options.from}`);
|
|
76785
|
+
console.log(`[wapk] Rules: ${patchPatterns.length}`);
|
|
76786
|
+
if (selectedPatchFiles.length === 0) {
|
|
76787
|
+
console.log("[wapk] No files matched .wapkpatch. Archive was not modified.");
|
|
76788
|
+
return {
|
|
76789
|
+
archiveLabel: targetSnapshot.label ?? targetHandle.label,
|
|
76790
|
+
patchedPaths: [],
|
|
76791
|
+
addedPaths: [],
|
|
76792
|
+
updatedPaths: [],
|
|
76793
|
+
unchangedPaths: []
|
|
76794
|
+
};
|
|
76795
|
+
}
|
|
76796
|
+
if (patchResult.patchedPaths.length === 0) {
|
|
76797
|
+
console.log("[wapk] Matching patch files were already up to date. Archive was not modified.");
|
|
76798
|
+
return {
|
|
76799
|
+
archiveLabel: targetSnapshot.label ?? targetHandle.label,
|
|
76800
|
+
patchedPaths: [],
|
|
76801
|
+
addedPaths: [],
|
|
76802
|
+
updatedPaths: [],
|
|
76803
|
+
unchangedPaths: patchResult.unchangedPaths
|
|
76804
|
+
};
|
|
76805
|
+
}
|
|
76806
|
+
const writeResult = await writeWapkArchiveFromMemory(
|
|
76807
|
+
targetHandle,
|
|
76808
|
+
targetArchive.header,
|
|
76809
|
+
patchResult.files,
|
|
76810
|
+
targetLock
|
|
76811
|
+
);
|
|
76812
|
+
console.log(`[wapk] Applied ${patchResult.patchedPaths.length} patch file${patchResult.patchedPaths.length === 1 ? "" : "s"}.`);
|
|
76813
|
+
return {
|
|
76814
|
+
archiveLabel: writeResult.label,
|
|
76815
|
+
patchedPaths: patchResult.patchedPaths,
|
|
76816
|
+
addedPaths: patchResult.addedPaths,
|
|
76817
|
+
updatedPaths: patchResult.updatedPaths,
|
|
76818
|
+
unchangedPaths: patchResult.unchangedPaths
|
|
76819
|
+
};
|
|
76820
|
+
}
|
|
76399
76821
|
async function prepareWapkApp(wapkPath, options = {}) {
|
|
76400
76822
|
const archiveHandle = resolveArchiveHandle(wapkPath, options.googleDrive);
|
|
76401
76823
|
const archivePath = archiveHandle.identifier;
|
|
@@ -76504,6 +76926,8 @@ function inspectWapkArchive(wapkPath, options = {}) {
|
|
|
76504
76926
|
console.log(`App: ${decoded.header.version}`);
|
|
76505
76927
|
console.log(`Runtime: ${decoded.header.runtime}`);
|
|
76506
76928
|
console.log(`Entry: ${decoded.header.entry}`);
|
|
76929
|
+
console.log(`App ID: ${decoded.header.appId ?? "n/a"}`);
|
|
76930
|
+
console.log(`Publisher:${decoded.header.publisherId ? ` ${decoded.header.publisherId}` : " n/a"}`);
|
|
76507
76931
|
console.log(`Port: ${decoded.header.port ?? "default"}`);
|
|
76508
76932
|
console.log(`Created: ${decoded.header.createdAt}`);
|
|
76509
76933
|
if (decoded.header.env && Object.keys(decoded.header.env).length > 0) {
|
|
@@ -76535,6 +76959,8 @@ function printWapkHelp() {
|
|
|
76535
76959
|
" elit wapk gdrive://<fileId> --online",
|
|
76536
76960
|
" elit wapk pack [directory]",
|
|
76537
76961
|
" elit wapk pack [directory] --password secret-123",
|
|
76962
|
+
" elit wapk patch <file.wapk> --from <patch.wapk>",
|
|
76963
|
+
" elit wapk patch <file.wapk> --use <patch.wapk>",
|
|
76538
76964
|
" elit wapk inspect <file.wapk>",
|
|
76539
76965
|
" elit wapk extract <file.wapk>",
|
|
76540
76966
|
"",
|
|
@@ -76546,24 +76972,32 @@ function printWapkHelp() {
|
|
|
76546
76972
|
" --archive-watch Pull external archive changes back into the temp workdir",
|
|
76547
76973
|
" --no-archive-watch Disable external archive read sync",
|
|
76548
76974
|
" --online Create an Elit Run share session, stay alive, and close on Ctrl+C",
|
|
76975
|
+
" --allow-sigterm-close Allow SIGTERM to close an online shared session",
|
|
76549
76976
|
" --online-url <url> Elit Run URL (default: auto-detect localhost:4177 or localhost:4179)",
|
|
76550
76977
|
" --google-drive-file-id <id> Run a remote .wapk directly from Google Drive",
|
|
76551
76978
|
" --google-drive-token-env <name> Env var containing the Google Drive OAuth token",
|
|
76552
76979
|
" --google-drive-access-token <value> OAuth token for Google Drive API calls",
|
|
76553
76980
|
" --google-drive-shared-drive Include supportsAllDrives=true for shared drives",
|
|
76981
|
+
" --from <file.wapk> Patch source archive for elit wapk patch",
|
|
76982
|
+
" --use <file.wapk> Alias for --from",
|
|
76983
|
+
" --from-password <value> Password for unlocking the patch archive",
|
|
76554
76984
|
" --include-deps Legacy compatibility flag; node_modules are packed by default",
|
|
76555
76985
|
" --password <value> Password for locking or unlocking the archive",
|
|
76556
76986
|
" -h, --help Show this help",
|
|
76557
76987
|
"",
|
|
76558
76988
|
"Notes:",
|
|
76559
76989
|
" - Pack reads wapk from elit.config.* and falls back to package.json.",
|
|
76990
|
+
" - If appId or publisherId is not configured, pack auto-generates stable defaults from package metadata.",
|
|
76560
76991
|
" - Pack includes node_modules by default; use .wapkignore if you need to exclude them, and !pattern to re-include later matches.",
|
|
76992
|
+
" - Patch reads .wapkpatch from the patch archive and applies only matching archive-relative paths.",
|
|
76993
|
+
" - Patch keeps the target archive metadata and lock mode; use --from-password when the patch archive uses a different password.",
|
|
76561
76994
|
" - Run never installs dependencies automatically; archives must include the runtime dependencies they need.",
|
|
76562
76995
|
" - Run mode can read config.wapk.run for default file/runtime/live-sync options.",
|
|
76563
76996
|
" - Browser-style archives with scripts.start or wapk.script.start run that start script automatically.",
|
|
76564
76997
|
" - Run mode keeps files in RAM and syncs changes both to and from the archive source.",
|
|
76565
76998
|
" - Google Drive mode talks to the Drive API directly; no local archive file is required.",
|
|
76566
76999
|
" - Online mode creates a shared session on Elit Run directly, keeps the CLI alive, and closes it on Ctrl+C.",
|
|
77000
|
+
" - Online mode ignores SIGTERM by default; pass --allow-sigterm-close if an external supervisor should close the shared session with SIGTERM.",
|
|
76567
77001
|
" - Locked archives in online mode must provide --password so the CLI can build the shared snapshot.",
|
|
76568
77002
|
" - Locked archives require the same password for run/extract/inspect.",
|
|
76569
77003
|
" - Archives stay unlocked by default unless a password is provided.",
|
|
@@ -76613,6 +77047,7 @@ function parseRunArgs(args) {
|
|
|
76613
77047
|
let archiveSyncInterval;
|
|
76614
77048
|
let online;
|
|
76615
77049
|
let onlineUrl;
|
|
77050
|
+
let allowSigtermClose;
|
|
76616
77051
|
let password;
|
|
76617
77052
|
for (let index = 0; index < args.length; index++) {
|
|
76618
77053
|
const arg = args[index];
|
|
@@ -76664,6 +77099,10 @@ function parseRunArgs(args) {
|
|
|
76664
77099
|
onlineUrl = readRequiredOptionValue(args, ++index, "--online-url");
|
|
76665
77100
|
break;
|
|
76666
77101
|
}
|
|
77102
|
+
case "--allow-sigterm-close": {
|
|
77103
|
+
allowSigtermClose = true;
|
|
77104
|
+
break;
|
|
77105
|
+
}
|
|
76667
77106
|
case "--google-drive-file-id": {
|
|
76668
77107
|
googleDrive = {
|
|
76669
77108
|
...googleDrive,
|
|
@@ -76706,7 +77145,7 @@ function parseRunArgs(args) {
|
|
|
76706
77145
|
break;
|
|
76707
77146
|
}
|
|
76708
77147
|
}
|
|
76709
|
-
return { file, googleDrive, runtime: runtime2, syncInterval, useWatcher, watchArchive, archiveSyncInterval, online, onlineUrl, password };
|
|
77148
|
+
return { file, googleDrive, runtime: runtime2, syncInterval, useWatcher, watchArchive, archiveSyncInterval, online, onlineUrl, allowSigtermClose, password };
|
|
76710
77149
|
}
|
|
76711
77150
|
function parsePackArgs(args) {
|
|
76712
77151
|
let directory = ".";
|
|
@@ -76732,6 +77171,46 @@ function parsePackArgs(args) {
|
|
|
76732
77171
|
}
|
|
76733
77172
|
return { directory, includeDeps, password };
|
|
76734
77173
|
}
|
|
77174
|
+
function parsePatchArgs(args) {
|
|
77175
|
+
let file;
|
|
77176
|
+
let from;
|
|
77177
|
+
let password;
|
|
77178
|
+
let fromPassword;
|
|
77179
|
+
for (let index = 0; index < args.length; index++) {
|
|
77180
|
+
const arg = args[index];
|
|
77181
|
+
switch (arg) {
|
|
77182
|
+
case "--from":
|
|
77183
|
+
case "--use": {
|
|
77184
|
+
if (from) {
|
|
77185
|
+
throw new Error("WAPK patch accepts exactly one patch archive via --from or --use.");
|
|
77186
|
+
}
|
|
77187
|
+
from = readRequiredOptionValue(args, ++index, arg);
|
|
77188
|
+
break;
|
|
77189
|
+
}
|
|
77190
|
+
case "--password": {
|
|
77191
|
+
password = readRequiredOptionValue(args, ++index, "--password");
|
|
77192
|
+
break;
|
|
77193
|
+
}
|
|
77194
|
+
case "--from-password": {
|
|
77195
|
+
fromPassword = readRequiredOptionValue(args, ++index, "--from-password");
|
|
77196
|
+
break;
|
|
77197
|
+
}
|
|
77198
|
+
default:
|
|
77199
|
+
if (arg.startsWith("-")) {
|
|
77200
|
+
throw new Error(`Unknown WAPK option: ${arg}`);
|
|
77201
|
+
}
|
|
77202
|
+
if (file) {
|
|
77203
|
+
throw new Error("Usage: elit wapk patch <file.wapk> --from <patch.wapk>");
|
|
77204
|
+
}
|
|
77205
|
+
file = arg;
|
|
77206
|
+
break;
|
|
77207
|
+
}
|
|
77208
|
+
}
|
|
77209
|
+
if (!file || !from) {
|
|
77210
|
+
throw new Error("Usage: elit wapk patch <file.wapk> --from <patch.wapk>");
|
|
77211
|
+
}
|
|
77212
|
+
return { file, from, password, fromPassword };
|
|
77213
|
+
}
|
|
76735
77214
|
async function readConfiguredWapkRunDefaults(cwd) {
|
|
76736
77215
|
const config = await loadConfig(cwd);
|
|
76737
77216
|
const runConfig = normalizeWapkRunConfig(config?.wapk?.run);
|
|
@@ -76771,6 +77250,7 @@ function resolveConfiguredWapkRunOptions(options, defaults) {
|
|
|
76771
77250
|
archiveSyncInterval: options.archiveSyncInterval ?? defaults?.archiveSyncInterval,
|
|
76772
77251
|
online: options.online ?? defaults?.online ?? Boolean(onlineUrl),
|
|
76773
77252
|
onlineUrl,
|
|
77253
|
+
allowSigtermClose: options.allowSigtermClose === true,
|
|
76774
77254
|
password: options.password ?? defaults?.password
|
|
76775
77255
|
};
|
|
76776
77256
|
}
|
|
@@ -76803,6 +77283,15 @@ async function runWapkCommand(args, cwd = process.cwd()) {
|
|
|
76803
77283
|
});
|
|
76804
77284
|
return;
|
|
76805
77285
|
}
|
|
77286
|
+
if (args[0] === "patch") {
|
|
77287
|
+
const options = parsePatchArgs(args.slice(1));
|
|
77288
|
+
await patchWapkArchive(options.file, {
|
|
77289
|
+
from: options.from,
|
|
77290
|
+
password: options.password,
|
|
77291
|
+
fromPassword: options.fromPassword
|
|
77292
|
+
});
|
|
77293
|
+
return;
|
|
77294
|
+
}
|
|
76806
77295
|
if (args[0] === "inspect") {
|
|
76807
77296
|
const options = parseArchiveAccessArgs(args.slice(1), "Usage: elit wapk inspect <file.wapk>");
|
|
76808
77297
|
inspectWapkArchive(options.file, options);
|
|
@@ -76831,6 +77320,7 @@ async function runWapkCommand(args, cwd = process.cwd()) {
|
|
|
76831
77320
|
await runWapkOnline(archiveSpecifier, {
|
|
76832
77321
|
googleDrive: runOptions.googleDrive,
|
|
76833
77322
|
onlineUrl: runOptions.onlineUrl,
|
|
77323
|
+
allowSigtermClose: runOptions.allowSigtermClose,
|
|
76834
77324
|
password: runOptions.password
|
|
76835
77325
|
});
|
|
76836
77326
|
return;
|
|
@@ -83163,6 +83653,7 @@ WAPK Options:
|
|
|
83163
83653
|
elit wapk run [file.wapk] Run a packaged app or the configured default archive
|
|
83164
83654
|
elit wapk run --google-drive-file-id <id> Run a packaged app directly from Google Drive
|
|
83165
83655
|
elit wapk pack [directory] Pack a directory into a .wapk archive
|
|
83656
|
+
elit wapk patch <file.wapk> --from <patch.wapk> Apply a manifest-driven patch archive
|
|
83166
83657
|
elit wapk inspect <file.wapk> Inspect a .wapk archive
|
|
83167
83658
|
elit wapk extract <file.wapk> Extract a .wapk archive
|
|
83168
83659
|
elit wapk --runtime node|bun|deno [file] Override the packaged runtime
|