@arcote.tech/arc-cli 0.7.0 → 0.7.1
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 +1382 -1343
- package/package.json +7 -7
- package/src/builder/access-extractor.ts +10 -24
- package/src/builder/module-builder.ts +293 -153
- 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
|
}
|
|
@@ -26312,325 +26591,56 @@ ${colors3.yellow}Type declaration errors:${colors3.reset}`);
|
|
|
26312
26591
|
rebuildsInProgress.delete(key);
|
|
26313
26592
|
}
|
|
26314
26593
|
})();
|
|
26315
|
-
rebuildsInProgress.set(key, rebuildPromise);
|
|
26316
|
-
await rebuildPromise;
|
|
26317
|
-
}
|
|
26318
|
-
});
|
|
26319
|
-
devContexts.push({
|
|
26320
|
-
configPath,
|
|
26321
|
-
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));
|
|
26594
|
+
rebuildsInProgress.set(key, rebuildPromise);
|
|
26595
|
+
await rebuildPromise;
|
|
26596
|
+
}
|
|
26597
|
+
});
|
|
26598
|
+
devContexts.push({
|
|
26599
|
+
configPath,
|
|
26600
|
+
config,
|
|
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,7 @@ 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 externals = [...peerDeps, ...npmDeps];
|
|
26945
|
+
const externals = [...peerDeps, ...Object.keys(allDeps)];
|
|
26919
26946
|
const result = await Bun.build({
|
|
26920
26947
|
entrypoints: [pkg.entrypoint],
|
|
26921
26948
|
outdir: join8(outDir, "main"),
|
|
@@ -26956,125 +26983,163 @@ async function buildContextPackages(rootDir, packages, cache, noCache) {
|
|
|
26956
26983
|
}
|
|
26957
26984
|
return { declarationErrors };
|
|
26958
26985
|
}
|
|
26959
|
-
async function
|
|
26986
|
+
async function buildBrowserApp(rootDir, outDir, plan, cache, noCache, i18nCollector) {
|
|
26960
26987
|
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
|
-
}));
|
|
26988
|
+
const publicMembers = plan.groups.get("public") ?? [];
|
|
26989
|
+
const protectedGroups = plan.chunks.filter((c) => c !== "public").map((c) => ({ name: c, members: plan.groups.get(c) ?? [] })).filter((g) => g.members.length > 0);
|
|
26990
|
+
const unitId = "browser-app";
|
|
26991
|
+
const allMembers = [];
|
|
26992
|
+
for (const m of publicMembers) {
|
|
26993
|
+
allMembers.push({ name: m.pkg.name, group: "public", srcHash: pkgSourceHash(m.pkg) });
|
|
26994
|
+
}
|
|
26995
|
+
for (const g of protectedGroups) {
|
|
26996
|
+
for (const m of g.members) {
|
|
26997
|
+
allMembers.push({ name: m.pkg.name, group: g.name, srcHash: pkgSourceHash(m.pkg) });
|
|
26998
|
+
}
|
|
26999
|
+
}
|
|
26986
27000
|
const inputHash = sha256OfJson({
|
|
26987
|
-
|
|
26988
|
-
|
|
26989
|
-
|
|
27001
|
+
members: allMembers,
|
|
27002
|
+
groups: [
|
|
27003
|
+
"initial",
|
|
27004
|
+
...protectedGroups.map((g) => g.name).sort()
|
|
27005
|
+
],
|
|
26990
27006
|
define: { ONLY_SERVER: "false", ONLY_BROWSER: "true", ONLY_CLIENT: "true" }
|
|
26991
27007
|
});
|
|
26992
27008
|
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
|
-
});
|
|
27009
|
+
const cached = cache.units[unitId]?.outputHashes;
|
|
27010
|
+
if (cached?._manifest) {
|
|
27011
|
+
try {
|
|
27012
|
+
const m = JSON.parse(cached._manifest);
|
|
27013
|
+
const allFiles = [
|
|
27014
|
+
m.initial.file,
|
|
27015
|
+
...Object.values(m.groups).map((g) => g.file),
|
|
27016
|
+
...m.sharedChunks
|
|
27017
|
+
];
|
|
27018
|
+
if (allFiles.every((f) => existsSync7(join8(outDir, f)))) {
|
|
27019
|
+
console.log(` \u2713 cached: ${unitId}`);
|
|
27020
|
+
return { ...m, cached: true };
|
|
27021
|
+
}
|
|
27022
|
+
} catch {}
|
|
27009
27023
|
}
|
|
27010
|
-
|
|
27011
|
-
|
|
27012
|
-
|
|
27024
|
+
}
|
|
27025
|
+
console.log(` building: ${unitId} (initial: ${publicMembers.length} modules, groups: ${protectedGroups.map((g) => `${g.name}=${g.members.length}`).join(",") || "none"})`);
|
|
27026
|
+
if (existsSync7(outDir)) {
|
|
27027
|
+
for (const f of readdirSync4(outDir)) {
|
|
27028
|
+
if (f.endsWith(".js"))
|
|
27029
|
+
rmSync(join8(outDir, f), { force: true });
|
|
27013
27030
|
}
|
|
27014
|
-
console.log(` rebuilding ${unitId}: output file missing`);
|
|
27015
27031
|
}
|
|
27016
|
-
|
|
27017
|
-
const tmpDir = join8(chunkOutDir, "_entries");
|
|
27032
|
+
const tmpDir = join8(outDir, "_entries");
|
|
27018
27033
|
mkdirSync6(tmpDir, { recursive: true });
|
|
27019
|
-
const
|
|
27020
|
-
|
|
27021
|
-
|
|
27022
|
-
|
|
27023
|
-
|
|
27024
|
-
|
|
27034
|
+
const importLines = (pkgs) => pkgs.map((m) => `import "${m.pkg.name}";`).join(`
|
|
27035
|
+
`);
|
|
27036
|
+
const initialEntry = join8(tmpDir, "initial.ts");
|
|
27037
|
+
writeFileSync6(initialEntry, `${importLines(publicMembers)}
|
|
27038
|
+
export { startApp } from "@arcote.tech/platform";
|
|
27039
|
+
`);
|
|
27040
|
+
const entryPaths = [initialEntry];
|
|
27041
|
+
const groupModuleMap = new Map;
|
|
27042
|
+
for (const g of protectedGroups) {
|
|
27043
|
+
const entry = join8(tmpDir, `${g.name}.ts`);
|
|
27044
|
+
writeFileSync6(entry, `${importLines(g.members)}
|
|
27045
|
+
`);
|
|
27046
|
+
entryPaths.push(entry);
|
|
27047
|
+
groupModuleMap.set(g.name, g.members.map((m) => m.moduleName));
|
|
27048
|
+
}
|
|
27049
|
+
const allMemberPkgs = new Map;
|
|
27050
|
+
for (const m of publicMembers)
|
|
27051
|
+
allMemberPkgs.set(m.pkg.name, m.pkg);
|
|
27052
|
+
for (const g of protectedGroups)
|
|
27053
|
+
for (const m of g.members)
|
|
27054
|
+
allMemberPkgs.set(m.pkg.name, m.pkg);
|
|
27055
|
+
const patchedPkgJsons = [];
|
|
27056
|
+
for (const pkg of allMemberPkgs.values()) {
|
|
27057
|
+
const pkgJsonPath = join8(pkg.path, "package.json");
|
|
27058
|
+
if (!existsSync7(pkgJsonPath))
|
|
27059
|
+
continue;
|
|
27060
|
+
const original = readFileSync7(pkgJsonPath, "utf-8");
|
|
27061
|
+
const parsed = JSON.parse(original);
|
|
27062
|
+
if (parsed.sideEffects === true)
|
|
27063
|
+
continue;
|
|
27064
|
+
parsed.sideEffects = true;
|
|
27065
|
+
writeFileSync6(pkgJsonPath, JSON.stringify(parsed, null, 2) + `
|
|
27025
27066
|
`);
|
|
27026
|
-
|
|
27067
|
+
patchedPkgJsons.push({ path: pkgJsonPath, original });
|
|
27027
27068
|
}
|
|
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
|
-
});
|
|
27069
|
+
let result;
|
|
27070
|
+
try {
|
|
27071
|
+
result = await Bun.build({
|
|
27072
|
+
entrypoints: entryPaths,
|
|
27073
|
+
outdir: outDir,
|
|
27074
|
+
splitting: true,
|
|
27075
|
+
format: "esm",
|
|
27076
|
+
target: "browser",
|
|
27077
|
+
external: [],
|
|
27078
|
+
plugins: [
|
|
27079
|
+
singleReactPlugin(rootDir),
|
|
27080
|
+
jsxDevShimPlugin(),
|
|
27081
|
+
i18nExtractPlugin(i18nCollector, rootDir)
|
|
27082
|
+
],
|
|
27083
|
+
naming: "[name].[ext]",
|
|
27084
|
+
define: {
|
|
27085
|
+
ONLY_SERVER: "false",
|
|
27086
|
+
ONLY_BROWSER: "true",
|
|
27087
|
+
ONLY_CLIENT: "true",
|
|
27088
|
+
"process.env.NODE_ENV": '"production"'
|
|
27089
|
+
}
|
|
27090
|
+
});
|
|
27091
|
+
} finally {
|
|
27092
|
+
for (const p of patchedPkgJsons)
|
|
27093
|
+
writeFileSync6(p.path, p.original);
|
|
27094
|
+
}
|
|
27095
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
27055
27096
|
if (!result.success) {
|
|
27056
|
-
console.error(`Chunk "${chunk}" build failed:`);
|
|
27057
27097
|
for (const log2 of result.logs)
|
|
27058
27098
|
console.error(log2);
|
|
27059
|
-
throw new Error(
|
|
27099
|
+
throw new Error("Browser app build failed");
|
|
27100
|
+
}
|
|
27101
|
+
let initialFile = "";
|
|
27102
|
+
let initialHash = "";
|
|
27103
|
+
const groups = {};
|
|
27104
|
+
const sharedChunks = [];
|
|
27105
|
+
for (const out of result.outputs) {
|
|
27106
|
+
const name = basename2(out.path);
|
|
27107
|
+
if (out.kind === "entry-point") {
|
|
27108
|
+
const bytes = readFileSync7(out.path);
|
|
27109
|
+
const hash = sha256Hex(bytes).slice(0, 16);
|
|
27110
|
+
const stem = name.replace(/\.js$/, "");
|
|
27111
|
+
const finalName = `${stem}.${hash}.js`;
|
|
27112
|
+
const finalPath = join8(outDir, finalName);
|
|
27113
|
+
rmSync(finalPath, { force: true });
|
|
27114
|
+
writeFileSync6(finalPath, bytes);
|
|
27115
|
+
rmSync(out.path, { force: true });
|
|
27116
|
+
if (stem === "initial") {
|
|
27117
|
+
initialFile = finalName;
|
|
27118
|
+
initialHash = hash;
|
|
27119
|
+
} else {
|
|
27120
|
+
groups[stem] = {
|
|
27121
|
+
file: finalName,
|
|
27122
|
+
hash,
|
|
27123
|
+
modules: groupModuleMap.get(stem) ?? []
|
|
27124
|
+
};
|
|
27125
|
+
}
|
|
27126
|
+
} else if (out.kind === "chunk") {
|
|
27127
|
+
sharedChunks.push(name);
|
|
27128
|
+
}
|
|
27060
27129
|
}
|
|
27061
|
-
|
|
27062
|
-
|
|
27063
|
-
|
|
27064
|
-
|
|
27065
|
-
|
|
27066
|
-
|
|
27067
|
-
|
|
27068
|
-
|
|
27069
|
-
|
|
27070
|
-
|
|
27071
|
-
|
|
27072
|
-
chunk,
|
|
27073
|
-
hash
|
|
27074
|
-
};
|
|
27130
|
+
if (!initialFile) {
|
|
27131
|
+
throw new Error("Browser app build: initial entry not found in outputs");
|
|
27132
|
+
}
|
|
27133
|
+
const manifest = {
|
|
27134
|
+
initial: { file: initialFile, hash: initialHash },
|
|
27135
|
+
groups,
|
|
27136
|
+
sharedChunks,
|
|
27137
|
+
cached: false
|
|
27138
|
+
};
|
|
27139
|
+
updateCache(cache, unitId, inputHash, {
|
|
27140
|
+
outputHashes: { _manifest: JSON.stringify(manifest) }
|
|
27075
27141
|
});
|
|
27076
|
-
|
|
27077
|
-
return { modules, cached: false };
|
|
27142
|
+
return manifest;
|
|
27078
27143
|
}
|
|
27079
27144
|
async function buildTranslations(rootDir, arcDir, cache, noCache) {
|
|
27080
27145
|
const localesDir = join8(rootDir, "locales");
|
|
@@ -27216,17 +27281,10 @@ import {
|
|
|
27216
27281
|
existsSync as existsSync8,
|
|
27217
27282
|
mkdirSync as mkdirSync7,
|
|
27218
27283
|
readFileSync as readFileSync8,
|
|
27219
|
-
realpathSync as realpathSync2,
|
|
27220
27284
|
unlinkSync as unlinkSync2,
|
|
27221
27285
|
writeFileSync as writeFileSync7
|
|
27222
27286
|
} 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
|
-
}
|
|
27287
|
+
import { join as join9 } from "path";
|
|
27230
27288
|
async function extractAccessMap(rootDir, packages) {
|
|
27231
27289
|
const serverBundles = packages.filter((p) => isContextPackage(p.packageJson)).map((p) => ({
|
|
27232
27290
|
name: p.name,
|
|
@@ -27244,8 +27302,7 @@ async function extractAccessMap(rootDir, packages) {
|
|
|
27244
27302
|
env: {
|
|
27245
27303
|
...process.env,
|
|
27246
27304
|
ARC_ACCESS_BUNDLES: JSON.stringify(serverBundles),
|
|
27247
|
-
ARC_ACCESS_OUT: outPath
|
|
27248
|
-
ARC_PLATFORM_ENTRY: locatePlatformServerEntry()
|
|
27305
|
+
ARC_ACCESS_OUT: outPath
|
|
27249
27306
|
},
|
|
27250
27307
|
stdout: "pipe",
|
|
27251
27308
|
stderr: "inherit"
|
|
@@ -27276,9 +27333,11 @@ if (!out) {
|
|
|
27276
27333
|
process.exit(2);
|
|
27277
27334
|
}
|
|
27278
27335
|
|
|
27279
|
-
//
|
|
27280
|
-
//
|
|
27281
|
-
|
|
27336
|
+
// Bare-specifier import \u2014 Bun walks up from this worker's location
|
|
27337
|
+
// (<rootDir>/.arc/.tmp/) to <rootDir>/node_modules and finds the package.
|
|
27338
|
+
// Single entry (./src/index.ts) \u2014 React imports on top level are benign
|
|
27339
|
+
// (createContext, function defs); no DOM access until actual render.
|
|
27340
|
+
const platform = await import("@arcote.tech/platform");
|
|
27282
27341
|
|
|
27283
27342
|
for (const { name, path } of bundles) {
|
|
27284
27343
|
try {
|
|
@@ -27436,7 +27495,7 @@ function resolveWorkspace() {
|
|
|
27436
27495
|
err("No package.json found");
|
|
27437
27496
|
process.exit(1);
|
|
27438
27497
|
}
|
|
27439
|
-
const rootDir =
|
|
27498
|
+
const rootDir = dirname6(packageJsonPath);
|
|
27440
27499
|
const rootPkg = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
27441
27500
|
const appName = rootPkg.name ?? "Arc App";
|
|
27442
27501
|
const arcDir = join11(rootDir, ".arc", "platform");
|
|
@@ -27471,8 +27530,7 @@ function resolveWorkspace() {
|
|
|
27471
27530
|
rootPkg,
|
|
27472
27531
|
appName,
|
|
27473
27532
|
arcDir,
|
|
27474
|
-
|
|
27475
|
-
shellDir: join11(arcDir, "shell"),
|
|
27533
|
+
browserDir: join11(arcDir, "browser"),
|
|
27476
27534
|
assetsDir: join11(arcDir, "assets"),
|
|
27477
27535
|
publicDir: join11(rootDir, "public"),
|
|
27478
27536
|
packages,
|
|
@@ -27492,32 +27550,27 @@ async function buildAll(ws, opts = {}) {
|
|
|
27492
27550
|
`);
|
|
27493
27551
|
const plan = planChunks(ws.packages, accessMap);
|
|
27494
27552
|
ok(`Chunks: ${plan.chunks.map((c) => `${c}(${plan.groups.get(c)?.length ?? 0})`).join(", ")}`);
|
|
27495
|
-
const
|
|
27496
|
-
|
|
27497
|
-
|
|
27553
|
+
const i18nCollector = new Map;
|
|
27554
|
+
const [browserResult] = await Promise.all([
|
|
27555
|
+
buildBrowserApp(ws.rootDir, ws.browserDir, plan, cache, noCache, i18nCollector),
|
|
27498
27556
|
buildStyles(ws.rootDir, ws.arcDir, ws.packages, themePath, cache, noCache),
|
|
27499
27557
|
copyBrowserAssets(ws, cache, noCache),
|
|
27500
27558
|
buildTranslations(ws.rootDir, ws.arcDir, cache, noCache)
|
|
27501
27559
|
]);
|
|
27560
|
+
const { finalizeTranslations: finalizeTranslations3 } = await Promise.resolve().then(() => (init_i18n(), exports_i18n));
|
|
27561
|
+
await finalizeTranslations3(ws.rootDir, ws.arcDir, i18nCollector);
|
|
27502
27562
|
collectFrameworkDeps(ws.arcDir, ws.rootDir, ws.packages);
|
|
27503
27563
|
saveBuildCache(ws.arcDir, cache);
|
|
27504
|
-
const finalManifest = assembleManifest(ws,
|
|
27505
|
-
writeFileSync9(join11(ws.
|
|
27564
|
+
const finalManifest = assembleManifest(ws, browserResult, cache);
|
|
27565
|
+
writeFileSync9(join11(ws.arcDir, "manifest.json"), JSON.stringify(finalManifest, null, 2));
|
|
27506
27566
|
return finalManifest;
|
|
27507
27567
|
}
|
|
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);
|
|
27568
|
+
function assembleManifest(ws, browser, cache) {
|
|
27516
27569
|
const stylesHash = cache.units["styles"]?.outputHash ?? "";
|
|
27517
27570
|
return {
|
|
27518
|
-
|
|
27519
|
-
|
|
27520
|
-
|
|
27571
|
+
initial: browser.initial,
|
|
27572
|
+
groups: browser.groups,
|
|
27573
|
+
sharedChunks: browser.sharedChunks,
|
|
27521
27574
|
stylesHash,
|
|
27522
27575
|
buildTime: new Date().toISOString()
|
|
27523
27576
|
};
|
|
@@ -27619,170 +27672,12 @@ async function copyBrowserAssets(ws, cache, noCache) {
|
|
|
27619
27672
|
const outputHashes = {};
|
|
27620
27673
|
for (const asset of assets) {
|
|
27621
27674
|
const dest = join11(ws.assetsDir, asset.to);
|
|
27622
|
-
mkdirSync9(
|
|
27675
|
+
mkdirSync9(dirname6(dest), { recursive: true });
|
|
27623
27676
|
copyFileSync(asset.src, dest);
|
|
27624
27677
|
outputHashes[asset.to] = sha256Hex(readFileSync10(dest));
|
|
27625
27678
|
}
|
|
27626
27679
|
updateCache(cache, unitId, inputHash, { outputHashes });
|
|
27627
27680
|
}
|
|
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
27681
|
async function loadServerContext(ws) {
|
|
27787
27682
|
globalThis.ONLY_SERVER = true;
|
|
27788
27683
|
globalThis.ONLY_BROWSER = false;
|
|
@@ -27830,24 +27725,25 @@ async function loadServerContext(ws) {
|
|
|
27830
27725
|
async function platformBuild(opts = {}) {
|
|
27831
27726
|
const ws = resolveWorkspace();
|
|
27832
27727
|
const manifest = await buildAll(ws, { noCache: opts.noCache });
|
|
27833
|
-
|
|
27728
|
+
const groupCount = Object.keys(manifest.groups).length;
|
|
27729
|
+
ok(`Platform built \u2014 initial + ${groupCount} group(s)`);
|
|
27834
27730
|
}
|
|
27835
27731
|
|
|
27836
27732
|
// src/commands/platform-deploy.ts
|
|
27837
|
-
import { existsSync as
|
|
27838
|
-
import { dirname as
|
|
27839
|
-
import { fileURLToPath as
|
|
27733
|
+
import { existsSync as existsSync17, readFileSync as readFileSync14 } from "fs";
|
|
27734
|
+
import { dirname as dirname8, join as join19 } from "path";
|
|
27735
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
27840
27736
|
|
|
27841
27737
|
// src/deploy/bootstrap.ts
|
|
27842
27738
|
var {spawn: spawn4 } = globalThis.Bun;
|
|
27843
27739
|
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync13 } from "fs";
|
|
27844
27740
|
import { tmpdir as tmpdir2 } from "os";
|
|
27845
|
-
import { join as
|
|
27741
|
+
import { join as join17 } from "path";
|
|
27846
27742
|
|
|
27847
27743
|
// src/deploy/ansible.ts
|
|
27848
27744
|
import { spawn as nodeSpawn } from "child_process";
|
|
27849
|
-
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
|
|
27850
|
-
import { tmpdir } from "os";
|
|
27745
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
|
|
27746
|
+
import { homedir, tmpdir } from "os";
|
|
27851
27747
|
import { join as join12 } from "path";
|
|
27852
27748
|
|
|
27853
27749
|
// src/deploy/assets.ts
|
|
@@ -28042,7 +27938,22 @@ var ANSIBLE_SITE_YML = `---
|
|
|
28042
27938
|
- { policy: deny, dir: incoming }
|
|
28043
27939
|
- { policy: allow, dir: outgoing }
|
|
28044
27940
|
|
|
28045
|
-
- name:
|
|
27941
|
+
- name: Remove legacy ufw limit rule on SSH (replaced by plain allow)
|
|
27942
|
+
# If a prior bootstrap installed \`ufw limit 22/tcp\`, drop it \u2014 otherwise
|
|
27943
|
+
# the limit rule shadows the allow rule and rate-throttles deploy flows.
|
|
27944
|
+
ufw:
|
|
27945
|
+
rule: limit
|
|
27946
|
+
port: "{{ ssh_port }}"
|
|
27947
|
+
proto: tcp
|
|
27948
|
+
delete: true
|
|
27949
|
+
ignore_errors: true
|
|
27950
|
+
|
|
27951
|
+
- name: Open firewall ports (SSH key-only auth, no brute-force surface)
|
|
27952
|
+
# SSH on port 22: PasswordAuthentication=no + key-only means brute force
|
|
27953
|
+
# is impossible without the operator's private key. Rate-limiting (ufw
|
|
27954
|
+
# limit / fail2ban sshd jail) breaks legitimate deploy flows that open
|
|
27955
|
+
# many short SSH connections in sequence (canSsh -> sshExec -> scp -> ...).
|
|
27956
|
+
# 80/443: Caddy ACME + app traffic, never rate-limited.
|
|
28046
27957
|
ufw:
|
|
28047
27958
|
rule: allow
|
|
28048
27959
|
port: "{{ item }}"
|
|
@@ -28056,17 +27967,18 @@ var ANSIBLE_SITE_YML = `---
|
|
|
28056
27967
|
ufw:
|
|
28057
27968
|
state: enabled
|
|
28058
27969
|
|
|
28059
|
-
- name:
|
|
27970
|
+
- name: Disable fail2ban sshd jail
|
|
27971
|
+
# Key-only SSH + ufw rate-limit make fail2ban for sshd redundant and
|
|
27972
|
+
# actively harmful when the operator's IP roams. Keep fail2ban installed
|
|
27973
|
+
# for future jails (web/db) but turn off the sshd jail explicitly.
|
|
28060
27974
|
copy:
|
|
28061
27975
|
dest: /etc/fail2ban/jail.local
|
|
28062
27976
|
content: |
|
|
28063
27977
|
[sshd]
|
|
28064
|
-
enabled =
|
|
28065
|
-
|
|
28066
|
-
maxretry = 5
|
|
28067
|
-
findtime = 600
|
|
28068
|
-
bantime = 3600
|
|
27978
|
+
enabled = false
|
|
27979
|
+
{% if extra_allowed_ips %}
|
|
28069
27980
|
ignoreip = 127.0.0.1/8 ::1 {{ extra_allowed_ips | join(' ') }}
|
|
27981
|
+
{% endif %}
|
|
28070
27982
|
mode: "0644"
|
|
28071
27983
|
notify: restart fail2ban
|
|
28072
27984
|
|
|
@@ -28114,18 +28026,32 @@ async function materializeAssets(targetDir, files) {
|
|
|
28114
28026
|
}
|
|
28115
28027
|
|
|
28116
28028
|
// src/deploy/ansible.ts
|
|
28029
|
+
function pickSshKeyForAnsible(configured) {
|
|
28030
|
+
if (configured) {
|
|
28031
|
+
const expanded = configured.startsWith("~") ? join12(homedir(), configured.slice(1)) : configured;
|
|
28032
|
+
return existsSync11(expanded) ? expanded : null;
|
|
28033
|
+
}
|
|
28034
|
+
for (const name of ["id_ed25519", "id_ecdsa", "id_rsa"]) {
|
|
28035
|
+
const path4 = join12(homedir(), ".ssh", name);
|
|
28036
|
+
if (existsSync11(path4))
|
|
28037
|
+
return path4;
|
|
28038
|
+
}
|
|
28039
|
+
return null;
|
|
28040
|
+
}
|
|
28117
28041
|
async function runAnsible(inputs) {
|
|
28118
28042
|
const workDir = join12(tmpdir(), "arc-deploy", `ansible-${Date.now()}`);
|
|
28119
28043
|
mkdirSync10(workDir, { recursive: true });
|
|
28120
28044
|
await materializeAssets(workDir, ASSETS.ansible);
|
|
28121
28045
|
const user = inputs.asRoot ? "root" : inputs.target.user;
|
|
28122
28046
|
const port = inputs.ansible?.sshPort ?? inputs.target.port;
|
|
28047
|
+
const sshKey = pickSshKeyForAnsible(inputs.target.sshKey);
|
|
28048
|
+
const sshKeyArg = sshKey ? ` -o IdentitiesOnly=yes -i ${sshKey}` : "";
|
|
28123
28049
|
const inventory = [
|
|
28124
28050
|
"[arc]",
|
|
28125
28051
|
`${inputs.target.host} ansible_user=${user} ansible_port=${port}`,
|
|
28126
28052
|
"",
|
|
28127
28053
|
"[arc:vars]",
|
|
28128
|
-
|
|
28054
|
+
`ansible_ssh_common_args='-o StrictHostKeyChecking=accept-new -o BatchMode=yes -o PreferredAuthentications=publickey${sshKeyArg}'`,
|
|
28129
28055
|
"ansible_python_interpreter=/usr/bin/python3",
|
|
28130
28056
|
""
|
|
28131
28057
|
].join(`
|
|
@@ -28224,7 +28150,7 @@ function generateCompose({ cfg }) {
|
|
|
28224
28150
|
for (const [name, env2] of Object.entries(cfg.envs)) {
|
|
28225
28151
|
const upperName = name.toUpperCase().replace(/-/g, "_");
|
|
28226
28152
|
lines.push(` arc-${name}:`);
|
|
28227
|
-
lines.push(` image: \${ARC_IMAGE_${upperName}
|
|
28153
|
+
lines.push(` image: \${ARC_IMAGE_${upperName}:-arc-${name}:not-deployed}`);
|
|
28228
28154
|
lines.push(` container_name: arc-${name}`);
|
|
28229
28155
|
lines.push(" restart: unless-stopped");
|
|
28230
28156
|
lines.push(" volumes:");
|
|
@@ -28278,16 +28204,16 @@ async function generateHtpasswd(user, password) {
|
|
|
28278
28204
|
// src/deploy/terraform.ts
|
|
28279
28205
|
import { spawn as nodeSpawn2 } from "child_process";
|
|
28280
28206
|
import { createHash as createHash2 } from "crypto";
|
|
28281
|
-
import { existsSync as
|
|
28282
|
-
import { homedir } from "os";
|
|
28207
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "fs";
|
|
28208
|
+
import { homedir as homedir2 } from "os";
|
|
28283
28209
|
import { join as join13 } from "path";
|
|
28284
28210
|
async function runTerraform(inputs) {
|
|
28285
28211
|
const wsHash = createHash2("sha256").update(inputs.workspaceDir).digest("hex").slice(0, 16);
|
|
28286
|
-
const workDir = join13(
|
|
28212
|
+
const workDir = join13(homedir2(), ".arc-deploy", wsHash, "tf");
|
|
28287
28213
|
mkdirSync11(workDir, { recursive: true });
|
|
28288
28214
|
await materializeAssets(workDir, ASSETS.terraform);
|
|
28289
28215
|
const sshPubKey = inputs.tf.sshPublicKey ?? expandHome("~/.ssh/id_ed25519.pub");
|
|
28290
|
-
if (!
|
|
28216
|
+
if (!existsSync12(expandHome(sshPubKey))) {
|
|
28291
28217
|
throw new Error(`SSH public key not found at ${sshPubKey}. Set provision.terraform.sshPublicKey in deploy.arc.json.`);
|
|
28292
28218
|
}
|
|
28293
28219
|
const tfvars = [
|
|
@@ -28358,33 +28284,93 @@ function expandHome(p) {
|
|
|
28358
28284
|
}
|
|
28359
28285
|
|
|
28360
28286
|
// src/deploy/config.ts
|
|
28361
|
-
import { existsSync as
|
|
28287
|
+
import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "fs";
|
|
28288
|
+
import { join as join15 } from "path";
|
|
28289
|
+
|
|
28290
|
+
// src/deploy/env-file.ts
|
|
28291
|
+
import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
|
|
28362
28292
|
import { join as join14 } from "path";
|
|
28293
|
+
function loadDeployEnvFiles(rootDir, envNames) {
|
|
28294
|
+
const globalsPath = join14(rootDir, "deploy.arc.env");
|
|
28295
|
+
const globals = existsSync13(globalsPath) ? parseEnvFile(readFileSync11(globalsPath, "utf-8"), globalsPath) : {};
|
|
28296
|
+
const perEnv = {};
|
|
28297
|
+
for (const name of envNames) {
|
|
28298
|
+
const envPath = join14(rootDir, `deploy.arc.${name}.env`);
|
|
28299
|
+
if (existsSync13(envPath)) {
|
|
28300
|
+
perEnv[name] = parseEnvFile(readFileSync11(envPath, "utf-8"), envPath);
|
|
28301
|
+
}
|
|
28302
|
+
}
|
|
28303
|
+
return { globals, perEnv };
|
|
28304
|
+
}
|
|
28305
|
+
function applyDeployGlobals(globals) {
|
|
28306
|
+
for (const [k, v] of Object.entries(globals)) {
|
|
28307
|
+
if (process.env[k] === undefined) {
|
|
28308
|
+
process.env[k] = v;
|
|
28309
|
+
}
|
|
28310
|
+
}
|
|
28311
|
+
}
|
|
28312
|
+
function parseEnvFile(content, pathForErrors) {
|
|
28313
|
+
const out = {};
|
|
28314
|
+
const lines = content.split(/\r?\n/);
|
|
28315
|
+
for (let i = 0;i < lines.length; i++) {
|
|
28316
|
+
const raw = lines[i];
|
|
28317
|
+
const line = raw.trim();
|
|
28318
|
+
if (!line || line.startsWith("#"))
|
|
28319
|
+
continue;
|
|
28320
|
+
const eq = line.indexOf("=");
|
|
28321
|
+
if (eq <= 0) {
|
|
28322
|
+
throw new Error(`${pathForErrors}:${i + 1}: malformed line (expected KEY=VALUE): ${raw}`);
|
|
28323
|
+
}
|
|
28324
|
+
const key = line.slice(0, eq).trim();
|
|
28325
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
|
|
28326
|
+
throw new Error(`${pathForErrors}:${i + 1}: invalid variable name "${key}"`);
|
|
28327
|
+
}
|
|
28328
|
+
let value = line.slice(eq + 1).trim();
|
|
28329
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
28330
|
+
value = value.slice(1, -1);
|
|
28331
|
+
}
|
|
28332
|
+
out[key] = value;
|
|
28333
|
+
}
|
|
28334
|
+
return out;
|
|
28335
|
+
}
|
|
28336
|
+
|
|
28337
|
+
// src/deploy/config.ts
|
|
28363
28338
|
var DEPLOY_CONFIG_FILE = "deploy.arc.json";
|
|
28364
28339
|
function deployConfigPath(rootDir) {
|
|
28365
|
-
return
|
|
28340
|
+
return join15(rootDir, DEPLOY_CONFIG_FILE);
|
|
28366
28341
|
}
|
|
28367
28342
|
function deployConfigExists(rootDir) {
|
|
28368
|
-
return
|
|
28343
|
+
return existsSync14(deployConfigPath(rootDir));
|
|
28369
28344
|
}
|
|
28370
28345
|
function loadDeployConfig(rootDir) {
|
|
28371
28346
|
const path4 = deployConfigPath(rootDir);
|
|
28372
|
-
if (!
|
|
28347
|
+
if (!existsSync14(path4)) {
|
|
28373
28348
|
throw new Error(`Missing ${DEPLOY_CONFIG_FILE} at ${path4}`);
|
|
28374
28349
|
}
|
|
28375
|
-
const raw =
|
|
28350
|
+
const raw = readFileSync12(path4, "utf-8");
|
|
28376
28351
|
let parsed;
|
|
28377
28352
|
try {
|
|
28378
28353
|
parsed = JSON.parse(raw);
|
|
28379
28354
|
} catch (e) {
|
|
28380
28355
|
throw new Error(`Invalid JSON in ${DEPLOY_CONFIG_FILE}: ${e.message}`);
|
|
28381
28356
|
}
|
|
28357
|
+
const envNames = isObject(parsed) && isObject(parsed.envs) ? Object.keys(parsed.envs) : [];
|
|
28358
|
+
const envFiles = loadDeployEnvFiles(rootDir, envNames);
|
|
28359
|
+
applyDeployGlobals(envFiles.globals);
|
|
28382
28360
|
const expanded = expandEnvVars(parsed, process.env);
|
|
28383
|
-
|
|
28361
|
+
const validated = validateDeployConfig(expanded);
|
|
28362
|
+
for (const [envName, vars] of Object.entries(envFiles.perEnv)) {
|
|
28363
|
+
if (!(envName in validated.envs))
|
|
28364
|
+
continue;
|
|
28365
|
+
const env2 = validated.envs[envName];
|
|
28366
|
+
const merged = { ...vars, ...env2.envVars ?? {} };
|
|
28367
|
+
validated.envs[envName] = { ...env2, envVars: merged };
|
|
28368
|
+
}
|
|
28369
|
+
return validated;
|
|
28384
28370
|
}
|
|
28385
28371
|
function saveDeployConfig(rootDir, cfg) {
|
|
28386
28372
|
const path4 = deployConfigPath(rootDir);
|
|
28387
|
-
const raw =
|
|
28373
|
+
const raw = existsSync14(path4) ? JSON.parse(readFileSync12(path4, "utf-8")) : {};
|
|
28388
28374
|
raw.target = { ...raw.target, ...cfg.target };
|
|
28389
28375
|
writeFileSync12(path4, JSON.stringify(raw, null, 2) + `
|
|
28390
28376
|
`);
|
|
@@ -28552,22 +28538,47 @@ function cfgErr(path4, expected) {
|
|
|
28552
28538
|
|
|
28553
28539
|
// src/deploy/ssh.ts
|
|
28554
28540
|
var {spawn: spawn3 } = globalThis.Bun;
|
|
28541
|
+
import { existsSync as existsSync15 } from "fs";
|
|
28542
|
+
import { homedir as homedir3 } from "os";
|
|
28543
|
+
import { join as join16 } from "path";
|
|
28544
|
+
function pickSshKey(target) {
|
|
28545
|
+
if (target.sshKey) {
|
|
28546
|
+
const expanded = target.sshKey.startsWith("~") ? join16(homedir3(), target.sshKey.slice(1)) : target.sshKey;
|
|
28547
|
+
return existsSync15(expanded) ? expanded : null;
|
|
28548
|
+
}
|
|
28549
|
+
for (const name of ["id_ed25519", "id_ecdsa", "id_rsa"]) {
|
|
28550
|
+
const path4 = join16(homedir3(), ".ssh", name);
|
|
28551
|
+
if (existsSync15(path4))
|
|
28552
|
+
return path4;
|
|
28553
|
+
}
|
|
28554
|
+
return null;
|
|
28555
|
+
}
|
|
28555
28556
|
async function streamToString(stream2) {
|
|
28556
28557
|
if (!stream2 || typeof stream2 === "number")
|
|
28557
28558
|
return "";
|
|
28558
28559
|
return new Response(stream2).text();
|
|
28559
28560
|
}
|
|
28560
28561
|
function baseSshArgs(target) {
|
|
28562
|
+
const key = pickSshKey(target);
|
|
28561
28563
|
const args = [
|
|
28562
28564
|
"-o",
|
|
28563
28565
|
"BatchMode=yes",
|
|
28564
28566
|
"-o",
|
|
28565
28567
|
"StrictHostKeyChecking=accept-new",
|
|
28568
|
+
"-o",
|
|
28569
|
+
"PreferredAuthentications=publickey",
|
|
28570
|
+
"-o",
|
|
28571
|
+
"ConnectTimeout=5",
|
|
28572
|
+
"-o",
|
|
28573
|
+
"ServerAliveInterval=10",
|
|
28574
|
+
"-o",
|
|
28575
|
+
"ServerAliveCountMax=2",
|
|
28566
28576
|
"-p",
|
|
28567
28577
|
String(target.port)
|
|
28568
28578
|
];
|
|
28569
|
-
if (
|
|
28570
|
-
args.push("-i",
|
|
28579
|
+
if (key) {
|
|
28580
|
+
args.push("-o", "IdentitiesOnly=yes", "-i", key);
|
|
28581
|
+
}
|
|
28571
28582
|
return args;
|
|
28572
28583
|
}
|
|
28573
28584
|
async function sshExec(target, cmd, opts = {}) {
|
|
@@ -28610,28 +28621,23 @@ async function canSsh(target) {
|
|
|
28610
28621
|
const res = await sshExec(target, "true", { quiet: true });
|
|
28611
28622
|
return res.exitCode === 0;
|
|
28612
28623
|
}
|
|
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
28624
|
async function scpUpload(target, localPath, remotePath) {
|
|
28625
|
+
const key = pickSshKey(target);
|
|
28625
28626
|
const args = [
|
|
28626
28627
|
"-o",
|
|
28627
28628
|
"BatchMode=yes",
|
|
28628
28629
|
"-o",
|
|
28629
28630
|
"StrictHostKeyChecking=accept-new",
|
|
28631
|
+
"-o",
|
|
28632
|
+
"PreferredAuthentications=publickey",
|
|
28633
|
+
"-o",
|
|
28634
|
+
"ConnectTimeout=5",
|
|
28630
28635
|
"-P",
|
|
28631
28636
|
String(target.port)
|
|
28632
28637
|
];
|
|
28633
|
-
if (
|
|
28634
|
-
args.push("-i",
|
|
28638
|
+
if (key) {
|
|
28639
|
+
args.push("-o", "IdentitiesOnly=yes", "-i", key);
|
|
28640
|
+
}
|
|
28635
28641
|
args.push(localPath, `${target.user}@${target.host}:${remotePath}`);
|
|
28636
28642
|
const proc2 = spawn3({ cmd: ["scp", ...args], stderr: "pipe" });
|
|
28637
28643
|
const [stderr, exitCode] = await Promise.all([
|
|
@@ -28689,6 +28695,18 @@ JSON`);
|
|
|
28689
28695
|
}
|
|
28690
28696
|
|
|
28691
28697
|
// src/deploy/bootstrap.ts
|
|
28698
|
+
async function waitForAnySsh(targets, opts = {}) {
|
|
28699
|
+
const timeout = opts.timeoutMs ?? 300000;
|
|
28700
|
+
const interval = opts.intervalMs ?? 5000;
|
|
28701
|
+
const start = Date.now();
|
|
28702
|
+
while (Date.now() - start < timeout) {
|
|
28703
|
+
const results = await Promise.all(targets.map((t) => canSsh(t)));
|
|
28704
|
+
if (results.some(Boolean))
|
|
28705
|
+
return;
|
|
28706
|
+
await Bun.sleep(interval);
|
|
28707
|
+
}
|
|
28708
|
+
throw new Error(`Timed out waiting for SSH on ${targets.map((t) => `${t.user}@${t.host}`).join(" or ")}`);
|
|
28709
|
+
}
|
|
28692
28710
|
async function bootstrap(inputs) {
|
|
28693
28711
|
const { cfg, state, rootDir } = inputs;
|
|
28694
28712
|
if (state.kind === "unreachable") {
|
|
@@ -28710,12 +28728,16 @@ async function bootstrap(inputs) {
|
|
|
28710
28728
|
cfg.target.host = tfOut.serverIp;
|
|
28711
28729
|
saveDeployConfig(rootDir, cfg);
|
|
28712
28730
|
log2("Waiting for SSH to come up...");
|
|
28713
|
-
await
|
|
28731
|
+
await waitForAnySsh([
|
|
28732
|
+
{ ...cfg.target, user: "root" },
|
|
28733
|
+
{ ...cfg.target, user: cfg.target.user }
|
|
28734
|
+
]);
|
|
28714
28735
|
ok("SSH reachable");
|
|
28715
28736
|
}
|
|
28716
|
-
|
|
28737
|
+
const needAnsible = state.kind === "unreachable" || state.kind === "no-docker" || inputs.forceAnsible === true;
|
|
28738
|
+
if (needAnsible) {
|
|
28717
28739
|
log2("Running Ansible bootstrap (Docker + firewall + SSH hardening)...");
|
|
28718
|
-
const deployUserWorks = state.kind
|
|
28740
|
+
const deployUserWorks = state.kind !== "unreachable" && await canSsh(cfg.target);
|
|
28719
28741
|
const asRoot = !deployUserWorks;
|
|
28720
28742
|
await runAnsible({
|
|
28721
28743
|
target: cfg.target,
|
|
@@ -28724,7 +28746,8 @@ async function bootstrap(inputs) {
|
|
|
28724
28746
|
});
|
|
28725
28747
|
ok("Host bootstrapped");
|
|
28726
28748
|
}
|
|
28727
|
-
|
|
28749
|
+
const needUpStack = state.kind !== "ready" || state.marker === null || state.marker.configHash !== inputs.configHash || !await isRegistryRunning(cfg);
|
|
28750
|
+
if (needUpStack) {
|
|
28728
28751
|
await upStack(inputs);
|
|
28729
28752
|
ok("Docker stack up");
|
|
28730
28753
|
}
|
|
@@ -28734,9 +28757,14 @@ async function bootstrap(inputs) {
|
|
|
28734
28757
|
updatedAt: new Date().toISOString()
|
|
28735
28758
|
});
|
|
28736
28759
|
}
|
|
28760
|
+
async function isRegistryRunning(cfg) {
|
|
28761
|
+
const res = await sshExec(cfg.target, `cd ${cfg.target.remoteDir} && docker compose ps --status running --format '{{.Service}}' 2>/dev/null || true`, { quiet: true });
|
|
28762
|
+
return res.stdout.split(`
|
|
28763
|
+
`).map((s) => s.trim()).includes("registry");
|
|
28764
|
+
}
|
|
28737
28765
|
async function upStack(inputs) {
|
|
28738
28766
|
const { cfg } = inputs;
|
|
28739
|
-
const workDir =
|
|
28767
|
+
const workDir = join17(tmpdir2(), "arc-deploy", `stack-${Date.now()}`);
|
|
28740
28768
|
mkdirSync12(workDir, { recursive: true });
|
|
28741
28769
|
await assertRegistryDnsResolves(cfg);
|
|
28742
28770
|
const password = process.env[cfg.registry.passwordEnv];
|
|
@@ -28744,17 +28772,17 @@ async function upStack(inputs) {
|
|
|
28744
28772
|
throw new Error(`Registry password env var ${cfg.registry.passwordEnv} is not set. ` + `Set it (e.g. \`export ${cfg.registry.passwordEnv}=...\`) before bootstrap.`);
|
|
28745
28773
|
}
|
|
28746
28774
|
const htpasswdLine = await generateHtpasswd(cfg.registry.username, password);
|
|
28747
|
-
writeFileSync13(
|
|
28748
|
-
writeFileSync13(
|
|
28749
|
-
writeFileSync13(
|
|
28775
|
+
writeFileSync13(join17(workDir, "htpasswd"), htpasswdLine);
|
|
28776
|
+
writeFileSync13(join17(workDir, "Caddyfile"), generateCaddyfile(cfg));
|
|
28777
|
+
writeFileSync13(join17(workDir, "docker-compose.yml"), generateCompose({ cfg }));
|
|
28750
28778
|
await assertExec(cfg.target, `sudo mkdir -p ${cfg.target.remoteDir} && sudo chown ${cfg.target.user}:${cfg.target.user} ${cfg.target.remoteDir}`);
|
|
28751
28779
|
for (const name of Object.keys(cfg.envs)) {
|
|
28752
28780
|
await assertExec(cfg.target, `mkdir -p ${cfg.target.remoteDir}/${name}`);
|
|
28753
28781
|
}
|
|
28754
28782
|
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,
|
|
28783
|
+
await scpUpload(cfg.target, join17(workDir, "Caddyfile"), `${cfg.target.remoteDir}/Caddyfile`);
|
|
28784
|
+
await scpUpload(cfg.target, join17(workDir, "docker-compose.yml"), `${cfg.target.remoteDir}/docker-compose.yml`);
|
|
28785
|
+
await scpUpload(cfg.target, join17(workDir, "htpasswd"), `${cfg.target.remoteDir}/registry-auth/htpasswd`);
|
|
28758
28786
|
await assertExec(cfg.target, `touch ${cfg.target.remoteDir}/.env`);
|
|
28759
28787
|
await assertExec(cfg.target, `cd ${cfg.target.remoteDir} && docker compose pull --ignore-pull-failures caddy registry && docker compose up -d caddy registry`);
|
|
28760
28788
|
await sshDockerLogin(cfg);
|
|
@@ -28768,18 +28796,23 @@ async function sshDockerLogin(cfg) {
|
|
|
28768
28796
|
if (!password) {
|
|
28769
28797
|
throw new Error(`Registry password env var ${cfg.registry.passwordEnv} is not set on the deploy host (CLI machine).`);
|
|
28770
28798
|
}
|
|
28771
|
-
const cmd = `
|
|
28799
|
+
const cmd = `docker login ${cfg.registry.domain} -u ${cfg.registry.username} --password-stdin`;
|
|
28772
28800
|
const proc2 = spawn4({
|
|
28773
28801
|
cmd: [
|
|
28774
28802
|
"ssh",
|
|
28775
28803
|
...baseSshArgs(cfg.target),
|
|
28776
28804
|
`${cfg.target.user}@${cfg.target.host}`,
|
|
28777
28805
|
"--",
|
|
28778
|
-
|
|
28806
|
+
cmd
|
|
28779
28807
|
],
|
|
28808
|
+
stdin: "pipe",
|
|
28780
28809
|
stdout: "pipe",
|
|
28781
28810
|
stderr: "pipe"
|
|
28782
28811
|
});
|
|
28812
|
+
if (proc2.stdin) {
|
|
28813
|
+
await proc2.stdin.write(new TextEncoder().encode(password));
|
|
28814
|
+
await proc2.stdin.end?.();
|
|
28815
|
+
}
|
|
28783
28816
|
const exit = await proc2.exited;
|
|
28784
28817
|
if (exit !== 0) {
|
|
28785
28818
|
const stderr = await new Response(proc2.stderr).text();
|
|
@@ -28801,24 +28834,39 @@ async function listConfiguredEnvs(cfg) {
|
|
|
28801
28834
|
return [...set];
|
|
28802
28835
|
}
|
|
28803
28836
|
async function assertRegistryDnsResolves(cfg) {
|
|
28837
|
+
const apex = apexDomain(cfg.registry.domain);
|
|
28838
|
+
let nameservers = await digQuery("8.8.8.8", "NS", apex);
|
|
28839
|
+
nameservers = nameservers.map((s) => s.replace(/\.$/, ""));
|
|
28840
|
+
const sources = [...nameservers, "1.1.1.1", "8.8.8.8"];
|
|
28841
|
+
let lastAnswers = [];
|
|
28842
|
+
for (const source of sources) {
|
|
28843
|
+
const answers = await digQuery(source, "A", cfg.registry.domain);
|
|
28844
|
+
if (answers.length === 0)
|
|
28845
|
+
continue;
|
|
28846
|
+
lastAnswers = answers;
|
|
28847
|
+
if (answers.includes(cfg.target.host))
|
|
28848
|
+
return;
|
|
28849
|
+
}
|
|
28850
|
+
if (lastAnswers.length === 0) {
|
|
28851
|
+
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.`);
|
|
28852
|
+
}
|
|
28853
|
+
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.`);
|
|
28854
|
+
}
|
|
28855
|
+
function apexDomain(host) {
|
|
28856
|
+
const parts = host.split(".");
|
|
28857
|
+
return parts.slice(-2).join(".");
|
|
28858
|
+
}
|
|
28859
|
+
async function digQuery(server, type, name) {
|
|
28804
28860
|
const proc2 = spawn4({
|
|
28805
|
-
cmd: ["dig", "+short", "+time=3", "+tries=1",
|
|
28861
|
+
cmd: ["dig", `@${server}`, "+short", "+time=3", "+tries=1", type, name],
|
|
28806
28862
|
stdout: "pipe",
|
|
28807
28863
|
stderr: "ignore"
|
|
28808
28864
|
});
|
|
28809
28865
|
const exit = await proc2.exited;
|
|
28810
|
-
if (exit !== 0)
|
|
28811
|
-
|
|
28812
|
-
|
|
28813
|
-
}
|
|
28814
|
-
const resolved = (await new Response(proc2.stdout).text()).split(`
|
|
28866
|
+
if (exit !== 0)
|
|
28867
|
+
return [];
|
|
28868
|
+
return (await new Response(proc2.stdout).text()).split(`
|
|
28815
28869
|
`).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
28870
|
}
|
|
28823
28871
|
|
|
28824
28872
|
// src/deploy/deploy-env.ts
|
|
@@ -28831,7 +28879,7 @@ async function updateEnvDeployment(opts) {
|
|
|
28831
28879
|
const envPath = `${cfg.target.remoteDir}/.env`;
|
|
28832
28880
|
const escapedRef = fullRef.replace(/"/g, "\\\"");
|
|
28833
28881
|
const updateScript = [
|
|
28834
|
-
`touch ${envPath}`,
|
|
28882
|
+
`touch ${envPath} && `,
|
|
28835
28883
|
`awk -v line="${envVarName}=${escapedRef}" -v key="${envVarName}=" '`,
|
|
28836
28884
|
` BEGIN { replaced=0 } `,
|
|
28837
28885
|
` $0 ~ "^"key { print line; replaced=1; next } `,
|
|
@@ -28881,15 +28929,15 @@ var {spawn: spawn5 } = globalThis.Bun;
|
|
|
28881
28929
|
import { createHash as createHash3 } from "crypto";
|
|
28882
28930
|
import {
|
|
28883
28931
|
copyFileSync as copyFileSync2,
|
|
28884
|
-
existsSync as
|
|
28932
|
+
existsSync as existsSync16,
|
|
28885
28933
|
mkdirSync as mkdirSync13,
|
|
28886
|
-
readFileSync as
|
|
28887
|
-
realpathSync as
|
|
28934
|
+
readFileSync as readFileSync13,
|
|
28935
|
+
realpathSync as realpathSync2,
|
|
28888
28936
|
writeFileSync as writeFileSync14
|
|
28889
28937
|
} from "fs";
|
|
28890
28938
|
import { tmpdir as tmpdir3 } from "os";
|
|
28891
|
-
import { dirname as
|
|
28892
|
-
import { fileURLToPath as
|
|
28939
|
+
import { dirname as dirname7, join as join18 } from "path";
|
|
28940
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
28893
28941
|
|
|
28894
28942
|
// src/deploy/image-template.ts
|
|
28895
28943
|
function generateDockerfile(inputs) {
|
|
@@ -28938,8 +28986,8 @@ function generateDockerfile(inputs) {
|
|
|
28938
28986
|
// src/deploy/image.ts
|
|
28939
28987
|
async function buildImage(ws, opts) {
|
|
28940
28988
|
await ensureDocker();
|
|
28941
|
-
const manifestPath =
|
|
28942
|
-
if (!
|
|
28989
|
+
const manifestPath = join18(ws.arcDir, "manifest.json");
|
|
28990
|
+
if (!existsSync16(manifestPath)) {
|
|
28943
28991
|
throw new Error(`No build manifest at ${manifestPath}. Run \`arc platform build\` first or omit --skip-build.`);
|
|
28944
28992
|
}
|
|
28945
28993
|
embedCliBundle(ws);
|
|
@@ -28949,12 +28997,13 @@ async function buildImage(ws, opts) {
|
|
|
28949
28997
|
const dockerfileInputs = collectDockerfileInputs(ws);
|
|
28950
28998
|
const dockerfile = generateDockerfile(dockerfileInputs);
|
|
28951
28999
|
const buildContextDir = ws.rootDir;
|
|
28952
|
-
const dockerfileDir =
|
|
29000
|
+
const dockerfileDir = join18(tmpdir3(), `arc-image-${Date.now()}`);
|
|
28953
29001
|
mkdirSync13(dockerfileDir, { recursive: true });
|
|
28954
|
-
const dockerfilePath =
|
|
29002
|
+
const dockerfilePath = join18(dockerfileDir, "Dockerfile");
|
|
28955
29003
|
writeFileSync14(dockerfilePath, dockerfile);
|
|
28956
29004
|
const buildArgs = [
|
|
28957
29005
|
"build",
|
|
29006
|
+
"--platform=linux/amd64",
|
|
28958
29007
|
"-f",
|
|
28959
29008
|
dockerfilePath,
|
|
28960
29009
|
"-t",
|
|
@@ -28976,20 +29025,20 @@ async function buildImage(ws, opts) {
|
|
|
28976
29025
|
}
|
|
28977
29026
|
function embedCliBundle(ws) {
|
|
28978
29027
|
const source = locateCliBundle();
|
|
28979
|
-
const target =
|
|
29028
|
+
const target = join18(ws.arcDir, "host.js");
|
|
28980
29029
|
copyFileSync2(source, target);
|
|
28981
29030
|
}
|
|
28982
29031
|
function locateCliBundle() {
|
|
28983
|
-
const here =
|
|
28984
|
-
let cur =
|
|
29032
|
+
const here = fileURLToPath5(import.meta.url);
|
|
29033
|
+
let cur = dirname7(here);
|
|
28985
29034
|
while (cur !== "/" && cur !== "") {
|
|
28986
|
-
const candidate =
|
|
28987
|
-
if (
|
|
29035
|
+
const candidate = join18(cur, "package.json");
|
|
29036
|
+
if (existsSync16(candidate)) {
|
|
28988
29037
|
try {
|
|
28989
|
-
const pkg = JSON.parse(
|
|
29038
|
+
const pkg = JSON.parse(readFileSync13(candidate, "utf-8"));
|
|
28990
29039
|
if (pkg.name === "@arcote.tech/arc-cli") {
|
|
28991
|
-
const distIndex =
|
|
28992
|
-
if (!
|
|
29040
|
+
const distIndex = join18(realpathSync2(cur), "dist", "index.js");
|
|
29041
|
+
if (!existsSync16(distIndex)) {
|
|
28993
29042
|
throw new Error(`arc-cli bundle missing at ${distIndex}. Run \`bun run build\` in packages/cli/.`);
|
|
28994
29043
|
}
|
|
28995
29044
|
return distIndex;
|
|
@@ -28999,7 +29048,7 @@ function locateCliBundle() {
|
|
|
28999
29048
|
throw e;
|
|
29000
29049
|
}
|
|
29001
29050
|
}
|
|
29002
|
-
const parent =
|
|
29051
|
+
const parent = dirname7(cur);
|
|
29003
29052
|
if (parent === cur)
|
|
29004
29053
|
break;
|
|
29005
29054
|
cur = parent;
|
|
@@ -29021,17 +29070,17 @@ async function ensureDocker() {
|
|
|
29021
29070
|
}
|
|
29022
29071
|
}
|
|
29023
29072
|
function computeContentHash(manifestPath) {
|
|
29024
|
-
const raw = JSON.parse(
|
|
29073
|
+
const raw = JSON.parse(readFileSync13(manifestPath, "utf-8"));
|
|
29025
29074
|
delete raw.buildTime;
|
|
29026
29075
|
const canonical = JSON.stringify(raw);
|
|
29027
29076
|
return createHash3("sha256").update(canonical).digest("hex").slice(0, 12);
|
|
29028
29077
|
}
|
|
29029
29078
|
function collectDockerfileInputs(ws) {
|
|
29030
|
-
const hasPublicDir =
|
|
29031
|
-
const hasLocales =
|
|
29079
|
+
const hasPublicDir = existsSync16(join18(ws.rootDir, "public"));
|
|
29080
|
+
const hasLocales = existsSync16(join18(ws.rootDir, "locales"));
|
|
29032
29081
|
let manifestPath;
|
|
29033
29082
|
for (const name of ["manifest.webmanifest", "manifest.json"]) {
|
|
29034
|
-
if (
|
|
29083
|
+
if (existsSync16(join18(ws.rootDir, name))) {
|
|
29035
29084
|
manifestPath = name;
|
|
29036
29085
|
break;
|
|
29037
29086
|
}
|
|
@@ -29852,14 +29901,14 @@ async function platformDeploy(envArg, options = {}) {
|
|
|
29852
29901
|
err(`Unknown env "${envArg}". Known: ${Object.keys(cfg.envs).join(", ")}`);
|
|
29853
29902
|
process.exit(1);
|
|
29854
29903
|
})() : Object.keys(cfg.envs);
|
|
29855
|
-
const manifestPath =
|
|
29904
|
+
const manifestPath = join19(ws.arcDir, "manifest.json");
|
|
29856
29905
|
if (!options.imageTag) {
|
|
29857
|
-
const needBuild = options.rebuild || !
|
|
29906
|
+
const needBuild = options.rebuild || !existsSync17(manifestPath);
|
|
29858
29907
|
if (needBuild && !options.skipBuild) {
|
|
29859
29908
|
log2("Building platform...");
|
|
29860
29909
|
await buildAll(ws, { noCache: options.rebuild });
|
|
29861
29910
|
ok("Build complete");
|
|
29862
|
-
} else if (!
|
|
29911
|
+
} else if (!existsSync17(manifestPath)) {
|
|
29863
29912
|
err("No build found and --skip-build was set.");
|
|
29864
29913
|
process.exit(1);
|
|
29865
29914
|
}
|
|
@@ -29884,25 +29933,26 @@ async function platformDeploy(envArg, options = {}) {
|
|
|
29884
29933
|
log2(`contentHash: ${contentHash}`);
|
|
29885
29934
|
return;
|
|
29886
29935
|
}
|
|
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
29936
|
}
|
|
29893
29937
|
log2("Inspecting remote server...");
|
|
29894
29938
|
const state = await detectRemoteState(cfg);
|
|
29895
29939
|
log2(`Remote state: ${state.kind}`);
|
|
29896
29940
|
const cliVersion = readCliVersion();
|
|
29897
29941
|
const configHash = await hashDeployConfig(ws.rootDir);
|
|
29898
|
-
|
|
29899
|
-
|
|
29900
|
-
|
|
29901
|
-
|
|
29902
|
-
|
|
29903
|
-
|
|
29904
|
-
|
|
29905
|
-
|
|
29942
|
+
await bootstrap({
|
|
29943
|
+
cfg,
|
|
29944
|
+
rootDir: ws.rootDir,
|
|
29945
|
+
state,
|
|
29946
|
+
cliVersion,
|
|
29947
|
+
configHash,
|
|
29948
|
+
forceAnsible: options.forceBootstrap
|
|
29949
|
+
});
|
|
29950
|
+
if (!options.imageTag) {
|
|
29951
|
+
log2(`Logging in to ${cfg.registry.domain}...`);
|
|
29952
|
+
await dockerLogin(cfg.registry);
|
|
29953
|
+
log2(`Pushing ${fullRef}...`);
|
|
29954
|
+
await dockerPush(fullRef);
|
|
29955
|
+
ok("Image pushed");
|
|
29906
29956
|
}
|
|
29907
29957
|
for (const env2 of targetEnvs) {
|
|
29908
29958
|
log2(`Updating env "${env2}"...`);
|
|
@@ -29921,17 +29971,17 @@ async function platformDeploy(envArg, options = {}) {
|
|
|
29921
29971
|
}
|
|
29922
29972
|
function readCliVersion() {
|
|
29923
29973
|
try {
|
|
29924
|
-
let cur =
|
|
29925
|
-
const root =
|
|
29974
|
+
let cur = dirname8(fileURLToPath6(import.meta.url));
|
|
29975
|
+
const root = dirname8(cur).startsWith("/") ? "/" : ".";
|
|
29926
29976
|
while (cur !== root && cur !== "") {
|
|
29927
|
-
const candidate =
|
|
29928
|
-
if (
|
|
29929
|
-
const pkg = JSON.parse(
|
|
29977
|
+
const candidate = join19(cur, "package.json");
|
|
29978
|
+
if (existsSync17(candidate)) {
|
|
29979
|
+
const pkg = JSON.parse(readFileSync14(candidate, "utf-8"));
|
|
29930
29980
|
if (pkg.name === "@arcote.tech/arc-cli") {
|
|
29931
29981
|
return pkg.version ?? "unknown";
|
|
29932
29982
|
}
|
|
29933
29983
|
}
|
|
29934
|
-
const parent =
|
|
29984
|
+
const parent = dirname8(cur);
|
|
29935
29985
|
if (parent === cur)
|
|
29936
29986
|
break;
|
|
29937
29987
|
cur = parent;
|
|
@@ -29942,16 +29992,16 @@ function readCliVersion() {
|
|
|
29942
29992
|
}
|
|
29943
29993
|
}
|
|
29944
29994
|
async function hashDeployConfig(rootDir) {
|
|
29945
|
-
const p2 =
|
|
29946
|
-
const content =
|
|
29995
|
+
const p2 = join19(rootDir, "deploy.arc.json");
|
|
29996
|
+
const content = readFileSync14(p2);
|
|
29947
29997
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
29948
29998
|
hasher.update(content);
|
|
29949
29999
|
return hasher.digest("hex").slice(0, 16);
|
|
29950
30000
|
}
|
|
29951
30001
|
|
|
29952
30002
|
// src/platform/startup.ts
|
|
29953
|
-
import { existsSync as
|
|
29954
|
-
import { join as
|
|
30003
|
+
import { existsSync as existsSync19, readFileSync as readFileSync15, watch } from "fs";
|
|
30004
|
+
import { join as join21 } from "path";
|
|
29955
30005
|
|
|
29956
30006
|
// ../host/src/create-server.ts
|
|
29957
30007
|
var import_jsonwebtoken = __toESM(require_jsonwebtoken(), 1);
|
|
@@ -31197,8 +31247,8 @@ function querySubscriptionHandler() {
|
|
|
31197
31247
|
subscriptionId,
|
|
31198
31248
|
data: data ?? null
|
|
31199
31249
|
});
|
|
31200
|
-
} catch (
|
|
31201
|
-
console.error(`[Arc] Query subscription error:`,
|
|
31250
|
+
} catch (err3) {
|
|
31251
|
+
console.error(`[Arc] Query subscription error:`, err3);
|
|
31202
31252
|
}
|
|
31203
31253
|
};
|
|
31204
31254
|
sendData();
|
|
@@ -31401,25 +31451,14 @@ async function createArcServer(config) {
|
|
|
31401
31451
|
};
|
|
31402
31452
|
}
|
|
31403
31453
|
// src/platform/server.ts
|
|
31404
|
-
|
|
31405
|
-
import {
|
|
31406
|
-
|
|
31407
|
-
|
|
31408
|
-
|
|
31409
|
-
|
|
31410
|
-
|
|
31411
|
-
}
|
|
31454
|
+
init_i18n();
|
|
31455
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync14 } from "fs";
|
|
31456
|
+
import { join as join20 } from "path";
|
|
31457
|
+
function generateShellHtml(appName, manifest, initial) {
|
|
31458
|
+
const initialUrl = initial ? `/browser/${initial.file}` : null;
|
|
31459
|
+
if (!initialUrl) {
|
|
31460
|
+
throw new Error("generateShellHtml: initial bundle missing from manifest");
|
|
31412
31461
|
}
|
|
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
31462
|
return `<!doctype html>
|
|
31424
31463
|
<html lang="en">
|
|
31425
31464
|
<head>
|
|
@@ -31430,18 +31469,13 @@ function generateShellHtml(appName, manifest, arcEntries) {
|
|
|
31430
31469
|
<link rel="manifest" href="/manifest.json">` : ""}
|
|
31431
31470
|
<link rel="stylesheet" href="/styles.css" />
|
|
31432
31471
|
<link rel="stylesheet" href="/theme.css" />
|
|
31433
|
-
<
|
|
31472
|
+
<link rel="modulepreload" href="${initialUrl}" />
|
|
31434
31473
|
</head>
|
|
31435
31474
|
<body>
|
|
31436
31475
|
<div id="root"></div>
|
|
31437
31476
|
<script type="module">
|
|
31438
|
-
import {
|
|
31439
|
-
|
|
31440
|
-
import { PlatformApp } from "@arcote.tech/platform";
|
|
31441
|
-
|
|
31442
|
-
createRoot(document.getElementById("root")).render(
|
|
31443
|
-
createElement(PlatformApp)
|
|
31444
|
-
);
|
|
31477
|
+
import { startApp } from "${initialUrl}";
|
|
31478
|
+
startApp("root");
|
|
31445
31479
|
</script>
|
|
31446
31480
|
</body>
|
|
31447
31481
|
</html>`;
|
|
@@ -31466,28 +31500,39 @@ function getMime(path4) {
|
|
|
31466
31500
|
return MIME[ext2] ?? "application/octet-stream";
|
|
31467
31501
|
}
|
|
31468
31502
|
function serveFile(filePath, headers = {}) {
|
|
31469
|
-
if (!
|
|
31503
|
+
if (!existsSync18(filePath))
|
|
31470
31504
|
return new Response("Not Found", { status: 404 });
|
|
31471
31505
|
return new Response(Bun.file(filePath), {
|
|
31472
31506
|
headers: { "Content-Type": getMime(filePath), ...headers }
|
|
31473
31507
|
});
|
|
31474
31508
|
}
|
|
31475
|
-
var MODULE_SIG_SECRET = process.env.ARC_MODULE_SECRET ??
|
|
31509
|
+
var MODULE_SIG_SECRET = process.env.ARC_MODULE_SECRET ?? "";
|
|
31476
31510
|
var MODULE_SIG_TTL = 3600;
|
|
31477
|
-
function
|
|
31511
|
+
function ensureModuleSigSecret(ws, devMode) {
|
|
31512
|
+
if (MODULE_SIG_SECRET)
|
|
31513
|
+
return;
|
|
31514
|
+
if (devMode) {
|
|
31515
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
31516
|
+
hasher.update(`arc-dev-secret:${ws.rootDir}`);
|
|
31517
|
+
MODULE_SIG_SECRET = hasher.digest("hex").slice(0, 32);
|
|
31518
|
+
} else {
|
|
31519
|
+
MODULE_SIG_SECRET = crypto.randomUUID();
|
|
31520
|
+
}
|
|
31521
|
+
}
|
|
31522
|
+
function signGroupUrl(file) {
|
|
31478
31523
|
const exp = Math.floor(Date.now() / 1000) + MODULE_SIG_TTL;
|
|
31479
31524
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
31480
|
-
hasher.update(`${
|
|
31525
|
+
hasher.update(`${file}:${exp}:${MODULE_SIG_SECRET}`);
|
|
31481
31526
|
const sig = hasher.digest("hex").slice(0, 16);
|
|
31482
|
-
return `/
|
|
31527
|
+
return `/browser/${file}?sig=${sig}&exp=${exp}`;
|
|
31483
31528
|
}
|
|
31484
|
-
function
|
|
31529
|
+
function verifyGroupSignature(file, sig, exp) {
|
|
31485
31530
|
if (!sig || !exp)
|
|
31486
31531
|
return false;
|
|
31487
31532
|
if (Number(exp) < Date.now() / 1000)
|
|
31488
31533
|
return false;
|
|
31489
31534
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
31490
|
-
hasher.update(`${
|
|
31535
|
+
hasher.update(`${file}:${exp}:${MODULE_SIG_SECRET}`);
|
|
31491
31536
|
return hasher.digest("hex").slice(0, 16) === sig;
|
|
31492
31537
|
}
|
|
31493
31538
|
function decodeTokenPayload(jwt2) {
|
|
@@ -31522,90 +31567,85 @@ function parseArcTokensHeader(header) {
|
|
|
31522
31567
|
return payloads;
|
|
31523
31568
|
}
|
|
31524
31569
|
async function filterManifestForTokens(manifest, moduleAccessMap, tokenPayloads) {
|
|
31525
|
-
const
|
|
31570
|
+
const allowedGroups = new Set;
|
|
31526
31571
|
for (const t of tokenPayloads) {
|
|
31527
31572
|
if (t?.tokenType)
|
|
31528
|
-
|
|
31573
|
+
allowedGroups.add(t.tokenType);
|
|
31529
31574
|
}
|
|
31530
|
-
const
|
|
31531
|
-
for (const
|
|
31532
|
-
if (!
|
|
31533
|
-
continue;
|
|
31534
|
-
if (mod.chunk === "public") {
|
|
31535
|
-
filtered.push(mod);
|
|
31575
|
+
const filteredGroups = {};
|
|
31576
|
+
for (const [name, group] of Object.entries(manifest.groups)) {
|
|
31577
|
+
if (!allowedGroups.has(name))
|
|
31536
31578
|
continue;
|
|
31537
|
-
|
|
31538
|
-
const
|
|
31539
|
-
|
|
31540
|
-
|
|
31541
|
-
|
|
31579
|
+
let allGranted = true;
|
|
31580
|
+
for (const moduleName of group.modules) {
|
|
31581
|
+
const access = moduleAccessMap.get(moduleName);
|
|
31582
|
+
if (!access || access.rules.length === 0)
|
|
31583
|
+
continue;
|
|
31584
|
+
let granted = false;
|
|
31542
31585
|
for (const rule of access.rules) {
|
|
31543
|
-
if (rule.token.name !==
|
|
31586
|
+
if (rule.token.name !== name)
|
|
31544
31587
|
continue;
|
|
31545
|
-
const matching = tokenPayloads.find((t) => t.tokenType ===
|
|
31588
|
+
const matching = tokenPayloads.find((t) => t.tokenType === name);
|
|
31546
31589
|
if (!matching)
|
|
31547
31590
|
continue;
|
|
31548
31591
|
granted = rule.check ? await rule.check(matching) : true;
|
|
31549
31592
|
if (granted)
|
|
31550
31593
|
break;
|
|
31551
31594
|
}
|
|
31595
|
+
if (!granted) {
|
|
31596
|
+
allGranted = false;
|
|
31597
|
+
break;
|
|
31598
|
+
}
|
|
31552
31599
|
}
|
|
31553
|
-
if (
|
|
31554
|
-
|
|
31600
|
+
if (allGranted) {
|
|
31601
|
+
filteredGroups[name] = { ...group, url: signGroupUrl(group.file) };
|
|
31555
31602
|
}
|
|
31556
31603
|
}
|
|
31557
31604
|
return {
|
|
31558
|
-
|
|
31559
|
-
|
|
31560
|
-
|
|
31605
|
+
initial: manifest.initial,
|
|
31606
|
+
groups: filteredGroups,
|
|
31607
|
+
sharedChunks: manifest.sharedChunks,
|
|
31561
31608
|
stylesHash: manifest.stylesHash,
|
|
31562
31609
|
buildTime: manifest.buildTime
|
|
31563
31610
|
};
|
|
31564
31611
|
}
|
|
31565
|
-
var
|
|
31566
|
-
|
|
31567
|
-
function staticFilesHandler(ws, devMode) {
|
|
31612
|
+
var BROWSER_FILE_RE = /^[A-Za-z0-9_.-]+\.js$/;
|
|
31613
|
+
function staticFilesHandler(ws, devMode, getManifest) {
|
|
31568
31614
|
return (_req, url, ctx) => {
|
|
31569
31615
|
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)) {
|
|
31616
|
+
if (path4.startsWith("/browser/")) {
|
|
31617
|
+
const file = path4.slice(9);
|
|
31618
|
+
if (!BROWSER_FILE_RE.test(file)) {
|
|
31581
31619
|
return new Response("Not Found", { status: 404, headers: ctx.corsHeaders });
|
|
31582
31620
|
}
|
|
31583
|
-
|
|
31621
|
+
const manifest = getManifest();
|
|
31622
|
+
const isGroupEntry = Object.values(manifest.groups).some((g3) => g3.file === file);
|
|
31623
|
+
if (isGroupEntry) {
|
|
31584
31624
|
const sig = url.searchParams.get("sig");
|
|
31585
31625
|
const exp = url.searchParams.get("exp");
|
|
31586
|
-
if (!
|
|
31626
|
+
if (!verifyGroupSignature(file, sig, exp)) {
|
|
31587
31627
|
return new Response("Forbidden", { status: 403, headers: ctx.corsHeaders });
|
|
31588
31628
|
}
|
|
31589
31629
|
}
|
|
31590
|
-
return serveFile(
|
|
31630
|
+
return serveFile(join20(ws.browserDir, file), {
|
|
31591
31631
|
...ctx.corsHeaders,
|
|
31592
31632
|
"Cache-Control": devMode ? "no-cache" : "max-age=31536000,immutable"
|
|
31593
31633
|
});
|
|
31594
31634
|
}
|
|
31595
31635
|
if (path4.startsWith("/locales/"))
|
|
31596
|
-
return serveFile(
|
|
31636
|
+
return serveFile(join20(ws.arcDir, path4.slice(1)), ctx.corsHeaders);
|
|
31597
31637
|
if (path4.startsWith("/assets/"))
|
|
31598
|
-
return serveFile(
|
|
31638
|
+
return serveFile(join20(ws.assetsDir, path4.slice(8)), ctx.corsHeaders);
|
|
31599
31639
|
if (path4 === "/styles.css")
|
|
31600
|
-
return serveFile(
|
|
31640
|
+
return serveFile(join20(ws.arcDir, "styles.css"), ctx.corsHeaders);
|
|
31601
31641
|
if (path4 === "/theme.css")
|
|
31602
|
-
return serveFile(
|
|
31642
|
+
return serveFile(join20(ws.arcDir, "theme.css"), ctx.corsHeaders);
|
|
31603
31643
|
if ((path4 === "/manifest.json" || path4 === "/manifest.webmanifest") && ws.manifest) {
|
|
31604
31644
|
return serveFile(ws.manifest.path, ctx.corsHeaders);
|
|
31605
31645
|
}
|
|
31606
31646
|
if (path4.lastIndexOf(".") > path4.lastIndexOf("/")) {
|
|
31607
|
-
const publicFile =
|
|
31608
|
-
if (
|
|
31647
|
+
const publicFile = join20(ws.publicDir, path4.slice(1));
|
|
31648
|
+
if (existsSync18(publicFile))
|
|
31609
31649
|
return serveFile(publicFile, ctx.corsHeaders);
|
|
31610
31650
|
}
|
|
31611
31651
|
return null;
|
|
@@ -31630,7 +31670,7 @@ function apiEndpointsHandler(ws, getManifest, cm, moduleAccessMap) {
|
|
|
31630
31670
|
if (url.pathname === "/health") {
|
|
31631
31671
|
return Response.json({
|
|
31632
31672
|
status: "ok",
|
|
31633
|
-
|
|
31673
|
+
groups: Object.keys(getManifest().groups).length,
|
|
31634
31674
|
clients: cm?.clientCount ?? 0
|
|
31635
31675
|
}, { headers: ctx.corsHeaders });
|
|
31636
31676
|
}
|
|
@@ -31662,22 +31702,23 @@ function devReloadHandler(sseClients) {
|
|
|
31662
31702
|
});
|
|
31663
31703
|
};
|
|
31664
31704
|
}
|
|
31665
|
-
function spaFallbackHandler(
|
|
31705
|
+
function spaFallbackHandler(getShellHtml) {
|
|
31666
31706
|
return (_req, _url, ctx) => {
|
|
31667
|
-
return new Response(
|
|
31707
|
+
return new Response(getShellHtml(), {
|
|
31668
31708
|
headers: { ...ctx.corsHeaders, "Content-Type": "text/html" }
|
|
31669
31709
|
});
|
|
31670
31710
|
};
|
|
31671
31711
|
}
|
|
31672
31712
|
async function startPlatformServer(opts) {
|
|
31673
31713
|
const { ws, port, devMode, context } = opts;
|
|
31714
|
+
ensureModuleSigSecret(ws, !!devMode);
|
|
31674
31715
|
const moduleAccessMap = opts.moduleAccess ?? new Map;
|
|
31675
31716
|
let manifest = opts.manifest;
|
|
31676
31717
|
const getManifest = () => manifest;
|
|
31677
31718
|
const setManifest = (m4) => {
|
|
31678
31719
|
manifest = m4;
|
|
31679
31720
|
};
|
|
31680
|
-
const
|
|
31721
|
+
const getShellHtml = () => generateShellHtml(ws.appName, ws.manifest, manifest?.initial);
|
|
31681
31722
|
const sseClients = new Set;
|
|
31682
31723
|
const notifyReload = (m4) => {
|
|
31683
31724
|
const data = JSON.stringify(m4);
|
|
@@ -31714,8 +31755,8 @@ async function startPlatformServer(opts) {
|
|
|
31714
31755
|
const handlers = [
|
|
31715
31756
|
apiEndpointsHandler(ws, getManifest, null, moduleAccessMap),
|
|
31716
31757
|
devReloadHandler(sseClients),
|
|
31717
|
-
staticFilesHandler(ws, !!devMode),
|
|
31718
|
-
spaFallbackHandler(
|
|
31758
|
+
staticFilesHandler(ws, !!devMode, getManifest),
|
|
31759
|
+
spaFallbackHandler(getShellHtml)
|
|
31719
31760
|
];
|
|
31720
31761
|
for (const handler of handlers) {
|
|
31721
31762
|
const response = await handler(req, url, ctx);
|
|
@@ -31735,7 +31776,7 @@ async function startPlatformServer(opts) {
|
|
|
31735
31776
|
};
|
|
31736
31777
|
}
|
|
31737
31778
|
const { createBunSQLiteAdapterFactory: createBunSQLiteAdapterFactory2 } = await Promise.resolve().then(() => (init_dist(), exports_dist2));
|
|
31738
|
-
const dbPath = opts.dbPath ||
|
|
31779
|
+
const dbPath = opts.dbPath || join20(ws.arcDir, "data", "arc.db");
|
|
31739
31780
|
const dbDir = dbPath.substring(0, dbPath.lastIndexOf("/"));
|
|
31740
31781
|
if (dbDir)
|
|
31741
31782
|
mkdirSync14(dbDir, { recursive: true });
|
|
@@ -31746,8 +31787,8 @@ async function startPlatformServer(opts) {
|
|
|
31746
31787
|
httpHandlers: [
|
|
31747
31788
|
apiEndpointsHandler(ws, getManifest, null, moduleAccessMap),
|
|
31748
31789
|
devReloadHandler(sseClients),
|
|
31749
|
-
staticFilesHandler(ws, !!devMode),
|
|
31750
|
-
spaFallbackHandler(
|
|
31790
|
+
staticFilesHandler(ws, !!devMode, getManifest),
|
|
31791
|
+
spaFallbackHandler(getShellHtml)
|
|
31751
31792
|
],
|
|
31752
31793
|
onWsClose: (clientId) => cleanupClientSubs(clientId)
|
|
31753
31794
|
});
|
|
@@ -31765,17 +31806,17 @@ async function startPlatformServer(opts) {
|
|
|
31765
31806
|
async function startPlatform(opts) {
|
|
31766
31807
|
const { ws, devMode } = opts;
|
|
31767
31808
|
const port = opts.port ?? parseInt(process.env.PORT || "5005", 10);
|
|
31768
|
-
const dbPath = opts.dbPath ??
|
|
31809
|
+
const dbPath = opts.dbPath ?? join21(ws.rootDir, ".arc", "data", devMode ? "dev.db" : "prod.db");
|
|
31769
31810
|
let manifest;
|
|
31770
31811
|
if (devMode) {
|
|
31771
31812
|
manifest = await buildAll(ws);
|
|
31772
31813
|
} else {
|
|
31773
|
-
const manifestPath =
|
|
31774
|
-
if (!
|
|
31814
|
+
const manifestPath = join21(ws.arcDir, "manifest.json");
|
|
31815
|
+
if (!existsSync19(manifestPath)) {
|
|
31775
31816
|
err("No build found. Run `arc platform build` first.");
|
|
31776
31817
|
process.exit(1);
|
|
31777
31818
|
}
|
|
31778
|
-
manifest = JSON.parse(
|
|
31819
|
+
manifest = JSON.parse(readFileSync15(manifestPath, "utf-8"));
|
|
31779
31820
|
}
|
|
31780
31821
|
log2("Loading server context...");
|
|
31781
31822
|
const { context, moduleAccess } = await loadServerContext(ws);
|
|
@@ -31784,7 +31825,6 @@ async function startPlatform(opts) {
|
|
|
31784
31825
|
} else {
|
|
31785
31826
|
log2("No context \u2014 server endpoints skipped");
|
|
31786
31827
|
}
|
|
31787
|
-
const arcEntries = collectArcPeerDeps(ws.packages);
|
|
31788
31828
|
const platform3 = await startPlatformServer({
|
|
31789
31829
|
ws,
|
|
31790
31830
|
port,
|
|
@@ -31792,8 +31832,7 @@ async function startPlatform(opts) {
|
|
|
31792
31832
|
context,
|
|
31793
31833
|
moduleAccess,
|
|
31794
31834
|
dbPath,
|
|
31795
|
-
devMode
|
|
31796
|
-
arcEntries
|
|
31835
|
+
devMode
|
|
31797
31836
|
});
|
|
31798
31837
|
ok(`Server on http://localhost:${port}`);
|
|
31799
31838
|
if (platform3.contextHandler) {
|
|
@@ -31825,7 +31864,7 @@ function attachDevWatcher(ws, platform3) {
|
|
|
31825
31864
|
const next = await buildAll(ws);
|
|
31826
31865
|
platform3.setManifest(next);
|
|
31827
31866
|
platform3.notifyReload(next);
|
|
31828
|
-
ok(`Rebuilt \u2014 ${next.
|
|
31867
|
+
ok(`Rebuilt \u2014 initial + ${Object.keys(next.groups).length} group(s)`);
|
|
31829
31868
|
} catch (e2) {
|
|
31830
31869
|
console.error(`Rebuild failed: ${e2}`);
|
|
31831
31870
|
} finally {
|
|
@@ -31834,8 +31873,8 @@ function attachDevWatcher(ws, platform3) {
|
|
|
31834
31873
|
}, 300);
|
|
31835
31874
|
};
|
|
31836
31875
|
for (const pkg of ws.packages) {
|
|
31837
|
-
const srcDir =
|
|
31838
|
-
if (!
|
|
31876
|
+
const srcDir = join21(pkg.path, "src");
|
|
31877
|
+
if (!existsSync19(srcDir))
|
|
31839
31878
|
continue;
|
|
31840
31879
|
watch(srcDir, { recursive: true }, (_event, filename) => {
|
|
31841
31880
|
if (!filename || filename.includes(".arc") || filename.endsWith(".d.ts") || filename.includes("node_modules") || filename.includes("dist"))
|
|
@@ -31845,8 +31884,8 @@ function attachDevWatcher(ws, platform3) {
|
|
|
31845
31884
|
triggerRebuild();
|
|
31846
31885
|
});
|
|
31847
31886
|
}
|
|
31848
|
-
const localesDir =
|
|
31849
|
-
if (
|
|
31887
|
+
const localesDir = join21(ws.rootDir, "locales");
|
|
31888
|
+
if (existsSync19(localesDir)) {
|
|
31850
31889
|
watch(localesDir, { recursive: false }, (_event, filename) => {
|
|
31851
31890
|
if (!filename?.endsWith(".po"))
|
|
31852
31891
|
return;
|
|
@@ -31876,7 +31915,7 @@ var platform3 = program2.command("platform").description("Platform commands \u20
|
|
|
31876
31915
|
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
31916
|
platform3.command("build").description("Build platform for production").option("--no-cache", "Force full rebuild").action((opts) => platformBuild({ noCache: opts.cache === false }));
|
|
31878
31917
|
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));
|
|
31918
|
+
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
31919
|
program2.parse(process.argv);
|
|
31881
31920
|
if (process.argv.length === 2) {
|
|
31882
31921
|
program2.help();
|