@arcote.tech/arc-cli 0.7.0 → 0.7.2
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/index.js +1410 -1339
- package/package.json +7 -7
- package/src/builder/access-extractor.ts +10 -24
- package/src/builder/module-builder.ts +343 -160
- package/src/commands/platform-build.ts +2 -1
- package/src/commands/platform-deploy.ts +30 -21
- package/src/deploy/ansible.ts +23 -3
- package/src/deploy/assets/ansible/site.yml +23 -7
- package/src/deploy/assets.ts +23 -7
- package/src/deploy/bootstrap.ts +137 -28
- package/src/deploy/compose.ts +4 -3
- package/src/deploy/config.ts +38 -3
- package/src/deploy/deploy-env.ts +1 -1
- package/src/deploy/env-file.ts +103 -0
- package/src/deploy/image.ts +7 -1
- package/src/deploy/ssh.ts +51 -2
- package/src/index.ts +5 -0
- package/src/platform/server.ts +99 -99
- package/src/platform/shared.ts +28 -240
- package/src/platform/startup.ts +4 -5
package/dist/index.js
CHANGED
|
@@ -8974,547 +8974,826 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
8974
8974
|
exports.watch = watch;
|
|
8975
8975
|
});
|
|
8976
8976
|
|
|
8977
|
-
//
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
|
|
8993
|
-
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9002
|
-
|
|
9003
|
-
backward: (count = 1) => `${CSI}${count}D`,
|
|
9004
|
-
nextLine: (count = 1) => `${CSI}E`.repeat(count),
|
|
9005
|
-
prevLine: (count = 1) => `${CSI}F`.repeat(count),
|
|
9006
|
-
left: `${CSI}G`,
|
|
9007
|
-
hide: `${CSI}?25l`,
|
|
9008
|
-
show: `${CSI}?25h`,
|
|
9009
|
-
save: `${ESC2}7`,
|
|
9010
|
-
restore: `${ESC2}8`
|
|
9011
|
-
};
|
|
9012
|
-
var scroll = {
|
|
9013
|
-
up: (count = 1) => `${CSI}S`.repeat(count),
|
|
9014
|
-
down: (count = 1) => `${CSI}T`.repeat(count)
|
|
9015
|
-
};
|
|
9016
|
-
var erase = {
|
|
9017
|
-
screen: `${CSI}2J`,
|
|
9018
|
-
up: (count = 1) => `${CSI}1J`.repeat(count),
|
|
9019
|
-
down: (count = 1) => `${CSI}J`.repeat(count),
|
|
9020
|
-
line: `${CSI}2K`,
|
|
9021
|
-
lineEnd: `${CSI}K`,
|
|
9022
|
-
lineStart: `${CSI}1K`,
|
|
9023
|
-
lines(count) {
|
|
9024
|
-
let clear = "";
|
|
9025
|
-
for (let i = 0;i < count; i++)
|
|
9026
|
-
clear += this.line + (i < count - 1 ? cursor.up() : "");
|
|
9027
|
-
if (count)
|
|
9028
|
-
clear += cursor.left;
|
|
9029
|
-
return clear;
|
|
8977
|
+
// src/i18n/catalog.ts
|
|
8978
|
+
function hashMsgid(msgid) {
|
|
8979
|
+
const hasher = new Bun.CryptoHasher("md5");
|
|
8980
|
+
hasher.update(msgid);
|
|
8981
|
+
return hasher.digest("hex").slice(0, 8);
|
|
8982
|
+
}
|
|
8983
|
+
function parsePo(content) {
|
|
8984
|
+
const entries = [];
|
|
8985
|
+
const lines = content.split(`
|
|
8986
|
+
`);
|
|
8987
|
+
let locations = [];
|
|
8988
|
+
let hash = "";
|
|
8989
|
+
let msgid = "";
|
|
8990
|
+
let msgstr = "";
|
|
8991
|
+
let obsolete = false;
|
|
8992
|
+
let inManual = false;
|
|
8993
|
+
const flush = () => {
|
|
8994
|
+
if (msgid) {
|
|
8995
|
+
entries.push({
|
|
8996
|
+
msgid,
|
|
8997
|
+
msgstr,
|
|
8998
|
+
locations,
|
|
8999
|
+
hash: hash || hashMsgid(msgid),
|
|
9000
|
+
obsolete,
|
|
9001
|
+
...inManual ? { manual: true } : {}
|
|
9002
|
+
});
|
|
9030
9003
|
}
|
|
9004
|
+
locations = [];
|
|
9005
|
+
hash = "";
|
|
9006
|
+
msgid = "";
|
|
9007
|
+
msgstr = "";
|
|
9008
|
+
obsolete = false;
|
|
9031
9009
|
};
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
var p = process || {};
|
|
9038
|
-
var argv2 = p.argv || [];
|
|
9039
|
-
var env2 = p.env || {};
|
|
9040
|
-
var isColorSupported2 = !(!!env2.NO_COLOR || argv2.includes("--no-color")) && (!!env2.FORCE_COLOR || argv2.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env2.TERM !== "dumb" || !!env2.CI);
|
|
9041
|
-
var formatter = (open, close, replace = open) => (input) => {
|
|
9042
|
-
let string = "" + input, index = string.indexOf(close, open.length);
|
|
9043
|
-
return ~index ? open + replaceClose2(string, close, replace, index) + close : open + string + close;
|
|
9044
|
-
};
|
|
9045
|
-
var replaceClose2 = (string, close, replace, index) => {
|
|
9046
|
-
let result = "", cursor = 0;
|
|
9047
|
-
do {
|
|
9048
|
-
result += string.substring(cursor, index) + replace;
|
|
9049
|
-
cursor = index + close.length;
|
|
9050
|
-
index = string.indexOf(close, cursor);
|
|
9051
|
-
} while (~index);
|
|
9052
|
-
return result + string.substring(cursor);
|
|
9053
|
-
};
|
|
9054
|
-
var createColors2 = (enabled = isColorSupported2) => {
|
|
9055
|
-
let f = enabled ? formatter : () => String;
|
|
9056
|
-
return {
|
|
9057
|
-
isColorSupported: enabled,
|
|
9058
|
-
reset: f("\x1B[0m", "\x1B[0m"),
|
|
9059
|
-
bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
|
|
9060
|
-
dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
|
|
9061
|
-
italic: f("\x1B[3m", "\x1B[23m"),
|
|
9062
|
-
underline: f("\x1B[4m", "\x1B[24m"),
|
|
9063
|
-
inverse: f("\x1B[7m", "\x1B[27m"),
|
|
9064
|
-
hidden: f("\x1B[8m", "\x1B[28m"),
|
|
9065
|
-
strikethrough: f("\x1B[9m", "\x1B[29m"),
|
|
9066
|
-
black: f("\x1B[30m", "\x1B[39m"),
|
|
9067
|
-
red: f("\x1B[31m", "\x1B[39m"),
|
|
9068
|
-
green: f("\x1B[32m", "\x1B[39m"),
|
|
9069
|
-
yellow: f("\x1B[33m", "\x1B[39m"),
|
|
9070
|
-
blue: f("\x1B[34m", "\x1B[39m"),
|
|
9071
|
-
magenta: f("\x1B[35m", "\x1B[39m"),
|
|
9072
|
-
cyan: f("\x1B[36m", "\x1B[39m"),
|
|
9073
|
-
white: f("\x1B[37m", "\x1B[39m"),
|
|
9074
|
-
gray: f("\x1B[90m", "\x1B[39m"),
|
|
9075
|
-
bgBlack: f("\x1B[40m", "\x1B[49m"),
|
|
9076
|
-
bgRed: f("\x1B[41m", "\x1B[49m"),
|
|
9077
|
-
bgGreen: f("\x1B[42m", "\x1B[49m"),
|
|
9078
|
-
bgYellow: f("\x1B[43m", "\x1B[49m"),
|
|
9079
|
-
bgBlue: f("\x1B[44m", "\x1B[49m"),
|
|
9080
|
-
bgMagenta: f("\x1B[45m", "\x1B[49m"),
|
|
9081
|
-
bgCyan: f("\x1B[46m", "\x1B[49m"),
|
|
9082
|
-
bgWhite: f("\x1B[47m", "\x1B[49m"),
|
|
9083
|
-
blackBright: f("\x1B[90m", "\x1B[39m"),
|
|
9084
|
-
redBright: f("\x1B[91m", "\x1B[39m"),
|
|
9085
|
-
greenBright: f("\x1B[92m", "\x1B[39m"),
|
|
9086
|
-
yellowBright: f("\x1B[93m", "\x1B[39m"),
|
|
9087
|
-
blueBright: f("\x1B[94m", "\x1B[39m"),
|
|
9088
|
-
magentaBright: f("\x1B[95m", "\x1B[39m"),
|
|
9089
|
-
cyanBright: f("\x1B[96m", "\x1B[39m"),
|
|
9090
|
-
whiteBright: f("\x1B[97m", "\x1B[39m"),
|
|
9091
|
-
bgBlackBright: f("\x1B[100m", "\x1B[49m"),
|
|
9092
|
-
bgRedBright: f("\x1B[101m", "\x1B[49m"),
|
|
9093
|
-
bgGreenBright: f("\x1B[102m", "\x1B[49m"),
|
|
9094
|
-
bgYellowBright: f("\x1B[103m", "\x1B[49m"),
|
|
9095
|
-
bgBlueBright: f("\x1B[104m", "\x1B[49m"),
|
|
9096
|
-
bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
|
|
9097
|
-
bgCyanBright: f("\x1B[106m", "\x1B[49m"),
|
|
9098
|
-
bgWhiteBright: f("\x1B[107m", "\x1B[49m")
|
|
9099
|
-
};
|
|
9100
|
-
};
|
|
9101
|
-
module.exports = createColors2();
|
|
9102
|
-
module.exports.createColors = createColors2;
|
|
9103
|
-
});
|
|
9104
|
-
|
|
9105
|
-
// ../../node_modules/.bun/safe-buffer@5.2.1/node_modules/safe-buffer/index.js
|
|
9106
|
-
var require_safe_buffer = __commonJS((exports, module) => {
|
|
9107
|
-
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
9108
|
-
var buffer = __require("buffer");
|
|
9109
|
-
var Buffer2 = buffer.Buffer;
|
|
9110
|
-
function copyProps(src, dst) {
|
|
9111
|
-
for (var key in src) {
|
|
9112
|
-
dst[key] = src[key];
|
|
9113
|
-
}
|
|
9114
|
-
}
|
|
9115
|
-
if (Buffer2.from && Buffer2.alloc && Buffer2.allocUnsafe && Buffer2.allocUnsafeSlow) {
|
|
9116
|
-
module.exports = buffer;
|
|
9117
|
-
} else {
|
|
9118
|
-
copyProps(buffer, exports);
|
|
9119
|
-
exports.Buffer = SafeBuffer;
|
|
9120
|
-
}
|
|
9121
|
-
function SafeBuffer(arg, encodingOrOffset, length) {
|
|
9122
|
-
return Buffer2(arg, encodingOrOffset, length);
|
|
9123
|
-
}
|
|
9124
|
-
SafeBuffer.prototype = Object.create(Buffer2.prototype);
|
|
9125
|
-
copyProps(Buffer2, SafeBuffer);
|
|
9126
|
-
SafeBuffer.from = function(arg, encodingOrOffset, length) {
|
|
9127
|
-
if (typeof arg === "number") {
|
|
9128
|
-
throw new TypeError("Argument must not be a number");
|
|
9010
|
+
for (const line of lines) {
|
|
9011
|
+
const trimmed = line.trim();
|
|
9012
|
+
if (trimmed === "# manual") {
|
|
9013
|
+
inManual = true;
|
|
9014
|
+
continue;
|
|
9129
9015
|
}
|
|
9130
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
|
|
9016
|
+
if (trimmed === "# end manual") {
|
|
9017
|
+
if (msgid)
|
|
9018
|
+
flush();
|
|
9019
|
+
inManual = false;
|
|
9020
|
+
continue;
|
|
9135
9021
|
}
|
|
9136
|
-
|
|
9137
|
-
|
|
9138
|
-
|
|
9139
|
-
|
|
9140
|
-
} else {
|
|
9141
|
-
buf.fill(fill);
|
|
9142
|
-
}
|
|
9143
|
-
} else {
|
|
9144
|
-
buf.fill(0);
|
|
9022
|
+
if (trimmed === "" || trimmed.startsWith("#,")) {
|
|
9023
|
+
if (msgid)
|
|
9024
|
+
flush();
|
|
9025
|
+
continue;
|
|
9145
9026
|
}
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
|
|
9027
|
+
if (trimmed.startsWith("#:")) {
|
|
9028
|
+
if (msgid)
|
|
9029
|
+
flush();
|
|
9030
|
+
locations.push(trimmed.slice(3).trim());
|
|
9031
|
+
continue;
|
|
9151
9032
|
}
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9033
|
+
if (trimmed.startsWith("#.")) {
|
|
9034
|
+
const hashMatch = trimmed.match(/hash:(\w+)/);
|
|
9035
|
+
if (hashMatch)
|
|
9036
|
+
hash = hashMatch[1];
|
|
9037
|
+
continue;
|
|
9157
9038
|
}
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9164
|
-
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
|
|
9169
|
-
this.writable = true;
|
|
9170
|
-
this.readable = true;
|
|
9171
|
-
if (!data) {
|
|
9172
|
-
this.buffer = Buffer2.alloc(0);
|
|
9173
|
-
return this;
|
|
9039
|
+
if (trimmed.startsWith("#~")) {
|
|
9040
|
+
const rest = trimmed.slice(3).trim();
|
|
9041
|
+
if (rest.startsWith("msgid")) {
|
|
9042
|
+
if (msgid)
|
|
9043
|
+
flush();
|
|
9044
|
+
obsolete = true;
|
|
9045
|
+
msgid = extractQuoted(rest.slice(5));
|
|
9046
|
+
} else if (rest.startsWith("msgstr")) {
|
|
9047
|
+
msgstr = extractQuoted(rest.slice(6));
|
|
9048
|
+
}
|
|
9049
|
+
continue;
|
|
9174
9050
|
}
|
|
9175
|
-
if (
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9051
|
+
if (trimmed.startsWith("msgid")) {
|
|
9052
|
+
if (msgid)
|
|
9053
|
+
flush();
|
|
9054
|
+
msgid = extractQuoted(trimmed.slice(5));
|
|
9055
|
+
} else if (trimmed.startsWith("msgstr")) {
|
|
9056
|
+
msgstr = extractQuoted(trimmed.slice(6));
|
|
9179
9057
|
}
|
|
9180
|
-
|
|
9181
|
-
|
|
9182
|
-
|
|
9183
|
-
|
|
9184
|
-
|
|
9185
|
-
|
|
9186
|
-
|
|
9187
|
-
|
|
9188
|
-
|
|
9058
|
+
}
|
|
9059
|
+
flush();
|
|
9060
|
+
return entries;
|
|
9061
|
+
}
|
|
9062
|
+
function writePo(entries) {
|
|
9063
|
+
const lines = [];
|
|
9064
|
+
const manual = entries.filter((e) => e.manual);
|
|
9065
|
+
const active = entries.filter((e) => !e.obsolete && !e.manual);
|
|
9066
|
+
const obsolete = entries.filter((e) => e.obsolete);
|
|
9067
|
+
if (manual.length > 0) {
|
|
9068
|
+
lines.push("# manual");
|
|
9069
|
+
for (const entry of manual) {
|
|
9070
|
+
lines.push(`msgid ${quoteString(entry.msgid)}`);
|
|
9071
|
+
lines.push(`msgstr ${quoteString(entry.msgstr)}`);
|
|
9072
|
+
lines.push("");
|
|
9189
9073
|
}
|
|
9190
|
-
|
|
9074
|
+
lines.push("# end manual");
|
|
9075
|
+
lines.push("");
|
|
9191
9076
|
}
|
|
9192
|
-
|
|
9193
|
-
|
|
9194
|
-
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9198
|
-
|
|
9199
|
-
|
|
9200
|
-
this.emit("end", data);
|
|
9201
|
-
this.emit("close");
|
|
9202
|
-
this.writable = false;
|
|
9203
|
-
this.readable = false;
|
|
9204
|
-
};
|
|
9205
|
-
module.exports = DataStream;
|
|
9206
|
-
});
|
|
9207
|
-
|
|
9208
|
-
// ../../node_modules/.bun/ecdsa-sig-formatter@1.0.11/node_modules/ecdsa-sig-formatter/src/param-bytes-for-alg.js
|
|
9209
|
-
var require_param_bytes_for_alg = __commonJS((exports, module) => {
|
|
9210
|
-
function getParamSize(keySize) {
|
|
9211
|
-
var result = (keySize / 8 | 0) + (keySize % 8 === 0 ? 0 : 1);
|
|
9212
|
-
return result;
|
|
9077
|
+
for (const entry of active) {
|
|
9078
|
+
for (const loc of entry.locations) {
|
|
9079
|
+
lines.push(`#: ${loc}`);
|
|
9080
|
+
}
|
|
9081
|
+
lines.push(`#. hash:${entry.hash}`);
|
|
9082
|
+
lines.push(`msgid ${quoteString(entry.msgid)}`);
|
|
9083
|
+
lines.push(`msgstr ${quoteString(entry.msgstr)}`);
|
|
9084
|
+
lines.push("");
|
|
9213
9085
|
}
|
|
9214
|
-
|
|
9215
|
-
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
if (paramBytes) {
|
|
9222
|
-
return paramBytes;
|
|
9086
|
+
if (obsolete.length > 0) {
|
|
9087
|
+
lines.push("# Obsolete entries");
|
|
9088
|
+
lines.push("");
|
|
9089
|
+
for (const entry of obsolete) {
|
|
9090
|
+
lines.push(`#~ msgid ${quoteString(entry.msgid)}`);
|
|
9091
|
+
lines.push(`#~ msgstr ${quoteString(entry.msgstr)}`);
|
|
9092
|
+
lines.push("");
|
|
9223
9093
|
}
|
|
9224
|
-
throw new Error('Unknown algorithm "' + alg + '"');
|
|
9225
9094
|
}
|
|
9226
|
-
|
|
9227
|
-
|
|
9228
|
-
|
|
9229
|
-
|
|
9230
|
-
|
|
9231
|
-
|
|
9232
|
-
|
|
9233
|
-
var MAX_OCTET = 128;
|
|
9234
|
-
var CLASS_UNIVERSAL = 0;
|
|
9235
|
-
var PRIMITIVE_BIT = 32;
|
|
9236
|
-
var TAG_SEQ = 16;
|
|
9237
|
-
var TAG_INT = 2;
|
|
9238
|
-
var ENCODED_TAG_SEQ = TAG_SEQ | PRIMITIVE_BIT | CLASS_UNIVERSAL << 6;
|
|
9239
|
-
var ENCODED_TAG_INT = TAG_INT | CLASS_UNIVERSAL << 6;
|
|
9240
|
-
function base64Url(base64) {
|
|
9241
|
-
return base64.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
9095
|
+
return lines.join(`
|
|
9096
|
+
`);
|
|
9097
|
+
}
|
|
9098
|
+
function mergeCatalog(existing, extracted) {
|
|
9099
|
+
const existingMap = new Map;
|
|
9100
|
+
for (const entry of existing) {
|
|
9101
|
+
existingMap.set(entry.msgid, entry);
|
|
9242
9102
|
}
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
|
|
9246
|
-
|
|
9247
|
-
|
|
9248
|
-
|
|
9249
|
-
|
|
9103
|
+
const manualEntries = existing.filter((e) => e.manual);
|
|
9104
|
+
const manualIds = new Set(manualEntries.map((e) => e.msgid));
|
|
9105
|
+
const result = [];
|
|
9106
|
+
const seen = new Set;
|
|
9107
|
+
for (const [msgid, locations] of extracted) {
|
|
9108
|
+
seen.add(msgid);
|
|
9109
|
+
if (manualIds.has(msgid))
|
|
9110
|
+
continue;
|
|
9111
|
+
const prev = existingMap.get(msgid);
|
|
9112
|
+
result.push({
|
|
9113
|
+
msgid,
|
|
9114
|
+
msgstr: prev?.msgstr ?? "",
|
|
9115
|
+
locations: [...locations].sort(),
|
|
9116
|
+
hash: hashMsgid(msgid),
|
|
9117
|
+
obsolete: false
|
|
9118
|
+
});
|
|
9250
9119
|
}
|
|
9251
|
-
|
|
9252
|
-
|
|
9253
|
-
|
|
9254
|
-
|
|
9255
|
-
|
|
9256
|
-
|
|
9257
|
-
|
|
9258
|
-
throw new Error('Could not find expected "seq"');
|
|
9259
|
-
}
|
|
9260
|
-
var seqLength = signature[offset++];
|
|
9261
|
-
if (seqLength === (MAX_OCTET | 1)) {
|
|
9262
|
-
seqLength = signature[offset++];
|
|
9263
|
-
}
|
|
9264
|
-
if (inputLength - offset < seqLength) {
|
|
9265
|
-
throw new Error('"seq" specified length of "' + seqLength + '", only "' + (inputLength - offset) + '" remaining');
|
|
9266
|
-
}
|
|
9267
|
-
if (signature[offset++] !== ENCODED_TAG_INT) {
|
|
9268
|
-
throw new Error('Could not find expected "int" for "r"');
|
|
9269
|
-
}
|
|
9270
|
-
var rLength = signature[offset++];
|
|
9271
|
-
if (inputLength - offset - 2 < rLength) {
|
|
9272
|
-
throw new Error('"r" specified length of "' + rLength + '", only "' + (inputLength - offset - 2) + '" available');
|
|
9273
|
-
}
|
|
9274
|
-
if (maxEncodedParamLength < rLength) {
|
|
9275
|
-
throw new Error('"r" specified length of "' + rLength + '", max of "' + maxEncodedParamLength + '" is acceptable');
|
|
9276
|
-
}
|
|
9277
|
-
var rOffset = offset;
|
|
9278
|
-
offset += rLength;
|
|
9279
|
-
if (signature[offset++] !== ENCODED_TAG_INT) {
|
|
9280
|
-
throw new Error('Could not find expected "int" for "s"');
|
|
9281
|
-
}
|
|
9282
|
-
var sLength = signature[offset++];
|
|
9283
|
-
if (inputLength - offset !== sLength) {
|
|
9284
|
-
throw new Error('"s" specified length of "' + sLength + '", expected "' + (inputLength - offset) + '"');
|
|
9285
|
-
}
|
|
9286
|
-
if (maxEncodedParamLength < sLength) {
|
|
9287
|
-
throw new Error('"s" specified length of "' + sLength + '", max of "' + maxEncodedParamLength + '" is acceptable');
|
|
9288
|
-
}
|
|
9289
|
-
var sOffset = offset;
|
|
9290
|
-
offset += sLength;
|
|
9291
|
-
if (offset !== inputLength) {
|
|
9292
|
-
throw new Error('Expected to consume entire buffer, but "' + (inputLength - offset) + '" bytes remain');
|
|
9293
|
-
}
|
|
9294
|
-
var rPadding = paramBytes - rLength, sPadding = paramBytes - sLength;
|
|
9295
|
-
var dst = Buffer2.allocUnsafe(rPadding + rLength + sPadding + sLength);
|
|
9296
|
-
for (offset = 0;offset < rPadding; ++offset) {
|
|
9297
|
-
dst[offset] = 0;
|
|
9298
|
-
}
|
|
9299
|
-
signature.copy(dst, offset, rOffset + Math.max(-rPadding, 0), rOffset + rLength);
|
|
9300
|
-
offset = paramBytes;
|
|
9301
|
-
for (var o = offset;offset < o + sPadding; ++offset) {
|
|
9302
|
-
dst[offset] = 0;
|
|
9120
|
+
for (const entry of existing) {
|
|
9121
|
+
if (!seen.has(entry.msgid) && !entry.obsolete && !entry.manual && entry.msgstr) {
|
|
9122
|
+
result.push({
|
|
9123
|
+
...entry,
|
|
9124
|
+
obsolete: true,
|
|
9125
|
+
locations: []
|
|
9126
|
+
});
|
|
9303
9127
|
}
|
|
9304
|
-
signature.copy(dst, offset, sOffset + Math.max(-sPadding, 0), sOffset + sLength);
|
|
9305
|
-
dst = dst.toString("base64");
|
|
9306
|
-
dst = base64Url(dst);
|
|
9307
|
-
return dst;
|
|
9308
9128
|
}
|
|
9309
|
-
|
|
9310
|
-
|
|
9311
|
-
|
|
9312
|
-
|
|
9313
|
-
|
|
9314
|
-
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
}
|
|
9318
|
-
return padding;
|
|
9129
|
+
result.sort((a, b) => a.msgid.localeCompare(b.msgid));
|
|
9130
|
+
return [...manualEntries, ...result];
|
|
9131
|
+
}
|
|
9132
|
+
function extractQuoted(s) {
|
|
9133
|
+
const trimmed = s.trim();
|
|
9134
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
|
|
9135
|
+
return trimmed.slice(1, -1).replace(/\\n/g, `
|
|
9136
|
+
`).replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
9319
9137
|
}
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
|
|
9329
|
-
|
|
9330
|
-
|
|
9331
|
-
|
|
9332
|
-
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
dst[offset++] = rsBytes;
|
|
9338
|
-
} else {
|
|
9339
|
-
dst[offset++] = MAX_OCTET | 1;
|
|
9340
|
-
dst[offset++] = rsBytes & 255;
|
|
9341
|
-
}
|
|
9342
|
-
dst[offset++] = ENCODED_TAG_INT;
|
|
9343
|
-
dst[offset++] = rLength;
|
|
9344
|
-
if (rPadding < 0) {
|
|
9345
|
-
dst[offset++] = 0;
|
|
9346
|
-
offset += signature.copy(dst, offset, 0, paramBytes);
|
|
9347
|
-
} else {
|
|
9348
|
-
offset += signature.copy(dst, offset, rPadding, paramBytes);
|
|
9138
|
+
return trimmed;
|
|
9139
|
+
}
|
|
9140
|
+
function quoteString(s) {
|
|
9141
|
+
const escaped = s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n");
|
|
9142
|
+
return `"${escaped}"`;
|
|
9143
|
+
}
|
|
9144
|
+
|
|
9145
|
+
// src/i18n/compile.ts
|
|
9146
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
9147
|
+
import { join as join4 } from "path";
|
|
9148
|
+
function compileCatalog(poPath) {
|
|
9149
|
+
const content = readFileSync3(poPath, "utf-8");
|
|
9150
|
+
const entries = parsePo(content);
|
|
9151
|
+
const result = {};
|
|
9152
|
+
for (const entry of entries) {
|
|
9153
|
+
if (!entry.obsolete && entry.msgstr) {
|
|
9154
|
+
result[entry.msgid] = entry.msgstr;
|
|
9349
9155
|
}
|
|
9350
|
-
dst[offset++] = ENCODED_TAG_INT;
|
|
9351
|
-
dst[offset++] = sLength;
|
|
9352
|
-
if (sPadding < 0) {
|
|
9353
|
-
dst[offset++] = 0;
|
|
9354
|
-
signature.copy(dst, offset, paramBytes);
|
|
9355
|
-
} else {
|
|
9356
|
-
signature.copy(dst, offset, paramBytes + sPadding);
|
|
9357
|
-
}
|
|
9358
|
-
return dst;
|
|
9359
9156
|
}
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9157
|
+
const sorted = {};
|
|
9158
|
+
for (const key of Object.keys(result).sort()) {
|
|
9159
|
+
sorted[key] = result[key];
|
|
9160
|
+
}
|
|
9161
|
+
return sorted;
|
|
9162
|
+
}
|
|
9163
|
+
function compileAllCatalogs(localesDir, outDir) {
|
|
9164
|
+
mkdirSync3(outDir, { recursive: true });
|
|
9165
|
+
for (const file of readdirSync2(localesDir)) {
|
|
9166
|
+
if (!file.endsWith(".po"))
|
|
9167
|
+
continue;
|
|
9168
|
+
const locale = file.replace(".po", "");
|
|
9169
|
+
const compiled = compileCatalog(join4(localesDir, file));
|
|
9170
|
+
writeFileSync3(join4(outDir, `${locale}.json`), JSON.stringify(compiled));
|
|
9171
|
+
}
|
|
9172
|
+
}
|
|
9173
|
+
var init_compile = () => {};
|
|
9174
|
+
|
|
9175
|
+
// src/i18n/plugin.ts
|
|
9176
|
+
function i18nExtractPlugin(collector, rootDir) {
|
|
9177
|
+
return {
|
|
9178
|
+
name: "arc-i18n-extract",
|
|
9179
|
+
setup(build2) {
|
|
9180
|
+
build2.onLoad({ filter: /\.tsx?$/ }, async (args) => {
|
|
9181
|
+
const source = await Bun.file(args.path).text();
|
|
9182
|
+
const relPath = args.path.startsWith(rootDir) ? args.path.slice(rootDir.length + 1) : args.path;
|
|
9183
|
+
const transRegex = /<Trans>\s*([^<{]+?)\s*<\/Trans>/g;
|
|
9184
|
+
for (const match2 of source.matchAll(transRegex)) {
|
|
9185
|
+
const msgid = match2[1].trim();
|
|
9186
|
+
if (!msgid)
|
|
9187
|
+
continue;
|
|
9188
|
+
const line = source.substring(0, match2.index).split(`
|
|
9189
|
+
`).length;
|
|
9190
|
+
const loc = `${relPath}:${line}`;
|
|
9191
|
+
if (!collector.has(msgid))
|
|
9192
|
+
collector.set(msgid, new Set);
|
|
9193
|
+
collector.get(msgid).add(loc);
|
|
9194
|
+
}
|
|
9195
|
+
const tRegex = /\bt`([^`]+)`/g;
|
|
9196
|
+
for (const match2 of source.matchAll(tRegex)) {
|
|
9197
|
+
const msgid = match2[1];
|
|
9198
|
+
if (!msgid)
|
|
9199
|
+
continue;
|
|
9200
|
+
const line = source.substring(0, match2.index).split(`
|
|
9201
|
+
`).length;
|
|
9202
|
+
const loc = `${relPath}:${line}`;
|
|
9203
|
+
if (!collector.has(msgid))
|
|
9204
|
+
collector.set(msgid, new Set);
|
|
9205
|
+
collector.get(msgid).add(loc);
|
|
9206
|
+
}
|
|
9207
|
+
return;
|
|
9208
|
+
});
|
|
9209
|
+
}
|
|
9363
9210
|
};
|
|
9211
|
+
}
|
|
9212
|
+
|
|
9213
|
+
// src/i18n/index.ts
|
|
9214
|
+
var exports_i18n = {};
|
|
9215
|
+
__export(exports_i18n, {
|
|
9216
|
+
readTranslationsConfig: () => readTranslationsConfig,
|
|
9217
|
+
i18nExtractPlugin: () => i18nExtractPlugin,
|
|
9218
|
+
finalizeTranslations: () => finalizeTranslations
|
|
9219
|
+
});
|
|
9220
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
9221
|
+
import { dirname as dirname4, join as join5 } from "path";
|
|
9222
|
+
function readTranslationsConfig(rootDir) {
|
|
9223
|
+
const pkgPath = join5(rootDir, "package.json");
|
|
9224
|
+
if (!existsSync4(pkgPath))
|
|
9225
|
+
return null;
|
|
9226
|
+
const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
|
|
9227
|
+
const config = pkg.arc?.translations;
|
|
9228
|
+
if (!config?.locales?.length)
|
|
9229
|
+
return null;
|
|
9230
|
+
return {
|
|
9231
|
+
locales: config.locales,
|
|
9232
|
+
sourceLocale: config.sourceLocale ?? config.locales[0]
|
|
9233
|
+
};
|
|
9234
|
+
}
|
|
9235
|
+
async function finalizeTranslations(rootDir, outDir, collector) {
|
|
9236
|
+
const config = readTranslationsConfig(rootDir);
|
|
9237
|
+
if (!config || collector.size === 0)
|
|
9238
|
+
return;
|
|
9239
|
+
const localesJsonDir = join5(outDir, "locales");
|
|
9240
|
+
mkdirSync4(localesJsonDir, { recursive: true });
|
|
9241
|
+
console.log(` Extracted ${collector.size} translatable string(s) for ${config.locales.length} locale(s)`);
|
|
9242
|
+
for (const locale of config.locales) {
|
|
9243
|
+
const poPath = join5(rootDir, "locales", `${locale}.po`);
|
|
9244
|
+
mkdirSync4(dirname4(poPath), { recursive: true });
|
|
9245
|
+
const existing = existsSync4(poPath) ? parsePo(readFileSync4(poPath, "utf-8")) : [];
|
|
9246
|
+
const merged = mergeCatalog(existing, collector);
|
|
9247
|
+
writeFileSync4(poPath, writePo(merged));
|
|
9248
|
+
const compiled = compileCatalog(poPath);
|
|
9249
|
+
writeFileSync4(join5(localesJsonDir, `${locale}.json`), JSON.stringify(compiled));
|
|
9250
|
+
}
|
|
9251
|
+
}
|
|
9252
|
+
var init_i18n = __esm(() => {
|
|
9253
|
+
init_compile();
|
|
9364
9254
|
});
|
|
9365
9255
|
|
|
9366
|
-
// ../../node_modules/.bun/
|
|
9367
|
-
var
|
|
9368
|
-
var
|
|
9369
|
-
var
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
|
|
9379
|
-
|
|
9380
|
-
|
|
9256
|
+
// ../../node_modules/.bun/sisteransi@1.0.5/node_modules/sisteransi/src/index.js
|
|
9257
|
+
var require_src = __commonJS((exports, module) => {
|
|
9258
|
+
var ESC2 = "\x1B";
|
|
9259
|
+
var CSI = `${ESC2}[`;
|
|
9260
|
+
var beep2 = "\x07";
|
|
9261
|
+
var cursor = {
|
|
9262
|
+
to(x, y) {
|
|
9263
|
+
if (!y)
|
|
9264
|
+
return `${CSI}${x + 1}G`;
|
|
9265
|
+
return `${CSI}${y + 1};${x + 1}H`;
|
|
9266
|
+
},
|
|
9267
|
+
move(x, y) {
|
|
9268
|
+
let ret = "";
|
|
9269
|
+
if (x < 0)
|
|
9270
|
+
ret += `${CSI}${-x}D`;
|
|
9271
|
+
else if (x > 0)
|
|
9272
|
+
ret += `${CSI}${x}C`;
|
|
9273
|
+
if (y < 0)
|
|
9274
|
+
ret += `${CSI}${-y}A`;
|
|
9275
|
+
else if (y > 0)
|
|
9276
|
+
ret += `${CSI}${y}B`;
|
|
9277
|
+
return ret;
|
|
9278
|
+
},
|
|
9279
|
+
up: (count = 1) => `${CSI}${count}A`,
|
|
9280
|
+
down: (count = 1) => `${CSI}${count}B`,
|
|
9281
|
+
forward: (count = 1) => `${CSI}${count}C`,
|
|
9282
|
+
backward: (count = 1) => `${CSI}${count}D`,
|
|
9283
|
+
nextLine: (count = 1) => `${CSI}E`.repeat(count),
|
|
9284
|
+
prevLine: (count = 1) => `${CSI}F`.repeat(count),
|
|
9285
|
+
left: `${CSI}G`,
|
|
9286
|
+
hide: `${CSI}?25l`,
|
|
9287
|
+
show: `${CSI}?25h`,
|
|
9288
|
+
save: `${ESC2}7`,
|
|
9289
|
+
restore: `${ESC2}8`
|
|
9290
|
+
};
|
|
9291
|
+
var scroll = {
|
|
9292
|
+
up: (count = 1) => `${CSI}S`.repeat(count),
|
|
9293
|
+
down: (count = 1) => `${CSI}T`.repeat(count)
|
|
9294
|
+
};
|
|
9295
|
+
var erase = {
|
|
9296
|
+
screen: `${CSI}2J`,
|
|
9297
|
+
up: (count = 1) => `${CSI}1J`.repeat(count),
|
|
9298
|
+
down: (count = 1) => `${CSI}J`.repeat(count),
|
|
9299
|
+
line: `${CSI}2K`,
|
|
9300
|
+
lineEnd: `${CSI}K`,
|
|
9301
|
+
lineStart: `${CSI}1K`,
|
|
9302
|
+
lines(count) {
|
|
9303
|
+
let clear = "";
|
|
9304
|
+
for (let i = 0;i < count; i++)
|
|
9305
|
+
clear += this.line + (i < count - 1 ? cursor.up() : "");
|
|
9306
|
+
if (count)
|
|
9307
|
+
clear += cursor.left;
|
|
9308
|
+
return clear;
|
|
9381
9309
|
}
|
|
9382
|
-
return c2 === 0;
|
|
9383
|
-
}
|
|
9384
|
-
bufferEq.install = function() {
|
|
9385
|
-
Buffer2.prototype.equal = SlowBuffer.prototype.equal = function equal(that) {
|
|
9386
|
-
return bufferEq(this, that);
|
|
9387
|
-
};
|
|
9388
9310
|
};
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9311
|
+
module.exports = { cursor, scroll, erase, beep: beep2 };
|
|
9312
|
+
});
|
|
9313
|
+
|
|
9314
|
+
// ../../node_modules/.bun/picocolors@1.1.1/node_modules/picocolors/picocolors.js
|
|
9315
|
+
var require_picocolors = __commonJS((exports, module) => {
|
|
9316
|
+
var p = process || {};
|
|
9317
|
+
var argv2 = p.argv || [];
|
|
9318
|
+
var env2 = p.env || {};
|
|
9319
|
+
var isColorSupported2 = !(!!env2.NO_COLOR || argv2.includes("--no-color")) && (!!env2.FORCE_COLOR || argv2.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env2.TERM !== "dumb" || !!env2.CI);
|
|
9320
|
+
var formatter = (open, close, replace = open) => (input) => {
|
|
9321
|
+
let string = "" + input, index = string.indexOf(close, open.length);
|
|
9322
|
+
return ~index ? open + replaceClose2(string, close, replace, index) + close : open + string + close;
|
|
9323
|
+
};
|
|
9324
|
+
var replaceClose2 = (string, close, replace, index) => {
|
|
9325
|
+
let result = "", cursor = 0;
|
|
9326
|
+
do {
|
|
9327
|
+
result += string.substring(cursor, index) + replace;
|
|
9328
|
+
cursor = index + close.length;
|
|
9329
|
+
index = string.indexOf(close, cursor);
|
|
9330
|
+
} while (~index);
|
|
9331
|
+
return result + string.substring(cursor);
|
|
9332
|
+
};
|
|
9333
|
+
var createColors2 = (enabled = isColorSupported2) => {
|
|
9334
|
+
let f = enabled ? formatter : () => String;
|
|
9335
|
+
return {
|
|
9336
|
+
isColorSupported: enabled,
|
|
9337
|
+
reset: f("\x1B[0m", "\x1B[0m"),
|
|
9338
|
+
bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
|
|
9339
|
+
dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
|
|
9340
|
+
italic: f("\x1B[3m", "\x1B[23m"),
|
|
9341
|
+
underline: f("\x1B[4m", "\x1B[24m"),
|
|
9342
|
+
inverse: f("\x1B[7m", "\x1B[27m"),
|
|
9343
|
+
hidden: f("\x1B[8m", "\x1B[28m"),
|
|
9344
|
+
strikethrough: f("\x1B[9m", "\x1B[29m"),
|
|
9345
|
+
black: f("\x1B[30m", "\x1B[39m"),
|
|
9346
|
+
red: f("\x1B[31m", "\x1B[39m"),
|
|
9347
|
+
green: f("\x1B[32m", "\x1B[39m"),
|
|
9348
|
+
yellow: f("\x1B[33m", "\x1B[39m"),
|
|
9349
|
+
blue: f("\x1B[34m", "\x1B[39m"),
|
|
9350
|
+
magenta: f("\x1B[35m", "\x1B[39m"),
|
|
9351
|
+
cyan: f("\x1B[36m", "\x1B[39m"),
|
|
9352
|
+
white: f("\x1B[37m", "\x1B[39m"),
|
|
9353
|
+
gray: f("\x1B[90m", "\x1B[39m"),
|
|
9354
|
+
bgBlack: f("\x1B[40m", "\x1B[49m"),
|
|
9355
|
+
bgRed: f("\x1B[41m", "\x1B[49m"),
|
|
9356
|
+
bgGreen: f("\x1B[42m", "\x1B[49m"),
|
|
9357
|
+
bgYellow: f("\x1B[43m", "\x1B[49m"),
|
|
9358
|
+
bgBlue: f("\x1B[44m", "\x1B[49m"),
|
|
9359
|
+
bgMagenta: f("\x1B[45m", "\x1B[49m"),
|
|
9360
|
+
bgCyan: f("\x1B[46m", "\x1B[49m"),
|
|
9361
|
+
bgWhite: f("\x1B[47m", "\x1B[49m"),
|
|
9362
|
+
blackBright: f("\x1B[90m", "\x1B[39m"),
|
|
9363
|
+
redBright: f("\x1B[91m", "\x1B[39m"),
|
|
9364
|
+
greenBright: f("\x1B[92m", "\x1B[39m"),
|
|
9365
|
+
yellowBright: f("\x1B[93m", "\x1B[39m"),
|
|
9366
|
+
blueBright: f("\x1B[94m", "\x1B[39m"),
|
|
9367
|
+
magentaBright: f("\x1B[95m", "\x1B[39m"),
|
|
9368
|
+
cyanBright: f("\x1B[96m", "\x1B[39m"),
|
|
9369
|
+
whiteBright: f("\x1B[97m", "\x1B[39m"),
|
|
9370
|
+
bgBlackBright: f("\x1B[100m", "\x1B[49m"),
|
|
9371
|
+
bgRedBright: f("\x1B[101m", "\x1B[49m"),
|
|
9372
|
+
bgGreenBright: f("\x1B[102m", "\x1B[49m"),
|
|
9373
|
+
bgYellowBright: f("\x1B[103m", "\x1B[49m"),
|
|
9374
|
+
bgBlueBright: f("\x1B[104m", "\x1B[49m"),
|
|
9375
|
+
bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
|
|
9376
|
+
bgCyanBright: f("\x1B[106m", "\x1B[49m"),
|
|
9377
|
+
bgWhiteBright: f("\x1B[107m", "\x1B[49m")
|
|
9378
|
+
};
|
|
9394
9379
|
};
|
|
9380
|
+
module.exports = createColors2();
|
|
9381
|
+
module.exports.createColors = createColors2;
|
|
9395
9382
|
});
|
|
9396
9383
|
|
|
9397
|
-
// ../../node_modules/.bun/
|
|
9398
|
-
var
|
|
9399
|
-
|
|
9400
|
-
var
|
|
9401
|
-
var
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
var MSG_INVALID_SECRET = "secret must be a string or buffer";
|
|
9407
|
-
var MSG_INVALID_VERIFIER_KEY = "key must be a string or a buffer";
|
|
9408
|
-
var MSG_INVALID_SIGNER_KEY = "key must be a string, a buffer or an object";
|
|
9409
|
-
var supportsKeyObjects = typeof crypto2.createPublicKey === "function";
|
|
9410
|
-
if (supportsKeyObjects) {
|
|
9411
|
-
MSG_INVALID_VERIFIER_KEY += " or a KeyObject";
|
|
9412
|
-
MSG_INVALID_SECRET += "or a KeyObject";
|
|
9384
|
+
// ../../node_modules/.bun/safe-buffer@5.2.1/node_modules/safe-buffer/index.js
|
|
9385
|
+
var require_safe_buffer = __commonJS((exports, module) => {
|
|
9386
|
+
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
9387
|
+
var buffer = __require("buffer");
|
|
9388
|
+
var Buffer2 = buffer.Buffer;
|
|
9389
|
+
function copyProps(src, dst) {
|
|
9390
|
+
for (var key in src) {
|
|
9391
|
+
dst[key] = src[key];
|
|
9392
|
+
}
|
|
9413
9393
|
}
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
|
|
9394
|
+
if (Buffer2.from && Buffer2.alloc && Buffer2.allocUnsafe && Buffer2.allocUnsafeSlow) {
|
|
9395
|
+
module.exports = buffer;
|
|
9396
|
+
} else {
|
|
9397
|
+
copyProps(buffer, exports);
|
|
9398
|
+
exports.Buffer = SafeBuffer;
|
|
9399
|
+
}
|
|
9400
|
+
function SafeBuffer(arg, encodingOrOffset, length) {
|
|
9401
|
+
return Buffer2(arg, encodingOrOffset, length);
|
|
9402
|
+
}
|
|
9403
|
+
SafeBuffer.prototype = Object.create(Buffer2.prototype);
|
|
9404
|
+
copyProps(Buffer2, SafeBuffer);
|
|
9405
|
+
SafeBuffer.from = function(arg, encodingOrOffset, length) {
|
|
9406
|
+
if (typeof arg === "number") {
|
|
9407
|
+
throw new TypeError("Argument must not be a number");
|
|
9417
9408
|
}
|
|
9418
|
-
|
|
9419
|
-
|
|
9409
|
+
return Buffer2(arg, encodingOrOffset, length);
|
|
9410
|
+
};
|
|
9411
|
+
SafeBuffer.alloc = function(size, fill, encoding) {
|
|
9412
|
+
if (typeof size !== "number") {
|
|
9413
|
+
throw new TypeError("Argument must be a number");
|
|
9420
9414
|
}
|
|
9421
|
-
|
|
9422
|
-
|
|
9415
|
+
var buf = Buffer2(size);
|
|
9416
|
+
if (fill !== undefined) {
|
|
9417
|
+
if (typeof encoding === "string") {
|
|
9418
|
+
buf.fill(fill, encoding);
|
|
9419
|
+
} else {
|
|
9420
|
+
buf.fill(fill);
|
|
9421
|
+
}
|
|
9422
|
+
} else {
|
|
9423
|
+
buf.fill(0);
|
|
9423
9424
|
}
|
|
9424
|
-
|
|
9425
|
-
|
|
9425
|
+
return buf;
|
|
9426
|
+
};
|
|
9427
|
+
SafeBuffer.allocUnsafe = function(size) {
|
|
9428
|
+
if (typeof size !== "number") {
|
|
9429
|
+
throw new TypeError("Argument must be a number");
|
|
9426
9430
|
}
|
|
9427
|
-
|
|
9428
|
-
|
|
9431
|
+
return Buffer2(size);
|
|
9432
|
+
};
|
|
9433
|
+
SafeBuffer.allocUnsafeSlow = function(size) {
|
|
9434
|
+
if (typeof size !== "number") {
|
|
9435
|
+
throw new TypeError("Argument must be a number");
|
|
9429
9436
|
}
|
|
9430
|
-
|
|
9431
|
-
|
|
9437
|
+
return buffer.SlowBuffer(size);
|
|
9438
|
+
};
|
|
9439
|
+
});
|
|
9440
|
+
|
|
9441
|
+
// ../../node_modules/.bun/jws@4.0.1/node_modules/jws/lib/data-stream.js
|
|
9442
|
+
var require_data_stream = __commonJS((exports, module) => {
|
|
9443
|
+
var Buffer2 = require_safe_buffer().Buffer;
|
|
9444
|
+
var Stream2 = __require("stream");
|
|
9445
|
+
var util = __require("util");
|
|
9446
|
+
function DataStream(data) {
|
|
9447
|
+
this.buffer = null;
|
|
9448
|
+
this.writable = true;
|
|
9449
|
+
this.readable = true;
|
|
9450
|
+
if (!data) {
|
|
9451
|
+
this.buffer = Buffer2.alloc(0);
|
|
9452
|
+
return this;
|
|
9432
9453
|
}
|
|
9433
|
-
if (typeof
|
|
9434
|
-
|
|
9454
|
+
if (typeof data.pipe === "function") {
|
|
9455
|
+
this.buffer = Buffer2.alloc(0);
|
|
9456
|
+
data.pipe(this);
|
|
9457
|
+
return this;
|
|
9435
9458
|
}
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
|
|
9459
|
+
if (data.length || typeof data === "object") {
|
|
9460
|
+
this.buffer = data;
|
|
9461
|
+
this.writable = false;
|
|
9462
|
+
process.nextTick(function() {
|
|
9463
|
+
this.emit("end", data);
|
|
9464
|
+
this.readable = false;
|
|
9465
|
+
this.emit("close");
|
|
9466
|
+
}.bind(this));
|
|
9467
|
+
return this;
|
|
9440
9468
|
}
|
|
9441
|
-
|
|
9442
|
-
|
|
9469
|
+
throw new TypeError("Unexpected data type (" + typeof data + ")");
|
|
9470
|
+
}
|
|
9471
|
+
util.inherits(DataStream, Stream2);
|
|
9472
|
+
DataStream.prototype.write = function write(data) {
|
|
9473
|
+
this.buffer = Buffer2.concat([this.buffer, Buffer2.from(data)]);
|
|
9474
|
+
this.emit("data", data);
|
|
9475
|
+
};
|
|
9476
|
+
DataStream.prototype.end = function end(data) {
|
|
9477
|
+
if (data)
|
|
9478
|
+
this.write(data);
|
|
9479
|
+
this.emit("end", data);
|
|
9480
|
+
this.emit("close");
|
|
9481
|
+
this.writable = false;
|
|
9482
|
+
this.readable = false;
|
|
9483
|
+
};
|
|
9484
|
+
module.exports = DataStream;
|
|
9485
|
+
});
|
|
9486
|
+
|
|
9487
|
+
// ../../node_modules/.bun/ecdsa-sig-formatter@1.0.11/node_modules/ecdsa-sig-formatter/src/param-bytes-for-alg.js
|
|
9488
|
+
var require_param_bytes_for_alg = __commonJS((exports, module) => {
|
|
9489
|
+
function getParamSize(keySize) {
|
|
9490
|
+
var result = (keySize / 8 | 0) + (keySize % 8 === 0 ? 0 : 1);
|
|
9491
|
+
return result;
|
|
9492
|
+
}
|
|
9493
|
+
var paramBytesForAlg = {
|
|
9494
|
+
ES256: getParamSize(256),
|
|
9495
|
+
ES384: getParamSize(384),
|
|
9496
|
+
ES512: getParamSize(521)
|
|
9497
|
+
};
|
|
9498
|
+
function getParamBytesForAlg(alg) {
|
|
9499
|
+
var paramBytes = paramBytesForAlg[alg];
|
|
9500
|
+
if (paramBytes) {
|
|
9501
|
+
return paramBytes;
|
|
9443
9502
|
}
|
|
9444
|
-
|
|
9445
|
-
|
|
9503
|
+
throw new Error('Unknown algorithm "' + alg + '"');
|
|
9504
|
+
}
|
|
9505
|
+
module.exports = getParamBytesForAlg;
|
|
9506
|
+
});
|
|
9507
|
+
|
|
9508
|
+
// ../../node_modules/.bun/ecdsa-sig-formatter@1.0.11/node_modules/ecdsa-sig-formatter/src/ecdsa-sig-formatter.js
|
|
9509
|
+
var require_ecdsa_sig_formatter = __commonJS((exports, module) => {
|
|
9510
|
+
var Buffer2 = require_safe_buffer().Buffer;
|
|
9511
|
+
var getParamBytesForAlg = require_param_bytes_for_alg();
|
|
9512
|
+
var MAX_OCTET = 128;
|
|
9513
|
+
var CLASS_UNIVERSAL = 0;
|
|
9514
|
+
var PRIMITIVE_BIT = 32;
|
|
9515
|
+
var TAG_SEQ = 16;
|
|
9516
|
+
var TAG_INT = 2;
|
|
9517
|
+
var ENCODED_TAG_SEQ = TAG_SEQ | PRIMITIVE_BIT | CLASS_UNIVERSAL << 6;
|
|
9518
|
+
var ENCODED_TAG_INT = TAG_INT | CLASS_UNIVERSAL << 6;
|
|
9519
|
+
function base64Url(base64) {
|
|
9520
|
+
return base64.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
9521
|
+
}
|
|
9522
|
+
function signatureAsBuffer(signature) {
|
|
9523
|
+
if (Buffer2.isBuffer(signature)) {
|
|
9524
|
+
return signature;
|
|
9525
|
+
} else if (typeof signature === "string") {
|
|
9526
|
+
return Buffer2.from(signature, "base64");
|
|
9446
9527
|
}
|
|
9447
|
-
throw
|
|
9528
|
+
throw new TypeError("ECDSA signature must be a Base64 string or a Buffer");
|
|
9448
9529
|
}
|
|
9449
|
-
function
|
|
9450
|
-
|
|
9451
|
-
|
|
9530
|
+
function derToJose(signature, alg) {
|
|
9531
|
+
signature = signatureAsBuffer(signature);
|
|
9532
|
+
var paramBytes = getParamBytesForAlg(alg);
|
|
9533
|
+
var maxEncodedParamLength = paramBytes + 1;
|
|
9534
|
+
var inputLength = signature.length;
|
|
9535
|
+
var offset = 0;
|
|
9536
|
+
if (signature[offset++] !== ENCODED_TAG_SEQ) {
|
|
9537
|
+
throw new Error('Could not find expected "seq"');
|
|
9452
9538
|
}
|
|
9453
|
-
|
|
9454
|
-
|
|
9539
|
+
var seqLength = signature[offset++];
|
|
9540
|
+
if (seqLength === (MAX_OCTET | 1)) {
|
|
9541
|
+
seqLength = signature[offset++];
|
|
9455
9542
|
}
|
|
9456
|
-
if (
|
|
9457
|
-
throw
|
|
9543
|
+
if (inputLength - offset < seqLength) {
|
|
9544
|
+
throw new Error('"seq" specified length of "' + seqLength + '", only "' + (inputLength - offset) + '" remaining');
|
|
9458
9545
|
}
|
|
9459
|
-
if (
|
|
9460
|
-
throw
|
|
9546
|
+
if (signature[offset++] !== ENCODED_TAG_INT) {
|
|
9547
|
+
throw new Error('Could not find expected "int" for "r"');
|
|
9461
9548
|
}
|
|
9462
|
-
|
|
9463
|
-
|
|
9549
|
+
var rLength = signature[offset++];
|
|
9550
|
+
if (inputLength - offset - 2 < rLength) {
|
|
9551
|
+
throw new Error('"r" specified length of "' + rLength + '", only "' + (inputLength - offset - 2) + '" available');
|
|
9464
9552
|
}
|
|
9465
|
-
if (
|
|
9466
|
-
throw
|
|
9553
|
+
if (maxEncodedParamLength < rLength) {
|
|
9554
|
+
throw new Error('"r" specified length of "' + rLength + '", max of "' + maxEncodedParamLength + '" is acceptable');
|
|
9467
9555
|
}
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
|
|
9471
|
-
|
|
9472
|
-
function toBase64(base64url) {
|
|
9473
|
-
base64url = base64url.toString();
|
|
9474
|
-
var padding = 4 - base64url.length % 4;
|
|
9475
|
-
if (padding !== 4) {
|
|
9476
|
-
for (var i = 0;i < padding; ++i) {
|
|
9477
|
-
base64url += "=";
|
|
9478
|
-
}
|
|
9556
|
+
var rOffset = offset;
|
|
9557
|
+
offset += rLength;
|
|
9558
|
+
if (signature[offset++] !== ENCODED_TAG_INT) {
|
|
9559
|
+
throw new Error('Could not find expected "int" for "s"');
|
|
9479
9560
|
}
|
|
9480
|
-
|
|
9481
|
-
|
|
9482
|
-
|
|
9483
|
-
var args = [].slice.call(arguments, 1);
|
|
9484
|
-
var errMsg = util.format.bind(util, template).apply(null, args);
|
|
9485
|
-
return new TypeError(errMsg);
|
|
9486
|
-
}
|
|
9487
|
-
function bufferOrString(obj) {
|
|
9488
|
-
return Buffer2.isBuffer(obj) || typeof obj === "string";
|
|
9489
|
-
}
|
|
9490
|
-
function normalizeInput(thing) {
|
|
9491
|
-
if (!bufferOrString(thing))
|
|
9492
|
-
thing = JSON.stringify(thing);
|
|
9493
|
-
return thing;
|
|
9494
|
-
}
|
|
9495
|
-
function createHmacSigner(bits) {
|
|
9496
|
-
return function sign(thing, secret) {
|
|
9497
|
-
checkIsSecretKey(secret);
|
|
9498
|
-
thing = normalizeInput(thing);
|
|
9499
|
-
var hmac = crypto2.createHmac("sha" + bits, secret);
|
|
9500
|
-
var sig = (hmac.update(thing), hmac.digest("base64"));
|
|
9501
|
-
return fromBase64(sig);
|
|
9502
|
-
};
|
|
9503
|
-
}
|
|
9504
|
-
var bufferEqual;
|
|
9505
|
-
var timingSafeEqual = "timingSafeEqual" in crypto2 ? function timingSafeEqual2(a2, b2) {
|
|
9506
|
-
if (a2.byteLength !== b2.byteLength) {
|
|
9507
|
-
return false;
|
|
9561
|
+
var sLength = signature[offset++];
|
|
9562
|
+
if (inputLength - offset !== sLength) {
|
|
9563
|
+
throw new Error('"s" specified length of "' + sLength + '", expected "' + (inputLength - offset) + '"');
|
|
9508
9564
|
}
|
|
9509
|
-
|
|
9510
|
-
|
|
9511
|
-
if (!bufferEqual) {
|
|
9512
|
-
bufferEqual = require_buffer_equal_constant_time();
|
|
9565
|
+
if (maxEncodedParamLength < sLength) {
|
|
9566
|
+
throw new Error('"s" specified length of "' + sLength + '", max of "' + maxEncodedParamLength + '" is acceptable');
|
|
9513
9567
|
}
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
|
|
9517
|
-
|
|
9568
|
+
var sOffset = offset;
|
|
9569
|
+
offset += sLength;
|
|
9570
|
+
if (offset !== inputLength) {
|
|
9571
|
+
throw new Error('Expected to consume entire buffer, but "' + (inputLength - offset) + '" bytes remain');
|
|
9572
|
+
}
|
|
9573
|
+
var rPadding = paramBytes - rLength, sPadding = paramBytes - sLength;
|
|
9574
|
+
var dst = Buffer2.allocUnsafe(rPadding + rLength + sPadding + sLength);
|
|
9575
|
+
for (offset = 0;offset < rPadding; ++offset) {
|
|
9576
|
+
dst[offset] = 0;
|
|
9577
|
+
}
|
|
9578
|
+
signature.copy(dst, offset, rOffset + Math.max(-rPadding, 0), rOffset + rLength);
|
|
9579
|
+
offset = paramBytes;
|
|
9580
|
+
for (var o = offset;offset < o + sPadding; ++offset) {
|
|
9581
|
+
dst[offset] = 0;
|
|
9582
|
+
}
|
|
9583
|
+
signature.copy(dst, offset, sOffset + Math.max(-sPadding, 0), sOffset + sLength);
|
|
9584
|
+
dst = dst.toString("base64");
|
|
9585
|
+
dst = base64Url(dst);
|
|
9586
|
+
return dst;
|
|
9587
|
+
}
|
|
9588
|
+
function countPadding(buf, start, stop) {
|
|
9589
|
+
var padding = 0;
|
|
9590
|
+
while (start + padding < stop && buf[start + padding] === 0) {
|
|
9591
|
+
++padding;
|
|
9592
|
+
}
|
|
9593
|
+
var needsSign = buf[start + padding] >= MAX_OCTET;
|
|
9594
|
+
if (needsSign) {
|
|
9595
|
+
--padding;
|
|
9596
|
+
}
|
|
9597
|
+
return padding;
|
|
9598
|
+
}
|
|
9599
|
+
function joseToDer(signature, alg) {
|
|
9600
|
+
signature = signatureAsBuffer(signature);
|
|
9601
|
+
var paramBytes = getParamBytesForAlg(alg);
|
|
9602
|
+
var signatureBytes = signature.length;
|
|
9603
|
+
if (signatureBytes !== paramBytes * 2) {
|
|
9604
|
+
throw new TypeError('"' + alg + '" signatures must be "' + paramBytes * 2 + '" bytes, saw "' + signatureBytes + '"');
|
|
9605
|
+
}
|
|
9606
|
+
var rPadding = countPadding(signature, 0, paramBytes);
|
|
9607
|
+
var sPadding = countPadding(signature, paramBytes, signature.length);
|
|
9608
|
+
var rLength = paramBytes - rPadding;
|
|
9609
|
+
var sLength = paramBytes - sPadding;
|
|
9610
|
+
var rsBytes = 1 + 1 + rLength + 1 + 1 + sLength;
|
|
9611
|
+
var shortLength = rsBytes < MAX_OCTET;
|
|
9612
|
+
var dst = Buffer2.allocUnsafe((shortLength ? 2 : 3) + rsBytes);
|
|
9613
|
+
var offset = 0;
|
|
9614
|
+
dst[offset++] = ENCODED_TAG_SEQ;
|
|
9615
|
+
if (shortLength) {
|
|
9616
|
+
dst[offset++] = rsBytes;
|
|
9617
|
+
} else {
|
|
9618
|
+
dst[offset++] = MAX_OCTET | 1;
|
|
9619
|
+
dst[offset++] = rsBytes & 255;
|
|
9620
|
+
}
|
|
9621
|
+
dst[offset++] = ENCODED_TAG_INT;
|
|
9622
|
+
dst[offset++] = rLength;
|
|
9623
|
+
if (rPadding < 0) {
|
|
9624
|
+
dst[offset++] = 0;
|
|
9625
|
+
offset += signature.copy(dst, offset, 0, paramBytes);
|
|
9626
|
+
} else {
|
|
9627
|
+
offset += signature.copy(dst, offset, rPadding, paramBytes);
|
|
9628
|
+
}
|
|
9629
|
+
dst[offset++] = ENCODED_TAG_INT;
|
|
9630
|
+
dst[offset++] = sLength;
|
|
9631
|
+
if (sPadding < 0) {
|
|
9632
|
+
dst[offset++] = 0;
|
|
9633
|
+
signature.copy(dst, offset, paramBytes);
|
|
9634
|
+
} else {
|
|
9635
|
+
signature.copy(dst, offset, paramBytes + sPadding);
|
|
9636
|
+
}
|
|
9637
|
+
return dst;
|
|
9638
|
+
}
|
|
9639
|
+
module.exports = {
|
|
9640
|
+
derToJose,
|
|
9641
|
+
joseToDer
|
|
9642
|
+
};
|
|
9643
|
+
});
|
|
9644
|
+
|
|
9645
|
+
// ../../node_modules/.bun/buffer-equal-constant-time@1.0.1/node_modules/buffer-equal-constant-time/index.js
|
|
9646
|
+
var require_buffer_equal_constant_time = __commonJS((exports, module) => {
|
|
9647
|
+
var Buffer2 = __require("buffer").Buffer;
|
|
9648
|
+
var SlowBuffer = __require("buffer").SlowBuffer;
|
|
9649
|
+
module.exports = bufferEq;
|
|
9650
|
+
function bufferEq(a2, b2) {
|
|
9651
|
+
if (!Buffer2.isBuffer(a2) || !Buffer2.isBuffer(b2)) {
|
|
9652
|
+
return false;
|
|
9653
|
+
}
|
|
9654
|
+
if (a2.length !== b2.length) {
|
|
9655
|
+
return false;
|
|
9656
|
+
}
|
|
9657
|
+
var c2 = 0;
|
|
9658
|
+
for (var i = 0;i < a2.length; i++) {
|
|
9659
|
+
c2 |= a2[i] ^ b2[i];
|
|
9660
|
+
}
|
|
9661
|
+
return c2 === 0;
|
|
9662
|
+
}
|
|
9663
|
+
bufferEq.install = function() {
|
|
9664
|
+
Buffer2.prototype.equal = SlowBuffer.prototype.equal = function equal(that) {
|
|
9665
|
+
return bufferEq(this, that);
|
|
9666
|
+
};
|
|
9667
|
+
};
|
|
9668
|
+
var origBufEqual = Buffer2.prototype.equal;
|
|
9669
|
+
var origSlowBufEqual = SlowBuffer.prototype.equal;
|
|
9670
|
+
bufferEq.restore = function() {
|
|
9671
|
+
Buffer2.prototype.equal = origBufEqual;
|
|
9672
|
+
SlowBuffer.prototype.equal = origSlowBufEqual;
|
|
9673
|
+
};
|
|
9674
|
+
});
|
|
9675
|
+
|
|
9676
|
+
// ../../node_modules/.bun/jwa@2.0.1/node_modules/jwa/index.js
|
|
9677
|
+
var require_jwa = __commonJS((exports, module) => {
|
|
9678
|
+
var Buffer2 = require_safe_buffer().Buffer;
|
|
9679
|
+
var crypto2 = __require("crypto");
|
|
9680
|
+
var formatEcdsa = require_ecdsa_sig_formatter();
|
|
9681
|
+
var util = __require("util");
|
|
9682
|
+
var MSG_INVALID_ALGORITHM = `"%s" is not a valid algorithm.
|
|
9683
|
+
Supported algorithms are:
|
|
9684
|
+
"HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "PS256", "PS384", "PS512", "ES256", "ES384", "ES512" and "none".`;
|
|
9685
|
+
var MSG_INVALID_SECRET = "secret must be a string or buffer";
|
|
9686
|
+
var MSG_INVALID_VERIFIER_KEY = "key must be a string or a buffer";
|
|
9687
|
+
var MSG_INVALID_SIGNER_KEY = "key must be a string, a buffer or an object";
|
|
9688
|
+
var supportsKeyObjects = typeof crypto2.createPublicKey === "function";
|
|
9689
|
+
if (supportsKeyObjects) {
|
|
9690
|
+
MSG_INVALID_VERIFIER_KEY += " or a KeyObject";
|
|
9691
|
+
MSG_INVALID_SECRET += "or a KeyObject";
|
|
9692
|
+
}
|
|
9693
|
+
function checkIsPublicKey(key) {
|
|
9694
|
+
if (Buffer2.isBuffer(key)) {
|
|
9695
|
+
return;
|
|
9696
|
+
}
|
|
9697
|
+
if (typeof key === "string") {
|
|
9698
|
+
return;
|
|
9699
|
+
}
|
|
9700
|
+
if (!supportsKeyObjects) {
|
|
9701
|
+
throw typeError(MSG_INVALID_VERIFIER_KEY);
|
|
9702
|
+
}
|
|
9703
|
+
if (typeof key !== "object") {
|
|
9704
|
+
throw typeError(MSG_INVALID_VERIFIER_KEY);
|
|
9705
|
+
}
|
|
9706
|
+
if (typeof key.type !== "string") {
|
|
9707
|
+
throw typeError(MSG_INVALID_VERIFIER_KEY);
|
|
9708
|
+
}
|
|
9709
|
+
if (typeof key.asymmetricKeyType !== "string") {
|
|
9710
|
+
throw typeError(MSG_INVALID_VERIFIER_KEY);
|
|
9711
|
+
}
|
|
9712
|
+
if (typeof key.export !== "function") {
|
|
9713
|
+
throw typeError(MSG_INVALID_VERIFIER_KEY);
|
|
9714
|
+
}
|
|
9715
|
+
}
|
|
9716
|
+
function checkIsPrivateKey(key) {
|
|
9717
|
+
if (Buffer2.isBuffer(key)) {
|
|
9718
|
+
return;
|
|
9719
|
+
}
|
|
9720
|
+
if (typeof key === "string") {
|
|
9721
|
+
return;
|
|
9722
|
+
}
|
|
9723
|
+
if (typeof key === "object") {
|
|
9724
|
+
return;
|
|
9725
|
+
}
|
|
9726
|
+
throw typeError(MSG_INVALID_SIGNER_KEY);
|
|
9727
|
+
}
|
|
9728
|
+
function checkIsSecretKey(key) {
|
|
9729
|
+
if (Buffer2.isBuffer(key)) {
|
|
9730
|
+
return;
|
|
9731
|
+
}
|
|
9732
|
+
if (typeof key === "string") {
|
|
9733
|
+
return key;
|
|
9734
|
+
}
|
|
9735
|
+
if (!supportsKeyObjects) {
|
|
9736
|
+
throw typeError(MSG_INVALID_SECRET);
|
|
9737
|
+
}
|
|
9738
|
+
if (typeof key !== "object") {
|
|
9739
|
+
throw typeError(MSG_INVALID_SECRET);
|
|
9740
|
+
}
|
|
9741
|
+
if (key.type !== "secret") {
|
|
9742
|
+
throw typeError(MSG_INVALID_SECRET);
|
|
9743
|
+
}
|
|
9744
|
+
if (typeof key.export !== "function") {
|
|
9745
|
+
throw typeError(MSG_INVALID_SECRET);
|
|
9746
|
+
}
|
|
9747
|
+
}
|
|
9748
|
+
function fromBase64(base64) {
|
|
9749
|
+
return base64.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
9750
|
+
}
|
|
9751
|
+
function toBase64(base64url) {
|
|
9752
|
+
base64url = base64url.toString();
|
|
9753
|
+
var padding = 4 - base64url.length % 4;
|
|
9754
|
+
if (padding !== 4) {
|
|
9755
|
+
for (var i = 0;i < padding; ++i) {
|
|
9756
|
+
base64url += "=";
|
|
9757
|
+
}
|
|
9758
|
+
}
|
|
9759
|
+
return base64url.replace(/\-/g, "+").replace(/_/g, "/");
|
|
9760
|
+
}
|
|
9761
|
+
function typeError(template) {
|
|
9762
|
+
var args = [].slice.call(arguments, 1);
|
|
9763
|
+
var errMsg = util.format.bind(util, template).apply(null, args);
|
|
9764
|
+
return new TypeError(errMsg);
|
|
9765
|
+
}
|
|
9766
|
+
function bufferOrString(obj) {
|
|
9767
|
+
return Buffer2.isBuffer(obj) || typeof obj === "string";
|
|
9768
|
+
}
|
|
9769
|
+
function normalizeInput(thing) {
|
|
9770
|
+
if (!bufferOrString(thing))
|
|
9771
|
+
thing = JSON.stringify(thing);
|
|
9772
|
+
return thing;
|
|
9773
|
+
}
|
|
9774
|
+
function createHmacSigner(bits) {
|
|
9775
|
+
return function sign(thing, secret) {
|
|
9776
|
+
checkIsSecretKey(secret);
|
|
9777
|
+
thing = normalizeInput(thing);
|
|
9778
|
+
var hmac = crypto2.createHmac("sha" + bits, secret);
|
|
9779
|
+
var sig = (hmac.update(thing), hmac.digest("base64"));
|
|
9780
|
+
return fromBase64(sig);
|
|
9781
|
+
};
|
|
9782
|
+
}
|
|
9783
|
+
var bufferEqual;
|
|
9784
|
+
var timingSafeEqual = "timingSafeEqual" in crypto2 ? function timingSafeEqual2(a2, b2) {
|
|
9785
|
+
if (a2.byteLength !== b2.byteLength) {
|
|
9786
|
+
return false;
|
|
9787
|
+
}
|
|
9788
|
+
return crypto2.timingSafeEqual(a2, b2);
|
|
9789
|
+
} : function timingSafeEqual2(a2, b2) {
|
|
9790
|
+
if (!bufferEqual) {
|
|
9791
|
+
bufferEqual = require_buffer_equal_constant_time();
|
|
9792
|
+
}
|
|
9793
|
+
return bufferEqual(a2, b2);
|
|
9794
|
+
};
|
|
9795
|
+
function createHmacVerifier(bits) {
|
|
9796
|
+
return function verify(thing, signature, secret) {
|
|
9518
9797
|
var computedSig = createHmacSigner(bits)(thing, secret);
|
|
9519
9798
|
return timingSafeEqual(Buffer2.from(signature), Buffer2.from(computedSig));
|
|
9520
9799
|
};
|
|
@@ -9744,9 +10023,9 @@ var require_verify_stream = __commonJS((exports, module) => {
|
|
|
9744
10023
|
}
|
|
9745
10024
|
function jwsVerify(jwsSig, algorithm, secretOrKey) {
|
|
9746
10025
|
if (!algorithm) {
|
|
9747
|
-
var
|
|
9748
|
-
|
|
9749
|
-
throw
|
|
10026
|
+
var err3 = new Error("Missing algorithm parameter for jws.verify");
|
|
10027
|
+
err3.code = "MISSING_ALGORITHM";
|
|
10028
|
+
throw err3;
|
|
9750
10029
|
}
|
|
9751
10030
|
jwsSig = toString(jwsSig);
|
|
9752
10031
|
var signature = signatureFromJWS(jwsSig);
|
|
@@ -11934,9 +12213,9 @@ var require_verify = __commonJS((exports, module) => {
|
|
|
11934
12213
|
if (callback) {
|
|
11935
12214
|
done = callback;
|
|
11936
12215
|
} else {
|
|
11937
|
-
done = function(
|
|
11938
|
-
if (
|
|
11939
|
-
throw
|
|
12216
|
+
done = function(err3, data) {
|
|
12217
|
+
if (err3)
|
|
12218
|
+
throw err3;
|
|
11940
12219
|
return data;
|
|
11941
12220
|
};
|
|
11942
12221
|
}
|
|
@@ -11963,8 +12242,8 @@ var require_verify = __commonJS((exports, module) => {
|
|
|
11963
12242
|
let decodedToken;
|
|
11964
12243
|
try {
|
|
11965
12244
|
decodedToken = decode(jwtString, { complete: true });
|
|
11966
|
-
} catch (
|
|
11967
|
-
return done(
|
|
12245
|
+
} catch (err3) {
|
|
12246
|
+
return done(err3);
|
|
11968
12247
|
}
|
|
11969
12248
|
if (!decodedToken) {
|
|
11970
12249
|
return done(new JsonWebTokenError("invalid token"));
|
|
@@ -11981,9 +12260,9 @@ var require_verify = __commonJS((exports, module) => {
|
|
|
11981
12260
|
return secretCallback(null, secretOrPublicKey);
|
|
11982
12261
|
};
|
|
11983
12262
|
}
|
|
11984
|
-
return getSecret(header, function(
|
|
11985
|
-
if (
|
|
11986
|
-
return done(new JsonWebTokenError("error in secret or public key callback: " +
|
|
12263
|
+
return getSecret(header, function(err3, secretOrPublicKey2) {
|
|
12264
|
+
if (err3) {
|
|
12265
|
+
return done(new JsonWebTokenError("error in secret or public key callback: " + err3.message));
|
|
11987
12266
|
}
|
|
11988
12267
|
const hasSignature = parts[2].trim() !== "";
|
|
11989
12268
|
if (!hasSignature && secretOrPublicKey2) {
|
|
@@ -12619,11 +12898,11 @@ var require_sign = __commonJS((exports, module) => {
|
|
|
12619
12898
|
typ: isObjectPayload ? "JWT" : undefined,
|
|
12620
12899
|
kid: options.keyid
|
|
12621
12900
|
}, options.header);
|
|
12622
|
-
function failure(
|
|
12901
|
+
function failure(err3) {
|
|
12623
12902
|
if (callback) {
|
|
12624
|
-
return callback(
|
|
12903
|
+
return callback(err3);
|
|
12625
12904
|
}
|
|
12626
|
-
throw
|
|
12905
|
+
throw err3;
|
|
12627
12906
|
}
|
|
12628
12907
|
if (!secretOrPrivateKey && options.algorithm !== "none") {
|
|
12629
12908
|
return failure(new Error("secretOrPrivateKey must have a value"));
|
|
@@ -12695,8 +12974,8 @@ var require_sign = __commonJS((exports, module) => {
|
|
|
12695
12974
|
if (typeof options.notBefore !== "undefined") {
|
|
12696
12975
|
try {
|
|
12697
12976
|
payload.nbf = timespan(options.notBefore, timestamp2);
|
|
12698
|
-
} catch (
|
|
12699
|
-
return failure(
|
|
12977
|
+
} catch (err3) {
|
|
12978
|
+
return failure(err3);
|
|
12700
12979
|
}
|
|
12701
12980
|
if (typeof payload.nbf === "undefined") {
|
|
12702
12981
|
return failure(new Error('"notBefore" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60'));
|
|
@@ -12705,8 +12984,8 @@ var require_sign = __commonJS((exports, module) => {
|
|
|
12705
12984
|
if (typeof options.expiresIn !== "undefined" && typeof payload === "object") {
|
|
12706
12985
|
try {
|
|
12707
12986
|
payload.exp = timespan(options.expiresIn, timestamp2);
|
|
12708
|
-
} catch (
|
|
12709
|
-
return failure(
|
|
12987
|
+
} catch (err3) {
|
|
12988
|
+
return failure(err3);
|
|
12710
12989
|
}
|
|
12711
12990
|
if (typeof payload.exp === "undefined") {
|
|
12712
12991
|
return failure(new Error('"expiresIn" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60'));
|
|
@@ -13764,8 +14043,8 @@ class EventWire {
|
|
|
13764
14043
|
try {
|
|
13765
14044
|
const message = JSON.parse(event.data);
|
|
13766
14045
|
this.handleMessage(message);
|
|
13767
|
-
} catch (
|
|
13768
|
-
console.error("EventWire: Failed to parse message",
|
|
14046
|
+
} catch (err3) {
|
|
14047
|
+
console.error("EventWire: Failed to parse message", err3);
|
|
13769
14048
|
}
|
|
13770
14049
|
};
|
|
13771
14050
|
this.ws.onclose = (event) => {
|
|
@@ -13774,17 +14053,17 @@ class EventWire {
|
|
|
13774
14053
|
console.log("EventWire disconnected");
|
|
13775
14054
|
this.scheduleReconnect();
|
|
13776
14055
|
};
|
|
13777
|
-
this.ws.onerror = (
|
|
13778
|
-
console.error("EventWire error:",
|
|
14056
|
+
this.ws.onerror = (err3) => {
|
|
14057
|
+
console.error("EventWire error:", err3);
|
|
13779
14058
|
if (this.state === "connecting") {
|
|
13780
14059
|
this.state = "disconnected";
|
|
13781
14060
|
this.ws = null;
|
|
13782
14061
|
}
|
|
13783
14062
|
};
|
|
13784
|
-
} catch (
|
|
14063
|
+
} catch (err3) {
|
|
13785
14064
|
this.state = "disconnected";
|
|
13786
14065
|
this.ws = null;
|
|
13787
|
-
console.error("EventWire: Failed to connect",
|
|
14066
|
+
console.error("EventWire: Failed to connect", err3);
|
|
13788
14067
|
this.scheduleReconnect();
|
|
13789
14068
|
}
|
|
13790
14069
|
}
|
|
@@ -26319,318 +26598,49 @@ ${colors3.yellow}Type declaration errors:${colors3.reset}`);
|
|
|
26319
26598
|
devContexts.push({
|
|
26320
26599
|
configPath,
|
|
26321
26600
|
config,
|
|
26322
|
-
configDir,
|
|
26323
|
-
contexts,
|
|
26324
|
-
watchers: [watcher]
|
|
26325
|
-
});
|
|
26326
|
-
console.log("");
|
|
26327
|
-
log(`Watching for changes in ${configDir}...`, "cyan");
|
|
26328
|
-
}
|
|
26329
|
-
console.log("");
|
|
26330
|
-
log("Development mode started. Press Ctrl+C to stop.", "green");
|
|
26331
|
-
process.on("SIGINT", () => {
|
|
26332
|
-
console.log("");
|
|
26333
|
-
log("Shutting down dev mode...", "yellow");
|
|
26334
|
-
for (const devCtx of devContexts) {
|
|
26335
|
-
for (const watcher of devCtx.watchers) {
|
|
26336
|
-
watcher.close();
|
|
26337
|
-
}
|
|
26338
|
-
}
|
|
26339
|
-
process.exit(0);
|
|
26340
|
-
});
|
|
26341
|
-
} catch (err) {
|
|
26342
|
-
console.error("Error in dev command:", err);
|
|
26343
|
-
process.exit(1);
|
|
26344
|
-
}
|
|
26345
|
-
}
|
|
26346
|
-
|
|
26347
|
-
// src/platform/shared.ts
|
|
26348
|
-
import { copyFileSync, existsSync as existsSync10, mkdirSync as mkdirSync9, readFileSync as readFileSync10, readdirSync as readdirSync5, rmSync as rmSync2, writeFileSync as writeFileSync9 } from "fs";
|
|
26349
|
-
import { dirname as dirname7, join as join11 } from "path";
|
|
26350
|
-
|
|
26351
|
-
// src/builder/module-builder.ts
|
|
26352
|
-
import { execSync } from "child_process";
|
|
26353
|
-
import {
|
|
26354
|
-
existsSync as existsSync7,
|
|
26355
|
-
mkdirSync as mkdirSync6,
|
|
26356
|
-
readFileSync as readFileSync7,
|
|
26357
|
-
readdirSync as readdirSync4,
|
|
26358
|
-
rmSync,
|
|
26359
|
-
writeFileSync as writeFileSync6
|
|
26360
|
-
} from "fs";
|
|
26361
|
-
import { basename as basename2, dirname as dirname5, join as join8, relative as relative3 } from "path";
|
|
26362
|
-
|
|
26363
|
-
// src/i18n/index.ts
|
|
26364
|
-
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
26365
|
-
import { dirname as dirname4, join as join5 } from "path";
|
|
26366
|
-
|
|
26367
|
-
// src/i18n/catalog.ts
|
|
26368
|
-
function hashMsgid(msgid) {
|
|
26369
|
-
const hasher = new Bun.CryptoHasher("md5");
|
|
26370
|
-
hasher.update(msgid);
|
|
26371
|
-
return hasher.digest("hex").slice(0, 8);
|
|
26372
|
-
}
|
|
26373
|
-
function parsePo(content) {
|
|
26374
|
-
const entries = [];
|
|
26375
|
-
const lines = content.split(`
|
|
26376
|
-
`);
|
|
26377
|
-
let locations = [];
|
|
26378
|
-
let hash = "";
|
|
26379
|
-
let msgid = "";
|
|
26380
|
-
let msgstr = "";
|
|
26381
|
-
let obsolete = false;
|
|
26382
|
-
let inManual = false;
|
|
26383
|
-
const flush = () => {
|
|
26384
|
-
if (msgid) {
|
|
26385
|
-
entries.push({
|
|
26386
|
-
msgid,
|
|
26387
|
-
msgstr,
|
|
26388
|
-
locations,
|
|
26389
|
-
hash: hash || hashMsgid(msgid),
|
|
26390
|
-
obsolete,
|
|
26391
|
-
...inManual ? { manual: true } : {}
|
|
26392
|
-
});
|
|
26393
|
-
}
|
|
26394
|
-
locations = [];
|
|
26395
|
-
hash = "";
|
|
26396
|
-
msgid = "";
|
|
26397
|
-
msgstr = "";
|
|
26398
|
-
obsolete = false;
|
|
26399
|
-
};
|
|
26400
|
-
for (const line of lines) {
|
|
26401
|
-
const trimmed = line.trim();
|
|
26402
|
-
if (trimmed === "# manual") {
|
|
26403
|
-
inManual = true;
|
|
26404
|
-
continue;
|
|
26405
|
-
}
|
|
26406
|
-
if (trimmed === "# end manual") {
|
|
26407
|
-
if (msgid)
|
|
26408
|
-
flush();
|
|
26409
|
-
inManual = false;
|
|
26410
|
-
continue;
|
|
26411
|
-
}
|
|
26412
|
-
if (trimmed === "" || trimmed.startsWith("#,")) {
|
|
26413
|
-
if (msgid)
|
|
26414
|
-
flush();
|
|
26415
|
-
continue;
|
|
26416
|
-
}
|
|
26417
|
-
if (trimmed.startsWith("#:")) {
|
|
26418
|
-
if (msgid)
|
|
26419
|
-
flush();
|
|
26420
|
-
locations.push(trimmed.slice(3).trim());
|
|
26421
|
-
continue;
|
|
26422
|
-
}
|
|
26423
|
-
if (trimmed.startsWith("#.")) {
|
|
26424
|
-
const hashMatch = trimmed.match(/hash:(\w+)/);
|
|
26425
|
-
if (hashMatch)
|
|
26426
|
-
hash = hashMatch[1];
|
|
26427
|
-
continue;
|
|
26428
|
-
}
|
|
26429
|
-
if (trimmed.startsWith("#~")) {
|
|
26430
|
-
const rest = trimmed.slice(3).trim();
|
|
26431
|
-
if (rest.startsWith("msgid")) {
|
|
26432
|
-
if (msgid)
|
|
26433
|
-
flush();
|
|
26434
|
-
obsolete = true;
|
|
26435
|
-
msgid = extractQuoted(rest.slice(5));
|
|
26436
|
-
} else if (rest.startsWith("msgstr")) {
|
|
26437
|
-
msgstr = extractQuoted(rest.slice(6));
|
|
26438
|
-
}
|
|
26439
|
-
continue;
|
|
26440
|
-
}
|
|
26441
|
-
if (trimmed.startsWith("msgid")) {
|
|
26442
|
-
if (msgid)
|
|
26443
|
-
flush();
|
|
26444
|
-
msgid = extractQuoted(trimmed.slice(5));
|
|
26445
|
-
} else if (trimmed.startsWith("msgstr")) {
|
|
26446
|
-
msgstr = extractQuoted(trimmed.slice(6));
|
|
26447
|
-
}
|
|
26448
|
-
}
|
|
26449
|
-
flush();
|
|
26450
|
-
return entries;
|
|
26451
|
-
}
|
|
26452
|
-
function writePo(entries) {
|
|
26453
|
-
const lines = [];
|
|
26454
|
-
const manual = entries.filter((e) => e.manual);
|
|
26455
|
-
const active = entries.filter((e) => !e.obsolete && !e.manual);
|
|
26456
|
-
const obsolete = entries.filter((e) => e.obsolete);
|
|
26457
|
-
if (manual.length > 0) {
|
|
26458
|
-
lines.push("# manual");
|
|
26459
|
-
for (const entry of manual) {
|
|
26460
|
-
lines.push(`msgid ${quoteString(entry.msgid)}`);
|
|
26461
|
-
lines.push(`msgstr ${quoteString(entry.msgstr)}`);
|
|
26462
|
-
lines.push("");
|
|
26463
|
-
}
|
|
26464
|
-
lines.push("# end manual");
|
|
26465
|
-
lines.push("");
|
|
26466
|
-
}
|
|
26467
|
-
for (const entry of active) {
|
|
26468
|
-
for (const loc of entry.locations) {
|
|
26469
|
-
lines.push(`#: ${loc}`);
|
|
26470
|
-
}
|
|
26471
|
-
lines.push(`#. hash:${entry.hash}`);
|
|
26472
|
-
lines.push(`msgid ${quoteString(entry.msgid)}`);
|
|
26473
|
-
lines.push(`msgstr ${quoteString(entry.msgstr)}`);
|
|
26474
|
-
lines.push("");
|
|
26475
|
-
}
|
|
26476
|
-
if (obsolete.length > 0) {
|
|
26477
|
-
lines.push("# Obsolete entries");
|
|
26478
|
-
lines.push("");
|
|
26479
|
-
for (const entry of obsolete) {
|
|
26480
|
-
lines.push(`#~ msgid ${quoteString(entry.msgid)}`);
|
|
26481
|
-
lines.push(`#~ msgstr ${quoteString(entry.msgstr)}`);
|
|
26482
|
-
lines.push("");
|
|
26483
|
-
}
|
|
26484
|
-
}
|
|
26485
|
-
return lines.join(`
|
|
26486
|
-
`);
|
|
26487
|
-
}
|
|
26488
|
-
function mergeCatalog(existing, extracted) {
|
|
26489
|
-
const existingMap = new Map;
|
|
26490
|
-
for (const entry of existing) {
|
|
26491
|
-
existingMap.set(entry.msgid, entry);
|
|
26492
|
-
}
|
|
26493
|
-
const manualEntries = existing.filter((e) => e.manual);
|
|
26494
|
-
const manualIds = new Set(manualEntries.map((e) => e.msgid));
|
|
26495
|
-
const result = [];
|
|
26496
|
-
const seen = new Set;
|
|
26497
|
-
for (const [msgid, locations] of extracted) {
|
|
26498
|
-
seen.add(msgid);
|
|
26499
|
-
if (manualIds.has(msgid))
|
|
26500
|
-
continue;
|
|
26501
|
-
const prev = existingMap.get(msgid);
|
|
26502
|
-
result.push({
|
|
26503
|
-
msgid,
|
|
26504
|
-
msgstr: prev?.msgstr ?? "",
|
|
26505
|
-
locations: [...locations].sort(),
|
|
26506
|
-
hash: hashMsgid(msgid),
|
|
26507
|
-
obsolete: false
|
|
26508
|
-
});
|
|
26509
|
-
}
|
|
26510
|
-
for (const entry of existing) {
|
|
26511
|
-
if (!seen.has(entry.msgid) && !entry.obsolete && !entry.manual && entry.msgstr) {
|
|
26512
|
-
result.push({
|
|
26513
|
-
...entry,
|
|
26514
|
-
obsolete: true,
|
|
26515
|
-
locations: []
|
|
26516
|
-
});
|
|
26517
|
-
}
|
|
26518
|
-
}
|
|
26519
|
-
result.sort((a, b) => a.msgid.localeCompare(b.msgid));
|
|
26520
|
-
return [...manualEntries, ...result];
|
|
26521
|
-
}
|
|
26522
|
-
function extractQuoted(s) {
|
|
26523
|
-
const trimmed = s.trim();
|
|
26524
|
-
if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
|
|
26525
|
-
return trimmed.slice(1, -1).replace(/\\n/g, `
|
|
26526
|
-
`).replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
26527
|
-
}
|
|
26528
|
-
return trimmed;
|
|
26529
|
-
}
|
|
26530
|
-
function quoteString(s) {
|
|
26531
|
-
const escaped = s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n");
|
|
26532
|
-
return `"${escaped}"`;
|
|
26533
|
-
}
|
|
26534
|
-
|
|
26535
|
-
// src/i18n/compile.ts
|
|
26536
|
-
import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
26537
|
-
import { join as join4 } from "path";
|
|
26538
|
-
function compileCatalog(poPath) {
|
|
26539
|
-
const content = readFileSync3(poPath, "utf-8");
|
|
26540
|
-
const entries = parsePo(content);
|
|
26541
|
-
const result = {};
|
|
26542
|
-
for (const entry of entries) {
|
|
26543
|
-
if (!entry.obsolete && entry.msgstr) {
|
|
26544
|
-
result[entry.msgid] = entry.msgstr;
|
|
26545
|
-
}
|
|
26546
|
-
}
|
|
26547
|
-
const sorted = {};
|
|
26548
|
-
for (const key of Object.keys(result).sort()) {
|
|
26549
|
-
sorted[key] = result[key];
|
|
26550
|
-
}
|
|
26551
|
-
return sorted;
|
|
26552
|
-
}
|
|
26553
|
-
function compileAllCatalogs(localesDir, outDir) {
|
|
26554
|
-
mkdirSync3(outDir, { recursive: true });
|
|
26555
|
-
for (const file of readdirSync2(localesDir)) {
|
|
26556
|
-
if (!file.endsWith(".po"))
|
|
26557
|
-
continue;
|
|
26558
|
-
const locale = file.replace(".po", "");
|
|
26559
|
-
const compiled = compileCatalog(join4(localesDir, file));
|
|
26560
|
-
writeFileSync3(join4(outDir, `${locale}.json`), JSON.stringify(compiled));
|
|
26561
|
-
}
|
|
26562
|
-
}
|
|
26563
|
-
|
|
26564
|
-
// src/i18n/plugin.ts
|
|
26565
|
-
function i18nExtractPlugin(collector, rootDir) {
|
|
26566
|
-
return {
|
|
26567
|
-
name: "arc-i18n-extract",
|
|
26568
|
-
setup(build2) {
|
|
26569
|
-
build2.onLoad({ filter: /\.tsx?$/ }, async (args) => {
|
|
26570
|
-
const source = await Bun.file(args.path).text();
|
|
26571
|
-
const relPath = args.path.startsWith(rootDir) ? args.path.slice(rootDir.length + 1) : args.path;
|
|
26572
|
-
const transRegex = /<Trans>\s*([^<{]+?)\s*<\/Trans>/g;
|
|
26573
|
-
for (const match2 of source.matchAll(transRegex)) {
|
|
26574
|
-
const msgid = match2[1].trim();
|
|
26575
|
-
if (!msgid)
|
|
26576
|
-
continue;
|
|
26577
|
-
const line = source.substring(0, match2.index).split(`
|
|
26578
|
-
`).length;
|
|
26579
|
-
const loc = `${relPath}:${line}`;
|
|
26580
|
-
if (!collector.has(msgid))
|
|
26581
|
-
collector.set(msgid, new Set);
|
|
26582
|
-
collector.get(msgid).add(loc);
|
|
26583
|
-
}
|
|
26584
|
-
const tRegex = /\bt`([^`]+)`/g;
|
|
26585
|
-
for (const match2 of source.matchAll(tRegex)) {
|
|
26586
|
-
const msgid = match2[1];
|
|
26587
|
-
if (!msgid)
|
|
26588
|
-
continue;
|
|
26589
|
-
const line = source.substring(0, match2.index).split(`
|
|
26590
|
-
`).length;
|
|
26591
|
-
const loc = `${relPath}:${line}`;
|
|
26592
|
-
if (!collector.has(msgid))
|
|
26593
|
-
collector.set(msgid, new Set);
|
|
26594
|
-
collector.get(msgid).add(loc);
|
|
26595
|
-
}
|
|
26596
|
-
return;
|
|
26597
|
-
});
|
|
26598
|
-
}
|
|
26599
|
-
};
|
|
26600
|
-
}
|
|
26601
|
-
|
|
26602
|
-
// src/i18n/index.ts
|
|
26603
|
-
function readTranslationsConfig(rootDir) {
|
|
26604
|
-
const pkgPath = join5(rootDir, "package.json");
|
|
26605
|
-
if (!existsSync4(pkgPath))
|
|
26606
|
-
return null;
|
|
26607
|
-
const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
|
|
26608
|
-
const config = pkg.arc?.translations;
|
|
26609
|
-
if (!config?.locales?.length)
|
|
26610
|
-
return null;
|
|
26611
|
-
return {
|
|
26612
|
-
locales: config.locales,
|
|
26613
|
-
sourceLocale: config.sourceLocale ?? config.locales[0]
|
|
26614
|
-
};
|
|
26615
|
-
}
|
|
26616
|
-
async function finalizeTranslations(rootDir, outDir, collector) {
|
|
26617
|
-
const config = readTranslationsConfig(rootDir);
|
|
26618
|
-
if (!config || collector.size === 0)
|
|
26619
|
-
return;
|
|
26620
|
-
const localesJsonDir = join5(outDir, "locales");
|
|
26621
|
-
mkdirSync4(localesJsonDir, { recursive: true });
|
|
26622
|
-
console.log(` Extracted ${collector.size} translatable string(s) for ${config.locales.length} locale(s)`);
|
|
26623
|
-
for (const locale of config.locales) {
|
|
26624
|
-
const poPath = join5(rootDir, "locales", `${locale}.po`);
|
|
26625
|
-
mkdirSync4(dirname4(poPath), { recursive: true });
|
|
26626
|
-
const existing = existsSync4(poPath) ? parsePo(readFileSync4(poPath, "utf-8")) : [];
|
|
26627
|
-
const merged = mergeCatalog(existing, collector);
|
|
26628
|
-
writeFileSync4(poPath, writePo(merged));
|
|
26629
|
-
const compiled = compileCatalog(poPath);
|
|
26630
|
-
writeFileSync4(join5(localesJsonDir, `${locale}.json`), JSON.stringify(compiled));
|
|
26601
|
+
configDir,
|
|
26602
|
+
contexts,
|
|
26603
|
+
watchers: [watcher]
|
|
26604
|
+
});
|
|
26605
|
+
console.log("");
|
|
26606
|
+
log(`Watching for changes in ${configDir}...`, "cyan");
|
|
26607
|
+
}
|
|
26608
|
+
console.log("");
|
|
26609
|
+
log("Development mode started. Press Ctrl+C to stop.", "green");
|
|
26610
|
+
process.on("SIGINT", () => {
|
|
26611
|
+
console.log("");
|
|
26612
|
+
log("Shutting down dev mode...", "yellow");
|
|
26613
|
+
for (const devCtx of devContexts) {
|
|
26614
|
+
for (const watcher of devCtx.watchers) {
|
|
26615
|
+
watcher.close();
|
|
26616
|
+
}
|
|
26617
|
+
}
|
|
26618
|
+
process.exit(0);
|
|
26619
|
+
});
|
|
26620
|
+
} catch (err) {
|
|
26621
|
+
console.error("Error in dev command:", err);
|
|
26622
|
+
process.exit(1);
|
|
26631
26623
|
}
|
|
26632
26624
|
}
|
|
26633
26625
|
|
|
26626
|
+
// src/platform/shared.ts
|
|
26627
|
+
import { copyFileSync, existsSync as existsSync10, mkdirSync as mkdirSync9, readdirSync as readdirSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "fs";
|
|
26628
|
+
import { dirname as dirname6, join as join11 } from "path";
|
|
26629
|
+
|
|
26630
|
+
// src/builder/module-builder.ts
|
|
26631
|
+
import { execSync } from "child_process";
|
|
26632
|
+
import {
|
|
26633
|
+
existsSync as existsSync7,
|
|
26634
|
+
mkdirSync as mkdirSync6,
|
|
26635
|
+
readFileSync as readFileSync7,
|
|
26636
|
+
readdirSync as readdirSync4,
|
|
26637
|
+
rmSync,
|
|
26638
|
+
writeFileSync as writeFileSync6
|
|
26639
|
+
} from "fs";
|
|
26640
|
+
import { basename as basename2, dirname as dirname5, join as join8, relative as relative3 } from "path";
|
|
26641
|
+
init_i18n();
|
|
26642
|
+
init_compile();
|
|
26643
|
+
|
|
26634
26644
|
// src/builder/build-cache.ts
|
|
26635
26645
|
import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
26636
26646
|
import { join as join6 } from "path";
|
|
@@ -26799,6 +26809,24 @@ async function pAll(tasks, concurrency = DEFAULT_CONCURRENCY) {
|
|
|
26799
26809
|
}
|
|
26800
26810
|
|
|
26801
26811
|
// src/builder/module-builder.ts
|
|
26812
|
+
function singleReactPlugin(rootDir) {
|
|
26813
|
+
const reactPkgs = ["react", "react-dom", "react-dom/client", "react/jsx-runtime"];
|
|
26814
|
+
return {
|
|
26815
|
+
name: "single-react",
|
|
26816
|
+
setup(build2) {
|
|
26817
|
+
const resolved = new Map;
|
|
26818
|
+
for (const spec of reactPkgs) {
|
|
26819
|
+
try {
|
|
26820
|
+
resolved.set(spec, Bun.resolveSync(spec, rootDir));
|
|
26821
|
+
} catch {}
|
|
26822
|
+
}
|
|
26823
|
+
build2.onResolve({ filter: /^(react|react-dom|react-dom\/client|react\/jsx-runtime)$/ }, (args) => {
|
|
26824
|
+
const path4 = resolved.get(args.path);
|
|
26825
|
+
return path4 ? { path: path4 } : null;
|
|
26826
|
+
});
|
|
26827
|
+
}
|
|
26828
|
+
};
|
|
26829
|
+
}
|
|
26802
26830
|
function jsxDevShimPlugin() {
|
|
26803
26831
|
return {
|
|
26804
26832
|
name: "jsx-dev-runtime-shim",
|
|
@@ -26914,8 +26942,9 @@ async function buildContextClient(pkg, rootDir, client, cache, noCache) {
|
|
|
26914
26942
|
console.log(` building: ${pkg.name} (${client.name})`);
|
|
26915
26943
|
const peerDeps = Object.keys(pkg.packageJson.peerDependencies ?? {});
|
|
26916
26944
|
const allDeps = pkg.packageJson.dependencies ?? {};
|
|
26917
|
-
const
|
|
26918
|
-
const
|
|
26945
|
+
const isBrowser2 = client.name === "browser";
|
|
26946
|
+
const workspaceDeps = isBrowser2 ? Object.keys(allDeps) : Object.entries(allDeps).filter(([, spec]) => !spec.startsWith("workspace:")).map(([name]) => name);
|
|
26947
|
+
const externals = [...peerDeps, ...workspaceDeps];
|
|
26919
26948
|
const result = await Bun.build({
|
|
26920
26949
|
entrypoints: [pkg.entrypoint],
|
|
26921
26950
|
outdir: join8(outDir, "main"),
|
|
@@ -26944,9 +26973,39 @@ async function buildContextPackages(rootDir, packages, cache, noCache) {
|
|
|
26944
26973
|
const contexts = packages.filter((p) => isContextPackage(p.packageJson));
|
|
26945
26974
|
if (contexts.length === 0)
|
|
26946
26975
|
return { declarationErrors: [] };
|
|
26947
|
-
const
|
|
26948
|
-
const
|
|
26949
|
-
const
|
|
26976
|
+
const byName = new Map(contexts.map((p) => [p.name, p]));
|
|
26977
|
+
const remaining = new Set(contexts.map((p) => p.name));
|
|
26978
|
+
const done = new Set;
|
|
26979
|
+
const ordered = [];
|
|
26980
|
+
const workspaceDepsOf = (pkg) => {
|
|
26981
|
+
const deps = pkg.packageJson.dependencies ?? {};
|
|
26982
|
+
return Object.entries(deps).filter(([name, spec]) => spec.startsWith("workspace:") && byName.has(name)).map(([name]) => name);
|
|
26983
|
+
};
|
|
26984
|
+
while (remaining.size > 0) {
|
|
26985
|
+
const layer = [];
|
|
26986
|
+
for (const name of remaining) {
|
|
26987
|
+
const pkg = byName.get(name);
|
|
26988
|
+
const unmetDeps = workspaceDepsOf(pkg).filter((d) => !done.has(d));
|
|
26989
|
+
if (unmetDeps.length === 0)
|
|
26990
|
+
layer.push(pkg);
|
|
26991
|
+
}
|
|
26992
|
+
if (layer.length === 0) {
|
|
26993
|
+
const cycle = [...remaining].join(", ");
|
|
26994
|
+
throw new Error(`Workspace dependency cycle detected: ${cycle}`);
|
|
26995
|
+
}
|
|
26996
|
+
ordered.push(layer);
|
|
26997
|
+
for (const pkg of layer) {
|
|
26998
|
+
done.add(pkg.name);
|
|
26999
|
+
remaining.delete(pkg.name);
|
|
27000
|
+
}
|
|
27001
|
+
}
|
|
27002
|
+
const declarationErrors = [];
|
|
27003
|
+
for (const layer of ordered) {
|
|
27004
|
+
const tasks = layer.flatMap((pkg) => CONTEXT_CLIENTS.map((client) => () => buildContextClient(pkg, rootDir, client, cache, noCache)));
|
|
27005
|
+
const results = await pAll(tasks);
|
|
27006
|
+
for (const r of results)
|
|
27007
|
+
declarationErrors.push(...r.declarationErrors);
|
|
27008
|
+
}
|
|
26950
27009
|
if (declarationErrors.length > 0) {
|
|
26951
27010
|
console.warn(`
|
|
26952
27011
|
\x1B[33mType declaration errors:\x1B[0m`);
|
|
@@ -26956,125 +27015,163 @@ async function buildContextPackages(rootDir, packages, cache, noCache) {
|
|
|
26956
27015
|
}
|
|
26957
27016
|
return { declarationErrors };
|
|
26958
27017
|
}
|
|
26959
|
-
async function
|
|
27018
|
+
async function buildBrowserApp(rootDir, outDir, plan, cache, noCache, i18nCollector) {
|
|
26960
27019
|
mkdirSync6(outDir, { recursive: true });
|
|
26961
|
-
const
|
|
26962
|
-
const
|
|
26963
|
-
|
|
26964
|
-
|
|
26965
|
-
|
|
26966
|
-
|
|
26967
|
-
|
|
26968
|
-
|
|
26969
|
-
|
|
26970
|
-
|
|
26971
|
-
|
|
26972
|
-
|
|
26973
|
-
allCached = false;
|
|
26974
|
-
}
|
|
26975
|
-
await finalizeTranslations(rootDir, join8(outDir, ".."), i18nCollector);
|
|
26976
|
-
return { modules: aggregateModules, cached: allCached };
|
|
26977
|
-
}
|
|
26978
|
-
async function buildChunkGroup(rootDir, chunkOutDir, chunk, members, cache, noCache, i18nCollector) {
|
|
26979
|
-
const unitId = `modules-chunk:${chunk}`;
|
|
26980
|
-
const pkgHashes = members.map((m) => ({
|
|
26981
|
-
name: m.pkg.name,
|
|
26982
|
-
safeName: m.safeName,
|
|
26983
|
-
moduleName: m.moduleName,
|
|
26984
|
-
srcHash: pkgSourceHash(m.pkg)
|
|
26985
|
-
}));
|
|
27020
|
+
const publicMembers = plan.groups.get("public") ?? [];
|
|
27021
|
+
const protectedGroups = plan.chunks.filter((c) => c !== "public").map((c) => ({ name: c, members: plan.groups.get(c) ?? [] })).filter((g) => g.members.length > 0);
|
|
27022
|
+
const unitId = "browser-app";
|
|
27023
|
+
const allMembers = [];
|
|
27024
|
+
for (const m of publicMembers) {
|
|
27025
|
+
allMembers.push({ name: m.pkg.name, group: "public", srcHash: pkgSourceHash(m.pkg) });
|
|
27026
|
+
}
|
|
27027
|
+
for (const g of protectedGroups) {
|
|
27028
|
+
for (const m of g.members) {
|
|
27029
|
+
allMembers.push({ name: m.pkg.name, group: g.name, srcHash: pkgSourceHash(m.pkg) });
|
|
27030
|
+
}
|
|
27031
|
+
}
|
|
26986
27032
|
const inputHash = sha256OfJson({
|
|
26987
|
-
|
|
26988
|
-
|
|
26989
|
-
|
|
27033
|
+
members: allMembers,
|
|
27034
|
+
groups: [
|
|
27035
|
+
"initial",
|
|
27036
|
+
...protectedGroups.map((g) => g.name).sort()
|
|
27037
|
+
],
|
|
26990
27038
|
define: { ONLY_SERVER: "false", ONLY_BROWSER: "true", ONLY_CLIENT: "true" }
|
|
26991
27039
|
});
|
|
26992
27040
|
if (!noCache && isCacheHit(cache, unitId, inputHash)) {
|
|
26993
|
-
const
|
|
26994
|
-
|
|
26995
|
-
|
|
26996
|
-
|
|
26997
|
-
|
|
26998
|
-
|
|
26999
|
-
|
|
27000
|
-
|
|
27001
|
-
|
|
27002
|
-
|
|
27003
|
-
|
|
27004
|
-
|
|
27005
|
-
|
|
27006
|
-
|
|
27007
|
-
hash: existing[h.safeName] ?? sha256Hex(readFileSync7(filePath))
|
|
27008
|
-
});
|
|
27041
|
+
const cached = cache.units[unitId]?.outputHashes;
|
|
27042
|
+
if (cached?._manifest) {
|
|
27043
|
+
try {
|
|
27044
|
+
const m = JSON.parse(cached._manifest);
|
|
27045
|
+
const allFiles = [
|
|
27046
|
+
m.initial.file,
|
|
27047
|
+
...Object.values(m.groups).map((g) => g.file),
|
|
27048
|
+
...m.sharedChunks
|
|
27049
|
+
];
|
|
27050
|
+
if (allFiles.every((f) => existsSync7(join8(outDir, f)))) {
|
|
27051
|
+
console.log(` \u2713 cached: ${unitId}`);
|
|
27052
|
+
return { ...m, cached: true };
|
|
27053
|
+
}
|
|
27054
|
+
} catch {}
|
|
27009
27055
|
}
|
|
27010
|
-
|
|
27011
|
-
|
|
27012
|
-
|
|
27056
|
+
}
|
|
27057
|
+
console.log(` building: ${unitId} (initial: ${publicMembers.length} modules, groups: ${protectedGroups.map((g) => `${g.name}=${g.members.length}`).join(",") || "none"})`);
|
|
27058
|
+
if (existsSync7(outDir)) {
|
|
27059
|
+
for (const f of readdirSync4(outDir)) {
|
|
27060
|
+
if (f.endsWith(".js"))
|
|
27061
|
+
rmSync(join8(outDir, f), { force: true });
|
|
27013
27062
|
}
|
|
27014
|
-
console.log(` rebuilding ${unitId}: output file missing`);
|
|
27015
27063
|
}
|
|
27016
|
-
|
|
27017
|
-
const tmpDir = join8(chunkOutDir, "_entries");
|
|
27064
|
+
const tmpDir = join8(outDir, "_entries");
|
|
27018
27065
|
mkdirSync6(tmpDir, { recursive: true });
|
|
27019
|
-
const
|
|
27020
|
-
|
|
27021
|
-
|
|
27022
|
-
|
|
27023
|
-
|
|
27024
|
-
|
|
27066
|
+
const importLines = (pkgs) => pkgs.map((m) => `import "${m.pkg.name}";`).join(`
|
|
27067
|
+
`);
|
|
27068
|
+
const initialEntry = join8(tmpDir, "initial.ts");
|
|
27069
|
+
writeFileSync6(initialEntry, `${importLines(publicMembers)}
|
|
27070
|
+
export { startApp } from "@arcote.tech/platform";
|
|
27071
|
+
`);
|
|
27072
|
+
const entryPaths = [initialEntry];
|
|
27073
|
+
const groupModuleMap = new Map;
|
|
27074
|
+
for (const g of protectedGroups) {
|
|
27075
|
+
const entry = join8(tmpDir, `${g.name}.ts`);
|
|
27076
|
+
writeFileSync6(entry, `${importLines(g.members)}
|
|
27077
|
+
`);
|
|
27078
|
+
entryPaths.push(entry);
|
|
27079
|
+
groupModuleMap.set(g.name, g.members.map((m) => m.moduleName));
|
|
27080
|
+
}
|
|
27081
|
+
const allMemberPkgs = new Map;
|
|
27082
|
+
for (const m of publicMembers)
|
|
27083
|
+
allMemberPkgs.set(m.pkg.name, m.pkg);
|
|
27084
|
+
for (const g of protectedGroups)
|
|
27085
|
+
for (const m of g.members)
|
|
27086
|
+
allMemberPkgs.set(m.pkg.name, m.pkg);
|
|
27087
|
+
const patchedPkgJsons = [];
|
|
27088
|
+
for (const pkg of allMemberPkgs.values()) {
|
|
27089
|
+
const pkgJsonPath = join8(pkg.path, "package.json");
|
|
27090
|
+
if (!existsSync7(pkgJsonPath))
|
|
27091
|
+
continue;
|
|
27092
|
+
const original = readFileSync7(pkgJsonPath, "utf-8");
|
|
27093
|
+
const parsed = JSON.parse(original);
|
|
27094
|
+
if (parsed.sideEffects === true)
|
|
27095
|
+
continue;
|
|
27096
|
+
parsed.sideEffects = true;
|
|
27097
|
+
writeFileSync6(pkgJsonPath, JSON.stringify(parsed, null, 2) + `
|
|
27025
27098
|
`);
|
|
27026
|
-
|
|
27099
|
+
patchedPkgJsons.push({ path: pkgJsonPath, original });
|
|
27027
27100
|
}
|
|
27028
|
-
|
|
27029
|
-
|
|
27030
|
-
|
|
27031
|
-
|
|
27032
|
-
|
|
27033
|
-
|
|
27034
|
-
|
|
27035
|
-
|
|
27036
|
-
|
|
27037
|
-
|
|
27038
|
-
|
|
27039
|
-
|
|
27040
|
-
|
|
27041
|
-
|
|
27042
|
-
|
|
27043
|
-
|
|
27044
|
-
|
|
27045
|
-
|
|
27046
|
-
|
|
27047
|
-
|
|
27048
|
-
|
|
27049
|
-
|
|
27050
|
-
|
|
27051
|
-
|
|
27052
|
-
|
|
27053
|
-
|
|
27054
|
-
});
|
|
27101
|
+
let result;
|
|
27102
|
+
try {
|
|
27103
|
+
result = await Bun.build({
|
|
27104
|
+
entrypoints: entryPaths,
|
|
27105
|
+
outdir: outDir,
|
|
27106
|
+
splitting: true,
|
|
27107
|
+
format: "esm",
|
|
27108
|
+
target: "browser",
|
|
27109
|
+
external: [],
|
|
27110
|
+
plugins: [
|
|
27111
|
+
singleReactPlugin(rootDir),
|
|
27112
|
+
jsxDevShimPlugin(),
|
|
27113
|
+
i18nExtractPlugin(i18nCollector, rootDir)
|
|
27114
|
+
],
|
|
27115
|
+
naming: "[name].[ext]",
|
|
27116
|
+
define: {
|
|
27117
|
+
ONLY_SERVER: "false",
|
|
27118
|
+
ONLY_BROWSER: "true",
|
|
27119
|
+
ONLY_CLIENT: "true",
|
|
27120
|
+
"process.env.NODE_ENV": '"production"'
|
|
27121
|
+
}
|
|
27122
|
+
});
|
|
27123
|
+
} finally {
|
|
27124
|
+
for (const p of patchedPkgJsons)
|
|
27125
|
+
writeFileSync6(p.path, p.original);
|
|
27126
|
+
}
|
|
27127
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
27055
27128
|
if (!result.success) {
|
|
27056
|
-
console.error(`Chunk "${chunk}" build failed:`);
|
|
27057
27129
|
for (const log2 of result.logs)
|
|
27058
27130
|
console.error(log2);
|
|
27059
|
-
throw new Error(
|
|
27131
|
+
throw new Error("Browser app build failed");
|
|
27132
|
+
}
|
|
27133
|
+
let initialFile = "";
|
|
27134
|
+
let initialHash = "";
|
|
27135
|
+
const groups = {};
|
|
27136
|
+
const sharedChunks = [];
|
|
27137
|
+
for (const out of result.outputs) {
|
|
27138
|
+
const name = basename2(out.path);
|
|
27139
|
+
if (out.kind === "entry-point") {
|
|
27140
|
+
const bytes = readFileSync7(out.path);
|
|
27141
|
+
const hash = sha256Hex(bytes).slice(0, 16);
|
|
27142
|
+
const stem = name.replace(/\.js$/, "");
|
|
27143
|
+
const finalName = `${stem}.${hash}.js`;
|
|
27144
|
+
const finalPath = join8(outDir, finalName);
|
|
27145
|
+
rmSync(finalPath, { force: true });
|
|
27146
|
+
writeFileSync6(finalPath, bytes);
|
|
27147
|
+
rmSync(out.path, { force: true });
|
|
27148
|
+
if (stem === "initial") {
|
|
27149
|
+
initialFile = finalName;
|
|
27150
|
+
initialHash = hash;
|
|
27151
|
+
} else {
|
|
27152
|
+
groups[stem] = {
|
|
27153
|
+
file: finalName,
|
|
27154
|
+
hash,
|
|
27155
|
+
modules: groupModuleMap.get(stem) ?? []
|
|
27156
|
+
};
|
|
27157
|
+
}
|
|
27158
|
+
} else if (out.kind === "chunk") {
|
|
27159
|
+
sharedChunks.push(name);
|
|
27160
|
+
}
|
|
27060
27161
|
}
|
|
27061
|
-
|
|
27062
|
-
|
|
27063
|
-
|
|
27064
|
-
|
|
27065
|
-
|
|
27066
|
-
|
|
27067
|
-
|
|
27068
|
-
|
|
27069
|
-
|
|
27070
|
-
|
|
27071
|
-
|
|
27072
|
-
chunk,
|
|
27073
|
-
hash
|
|
27074
|
-
};
|
|
27162
|
+
if (!initialFile) {
|
|
27163
|
+
throw new Error("Browser app build: initial entry not found in outputs");
|
|
27164
|
+
}
|
|
27165
|
+
const manifest = {
|
|
27166
|
+
initial: { file: initialFile, hash: initialHash },
|
|
27167
|
+
groups,
|
|
27168
|
+
sharedChunks,
|
|
27169
|
+
cached: false
|
|
27170
|
+
};
|
|
27171
|
+
updateCache(cache, unitId, inputHash, {
|
|
27172
|
+
outputHashes: { _manifest: JSON.stringify(manifest) }
|
|
27075
27173
|
});
|
|
27076
|
-
|
|
27077
|
-
return { modules, cached: false };
|
|
27174
|
+
return manifest;
|
|
27078
27175
|
}
|
|
27079
27176
|
async function buildTranslations(rootDir, arcDir, cache, noCache) {
|
|
27080
27177
|
const localesDir = join8(rootDir, "locales");
|
|
@@ -27216,17 +27313,10 @@ import {
|
|
|
27216
27313
|
existsSync as existsSync8,
|
|
27217
27314
|
mkdirSync as mkdirSync7,
|
|
27218
27315
|
readFileSync as readFileSync8,
|
|
27219
|
-
realpathSync as realpathSync2,
|
|
27220
27316
|
unlinkSync as unlinkSync2,
|
|
27221
27317
|
writeFileSync as writeFileSync7
|
|
27222
27318
|
} from "fs";
|
|
27223
|
-
import {
|
|
27224
|
-
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
27225
|
-
function locatePlatformServerEntry() {
|
|
27226
|
-
const here = fileURLToPath5(import.meta.url);
|
|
27227
|
-
const arcRoot = realpathSync2(dirname6(dirname6(dirname6(dirname6(here)))));
|
|
27228
|
-
return join9(arcRoot, "packages", "platform", "src", "index.server.ts");
|
|
27229
|
-
}
|
|
27319
|
+
import { join as join9 } from "path";
|
|
27230
27320
|
async function extractAccessMap(rootDir, packages) {
|
|
27231
27321
|
const serverBundles = packages.filter((p) => isContextPackage(p.packageJson)).map((p) => ({
|
|
27232
27322
|
name: p.name,
|
|
@@ -27244,8 +27334,7 @@ async function extractAccessMap(rootDir, packages) {
|
|
|
27244
27334
|
env: {
|
|
27245
27335
|
...process.env,
|
|
27246
27336
|
ARC_ACCESS_BUNDLES: JSON.stringify(serverBundles),
|
|
27247
|
-
ARC_ACCESS_OUT: outPath
|
|
27248
|
-
ARC_PLATFORM_ENTRY: locatePlatformServerEntry()
|
|
27337
|
+
ARC_ACCESS_OUT: outPath
|
|
27249
27338
|
},
|
|
27250
27339
|
stdout: "pipe",
|
|
27251
27340
|
stderr: "inherit"
|
|
@@ -27276,9 +27365,11 @@ if (!out) {
|
|
|
27276
27365
|
process.exit(2);
|
|
27277
27366
|
}
|
|
27278
27367
|
|
|
27279
|
-
//
|
|
27280
|
-
//
|
|
27281
|
-
|
|
27368
|
+
// Bare-specifier import \u2014 Bun walks up from this worker's location
|
|
27369
|
+
// (<rootDir>/.arc/.tmp/) to <rootDir>/node_modules and finds the package.
|
|
27370
|
+
// Single entry (./src/index.ts) \u2014 React imports on top level are benign
|
|
27371
|
+
// (createContext, function defs); no DOM access until actual render.
|
|
27372
|
+
const platform = await import("@arcote.tech/platform");
|
|
27282
27373
|
|
|
27283
27374
|
for (const { name, path } of bundles) {
|
|
27284
27375
|
try {
|
|
@@ -27436,7 +27527,7 @@ function resolveWorkspace() {
|
|
|
27436
27527
|
err("No package.json found");
|
|
27437
27528
|
process.exit(1);
|
|
27438
27529
|
}
|
|
27439
|
-
const rootDir =
|
|
27530
|
+
const rootDir = dirname6(packageJsonPath);
|
|
27440
27531
|
const rootPkg = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
27441
27532
|
const appName = rootPkg.name ?? "Arc App";
|
|
27442
27533
|
const arcDir = join11(rootDir, ".arc", "platform");
|
|
@@ -27471,8 +27562,7 @@ function resolveWorkspace() {
|
|
|
27471
27562
|
rootPkg,
|
|
27472
27563
|
appName,
|
|
27473
27564
|
arcDir,
|
|
27474
|
-
|
|
27475
|
-
shellDir: join11(arcDir, "shell"),
|
|
27565
|
+
browserDir: join11(arcDir, "browser"),
|
|
27476
27566
|
assetsDir: join11(arcDir, "assets"),
|
|
27477
27567
|
publicDir: join11(rootDir, "public"),
|
|
27478
27568
|
packages,
|
|
@@ -27492,32 +27582,27 @@ async function buildAll(ws, opts = {}) {
|
|
|
27492
27582
|
`);
|
|
27493
27583
|
const plan = planChunks(ws.packages, accessMap);
|
|
27494
27584
|
ok(`Chunks: ${plan.chunks.map((c) => `${c}(${plan.groups.get(c)?.length ?? 0})`).join(", ")}`);
|
|
27495
|
-
const
|
|
27496
|
-
|
|
27497
|
-
|
|
27585
|
+
const i18nCollector = new Map;
|
|
27586
|
+
const [browserResult] = await Promise.all([
|
|
27587
|
+
buildBrowserApp(ws.rootDir, ws.browserDir, plan, cache, noCache, i18nCollector),
|
|
27498
27588
|
buildStyles(ws.rootDir, ws.arcDir, ws.packages, themePath, cache, noCache),
|
|
27499
27589
|
copyBrowserAssets(ws, cache, noCache),
|
|
27500
27590
|
buildTranslations(ws.rootDir, ws.arcDir, cache, noCache)
|
|
27501
27591
|
]);
|
|
27592
|
+
const { finalizeTranslations: finalizeTranslations3 } = await Promise.resolve().then(() => (init_i18n(), exports_i18n));
|
|
27593
|
+
await finalizeTranslations3(ws.rootDir, ws.arcDir, i18nCollector);
|
|
27502
27594
|
collectFrameworkDeps(ws.arcDir, ws.rootDir, ws.packages);
|
|
27503
27595
|
saveBuildCache(ws.arcDir, cache);
|
|
27504
|
-
const finalManifest = assembleManifest(ws,
|
|
27505
|
-
writeFileSync9(join11(ws.
|
|
27596
|
+
const finalManifest = assembleManifest(ws, browserResult, cache);
|
|
27597
|
+
writeFileSync9(join11(ws.arcDir, "manifest.json"), JSON.stringify(finalManifest, null, 2));
|
|
27506
27598
|
return finalManifest;
|
|
27507
27599
|
}
|
|
27508
|
-
function assembleManifest(ws,
|
|
27509
|
-
const shellEntries = {};
|
|
27510
|
-
for (const [unitId, entry] of Object.entries(cache.units)) {
|
|
27511
|
-
if (unitId.startsWith("shell:") && entry.outputHash) {
|
|
27512
|
-
shellEntries[unitId] = entry.outputHash;
|
|
27513
|
-
}
|
|
27514
|
-
}
|
|
27515
|
-
const shellHash = sha256OfJson(shellEntries);
|
|
27600
|
+
function assembleManifest(ws, browser, cache) {
|
|
27516
27601
|
const stylesHash = cache.units["styles"]?.outputHash ?? "";
|
|
27517
27602
|
return {
|
|
27518
|
-
|
|
27519
|
-
|
|
27520
|
-
|
|
27603
|
+
initial: browser.initial,
|
|
27604
|
+
groups: browser.groups,
|
|
27605
|
+
sharedChunks: browser.sharedChunks,
|
|
27521
27606
|
stylesHash,
|
|
27522
27607
|
buildTime: new Date().toISOString()
|
|
27523
27608
|
};
|
|
@@ -27619,170 +27704,12 @@ async function copyBrowserAssets(ws, cache, noCache) {
|
|
|
27619
27704
|
const outputHashes = {};
|
|
27620
27705
|
for (const asset of assets) {
|
|
27621
27706
|
const dest = join11(ws.assetsDir, asset.to);
|
|
27622
|
-
mkdirSync9(
|
|
27707
|
+
mkdirSync9(dirname6(dest), { recursive: true });
|
|
27623
27708
|
copyFileSync(asset.src, dest);
|
|
27624
27709
|
outputHashes[asset.to] = sha256Hex(readFileSync10(dest));
|
|
27625
27710
|
}
|
|
27626
27711
|
updateCache(cache, unitId, inputHash, { outputHashes });
|
|
27627
27712
|
}
|
|
27628
|
-
function collectArcPeerDeps(packages) {
|
|
27629
|
-
const seen = new Set;
|
|
27630
|
-
for (const pkg of ["@arcote.tech/arc", "@arcote.tech/arc-ds", "@arcote.tech/arc-react", "@arcote.tech/platform"]) {
|
|
27631
|
-
seen.add(pkg);
|
|
27632
|
-
}
|
|
27633
|
-
for (const wp of packages) {
|
|
27634
|
-
const peerDeps = wp.packageJson.peerDependencies ?? {};
|
|
27635
|
-
for (const dep of Object.keys(peerDeps)) {
|
|
27636
|
-
if (dep.startsWith("@arcote.tech/"))
|
|
27637
|
-
seen.add(dep);
|
|
27638
|
-
}
|
|
27639
|
-
}
|
|
27640
|
-
return [...seen].map((pkg) => {
|
|
27641
|
-
const short = pkg === "@arcote.tech/platform" ? "platform" : pkg.replace("@arcote.tech/", "");
|
|
27642
|
-
return [short, pkg];
|
|
27643
|
-
});
|
|
27644
|
-
}
|
|
27645
|
-
var REACT_ENTRIES = [
|
|
27646
|
-
[
|
|
27647
|
-
"react",
|
|
27648
|
-
`import React from "react";
|
|
27649
|
-
export default React;
|
|
27650
|
-
export const {
|
|
27651
|
-
Children, Component, Fragment, Profiler, PureComponent, StrictMode, Suspense,
|
|
27652
|
-
cloneElement, createContext, createElement, createRef, forwardRef, isValidElement,
|
|
27653
|
-
lazy, memo, startTransition, use, useCallback, useContext, useDebugValue,
|
|
27654
|
-
useDeferredValue, useEffect, useId, useImperativeHandle, useInsertionEffect,
|
|
27655
|
-
useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore,
|
|
27656
|
-
useTransition, version, useActionState, useOptimistic,
|
|
27657
|
-
} = React;`
|
|
27658
|
-
],
|
|
27659
|
-
["jsx-runtime", `export { jsx, jsxs, Fragment } from "react/jsx-runtime";`],
|
|
27660
|
-
[
|
|
27661
|
-
"jsx-dev-runtime",
|
|
27662
|
-
`export { jsxDEV, Fragment } from "react/jsx-dev-runtime";`
|
|
27663
|
-
],
|
|
27664
|
-
[
|
|
27665
|
-
"react-dom",
|
|
27666
|
-
`import ReactDOM from "react-dom";
|
|
27667
|
-
export default ReactDOM;
|
|
27668
|
-
export const { createPortal, flushSync } = ReactDOM;`
|
|
27669
|
-
],
|
|
27670
|
-
[
|
|
27671
|
-
"react-dom-client",
|
|
27672
|
-
`export { createRoot, hydrateRoot } from "react-dom/client";`
|
|
27673
|
-
]
|
|
27674
|
-
];
|
|
27675
|
-
var REACT_OUTPUT_FILES = REACT_ENTRIES.map(([n]) => `${n}.js`);
|
|
27676
|
-
var SHELL_BASE_EXTERNAL = [
|
|
27677
|
-
"react",
|
|
27678
|
-
"react-dom",
|
|
27679
|
-
"react/jsx-runtime",
|
|
27680
|
-
"react/jsx-dev-runtime",
|
|
27681
|
-
"react-dom/client"
|
|
27682
|
-
];
|
|
27683
|
-
var sourceFilter2 = (rel) => {
|
|
27684
|
-
if (rel.startsWith("dist/") || rel.startsWith("dist"))
|
|
27685
|
-
return false;
|
|
27686
|
-
if (rel.includes("/node_modules/") || rel.startsWith("node_modules"))
|
|
27687
|
-
return false;
|
|
27688
|
-
if (rel.startsWith(".arc/") || rel.startsWith(".arc"))
|
|
27689
|
-
return false;
|
|
27690
|
-
return true;
|
|
27691
|
-
};
|
|
27692
|
-
function arcPkgSrcHash(rootDir, pkg) {
|
|
27693
|
-
const srcDir = join11(rootDir, "node_modules", pkg, "src");
|
|
27694
|
-
if (existsSync10(srcDir))
|
|
27695
|
-
return sha256OfDir(srcDir, sourceFilter2);
|
|
27696
|
-
return sha256OfDir(join11(rootDir, "node_modules", pkg), sourceFilter2);
|
|
27697
|
-
}
|
|
27698
|
-
async function buildShellReact(shellDir, tmpDir, rootDir, cache, noCache) {
|
|
27699
|
-
const unitId = "shell:react";
|
|
27700
|
-
const inputHash = sha256OfJson({
|
|
27701
|
-
react: readInstalledVersion(rootDir, "react"),
|
|
27702
|
-
"react-dom": readInstalledVersion(rootDir, "react-dom"),
|
|
27703
|
-
entries: REACT_ENTRIES.map(([k, v]) => [k, v])
|
|
27704
|
-
});
|
|
27705
|
-
const requiredOutputs = REACT_OUTPUT_FILES.map((f) => join11(shellDir, f));
|
|
27706
|
-
if (!noCache && isCacheHit(cache, unitId, inputHash, requiredOutputs)) {
|
|
27707
|
-
console.log(` \u2713 cached: shell:react`);
|
|
27708
|
-
return;
|
|
27709
|
-
}
|
|
27710
|
-
console.log(` building: shell:react`);
|
|
27711
|
-
const reactEps = [];
|
|
27712
|
-
for (const [name, code] of REACT_ENTRIES) {
|
|
27713
|
-
const f = join11(tmpDir, `${name}.ts`);
|
|
27714
|
-
await Bun.write(f, code);
|
|
27715
|
-
reactEps.push(f);
|
|
27716
|
-
}
|
|
27717
|
-
const r = await Bun.build({
|
|
27718
|
-
entrypoints: reactEps,
|
|
27719
|
-
outdir: shellDir,
|
|
27720
|
-
splitting: true,
|
|
27721
|
-
format: "esm",
|
|
27722
|
-
target: "browser",
|
|
27723
|
-
naming: "[name].[ext]"
|
|
27724
|
-
});
|
|
27725
|
-
if (!r.success) {
|
|
27726
|
-
for (const l of r.logs)
|
|
27727
|
-
console.error(l);
|
|
27728
|
-
throw new Error("Shell React build failed");
|
|
27729
|
-
}
|
|
27730
|
-
const outputHash = sha256OfFiles(requiredOutputs);
|
|
27731
|
-
updateCache(cache, unitId, inputHash, { outputHash });
|
|
27732
|
-
}
|
|
27733
|
-
async function buildShellArcEntry(shortName, pkg, allArcPkgs, shellDir, tmpDir, rootDir, cache, noCache) {
|
|
27734
|
-
const unitId = `shell:arc:${shortName}`;
|
|
27735
|
-
const otherExternals = allArcPkgs.filter((p) => p !== pkg);
|
|
27736
|
-
const inputHash = sha256OfJson({
|
|
27737
|
-
pkg,
|
|
27738
|
-
version: readInstalledVersion(rootDir, pkg),
|
|
27739
|
-
src: arcPkgSrcHash(rootDir, pkg),
|
|
27740
|
-
base: SHELL_BASE_EXTERNAL,
|
|
27741
|
-
others: [...otherExternals].sort()
|
|
27742
|
-
});
|
|
27743
|
-
const outputFile = join11(shellDir, `${shortName}.js`);
|
|
27744
|
-
if (!noCache && isCacheHit(cache, unitId, inputHash, [outputFile])) {
|
|
27745
|
-
console.log(` \u2713 cached: ${unitId}`);
|
|
27746
|
-
return;
|
|
27747
|
-
}
|
|
27748
|
-
console.log(` building: ${unitId}`);
|
|
27749
|
-
const f = join11(tmpDir, `${shortName}.ts`);
|
|
27750
|
-
await Bun.write(f, `export * from "${pkg}";
|
|
27751
|
-
`);
|
|
27752
|
-
const r = await Bun.build({
|
|
27753
|
-
entrypoints: [f],
|
|
27754
|
-
outdir: shellDir,
|
|
27755
|
-
format: "esm",
|
|
27756
|
-
target: "browser",
|
|
27757
|
-
naming: "[name].[ext]",
|
|
27758
|
-
external: [...SHELL_BASE_EXTERNAL, ...otherExternals],
|
|
27759
|
-
define: {
|
|
27760
|
-
ONLY_SERVER: "false",
|
|
27761
|
-
ONLY_BROWSER: "true",
|
|
27762
|
-
ONLY_CLIENT: "true"
|
|
27763
|
-
}
|
|
27764
|
-
});
|
|
27765
|
-
if (!r.success) {
|
|
27766
|
-
for (const l of r.logs)
|
|
27767
|
-
console.error(l);
|
|
27768
|
-
throw new Error(`Shell build failed for ${pkg}`);
|
|
27769
|
-
}
|
|
27770
|
-
const outputHash = sha256OfFiles([outputFile]);
|
|
27771
|
-
updateCache(cache, unitId, inputHash, { outputHash });
|
|
27772
|
-
}
|
|
27773
|
-
async function buildShell(ws, cache, noCache) {
|
|
27774
|
-
mkdirSync9(ws.shellDir, { recursive: true });
|
|
27775
|
-
const tmpDir = join11(ws.shellDir, "_tmp");
|
|
27776
|
-
mkdirSync9(tmpDir, { recursive: true });
|
|
27777
|
-
const arcEntries = collectArcPeerDeps(ws.packages);
|
|
27778
|
-
const allArcPkgs = arcEntries.map(([, pkg]) => pkg);
|
|
27779
|
-
const tasks = [
|
|
27780
|
-
() => buildShellReact(ws.shellDir, tmpDir, ws.rootDir, cache, noCache),
|
|
27781
|
-
...arcEntries.map(([short, pkg]) => () => buildShellArcEntry(short, pkg, allArcPkgs, ws.shellDir, tmpDir, ws.rootDir, cache, noCache))
|
|
27782
|
-
];
|
|
27783
|
-
await pAll(tasks);
|
|
27784
|
-
rmSync2(tmpDir, { recursive: true, force: true });
|
|
27785
|
-
}
|
|
27786
27713
|
async function loadServerContext(ws) {
|
|
27787
27714
|
globalThis.ONLY_SERVER = true;
|
|
27788
27715
|
globalThis.ONLY_BROWSER = false;
|
|
@@ -27830,24 +27757,25 @@ async function loadServerContext(ws) {
|
|
|
27830
27757
|
async function platformBuild(opts = {}) {
|
|
27831
27758
|
const ws = resolveWorkspace();
|
|
27832
27759
|
const manifest = await buildAll(ws, { noCache: opts.noCache });
|
|
27833
|
-
|
|
27760
|
+
const groupCount = Object.keys(manifest.groups).length;
|
|
27761
|
+
ok(`Platform built \u2014 initial + ${groupCount} group(s)`);
|
|
27834
27762
|
}
|
|
27835
27763
|
|
|
27836
27764
|
// src/commands/platform-deploy.ts
|
|
27837
|
-
import { existsSync as
|
|
27838
|
-
import { dirname as
|
|
27839
|
-
import { fileURLToPath as
|
|
27765
|
+
import { existsSync as existsSync17, readFileSync as readFileSync14 } from "fs";
|
|
27766
|
+
import { dirname as dirname8, join as join19 } from "path";
|
|
27767
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
27840
27768
|
|
|
27841
27769
|
// src/deploy/bootstrap.ts
|
|
27842
27770
|
var {spawn: spawn4 } = globalThis.Bun;
|
|
27843
27771
|
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync13 } from "fs";
|
|
27844
27772
|
import { tmpdir as tmpdir2 } from "os";
|
|
27845
|
-
import { join as
|
|
27773
|
+
import { join as join17 } from "path";
|
|
27846
27774
|
|
|
27847
27775
|
// src/deploy/ansible.ts
|
|
27848
27776
|
import { spawn as nodeSpawn } from "child_process";
|
|
27849
|
-
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
|
|
27850
|
-
import { tmpdir } from "os";
|
|
27777
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
|
|
27778
|
+
import { homedir, tmpdir } from "os";
|
|
27851
27779
|
import { join as join12 } from "path";
|
|
27852
27780
|
|
|
27853
27781
|
// src/deploy/assets.ts
|
|
@@ -28042,7 +27970,22 @@ var ANSIBLE_SITE_YML = `---
|
|
|
28042
27970
|
- { policy: deny, dir: incoming }
|
|
28043
27971
|
- { policy: allow, dir: outgoing }
|
|
28044
27972
|
|
|
28045
|
-
- name:
|
|
27973
|
+
- name: Remove legacy ufw limit rule on SSH (replaced by plain allow)
|
|
27974
|
+
# If a prior bootstrap installed \`ufw limit 22/tcp\`, drop it \u2014 otherwise
|
|
27975
|
+
# the limit rule shadows the allow rule and rate-throttles deploy flows.
|
|
27976
|
+
ufw:
|
|
27977
|
+
rule: limit
|
|
27978
|
+
port: "{{ ssh_port }}"
|
|
27979
|
+
proto: tcp
|
|
27980
|
+
delete: true
|
|
27981
|
+
ignore_errors: true
|
|
27982
|
+
|
|
27983
|
+
- name: Open firewall ports (SSH key-only auth, no brute-force surface)
|
|
27984
|
+
# SSH on port 22: PasswordAuthentication=no + key-only means brute force
|
|
27985
|
+
# is impossible without the operator's private key. Rate-limiting (ufw
|
|
27986
|
+
# limit / fail2ban sshd jail) breaks legitimate deploy flows that open
|
|
27987
|
+
# many short SSH connections in sequence (canSsh -> sshExec -> scp -> ...).
|
|
27988
|
+
# 80/443: Caddy ACME + app traffic, never rate-limited.
|
|
28046
27989
|
ufw:
|
|
28047
27990
|
rule: allow
|
|
28048
27991
|
port: "{{ item }}"
|
|
@@ -28056,17 +27999,18 @@ var ANSIBLE_SITE_YML = `---
|
|
|
28056
27999
|
ufw:
|
|
28057
28000
|
state: enabled
|
|
28058
28001
|
|
|
28059
|
-
- name:
|
|
28002
|
+
- name: Disable fail2ban sshd jail
|
|
28003
|
+
# Key-only SSH + ufw rate-limit make fail2ban for sshd redundant and
|
|
28004
|
+
# actively harmful when the operator's IP roams. Keep fail2ban installed
|
|
28005
|
+
# for future jails (web/db) but turn off the sshd jail explicitly.
|
|
28060
28006
|
copy:
|
|
28061
28007
|
dest: /etc/fail2ban/jail.local
|
|
28062
28008
|
content: |
|
|
28063
28009
|
[sshd]
|
|
28064
|
-
enabled =
|
|
28065
|
-
|
|
28066
|
-
maxretry = 5
|
|
28067
|
-
findtime = 600
|
|
28068
|
-
bantime = 3600
|
|
28010
|
+
enabled = false
|
|
28011
|
+
{% if extra_allowed_ips %}
|
|
28069
28012
|
ignoreip = 127.0.0.1/8 ::1 {{ extra_allowed_ips | join(' ') }}
|
|
28013
|
+
{% endif %}
|
|
28070
28014
|
mode: "0644"
|
|
28071
28015
|
notify: restart fail2ban
|
|
28072
28016
|
|
|
@@ -28114,18 +28058,32 @@ async function materializeAssets(targetDir, files) {
|
|
|
28114
28058
|
}
|
|
28115
28059
|
|
|
28116
28060
|
// src/deploy/ansible.ts
|
|
28061
|
+
function pickSshKeyForAnsible(configured) {
|
|
28062
|
+
if (configured) {
|
|
28063
|
+
const expanded = configured.startsWith("~") ? join12(homedir(), configured.slice(1)) : configured;
|
|
28064
|
+
return existsSync11(expanded) ? expanded : null;
|
|
28065
|
+
}
|
|
28066
|
+
for (const name of ["id_ed25519", "id_ecdsa", "id_rsa"]) {
|
|
28067
|
+
const path4 = join12(homedir(), ".ssh", name);
|
|
28068
|
+
if (existsSync11(path4))
|
|
28069
|
+
return path4;
|
|
28070
|
+
}
|
|
28071
|
+
return null;
|
|
28072
|
+
}
|
|
28117
28073
|
async function runAnsible(inputs) {
|
|
28118
28074
|
const workDir = join12(tmpdir(), "arc-deploy", `ansible-${Date.now()}`);
|
|
28119
28075
|
mkdirSync10(workDir, { recursive: true });
|
|
28120
28076
|
await materializeAssets(workDir, ASSETS.ansible);
|
|
28121
28077
|
const user = inputs.asRoot ? "root" : inputs.target.user;
|
|
28122
28078
|
const port = inputs.ansible?.sshPort ?? inputs.target.port;
|
|
28079
|
+
const sshKey = pickSshKeyForAnsible(inputs.target.sshKey);
|
|
28080
|
+
const sshKeyArg = sshKey ? ` -o IdentitiesOnly=yes -i ${sshKey}` : "";
|
|
28123
28081
|
const inventory = [
|
|
28124
28082
|
"[arc]",
|
|
28125
28083
|
`${inputs.target.host} ansible_user=${user} ansible_port=${port}`,
|
|
28126
28084
|
"",
|
|
28127
28085
|
"[arc:vars]",
|
|
28128
|
-
|
|
28086
|
+
`ansible_ssh_common_args='-o StrictHostKeyChecking=accept-new -o BatchMode=yes -o PreferredAuthentications=publickey${sshKeyArg}'`,
|
|
28129
28087
|
"ansible_python_interpreter=/usr/bin/python3",
|
|
28130
28088
|
""
|
|
28131
28089
|
].join(`
|
|
@@ -28224,7 +28182,7 @@ function generateCompose({ cfg }) {
|
|
|
28224
28182
|
for (const [name, env2] of Object.entries(cfg.envs)) {
|
|
28225
28183
|
const upperName = name.toUpperCase().replace(/-/g, "_");
|
|
28226
28184
|
lines.push(` arc-${name}:`);
|
|
28227
|
-
lines.push(` image: \${ARC_IMAGE_${upperName}
|
|
28185
|
+
lines.push(` image: \${ARC_IMAGE_${upperName}:-arc-${name}:not-deployed}`);
|
|
28228
28186
|
lines.push(` container_name: arc-${name}`);
|
|
28229
28187
|
lines.push(" restart: unless-stopped");
|
|
28230
28188
|
lines.push(" volumes:");
|
|
@@ -28278,16 +28236,16 @@ async function generateHtpasswd(user, password) {
|
|
|
28278
28236
|
// src/deploy/terraform.ts
|
|
28279
28237
|
import { spawn as nodeSpawn2 } from "child_process";
|
|
28280
28238
|
import { createHash as createHash2 } from "crypto";
|
|
28281
|
-
import { existsSync as
|
|
28282
|
-
import { homedir } from "os";
|
|
28239
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "fs";
|
|
28240
|
+
import { homedir as homedir2 } from "os";
|
|
28283
28241
|
import { join as join13 } from "path";
|
|
28284
28242
|
async function runTerraform(inputs) {
|
|
28285
28243
|
const wsHash = createHash2("sha256").update(inputs.workspaceDir).digest("hex").slice(0, 16);
|
|
28286
|
-
const workDir = join13(
|
|
28244
|
+
const workDir = join13(homedir2(), ".arc-deploy", wsHash, "tf");
|
|
28287
28245
|
mkdirSync11(workDir, { recursive: true });
|
|
28288
28246
|
await materializeAssets(workDir, ASSETS.terraform);
|
|
28289
28247
|
const sshPubKey = inputs.tf.sshPublicKey ?? expandHome("~/.ssh/id_ed25519.pub");
|
|
28290
|
-
if (!
|
|
28248
|
+
if (!existsSync12(expandHome(sshPubKey))) {
|
|
28291
28249
|
throw new Error(`SSH public key not found at ${sshPubKey}. Set provision.terraform.sshPublicKey in deploy.arc.json.`);
|
|
28292
28250
|
}
|
|
28293
28251
|
const tfvars = [
|
|
@@ -28358,33 +28316,93 @@ function expandHome(p) {
|
|
|
28358
28316
|
}
|
|
28359
28317
|
|
|
28360
28318
|
// src/deploy/config.ts
|
|
28361
|
-
import { existsSync as
|
|
28319
|
+
import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "fs";
|
|
28320
|
+
import { join as join15 } from "path";
|
|
28321
|
+
|
|
28322
|
+
// src/deploy/env-file.ts
|
|
28323
|
+
import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
|
|
28362
28324
|
import { join as join14 } from "path";
|
|
28325
|
+
function loadDeployEnvFiles(rootDir, envNames) {
|
|
28326
|
+
const globalsPath = join14(rootDir, "deploy.arc.env");
|
|
28327
|
+
const globals = existsSync13(globalsPath) ? parseEnvFile(readFileSync11(globalsPath, "utf-8"), globalsPath) : {};
|
|
28328
|
+
const perEnv = {};
|
|
28329
|
+
for (const name of envNames) {
|
|
28330
|
+
const envPath = join14(rootDir, `deploy.arc.${name}.env`);
|
|
28331
|
+
if (existsSync13(envPath)) {
|
|
28332
|
+
perEnv[name] = parseEnvFile(readFileSync11(envPath, "utf-8"), envPath);
|
|
28333
|
+
}
|
|
28334
|
+
}
|
|
28335
|
+
return { globals, perEnv };
|
|
28336
|
+
}
|
|
28337
|
+
function applyDeployGlobals(globals) {
|
|
28338
|
+
for (const [k, v] of Object.entries(globals)) {
|
|
28339
|
+
if (process.env[k] === undefined) {
|
|
28340
|
+
process.env[k] = v;
|
|
28341
|
+
}
|
|
28342
|
+
}
|
|
28343
|
+
}
|
|
28344
|
+
function parseEnvFile(content, pathForErrors) {
|
|
28345
|
+
const out = {};
|
|
28346
|
+
const lines = content.split(/\r?\n/);
|
|
28347
|
+
for (let i = 0;i < lines.length; i++) {
|
|
28348
|
+
const raw = lines[i];
|
|
28349
|
+
const line = raw.trim();
|
|
28350
|
+
if (!line || line.startsWith("#"))
|
|
28351
|
+
continue;
|
|
28352
|
+
const eq = line.indexOf("=");
|
|
28353
|
+
if (eq <= 0) {
|
|
28354
|
+
throw new Error(`${pathForErrors}:${i + 1}: malformed line (expected KEY=VALUE): ${raw}`);
|
|
28355
|
+
}
|
|
28356
|
+
const key = line.slice(0, eq).trim();
|
|
28357
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
|
|
28358
|
+
throw new Error(`${pathForErrors}:${i + 1}: invalid variable name "${key}"`);
|
|
28359
|
+
}
|
|
28360
|
+
let value = line.slice(eq + 1).trim();
|
|
28361
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
28362
|
+
value = value.slice(1, -1);
|
|
28363
|
+
}
|
|
28364
|
+
out[key] = value;
|
|
28365
|
+
}
|
|
28366
|
+
return out;
|
|
28367
|
+
}
|
|
28368
|
+
|
|
28369
|
+
// src/deploy/config.ts
|
|
28363
28370
|
var DEPLOY_CONFIG_FILE = "deploy.arc.json";
|
|
28364
28371
|
function deployConfigPath(rootDir) {
|
|
28365
|
-
return
|
|
28372
|
+
return join15(rootDir, DEPLOY_CONFIG_FILE);
|
|
28366
28373
|
}
|
|
28367
28374
|
function deployConfigExists(rootDir) {
|
|
28368
|
-
return
|
|
28375
|
+
return existsSync14(deployConfigPath(rootDir));
|
|
28369
28376
|
}
|
|
28370
28377
|
function loadDeployConfig(rootDir) {
|
|
28371
28378
|
const path4 = deployConfigPath(rootDir);
|
|
28372
|
-
if (!
|
|
28379
|
+
if (!existsSync14(path4)) {
|
|
28373
28380
|
throw new Error(`Missing ${DEPLOY_CONFIG_FILE} at ${path4}`);
|
|
28374
28381
|
}
|
|
28375
|
-
const raw =
|
|
28382
|
+
const raw = readFileSync12(path4, "utf-8");
|
|
28376
28383
|
let parsed;
|
|
28377
28384
|
try {
|
|
28378
28385
|
parsed = JSON.parse(raw);
|
|
28379
28386
|
} catch (e) {
|
|
28380
28387
|
throw new Error(`Invalid JSON in ${DEPLOY_CONFIG_FILE}: ${e.message}`);
|
|
28381
28388
|
}
|
|
28389
|
+
const envNames = isObject(parsed) && isObject(parsed.envs) ? Object.keys(parsed.envs) : [];
|
|
28390
|
+
const envFiles = loadDeployEnvFiles(rootDir, envNames);
|
|
28391
|
+
applyDeployGlobals(envFiles.globals);
|
|
28382
28392
|
const expanded = expandEnvVars(parsed, process.env);
|
|
28383
|
-
|
|
28393
|
+
const validated = validateDeployConfig(expanded);
|
|
28394
|
+
for (const [envName, vars] of Object.entries(envFiles.perEnv)) {
|
|
28395
|
+
if (!(envName in validated.envs))
|
|
28396
|
+
continue;
|
|
28397
|
+
const env2 = validated.envs[envName];
|
|
28398
|
+
const merged = { ...vars, ...env2.envVars ?? {} };
|
|
28399
|
+
validated.envs[envName] = { ...env2, envVars: merged };
|
|
28400
|
+
}
|
|
28401
|
+
return validated;
|
|
28384
28402
|
}
|
|
28385
28403
|
function saveDeployConfig(rootDir, cfg) {
|
|
28386
28404
|
const path4 = deployConfigPath(rootDir);
|
|
28387
|
-
const raw =
|
|
28405
|
+
const raw = existsSync14(path4) ? JSON.parse(readFileSync12(path4, "utf-8")) : {};
|
|
28388
28406
|
raw.target = { ...raw.target, ...cfg.target };
|
|
28389
28407
|
writeFileSync12(path4, JSON.stringify(raw, null, 2) + `
|
|
28390
28408
|
`);
|
|
@@ -28552,22 +28570,47 @@ function cfgErr(path4, expected) {
|
|
|
28552
28570
|
|
|
28553
28571
|
// src/deploy/ssh.ts
|
|
28554
28572
|
var {spawn: spawn3 } = globalThis.Bun;
|
|
28573
|
+
import { existsSync as existsSync15 } from "fs";
|
|
28574
|
+
import { homedir as homedir3 } from "os";
|
|
28575
|
+
import { join as join16 } from "path";
|
|
28576
|
+
function pickSshKey(target) {
|
|
28577
|
+
if (target.sshKey) {
|
|
28578
|
+
const expanded = target.sshKey.startsWith("~") ? join16(homedir3(), target.sshKey.slice(1)) : target.sshKey;
|
|
28579
|
+
return existsSync15(expanded) ? expanded : null;
|
|
28580
|
+
}
|
|
28581
|
+
for (const name of ["id_ed25519", "id_ecdsa", "id_rsa"]) {
|
|
28582
|
+
const path4 = join16(homedir3(), ".ssh", name);
|
|
28583
|
+
if (existsSync15(path4))
|
|
28584
|
+
return path4;
|
|
28585
|
+
}
|
|
28586
|
+
return null;
|
|
28587
|
+
}
|
|
28555
28588
|
async function streamToString(stream2) {
|
|
28556
28589
|
if (!stream2 || typeof stream2 === "number")
|
|
28557
28590
|
return "";
|
|
28558
28591
|
return new Response(stream2).text();
|
|
28559
28592
|
}
|
|
28560
28593
|
function baseSshArgs(target) {
|
|
28594
|
+
const key = pickSshKey(target);
|
|
28561
28595
|
const args = [
|
|
28562
28596
|
"-o",
|
|
28563
28597
|
"BatchMode=yes",
|
|
28564
28598
|
"-o",
|
|
28565
28599
|
"StrictHostKeyChecking=accept-new",
|
|
28600
|
+
"-o",
|
|
28601
|
+
"PreferredAuthentications=publickey",
|
|
28602
|
+
"-o",
|
|
28603
|
+
"ConnectTimeout=5",
|
|
28604
|
+
"-o",
|
|
28605
|
+
"ServerAliveInterval=10",
|
|
28606
|
+
"-o",
|
|
28607
|
+
"ServerAliveCountMax=2",
|
|
28566
28608
|
"-p",
|
|
28567
28609
|
String(target.port)
|
|
28568
28610
|
];
|
|
28569
|
-
if (
|
|
28570
|
-
args.push("-i",
|
|
28611
|
+
if (key) {
|
|
28612
|
+
args.push("-o", "IdentitiesOnly=yes", "-i", key);
|
|
28613
|
+
}
|
|
28571
28614
|
return args;
|
|
28572
28615
|
}
|
|
28573
28616
|
async function sshExec(target, cmd, opts = {}) {
|
|
@@ -28610,28 +28653,23 @@ async function canSsh(target) {
|
|
|
28610
28653
|
const res = await sshExec(target, "true", { quiet: true });
|
|
28611
28654
|
return res.exitCode === 0;
|
|
28612
28655
|
}
|
|
28613
|
-
async function waitForSsh(target, opts = {}) {
|
|
28614
|
-
const timeout = opts.timeoutMs ?? 300000;
|
|
28615
|
-
const interval = opts.intervalMs ?? 1e4;
|
|
28616
|
-
const start = Date.now();
|
|
28617
|
-
while (Date.now() - start < timeout) {
|
|
28618
|
-
if (await canSsh(target))
|
|
28619
|
-
return;
|
|
28620
|
-
await Bun.sleep(interval);
|
|
28621
|
-
}
|
|
28622
|
-
throw new Error(`Timed out waiting for SSH on ${target.user}@${target.host}`);
|
|
28623
|
-
}
|
|
28624
28656
|
async function scpUpload(target, localPath, remotePath) {
|
|
28657
|
+
const key = pickSshKey(target);
|
|
28625
28658
|
const args = [
|
|
28626
28659
|
"-o",
|
|
28627
28660
|
"BatchMode=yes",
|
|
28628
28661
|
"-o",
|
|
28629
28662
|
"StrictHostKeyChecking=accept-new",
|
|
28663
|
+
"-o",
|
|
28664
|
+
"PreferredAuthentications=publickey",
|
|
28665
|
+
"-o",
|
|
28666
|
+
"ConnectTimeout=5",
|
|
28630
28667
|
"-P",
|
|
28631
28668
|
String(target.port)
|
|
28632
28669
|
];
|
|
28633
|
-
if (
|
|
28634
|
-
args.push("-i",
|
|
28670
|
+
if (key) {
|
|
28671
|
+
args.push("-o", "IdentitiesOnly=yes", "-i", key);
|
|
28672
|
+
}
|
|
28635
28673
|
args.push(localPath, `${target.user}@${target.host}:${remotePath}`);
|
|
28636
28674
|
const proc2 = spawn3({ cmd: ["scp", ...args], stderr: "pipe" });
|
|
28637
28675
|
const [stderr, exitCode] = await Promise.all([
|
|
@@ -28689,6 +28727,18 @@ JSON`);
|
|
|
28689
28727
|
}
|
|
28690
28728
|
|
|
28691
28729
|
// src/deploy/bootstrap.ts
|
|
28730
|
+
async function waitForAnySsh(targets, opts = {}) {
|
|
28731
|
+
const timeout = opts.timeoutMs ?? 300000;
|
|
28732
|
+
const interval = opts.intervalMs ?? 5000;
|
|
28733
|
+
const start = Date.now();
|
|
28734
|
+
while (Date.now() - start < timeout) {
|
|
28735
|
+
const results = await Promise.all(targets.map((t) => canSsh(t)));
|
|
28736
|
+
if (results.some(Boolean))
|
|
28737
|
+
return;
|
|
28738
|
+
await Bun.sleep(interval);
|
|
28739
|
+
}
|
|
28740
|
+
throw new Error(`Timed out waiting for SSH on ${targets.map((t) => `${t.user}@${t.host}`).join(" or ")}`);
|
|
28741
|
+
}
|
|
28692
28742
|
async function bootstrap(inputs) {
|
|
28693
28743
|
const { cfg, state, rootDir } = inputs;
|
|
28694
28744
|
if (state.kind === "unreachable") {
|
|
@@ -28710,12 +28760,16 @@ async function bootstrap(inputs) {
|
|
|
28710
28760
|
cfg.target.host = tfOut.serverIp;
|
|
28711
28761
|
saveDeployConfig(rootDir, cfg);
|
|
28712
28762
|
log2("Waiting for SSH to come up...");
|
|
28713
|
-
await
|
|
28763
|
+
await waitForAnySsh([
|
|
28764
|
+
{ ...cfg.target, user: "root" },
|
|
28765
|
+
{ ...cfg.target, user: cfg.target.user }
|
|
28766
|
+
]);
|
|
28714
28767
|
ok("SSH reachable");
|
|
28715
28768
|
}
|
|
28716
|
-
|
|
28769
|
+
const needAnsible = state.kind === "unreachable" || state.kind === "no-docker" || inputs.forceAnsible === true;
|
|
28770
|
+
if (needAnsible) {
|
|
28717
28771
|
log2("Running Ansible bootstrap (Docker + firewall + SSH hardening)...");
|
|
28718
|
-
const deployUserWorks = state.kind
|
|
28772
|
+
const deployUserWorks = state.kind !== "unreachable" && await canSsh(cfg.target);
|
|
28719
28773
|
const asRoot = !deployUserWorks;
|
|
28720
28774
|
await runAnsible({
|
|
28721
28775
|
target: cfg.target,
|
|
@@ -28724,7 +28778,8 @@ async function bootstrap(inputs) {
|
|
|
28724
28778
|
});
|
|
28725
28779
|
ok("Host bootstrapped");
|
|
28726
28780
|
}
|
|
28727
|
-
|
|
28781
|
+
const needUpStack = state.kind !== "ready" || state.marker === null || state.marker.configHash !== inputs.configHash || !await isRegistryRunning(cfg);
|
|
28782
|
+
if (needUpStack) {
|
|
28728
28783
|
await upStack(inputs);
|
|
28729
28784
|
ok("Docker stack up");
|
|
28730
28785
|
}
|
|
@@ -28734,9 +28789,14 @@ async function bootstrap(inputs) {
|
|
|
28734
28789
|
updatedAt: new Date().toISOString()
|
|
28735
28790
|
});
|
|
28736
28791
|
}
|
|
28792
|
+
async function isRegistryRunning(cfg) {
|
|
28793
|
+
const res = await sshExec(cfg.target, `cd ${cfg.target.remoteDir} && docker compose ps --status running --format '{{.Service}}' 2>/dev/null || true`, { quiet: true });
|
|
28794
|
+
return res.stdout.split(`
|
|
28795
|
+
`).map((s) => s.trim()).includes("registry");
|
|
28796
|
+
}
|
|
28737
28797
|
async function upStack(inputs) {
|
|
28738
28798
|
const { cfg } = inputs;
|
|
28739
|
-
const workDir =
|
|
28799
|
+
const workDir = join17(tmpdir2(), "arc-deploy", `stack-${Date.now()}`);
|
|
28740
28800
|
mkdirSync12(workDir, { recursive: true });
|
|
28741
28801
|
await assertRegistryDnsResolves(cfg);
|
|
28742
28802
|
const password = process.env[cfg.registry.passwordEnv];
|
|
@@ -28744,17 +28804,17 @@ async function upStack(inputs) {
|
|
|
28744
28804
|
throw new Error(`Registry password env var ${cfg.registry.passwordEnv} is not set. ` + `Set it (e.g. \`export ${cfg.registry.passwordEnv}=...\`) before bootstrap.`);
|
|
28745
28805
|
}
|
|
28746
28806
|
const htpasswdLine = await generateHtpasswd(cfg.registry.username, password);
|
|
28747
|
-
writeFileSync13(
|
|
28748
|
-
writeFileSync13(
|
|
28749
|
-
writeFileSync13(
|
|
28807
|
+
writeFileSync13(join17(workDir, "htpasswd"), htpasswdLine);
|
|
28808
|
+
writeFileSync13(join17(workDir, "Caddyfile"), generateCaddyfile(cfg));
|
|
28809
|
+
writeFileSync13(join17(workDir, "docker-compose.yml"), generateCompose({ cfg }));
|
|
28750
28810
|
await assertExec(cfg.target, `sudo mkdir -p ${cfg.target.remoteDir} && sudo chown ${cfg.target.user}:${cfg.target.user} ${cfg.target.remoteDir}`);
|
|
28751
28811
|
for (const name of Object.keys(cfg.envs)) {
|
|
28752
28812
|
await assertExec(cfg.target, `mkdir -p ${cfg.target.remoteDir}/${name}`);
|
|
28753
28813
|
}
|
|
28754
28814
|
await assertExec(cfg.target, `mkdir -p ${cfg.target.remoteDir}/registry-auth`);
|
|
28755
|
-
await scpUpload(cfg.target,
|
|
28756
|
-
await scpUpload(cfg.target,
|
|
28757
|
-
await scpUpload(cfg.target,
|
|
28815
|
+
await scpUpload(cfg.target, join17(workDir, "Caddyfile"), `${cfg.target.remoteDir}/Caddyfile`);
|
|
28816
|
+
await scpUpload(cfg.target, join17(workDir, "docker-compose.yml"), `${cfg.target.remoteDir}/docker-compose.yml`);
|
|
28817
|
+
await scpUpload(cfg.target, join17(workDir, "htpasswd"), `${cfg.target.remoteDir}/registry-auth/htpasswd`);
|
|
28758
28818
|
await assertExec(cfg.target, `touch ${cfg.target.remoteDir}/.env`);
|
|
28759
28819
|
await assertExec(cfg.target, `cd ${cfg.target.remoteDir} && docker compose pull --ignore-pull-failures caddy registry && docker compose up -d caddy registry`);
|
|
28760
28820
|
await sshDockerLogin(cfg);
|
|
@@ -28768,18 +28828,23 @@ async function sshDockerLogin(cfg) {
|
|
|
28768
28828
|
if (!password) {
|
|
28769
28829
|
throw new Error(`Registry password env var ${cfg.registry.passwordEnv} is not set on the deploy host (CLI machine).`);
|
|
28770
28830
|
}
|
|
28771
|
-
const cmd = `
|
|
28831
|
+
const cmd = `docker login ${cfg.registry.domain} -u ${cfg.registry.username} --password-stdin`;
|
|
28772
28832
|
const proc2 = spawn4({
|
|
28773
28833
|
cmd: [
|
|
28774
28834
|
"ssh",
|
|
28775
28835
|
...baseSshArgs(cfg.target),
|
|
28776
28836
|
`${cfg.target.user}@${cfg.target.host}`,
|
|
28777
28837
|
"--",
|
|
28778
|
-
|
|
28838
|
+
cmd
|
|
28779
28839
|
],
|
|
28840
|
+
stdin: "pipe",
|
|
28780
28841
|
stdout: "pipe",
|
|
28781
28842
|
stderr: "pipe"
|
|
28782
28843
|
});
|
|
28844
|
+
if (proc2.stdin) {
|
|
28845
|
+
await proc2.stdin.write(new TextEncoder().encode(password));
|
|
28846
|
+
await proc2.stdin.end?.();
|
|
28847
|
+
}
|
|
28783
28848
|
const exit = await proc2.exited;
|
|
28784
28849
|
if (exit !== 0) {
|
|
28785
28850
|
const stderr = await new Response(proc2.stderr).text();
|
|
@@ -28801,24 +28866,39 @@ async function listConfiguredEnvs(cfg) {
|
|
|
28801
28866
|
return [...set];
|
|
28802
28867
|
}
|
|
28803
28868
|
async function assertRegistryDnsResolves(cfg) {
|
|
28869
|
+
const apex = apexDomain(cfg.registry.domain);
|
|
28870
|
+
let nameservers = await digQuery("8.8.8.8", "NS", apex);
|
|
28871
|
+
nameservers = nameservers.map((s) => s.replace(/\.$/, ""));
|
|
28872
|
+
const sources = [...nameservers, "1.1.1.1", "8.8.8.8"];
|
|
28873
|
+
let lastAnswers = [];
|
|
28874
|
+
for (const source of sources) {
|
|
28875
|
+
const answers = await digQuery(source, "A", cfg.registry.domain);
|
|
28876
|
+
if (answers.length === 0)
|
|
28877
|
+
continue;
|
|
28878
|
+
lastAnswers = answers;
|
|
28879
|
+
if (answers.includes(cfg.target.host))
|
|
28880
|
+
return;
|
|
28881
|
+
}
|
|
28882
|
+
if (lastAnswers.length === 0) {
|
|
28883
|
+
throw new Error(`Registry DNS not configured: ${cfg.registry.domain} doesn't resolve. ` + `Add an A record pointing to ${cfg.target.host} and re-run deploy.`);
|
|
28884
|
+
}
|
|
28885
|
+
throw new Error(`Registry DNS mismatch: ${cfg.registry.domain} resolves to [${lastAnswers.join(", ")}], ` + `but target host is ${cfg.target.host}. Update the A record before continuing.`);
|
|
28886
|
+
}
|
|
28887
|
+
function apexDomain(host) {
|
|
28888
|
+
const parts = host.split(".");
|
|
28889
|
+
return parts.slice(-2).join(".");
|
|
28890
|
+
}
|
|
28891
|
+
async function digQuery(server, type, name) {
|
|
28804
28892
|
const proc2 = spawn4({
|
|
28805
|
-
cmd: ["dig", "+short", "+time=3", "+tries=1",
|
|
28893
|
+
cmd: ["dig", `@${server}`, "+short", "+time=3", "+tries=1", type, name],
|
|
28806
28894
|
stdout: "pipe",
|
|
28807
28895
|
stderr: "ignore"
|
|
28808
28896
|
});
|
|
28809
28897
|
const exit = await proc2.exited;
|
|
28810
|
-
if (exit !== 0)
|
|
28811
|
-
|
|
28812
|
-
|
|
28813
|
-
}
|
|
28814
|
-
const resolved = (await new Response(proc2.stdout).text()).split(`
|
|
28898
|
+
if (exit !== 0)
|
|
28899
|
+
return [];
|
|
28900
|
+
return (await new Response(proc2.stdout).text()).split(`
|
|
28815
28901
|
`).map((s) => s.trim()).filter(Boolean);
|
|
28816
|
-
if (resolved.length === 0) {
|
|
28817
|
-
throw new Error(`Registry DNS not configured: ${cfg.registry.domain} doesn't resolve. ` + `Add an A record pointing to ${cfg.target.host} and re-run deploy.`);
|
|
28818
|
-
}
|
|
28819
|
-
if (!resolved.includes(cfg.target.host)) {
|
|
28820
|
-
throw new Error(`Registry DNS mismatch: ${cfg.registry.domain} resolves to [${resolved.join(", ")}], ` + `but target host is ${cfg.target.host}. Update the A record before continuing.`);
|
|
28821
|
-
}
|
|
28822
28902
|
}
|
|
28823
28903
|
|
|
28824
28904
|
// src/deploy/deploy-env.ts
|
|
@@ -28831,7 +28911,7 @@ async function updateEnvDeployment(opts) {
|
|
|
28831
28911
|
const envPath = `${cfg.target.remoteDir}/.env`;
|
|
28832
28912
|
const escapedRef = fullRef.replace(/"/g, "\\\"");
|
|
28833
28913
|
const updateScript = [
|
|
28834
|
-
`touch ${envPath}`,
|
|
28914
|
+
`touch ${envPath} && `,
|
|
28835
28915
|
`awk -v line="${envVarName}=${escapedRef}" -v key="${envVarName}=" '`,
|
|
28836
28916
|
` BEGIN { replaced=0 } `,
|
|
28837
28917
|
` $0 ~ "^"key { print line; replaced=1; next } `,
|
|
@@ -28881,15 +28961,15 @@ var {spawn: spawn5 } = globalThis.Bun;
|
|
|
28881
28961
|
import { createHash as createHash3 } from "crypto";
|
|
28882
28962
|
import {
|
|
28883
28963
|
copyFileSync as copyFileSync2,
|
|
28884
|
-
existsSync as
|
|
28964
|
+
existsSync as existsSync16,
|
|
28885
28965
|
mkdirSync as mkdirSync13,
|
|
28886
|
-
readFileSync as
|
|
28887
|
-
realpathSync as
|
|
28966
|
+
readFileSync as readFileSync13,
|
|
28967
|
+
realpathSync as realpathSync2,
|
|
28888
28968
|
writeFileSync as writeFileSync14
|
|
28889
28969
|
} from "fs";
|
|
28890
28970
|
import { tmpdir as tmpdir3 } from "os";
|
|
28891
|
-
import { dirname as
|
|
28892
|
-
import { fileURLToPath as
|
|
28971
|
+
import { dirname as dirname7, join as join18 } from "path";
|
|
28972
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
28893
28973
|
|
|
28894
28974
|
// src/deploy/image-template.ts
|
|
28895
28975
|
function generateDockerfile(inputs) {
|
|
@@ -28938,8 +29018,8 @@ function generateDockerfile(inputs) {
|
|
|
28938
29018
|
// src/deploy/image.ts
|
|
28939
29019
|
async function buildImage(ws, opts) {
|
|
28940
29020
|
await ensureDocker();
|
|
28941
|
-
const manifestPath =
|
|
28942
|
-
if (!
|
|
29021
|
+
const manifestPath = join18(ws.arcDir, "manifest.json");
|
|
29022
|
+
if (!existsSync16(manifestPath)) {
|
|
28943
29023
|
throw new Error(`No build manifest at ${manifestPath}. Run \`arc platform build\` first or omit --skip-build.`);
|
|
28944
29024
|
}
|
|
28945
29025
|
embedCliBundle(ws);
|
|
@@ -28949,12 +29029,13 @@ async function buildImage(ws, opts) {
|
|
|
28949
29029
|
const dockerfileInputs = collectDockerfileInputs(ws);
|
|
28950
29030
|
const dockerfile = generateDockerfile(dockerfileInputs);
|
|
28951
29031
|
const buildContextDir = ws.rootDir;
|
|
28952
|
-
const dockerfileDir =
|
|
29032
|
+
const dockerfileDir = join18(tmpdir3(), `arc-image-${Date.now()}`);
|
|
28953
29033
|
mkdirSync13(dockerfileDir, { recursive: true });
|
|
28954
|
-
const dockerfilePath =
|
|
29034
|
+
const dockerfilePath = join18(dockerfileDir, "Dockerfile");
|
|
28955
29035
|
writeFileSync14(dockerfilePath, dockerfile);
|
|
28956
29036
|
const buildArgs = [
|
|
28957
29037
|
"build",
|
|
29038
|
+
"--platform=linux/amd64",
|
|
28958
29039
|
"-f",
|
|
28959
29040
|
dockerfilePath,
|
|
28960
29041
|
"-t",
|
|
@@ -28976,20 +29057,20 @@ async function buildImage(ws, opts) {
|
|
|
28976
29057
|
}
|
|
28977
29058
|
function embedCliBundle(ws) {
|
|
28978
29059
|
const source = locateCliBundle();
|
|
28979
|
-
const target =
|
|
29060
|
+
const target = join18(ws.arcDir, "host.js");
|
|
28980
29061
|
copyFileSync2(source, target);
|
|
28981
29062
|
}
|
|
28982
29063
|
function locateCliBundle() {
|
|
28983
|
-
const here =
|
|
28984
|
-
let cur =
|
|
29064
|
+
const here = fileURLToPath5(import.meta.url);
|
|
29065
|
+
let cur = dirname7(here);
|
|
28985
29066
|
while (cur !== "/" && cur !== "") {
|
|
28986
|
-
const candidate =
|
|
28987
|
-
if (
|
|
29067
|
+
const candidate = join18(cur, "package.json");
|
|
29068
|
+
if (existsSync16(candidate)) {
|
|
28988
29069
|
try {
|
|
28989
|
-
const pkg = JSON.parse(
|
|
29070
|
+
const pkg = JSON.parse(readFileSync13(candidate, "utf-8"));
|
|
28990
29071
|
if (pkg.name === "@arcote.tech/arc-cli") {
|
|
28991
|
-
const distIndex =
|
|
28992
|
-
if (!
|
|
29072
|
+
const distIndex = join18(realpathSync2(cur), "dist", "index.js");
|
|
29073
|
+
if (!existsSync16(distIndex)) {
|
|
28993
29074
|
throw new Error(`arc-cli bundle missing at ${distIndex}. Run \`bun run build\` in packages/cli/.`);
|
|
28994
29075
|
}
|
|
28995
29076
|
return distIndex;
|
|
@@ -28999,7 +29080,7 @@ function locateCliBundle() {
|
|
|
28999
29080
|
throw e;
|
|
29000
29081
|
}
|
|
29001
29082
|
}
|
|
29002
|
-
const parent =
|
|
29083
|
+
const parent = dirname7(cur);
|
|
29003
29084
|
if (parent === cur)
|
|
29004
29085
|
break;
|
|
29005
29086
|
cur = parent;
|
|
@@ -29021,17 +29102,17 @@ async function ensureDocker() {
|
|
|
29021
29102
|
}
|
|
29022
29103
|
}
|
|
29023
29104
|
function computeContentHash(manifestPath) {
|
|
29024
|
-
const raw = JSON.parse(
|
|
29105
|
+
const raw = JSON.parse(readFileSync13(manifestPath, "utf-8"));
|
|
29025
29106
|
delete raw.buildTime;
|
|
29026
29107
|
const canonical = JSON.stringify(raw);
|
|
29027
29108
|
return createHash3("sha256").update(canonical).digest("hex").slice(0, 12);
|
|
29028
29109
|
}
|
|
29029
29110
|
function collectDockerfileInputs(ws) {
|
|
29030
|
-
const hasPublicDir =
|
|
29031
|
-
const hasLocales =
|
|
29111
|
+
const hasPublicDir = existsSync16(join18(ws.rootDir, "public"));
|
|
29112
|
+
const hasLocales = existsSync16(join18(ws.rootDir, "locales"));
|
|
29032
29113
|
let manifestPath;
|
|
29033
29114
|
for (const name of ["manifest.webmanifest", "manifest.json"]) {
|
|
29034
|
-
if (
|
|
29115
|
+
if (existsSync16(join18(ws.rootDir, name))) {
|
|
29035
29116
|
manifestPath = name;
|
|
29036
29117
|
break;
|
|
29037
29118
|
}
|
|
@@ -29852,14 +29933,14 @@ async function platformDeploy(envArg, options = {}) {
|
|
|
29852
29933
|
err(`Unknown env "${envArg}". Known: ${Object.keys(cfg.envs).join(", ")}`);
|
|
29853
29934
|
process.exit(1);
|
|
29854
29935
|
})() : Object.keys(cfg.envs);
|
|
29855
|
-
const manifestPath =
|
|
29936
|
+
const manifestPath = join19(ws.arcDir, "manifest.json");
|
|
29856
29937
|
if (!options.imageTag) {
|
|
29857
|
-
const needBuild = options.rebuild || !
|
|
29938
|
+
const needBuild = options.rebuild || !existsSync17(manifestPath);
|
|
29858
29939
|
if (needBuild && !options.skipBuild) {
|
|
29859
29940
|
log2("Building platform...");
|
|
29860
29941
|
await buildAll(ws, { noCache: options.rebuild });
|
|
29861
29942
|
ok("Build complete");
|
|
29862
|
-
} else if (!
|
|
29943
|
+
} else if (!existsSync17(manifestPath)) {
|
|
29863
29944
|
err("No build found and --skip-build was set.");
|
|
29864
29945
|
process.exit(1);
|
|
29865
29946
|
}
|
|
@@ -29884,25 +29965,26 @@ async function platformDeploy(envArg, options = {}) {
|
|
|
29884
29965
|
log2(`contentHash: ${contentHash}`);
|
|
29885
29966
|
return;
|
|
29886
29967
|
}
|
|
29887
|
-
log2(`Logging in to ${cfg.registry.domain}...`);
|
|
29888
|
-
await dockerLogin(cfg.registry);
|
|
29889
|
-
log2(`Pushing ${fullRef}...`);
|
|
29890
|
-
await dockerPush(fullRef);
|
|
29891
|
-
ok("Image pushed");
|
|
29892
29968
|
}
|
|
29893
29969
|
log2("Inspecting remote server...");
|
|
29894
29970
|
const state = await detectRemoteState(cfg);
|
|
29895
29971
|
log2(`Remote state: ${state.kind}`);
|
|
29896
29972
|
const cliVersion = readCliVersion();
|
|
29897
29973
|
const configHash = await hashDeployConfig(ws.rootDir);
|
|
29898
|
-
|
|
29899
|
-
|
|
29900
|
-
|
|
29901
|
-
|
|
29902
|
-
|
|
29903
|
-
|
|
29904
|
-
|
|
29905
|
-
|
|
29974
|
+
await bootstrap({
|
|
29975
|
+
cfg,
|
|
29976
|
+
rootDir: ws.rootDir,
|
|
29977
|
+
state,
|
|
29978
|
+
cliVersion,
|
|
29979
|
+
configHash,
|
|
29980
|
+
forceAnsible: options.forceBootstrap
|
|
29981
|
+
});
|
|
29982
|
+
if (!options.imageTag) {
|
|
29983
|
+
log2(`Logging in to ${cfg.registry.domain}...`);
|
|
29984
|
+
await dockerLogin(cfg.registry);
|
|
29985
|
+
log2(`Pushing ${fullRef}...`);
|
|
29986
|
+
await dockerPush(fullRef);
|
|
29987
|
+
ok("Image pushed");
|
|
29906
29988
|
}
|
|
29907
29989
|
for (const env2 of targetEnvs) {
|
|
29908
29990
|
log2(`Updating env "${env2}"...`);
|
|
@@ -29921,17 +30003,17 @@ async function platformDeploy(envArg, options = {}) {
|
|
|
29921
30003
|
}
|
|
29922
30004
|
function readCliVersion() {
|
|
29923
30005
|
try {
|
|
29924
|
-
let cur =
|
|
29925
|
-
const root =
|
|
30006
|
+
let cur = dirname8(fileURLToPath6(import.meta.url));
|
|
30007
|
+
const root = dirname8(cur).startsWith("/") ? "/" : ".";
|
|
29926
30008
|
while (cur !== root && cur !== "") {
|
|
29927
|
-
const candidate =
|
|
29928
|
-
if (
|
|
29929
|
-
const pkg = JSON.parse(
|
|
30009
|
+
const candidate = join19(cur, "package.json");
|
|
30010
|
+
if (existsSync17(candidate)) {
|
|
30011
|
+
const pkg = JSON.parse(readFileSync14(candidate, "utf-8"));
|
|
29930
30012
|
if (pkg.name === "@arcote.tech/arc-cli") {
|
|
29931
30013
|
return pkg.version ?? "unknown";
|
|
29932
30014
|
}
|
|
29933
30015
|
}
|
|
29934
|
-
const parent =
|
|
30016
|
+
const parent = dirname8(cur);
|
|
29935
30017
|
if (parent === cur)
|
|
29936
30018
|
break;
|
|
29937
30019
|
cur = parent;
|
|
@@ -29942,16 +30024,16 @@ function readCliVersion() {
|
|
|
29942
30024
|
}
|
|
29943
30025
|
}
|
|
29944
30026
|
async function hashDeployConfig(rootDir) {
|
|
29945
|
-
const p2 =
|
|
29946
|
-
const content =
|
|
30027
|
+
const p2 = join19(rootDir, "deploy.arc.json");
|
|
30028
|
+
const content = readFileSync14(p2);
|
|
29947
30029
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
29948
30030
|
hasher.update(content);
|
|
29949
30031
|
return hasher.digest("hex").slice(0, 16);
|
|
29950
30032
|
}
|
|
29951
30033
|
|
|
29952
30034
|
// src/platform/startup.ts
|
|
29953
|
-
import { existsSync as
|
|
29954
|
-
import { join as
|
|
30035
|
+
import { existsSync as existsSync19, readFileSync as readFileSync15, watch } from "fs";
|
|
30036
|
+
import { join as join21 } from "path";
|
|
29955
30037
|
|
|
29956
30038
|
// ../host/src/create-server.ts
|
|
29957
30039
|
var import_jsonwebtoken = __toESM(require_jsonwebtoken(), 1);
|
|
@@ -31197,8 +31279,8 @@ function querySubscriptionHandler() {
|
|
|
31197
31279
|
subscriptionId,
|
|
31198
31280
|
data: data ?? null
|
|
31199
31281
|
});
|
|
31200
|
-
} catch (
|
|
31201
|
-
console.error(`[Arc] Query subscription error:`,
|
|
31282
|
+
} catch (err3) {
|
|
31283
|
+
console.error(`[Arc] Query subscription error:`, err3);
|
|
31202
31284
|
}
|
|
31203
31285
|
};
|
|
31204
31286
|
sendData();
|
|
@@ -31401,25 +31483,14 @@ async function createArcServer(config) {
|
|
|
31401
31483
|
};
|
|
31402
31484
|
}
|
|
31403
31485
|
// src/platform/server.ts
|
|
31404
|
-
|
|
31405
|
-
import {
|
|
31406
|
-
|
|
31407
|
-
|
|
31408
|
-
|
|
31409
|
-
|
|
31410
|
-
|
|
31411
|
-
}
|
|
31486
|
+
init_i18n();
|
|
31487
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync14 } from "fs";
|
|
31488
|
+
import { join as join20 } from "path";
|
|
31489
|
+
function generateShellHtml(appName, manifest, initial) {
|
|
31490
|
+
const initialUrl = initial ? `/browser/${initial.file}` : null;
|
|
31491
|
+
if (!initialUrl) {
|
|
31492
|
+
throw new Error("generateShellHtml: initial bundle missing from manifest");
|
|
31412
31493
|
}
|
|
31413
|
-
const importMap = {
|
|
31414
|
-
imports: {
|
|
31415
|
-
react: "/shell/react.js",
|
|
31416
|
-
"react/jsx-runtime": "/shell/jsx-runtime.js",
|
|
31417
|
-
"react/jsx-dev-runtime": "/shell/jsx-dev-runtime.js",
|
|
31418
|
-
"react-dom": "/shell/react-dom.js",
|
|
31419
|
-
"react-dom/client": "/shell/react-dom-client.js",
|
|
31420
|
-
...arcImports
|
|
31421
|
-
}
|
|
31422
|
-
};
|
|
31423
31494
|
return `<!doctype html>
|
|
31424
31495
|
<html lang="en">
|
|
31425
31496
|
<head>
|
|
@@ -31430,18 +31501,13 @@ function generateShellHtml(appName, manifest, arcEntries) {
|
|
|
31430
31501
|
<link rel="manifest" href="/manifest.json">` : ""}
|
|
31431
31502
|
<link rel="stylesheet" href="/styles.css" />
|
|
31432
31503
|
<link rel="stylesheet" href="/theme.css" />
|
|
31433
|
-
<
|
|
31504
|
+
<link rel="modulepreload" href="${initialUrl}" />
|
|
31434
31505
|
</head>
|
|
31435
31506
|
<body>
|
|
31436
31507
|
<div id="root"></div>
|
|
31437
31508
|
<script type="module">
|
|
31438
|
-
import {
|
|
31439
|
-
|
|
31440
|
-
import { PlatformApp } from "@arcote.tech/platform";
|
|
31441
|
-
|
|
31442
|
-
createRoot(document.getElementById("root")).render(
|
|
31443
|
-
createElement(PlatformApp)
|
|
31444
|
-
);
|
|
31509
|
+
import { startApp } from "${initialUrl}";
|
|
31510
|
+
startApp("root");
|
|
31445
31511
|
</script>
|
|
31446
31512
|
</body>
|
|
31447
31513
|
</html>`;
|
|
@@ -31466,28 +31532,39 @@ function getMime(path4) {
|
|
|
31466
31532
|
return MIME[ext2] ?? "application/octet-stream";
|
|
31467
31533
|
}
|
|
31468
31534
|
function serveFile(filePath, headers = {}) {
|
|
31469
|
-
if (!
|
|
31535
|
+
if (!existsSync18(filePath))
|
|
31470
31536
|
return new Response("Not Found", { status: 404 });
|
|
31471
31537
|
return new Response(Bun.file(filePath), {
|
|
31472
31538
|
headers: { "Content-Type": getMime(filePath), ...headers }
|
|
31473
31539
|
});
|
|
31474
31540
|
}
|
|
31475
|
-
var MODULE_SIG_SECRET = process.env.ARC_MODULE_SECRET ??
|
|
31541
|
+
var MODULE_SIG_SECRET = process.env.ARC_MODULE_SECRET ?? "";
|
|
31476
31542
|
var MODULE_SIG_TTL = 3600;
|
|
31477
|
-
function
|
|
31543
|
+
function ensureModuleSigSecret(ws, devMode) {
|
|
31544
|
+
if (MODULE_SIG_SECRET)
|
|
31545
|
+
return;
|
|
31546
|
+
if (devMode) {
|
|
31547
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
31548
|
+
hasher.update(`arc-dev-secret:${ws.rootDir}`);
|
|
31549
|
+
MODULE_SIG_SECRET = hasher.digest("hex").slice(0, 32);
|
|
31550
|
+
} else {
|
|
31551
|
+
MODULE_SIG_SECRET = crypto.randomUUID();
|
|
31552
|
+
}
|
|
31553
|
+
}
|
|
31554
|
+
function signGroupUrl(file) {
|
|
31478
31555
|
const exp = Math.floor(Date.now() / 1000) + MODULE_SIG_TTL;
|
|
31479
31556
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
31480
|
-
hasher.update(`${
|
|
31557
|
+
hasher.update(`${file}:${exp}:${MODULE_SIG_SECRET}`);
|
|
31481
31558
|
const sig = hasher.digest("hex").slice(0, 16);
|
|
31482
|
-
return `/
|
|
31559
|
+
return `/browser/${file}?sig=${sig}&exp=${exp}`;
|
|
31483
31560
|
}
|
|
31484
|
-
function
|
|
31561
|
+
function verifyGroupSignature(file, sig, exp) {
|
|
31485
31562
|
if (!sig || !exp)
|
|
31486
31563
|
return false;
|
|
31487
31564
|
if (Number(exp) < Date.now() / 1000)
|
|
31488
31565
|
return false;
|
|
31489
31566
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
31490
|
-
hasher.update(`${
|
|
31567
|
+
hasher.update(`${file}:${exp}:${MODULE_SIG_SECRET}`);
|
|
31491
31568
|
return hasher.digest("hex").slice(0, 16) === sig;
|
|
31492
31569
|
}
|
|
31493
31570
|
function decodeTokenPayload(jwt2) {
|
|
@@ -31522,90 +31599,85 @@ function parseArcTokensHeader(header) {
|
|
|
31522
31599
|
return payloads;
|
|
31523
31600
|
}
|
|
31524
31601
|
async function filterManifestForTokens(manifest, moduleAccessMap, tokenPayloads) {
|
|
31525
|
-
const
|
|
31602
|
+
const allowedGroups = new Set;
|
|
31526
31603
|
for (const t of tokenPayloads) {
|
|
31527
31604
|
if (t?.tokenType)
|
|
31528
|
-
|
|
31605
|
+
allowedGroups.add(t.tokenType);
|
|
31529
31606
|
}
|
|
31530
|
-
const
|
|
31531
|
-
for (const
|
|
31532
|
-
if (!
|
|
31533
|
-
continue;
|
|
31534
|
-
if (mod.chunk === "public") {
|
|
31535
|
-
filtered.push(mod);
|
|
31607
|
+
const filteredGroups = {};
|
|
31608
|
+
for (const [name, group] of Object.entries(manifest.groups)) {
|
|
31609
|
+
if (!allowedGroups.has(name))
|
|
31536
31610
|
continue;
|
|
31537
|
-
|
|
31538
|
-
const
|
|
31539
|
-
|
|
31540
|
-
|
|
31541
|
-
|
|
31611
|
+
let allGranted = true;
|
|
31612
|
+
for (const moduleName of group.modules) {
|
|
31613
|
+
const access = moduleAccessMap.get(moduleName);
|
|
31614
|
+
if (!access || access.rules.length === 0)
|
|
31615
|
+
continue;
|
|
31616
|
+
let granted = false;
|
|
31542
31617
|
for (const rule of access.rules) {
|
|
31543
|
-
if (rule.token.name !==
|
|
31618
|
+
if (rule.token.name !== name)
|
|
31544
31619
|
continue;
|
|
31545
|
-
const matching = tokenPayloads.find((t) => t.tokenType ===
|
|
31620
|
+
const matching = tokenPayloads.find((t) => t.tokenType === name);
|
|
31546
31621
|
if (!matching)
|
|
31547
31622
|
continue;
|
|
31548
31623
|
granted = rule.check ? await rule.check(matching) : true;
|
|
31549
31624
|
if (granted)
|
|
31550
31625
|
break;
|
|
31551
31626
|
}
|
|
31627
|
+
if (!granted) {
|
|
31628
|
+
allGranted = false;
|
|
31629
|
+
break;
|
|
31630
|
+
}
|
|
31552
31631
|
}
|
|
31553
|
-
if (
|
|
31554
|
-
|
|
31632
|
+
if (allGranted) {
|
|
31633
|
+
filteredGroups[name] = { ...group, url: signGroupUrl(group.file) };
|
|
31555
31634
|
}
|
|
31556
31635
|
}
|
|
31557
31636
|
return {
|
|
31558
|
-
|
|
31559
|
-
|
|
31560
|
-
|
|
31637
|
+
initial: manifest.initial,
|
|
31638
|
+
groups: filteredGroups,
|
|
31639
|
+
sharedChunks: manifest.sharedChunks,
|
|
31561
31640
|
stylesHash: manifest.stylesHash,
|
|
31562
31641
|
buildTime: manifest.buildTime
|
|
31563
31642
|
};
|
|
31564
31643
|
}
|
|
31565
|
-
var
|
|
31566
|
-
|
|
31567
|
-
function staticFilesHandler(ws, devMode) {
|
|
31644
|
+
var BROWSER_FILE_RE = /^[A-Za-z0-9_.-]+\.js$/;
|
|
31645
|
+
function staticFilesHandler(ws, devMode, getManifest) {
|
|
31568
31646
|
return (_req, url, ctx) => {
|
|
31569
31647
|
const path4 = url.pathname;
|
|
31570
|
-
if (path4.startsWith("/
|
|
31571
|
-
|
|
31572
|
-
|
|
31573
|
-
const rest = path4.slice(9);
|
|
31574
|
-
const slash = rest.indexOf("/");
|
|
31575
|
-
if (slash <= 0) {
|
|
31576
|
-
return new Response("Not Found", { status: 404, headers: ctx.corsHeaders });
|
|
31577
|
-
}
|
|
31578
|
-
const chunk = rest.slice(0, slash);
|
|
31579
|
-
const file = rest.slice(slash + 1);
|
|
31580
|
-
if (!CHUNK_NAME_RE.test(chunk) || !MODULE_FILE_RE.test(file)) {
|
|
31648
|
+
if (path4.startsWith("/browser/")) {
|
|
31649
|
+
const file = path4.slice(9);
|
|
31650
|
+
if (!BROWSER_FILE_RE.test(file)) {
|
|
31581
31651
|
return new Response("Not Found", { status: 404, headers: ctx.corsHeaders });
|
|
31582
31652
|
}
|
|
31583
|
-
|
|
31653
|
+
const manifest = getManifest();
|
|
31654
|
+
const isGroupEntry = Object.values(manifest.groups).some((g3) => g3.file === file);
|
|
31655
|
+
if (isGroupEntry) {
|
|
31584
31656
|
const sig = url.searchParams.get("sig");
|
|
31585
31657
|
const exp = url.searchParams.get("exp");
|
|
31586
|
-
if (!
|
|
31658
|
+
if (!verifyGroupSignature(file, sig, exp)) {
|
|
31587
31659
|
return new Response("Forbidden", { status: 403, headers: ctx.corsHeaders });
|
|
31588
31660
|
}
|
|
31589
31661
|
}
|
|
31590
|
-
return serveFile(
|
|
31662
|
+
return serveFile(join20(ws.browserDir, file), {
|
|
31591
31663
|
...ctx.corsHeaders,
|
|
31592
31664
|
"Cache-Control": devMode ? "no-cache" : "max-age=31536000,immutable"
|
|
31593
31665
|
});
|
|
31594
31666
|
}
|
|
31595
31667
|
if (path4.startsWith("/locales/"))
|
|
31596
|
-
return serveFile(
|
|
31668
|
+
return serveFile(join20(ws.arcDir, path4.slice(1)), ctx.corsHeaders);
|
|
31597
31669
|
if (path4.startsWith("/assets/"))
|
|
31598
|
-
return serveFile(
|
|
31670
|
+
return serveFile(join20(ws.assetsDir, path4.slice(8)), ctx.corsHeaders);
|
|
31599
31671
|
if (path4 === "/styles.css")
|
|
31600
|
-
return serveFile(
|
|
31672
|
+
return serveFile(join20(ws.arcDir, "styles.css"), ctx.corsHeaders);
|
|
31601
31673
|
if (path4 === "/theme.css")
|
|
31602
|
-
return serveFile(
|
|
31674
|
+
return serveFile(join20(ws.arcDir, "theme.css"), ctx.corsHeaders);
|
|
31603
31675
|
if ((path4 === "/manifest.json" || path4 === "/manifest.webmanifest") && ws.manifest) {
|
|
31604
31676
|
return serveFile(ws.manifest.path, ctx.corsHeaders);
|
|
31605
31677
|
}
|
|
31606
31678
|
if (path4.lastIndexOf(".") > path4.lastIndexOf("/")) {
|
|
31607
|
-
const publicFile =
|
|
31608
|
-
if (
|
|
31679
|
+
const publicFile = join20(ws.publicDir, path4.slice(1));
|
|
31680
|
+
if (existsSync18(publicFile))
|
|
31609
31681
|
return serveFile(publicFile, ctx.corsHeaders);
|
|
31610
31682
|
}
|
|
31611
31683
|
return null;
|
|
@@ -31630,7 +31702,7 @@ function apiEndpointsHandler(ws, getManifest, cm, moduleAccessMap) {
|
|
|
31630
31702
|
if (url.pathname === "/health") {
|
|
31631
31703
|
return Response.json({
|
|
31632
31704
|
status: "ok",
|
|
31633
|
-
|
|
31705
|
+
groups: Object.keys(getManifest().groups).length,
|
|
31634
31706
|
clients: cm?.clientCount ?? 0
|
|
31635
31707
|
}, { headers: ctx.corsHeaders });
|
|
31636
31708
|
}
|
|
@@ -31662,22 +31734,23 @@ function devReloadHandler(sseClients) {
|
|
|
31662
31734
|
});
|
|
31663
31735
|
};
|
|
31664
31736
|
}
|
|
31665
|
-
function spaFallbackHandler(
|
|
31737
|
+
function spaFallbackHandler(getShellHtml) {
|
|
31666
31738
|
return (_req, _url, ctx) => {
|
|
31667
|
-
return new Response(
|
|
31739
|
+
return new Response(getShellHtml(), {
|
|
31668
31740
|
headers: { ...ctx.corsHeaders, "Content-Type": "text/html" }
|
|
31669
31741
|
});
|
|
31670
31742
|
};
|
|
31671
31743
|
}
|
|
31672
31744
|
async function startPlatformServer(opts) {
|
|
31673
31745
|
const { ws, port, devMode, context } = opts;
|
|
31746
|
+
ensureModuleSigSecret(ws, !!devMode);
|
|
31674
31747
|
const moduleAccessMap = opts.moduleAccess ?? new Map;
|
|
31675
31748
|
let manifest = opts.manifest;
|
|
31676
31749
|
const getManifest = () => manifest;
|
|
31677
31750
|
const setManifest = (m4) => {
|
|
31678
31751
|
manifest = m4;
|
|
31679
31752
|
};
|
|
31680
|
-
const
|
|
31753
|
+
const getShellHtml = () => generateShellHtml(ws.appName, ws.manifest, manifest?.initial);
|
|
31681
31754
|
const sseClients = new Set;
|
|
31682
31755
|
const notifyReload = (m4) => {
|
|
31683
31756
|
const data = JSON.stringify(m4);
|
|
@@ -31714,8 +31787,8 @@ async function startPlatformServer(opts) {
|
|
|
31714
31787
|
const handlers = [
|
|
31715
31788
|
apiEndpointsHandler(ws, getManifest, null, moduleAccessMap),
|
|
31716
31789
|
devReloadHandler(sseClients),
|
|
31717
|
-
staticFilesHandler(ws, !!devMode),
|
|
31718
|
-
spaFallbackHandler(
|
|
31790
|
+
staticFilesHandler(ws, !!devMode, getManifest),
|
|
31791
|
+
spaFallbackHandler(getShellHtml)
|
|
31719
31792
|
];
|
|
31720
31793
|
for (const handler of handlers) {
|
|
31721
31794
|
const response = await handler(req, url, ctx);
|
|
@@ -31735,7 +31808,7 @@ async function startPlatformServer(opts) {
|
|
|
31735
31808
|
};
|
|
31736
31809
|
}
|
|
31737
31810
|
const { createBunSQLiteAdapterFactory: createBunSQLiteAdapterFactory2 } = await Promise.resolve().then(() => (init_dist(), exports_dist2));
|
|
31738
|
-
const dbPath = opts.dbPath ||
|
|
31811
|
+
const dbPath = opts.dbPath || join20(ws.arcDir, "data", "arc.db");
|
|
31739
31812
|
const dbDir = dbPath.substring(0, dbPath.lastIndexOf("/"));
|
|
31740
31813
|
if (dbDir)
|
|
31741
31814
|
mkdirSync14(dbDir, { recursive: true });
|
|
@@ -31746,8 +31819,8 @@ async function startPlatformServer(opts) {
|
|
|
31746
31819
|
httpHandlers: [
|
|
31747
31820
|
apiEndpointsHandler(ws, getManifest, null, moduleAccessMap),
|
|
31748
31821
|
devReloadHandler(sseClients),
|
|
31749
|
-
staticFilesHandler(ws, !!devMode),
|
|
31750
|
-
spaFallbackHandler(
|
|
31822
|
+
staticFilesHandler(ws, !!devMode, getManifest),
|
|
31823
|
+
spaFallbackHandler(getShellHtml)
|
|
31751
31824
|
],
|
|
31752
31825
|
onWsClose: (clientId) => cleanupClientSubs(clientId)
|
|
31753
31826
|
});
|
|
@@ -31765,17 +31838,17 @@ async function startPlatformServer(opts) {
|
|
|
31765
31838
|
async function startPlatform(opts) {
|
|
31766
31839
|
const { ws, devMode } = opts;
|
|
31767
31840
|
const port = opts.port ?? parseInt(process.env.PORT || "5005", 10);
|
|
31768
|
-
const dbPath = opts.dbPath ??
|
|
31841
|
+
const dbPath = opts.dbPath ?? join21(ws.rootDir, ".arc", "data", devMode ? "dev.db" : "prod.db");
|
|
31769
31842
|
let manifest;
|
|
31770
31843
|
if (devMode) {
|
|
31771
31844
|
manifest = await buildAll(ws);
|
|
31772
31845
|
} else {
|
|
31773
|
-
const manifestPath =
|
|
31774
|
-
if (!
|
|
31846
|
+
const manifestPath = join21(ws.arcDir, "manifest.json");
|
|
31847
|
+
if (!existsSync19(manifestPath)) {
|
|
31775
31848
|
err("No build found. Run `arc platform build` first.");
|
|
31776
31849
|
process.exit(1);
|
|
31777
31850
|
}
|
|
31778
|
-
manifest = JSON.parse(
|
|
31851
|
+
manifest = JSON.parse(readFileSync15(manifestPath, "utf-8"));
|
|
31779
31852
|
}
|
|
31780
31853
|
log2("Loading server context...");
|
|
31781
31854
|
const { context, moduleAccess } = await loadServerContext(ws);
|
|
@@ -31784,7 +31857,6 @@ async function startPlatform(opts) {
|
|
|
31784
31857
|
} else {
|
|
31785
31858
|
log2("No context \u2014 server endpoints skipped");
|
|
31786
31859
|
}
|
|
31787
|
-
const arcEntries = collectArcPeerDeps(ws.packages);
|
|
31788
31860
|
const platform3 = await startPlatformServer({
|
|
31789
31861
|
ws,
|
|
31790
31862
|
port,
|
|
@@ -31792,8 +31864,7 @@ async function startPlatform(opts) {
|
|
|
31792
31864
|
context,
|
|
31793
31865
|
moduleAccess,
|
|
31794
31866
|
dbPath,
|
|
31795
|
-
devMode
|
|
31796
|
-
arcEntries
|
|
31867
|
+
devMode
|
|
31797
31868
|
});
|
|
31798
31869
|
ok(`Server on http://localhost:${port}`);
|
|
31799
31870
|
if (platform3.contextHandler) {
|
|
@@ -31825,7 +31896,7 @@ function attachDevWatcher(ws, platform3) {
|
|
|
31825
31896
|
const next = await buildAll(ws);
|
|
31826
31897
|
platform3.setManifest(next);
|
|
31827
31898
|
platform3.notifyReload(next);
|
|
31828
|
-
ok(`Rebuilt \u2014 ${next.
|
|
31899
|
+
ok(`Rebuilt \u2014 initial + ${Object.keys(next.groups).length} group(s)`);
|
|
31829
31900
|
} catch (e2) {
|
|
31830
31901
|
console.error(`Rebuild failed: ${e2}`);
|
|
31831
31902
|
} finally {
|
|
@@ -31834,8 +31905,8 @@ function attachDevWatcher(ws, platform3) {
|
|
|
31834
31905
|
}, 300);
|
|
31835
31906
|
};
|
|
31836
31907
|
for (const pkg of ws.packages) {
|
|
31837
|
-
const srcDir =
|
|
31838
|
-
if (!
|
|
31908
|
+
const srcDir = join21(pkg.path, "src");
|
|
31909
|
+
if (!existsSync19(srcDir))
|
|
31839
31910
|
continue;
|
|
31840
31911
|
watch(srcDir, { recursive: true }, (_event, filename) => {
|
|
31841
31912
|
if (!filename || filename.includes(".arc") || filename.endsWith(".d.ts") || filename.includes("node_modules") || filename.includes("dist"))
|
|
@@ -31845,8 +31916,8 @@ function attachDevWatcher(ws, platform3) {
|
|
|
31845
31916
|
triggerRebuild();
|
|
31846
31917
|
});
|
|
31847
31918
|
}
|
|
31848
|
-
const localesDir =
|
|
31849
|
-
if (
|
|
31919
|
+
const localesDir = join21(ws.rootDir, "locales");
|
|
31920
|
+
if (existsSync19(localesDir)) {
|
|
31850
31921
|
watch(localesDir, { recursive: false }, (_event, filename) => {
|
|
31851
31922
|
if (!filename?.endsWith(".po"))
|
|
31852
31923
|
return;
|
|
@@ -31876,7 +31947,7 @@ var platform3 = program2.command("platform").description("Platform commands \u20
|
|
|
31876
31947
|
platform3.command("dev").description("Start platform in dev mode (Bun server + Vite HMR)").option("--no-cache", "Force full rebuild on startup").action((opts) => platformDev({ noCache: opts.cache === false }));
|
|
31877
31948
|
platform3.command("build").description("Build platform for production").option("--no-cache", "Force full rebuild").action((opts) => platformBuild({ noCache: opts.cache === false }));
|
|
31878
31949
|
platform3.command("start").description("Start platform in production mode (requires prior build)").action(platformStart);
|
|
31879
|
-
platform3.command("deploy [env]").description("Deploy platform to a remote server (reads deploy.arc.json, surveys if missing)").option("--skip-build", "Skip local build step").option("--rebuild", "Force rebuild before deploy").option("--build-only", "Build the Docker image locally, then exit (no remote push)").option("--image-tag <hash>", "Roll back / pin to an existing image tag instead of building a new one").action((env2, opts) => platformDeploy(env2, opts));
|
|
31950
|
+
platform3.command("deploy [env]").description("Deploy platform to a remote server (reads deploy.arc.json, surveys if missing)").option("--skip-build", "Skip local build step").option("--rebuild", "Force rebuild before deploy").option("--build-only", "Build the Docker image locally, then exit (no remote push)").option("--image-tag <hash>", "Roll back / pin to an existing image tag instead of building a new one").option("--force-bootstrap", "Re-run Ansible host bootstrap even if the server is already configured").action((env2, opts) => platformDeploy(env2, opts));
|
|
31880
31951
|
program2.parse(process.argv);
|
|
31881
31952
|
if (process.argv.length === 2) {
|
|
31882
31953
|
program2.help();
|