@minnovate/shadow-publisher 0.11.5 → 0.11.7
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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-publisher",
|
|
3
3
|
"displayName": "Git Publisher",
|
|
4
|
-
"version": "0.11.
|
|
4
|
+
"version": "0.11.7",
|
|
5
5
|
"description": "Publish an app folder's Git history to the serverless Git publishing backend and keep it updated (\"publish my app\", \"update my app\", \"fetch the engineered version\").",
|
|
6
6
|
"author": { "name": "git-publisher project" },
|
|
7
7
|
"keywords": ["git", "publish", "deploy", "serverless"]
|
package/dist/publisher.cjs
CHANGED
|
@@ -4568,19 +4568,30 @@ var import_node_os2 = require("node:os");
|
|
|
4568
4568
|
var import_node_path4 = require("node:path");
|
|
4569
4569
|
|
|
4570
4570
|
// ../client/src/form-post.ts
|
|
4571
|
+
var FORM_POST_TIMEOUT_MS = 1e4;
|
|
4571
4572
|
async function postForm(base, path, fields, fetchImpl = globalThis.fetch) {
|
|
4572
|
-
|
|
4573
|
+
const bound = new AbortController();
|
|
4574
|
+
const timer = setTimeout(() => bound.abort(new DOMException("the request timed out", "TimeoutError")), FORM_POST_TIMEOUT_MS);
|
|
4573
4575
|
try {
|
|
4574
|
-
res
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4576
|
+
let res;
|
|
4577
|
+
try {
|
|
4578
|
+
res = await fetchImpl(`${base}${path}`, {
|
|
4579
|
+
method: "POST",
|
|
4580
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
4581
|
+
body: new URLSearchParams(fields).toString(),
|
|
4582
|
+
signal: bound.signal
|
|
4583
|
+
});
|
|
4584
|
+
} catch (e) {
|
|
4585
|
+
throw new PublisherError("UNAVAILABLE", `could not reach ${base}: ${e instanceof Error ? e.message : String(e)}`, { retryable: true, cause: e });
|
|
4586
|
+
}
|
|
4587
|
+
const body = await res.json().catch(() => ({}));
|
|
4588
|
+
if (bound.signal.aborted) {
|
|
4589
|
+
throw new PublisherError("UNAVAILABLE", `could not reach ${base}: the request timed out`, { retryable: true });
|
|
4590
|
+
}
|
|
4591
|
+
return { status: res.status, body: typeof body === "object" && body !== null ? body : {} };
|
|
4592
|
+
} finally {
|
|
4593
|
+
clearTimeout(timer);
|
|
4581
4594
|
}
|
|
4582
|
-
const body = await res.json().catch(() => ({}));
|
|
4583
|
-
return { status: res.status, body: typeof body === "object" && body !== null ? body : {} };
|
|
4584
4595
|
}
|
|
4585
4596
|
|
|
4586
4597
|
// ../client/src/credentials.ts
|
|
@@ -4949,6 +4960,25 @@ async function updateEntry(url2, change) {
|
|
|
4949
4960
|
await writeCredentials(file);
|
|
4950
4961
|
}
|
|
4951
4962
|
|
|
4963
|
+
// ../client/src/portal-refusal.ts
|
|
4964
|
+
function portalRefusalCode(body) {
|
|
4965
|
+
if (!isRecord(body)) {
|
|
4966
|
+
return null;
|
|
4967
|
+
}
|
|
4968
|
+
const error2 = body["error"];
|
|
4969
|
+
if (typeof error2 === "string") {
|
|
4970
|
+
return error2 === "" ? null : error2;
|
|
4971
|
+
}
|
|
4972
|
+
if (!isRecord(error2)) {
|
|
4973
|
+
return null;
|
|
4974
|
+
}
|
|
4975
|
+
const { code, message } = error2;
|
|
4976
|
+
return typeof code === "string" && code !== "" && typeof message === "string" ? code : null;
|
|
4977
|
+
}
|
|
4978
|
+
function isRecord(value) {
|
|
4979
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4980
|
+
}
|
|
4981
|
+
|
|
4952
4982
|
// ../client/src/application.ts
|
|
4953
4983
|
var APPLICATION_CREATION = "application-creation";
|
|
4954
4984
|
var ATTEMPTS = 3;
|
|
@@ -4973,7 +5003,7 @@ async function createApplication(input, opts) {
|
|
|
4973
5003
|
if (answer.status === 200 || answer.status === 201) {
|
|
4974
5004
|
return read(answer.body, answer.status === 201);
|
|
4975
5005
|
}
|
|
4976
|
-
const code =
|
|
5006
|
+
const code = portalRefusalCode(answer.body) ?? "";
|
|
4977
5007
|
if (answer.status === 401) {
|
|
4978
5008
|
throw new PublisherError("UNAUTHORIZED", 'the portal did not accept this credential; run "publisher login" again');
|
|
4979
5009
|
}
|
|
@@ -4995,9 +5025,9 @@ async function createApplication(input, opts) {
|
|
|
4995
5025
|
throw new PublisherError("UNAVAILABLE", `could not make the application: ${lastOutage}; run init again`, { retryable: true });
|
|
4996
5026
|
}
|
|
4997
5027
|
function read(body, created) {
|
|
4998
|
-
const application =
|
|
4999
|
-
const repository = RepositoryInfo.safeParse(
|
|
5000
|
-
if (!
|
|
5028
|
+
const application = isRecord2(body) ? body["application"] : void 0;
|
|
5029
|
+
const repository = RepositoryInfo.safeParse(isRecord2(body) ? body["repository"] : void 0);
|
|
5030
|
+
if (!isRecord2(application) || typeof application["appId"] !== "string" || !repository.success) {
|
|
5001
5031
|
throw new PublisherError("UNAVAILABLE", "the portal answered with an application this version cannot read");
|
|
5002
5032
|
}
|
|
5003
5033
|
return { appId: application["appId"], created, repository: repository.data };
|
|
@@ -5020,7 +5050,7 @@ async function post(fetchImpl, url2, token, body) {
|
|
|
5020
5050
|
return { status: 0, body: null };
|
|
5021
5051
|
}
|
|
5022
5052
|
}
|
|
5023
|
-
function
|
|
5053
|
+
function isRecord2(value) {
|
|
5024
5054
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5025
5055
|
}
|
|
5026
5056
|
|
|
@@ -5156,7 +5186,7 @@ var RUN_STAGES = ["received", "running", "deploying", "live"];
|
|
|
5156
5186
|
var STAGE_WORDS = { received: "received", running: "checked", deploying: "going live", live: "live" };
|
|
5157
5187
|
var STATES = ["pending", "in-progress", "done", "failed", "skipped"];
|
|
5158
5188
|
function readStages(run) {
|
|
5159
|
-
if (!
|
|
5189
|
+
if (!isRecord3(run)) {
|
|
5160
5190
|
return { malformed: "a run that is not an object" };
|
|
5161
5191
|
}
|
|
5162
5192
|
if (!Object.hasOwn(run, "stages")) {
|
|
@@ -5169,7 +5199,7 @@ function readStages(run) {
|
|
|
5169
5199
|
const out = [];
|
|
5170
5200
|
for (const [index, entry] of stages.entries()) {
|
|
5171
5201
|
const stage = RUN_STAGES[index];
|
|
5172
|
-
if (!
|
|
5202
|
+
if (!isRecord3(entry) || entry["stage"] !== stage) {
|
|
5173
5203
|
return { malformed: `stage ${index + 1} is not ${stage}` };
|
|
5174
5204
|
}
|
|
5175
5205
|
const state = entry["state"];
|
|
@@ -5254,12 +5284,12 @@ async function followRun(input, opts) {
|
|
|
5254
5284
|
opts.onStage?.(entry);
|
|
5255
5285
|
moved = true;
|
|
5256
5286
|
}
|
|
5257
|
-
if (
|
|
5287
|
+
if (isRecord3(run.run) && run.run["status"] === "awaiting-approval") {
|
|
5258
5288
|
return { kind: "waiting", stages: read2.stages };
|
|
5259
5289
|
}
|
|
5260
5290
|
const end = ending(read2.stages);
|
|
5261
5291
|
if (end !== null) {
|
|
5262
|
-
const runId =
|
|
5292
|
+
const runId = isRecord3(run.run) && typeof run.run["runId"] === "string" ? run.run["runId"] : null;
|
|
5263
5293
|
return { kind: "settled", ending: end, failedAt: read2.stages.find((s) => s.state === "failed")?.word ?? null, stages: read2.stages, runId };
|
|
5264
5294
|
}
|
|
5265
5295
|
if (opts.untilChange === true && moved && answered) {
|
|
@@ -5278,7 +5308,7 @@ async function followRun(input, opts) {
|
|
|
5278
5308
|
}
|
|
5279
5309
|
}
|
|
5280
5310
|
function soleRun(body) {
|
|
5281
|
-
if (!
|
|
5311
|
+
if (!isRecord3(body) || !Array.isArray(body["runs"])) {
|
|
5282
5312
|
return { detail: "an answer with no list of runs" };
|
|
5283
5313
|
}
|
|
5284
5314
|
const runs = body["runs"];
|
|
@@ -5335,7 +5365,7 @@ async function confirmPortal(portal, endpoint, fetchImpl = fetch) {
|
|
|
5335
5365
|
return null;
|
|
5336
5366
|
}
|
|
5337
5367
|
}
|
|
5338
|
-
function
|
|
5368
|
+
function isRecord3(value) {
|
|
5339
5369
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5340
5370
|
}
|
|
5341
5371
|
|
|
@@ -5372,8 +5402,7 @@ async function call(input, opts, body) {
|
|
|
5372
5402
|
return { kind: "moved-on" };
|
|
5373
5403
|
}
|
|
5374
5404
|
if (answer.status === 404) {
|
|
5375
|
-
|
|
5376
|
-
return code === "no-such-application" ? { kind: "no-application" } : { kind: "unavailable", detail: "the portal does not serve this address" };
|
|
5405
|
+
return portalRefusalCode(answer.body) === "no-such-application" ? { kind: "no-application" } : { kind: "unavailable", detail: "the portal does not serve this address" };
|
|
5377
5406
|
}
|
|
5378
5407
|
if (answer.status === 200) {
|
|
5379
5408
|
const view = readView(answer.body);
|
|
@@ -5383,7 +5412,7 @@ async function call(input, opts, body) {
|
|
|
5383
5412
|
}
|
|
5384
5413
|
}
|
|
5385
5414
|
function readView(body) {
|
|
5386
|
-
if (!
|
|
5415
|
+
if (!isRecord4(body)) {
|
|
5387
5416
|
return { detail: "an answer that is not a preparation" };
|
|
5388
5417
|
}
|
|
5389
5418
|
const { id, revision, status, message, questions, publication } = body;
|
|
@@ -5404,12 +5433,12 @@ function readView(body) {
|
|
|
5404
5433
|
}
|
|
5405
5434
|
const read2 = [];
|
|
5406
5435
|
for (const q of questions) {
|
|
5407
|
-
if (!
|
|
5436
|
+
if (!isRecord4(q) || typeof q["id"] !== "string" || typeof q["text"] !== "string" || !Array.isArray(q["options"]) || q["options"].length === 0) {
|
|
5408
5437
|
return { detail: "a question that cannot be answered" };
|
|
5409
5438
|
}
|
|
5410
5439
|
const options = [];
|
|
5411
5440
|
for (const o of q["options"]) {
|
|
5412
|
-
if (!
|
|
5441
|
+
if (!isRecord4(o) || typeof o["value"] !== "string" || typeof o["label"] !== "string") {
|
|
5413
5442
|
return { detail: "a question with an unreadable option" };
|
|
5414
5443
|
}
|
|
5415
5444
|
options.push({ value: o["value"], label: o["label"] });
|
|
@@ -5417,7 +5446,7 @@ function readView(body) {
|
|
|
5417
5446
|
read2.push({ id: q["id"], text: q["text"], options });
|
|
5418
5447
|
}
|
|
5419
5448
|
let pub = null;
|
|
5420
|
-
if (
|
|
5449
|
+
if (isRecord4(publication) && typeof publication["status"] === "string" && typeof publication["message"] === "string") {
|
|
5421
5450
|
pub = { status: publication["status"], message: publication["message"], ...typeof publication["url"] === "string" ? { url: publication["url"] } : {} };
|
|
5422
5451
|
}
|
|
5423
5452
|
return { id, revision, status, message, questions: read2, publication: pub, findings: readFindings(body["findings"]) };
|
|
@@ -5432,7 +5461,7 @@ function readFindings(value) {
|
|
|
5432
5461
|
if (out.length === MAX_FINDINGS) {
|
|
5433
5462
|
break;
|
|
5434
5463
|
}
|
|
5435
|
-
if (!
|
|
5464
|
+
if (!isRecord4(f)) {
|
|
5436
5465
|
continue;
|
|
5437
5466
|
}
|
|
5438
5467
|
const kind = text(f["kind"]);
|
|
@@ -5472,7 +5501,7 @@ async function ask2(fetchImpl, url2, token, body) {
|
|
|
5472
5501
|
return { status: 0, body: null };
|
|
5473
5502
|
}
|
|
5474
5503
|
}
|
|
5475
|
-
function
|
|
5504
|
+
function isRecord4(value) {
|
|
5476
5505
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5477
5506
|
}
|
|
5478
5507
|
|
|
@@ -6464,21 +6493,28 @@ function createPublisher(opts) {
|
|
|
6464
6493
|
}
|
|
6465
6494
|
|
|
6466
6495
|
// ../client/src/migrate.ts
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
6496
|
+
var CAPABILITIES_TIMEOUT_MS = 1e4;
|
|
6497
|
+
async function fetchCapabilities(endpoint, fetchImpl = fetch, opts = {}) {
|
|
6498
|
+
const bound = new AbortController();
|
|
6499
|
+
const timer = setTimeout(() => bound.abort(new DOMException("the capabilities request timed out", "TimeoutError")), opts.timeoutMs ?? CAPABILITIES_TIMEOUT_MS);
|
|
6500
|
+
const signal = opts.signal ? AbortSignal.any([opts.signal, bound.signal]) : bound.signal;
|
|
6501
|
+
try {
|
|
6502
|
+
const res = await fetchImpl(`${normalize(endpoint)}/v1/capabilities`, { method: "GET", signal });
|
|
6503
|
+
if (!res.ok) {
|
|
6504
|
+
throw new Error(`answered ${res.status}`);
|
|
6505
|
+
}
|
|
6506
|
+
return await res.json();
|
|
6507
|
+
} finally {
|
|
6508
|
+
clearTimeout(timer);
|
|
6471
6509
|
}
|
|
6472
|
-
return await res.json();
|
|
6473
6510
|
}
|
|
6474
6511
|
async function probeEndpoint(endpoint, opts = {}) {
|
|
6475
6512
|
const from = normalize(endpoint);
|
|
6476
|
-
const signal = AbortSignal.timeout(opts.timeoutMs ?? 1e4);
|
|
6477
6513
|
let advertised;
|
|
6478
6514
|
try {
|
|
6479
|
-
advertised = (await fetchCapabilities(from, opts.fetch,
|
|
6515
|
+
advertised = (await fetchCapabilities(from, opts.fetch, opts.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {})).endpoints?.control;
|
|
6480
6516
|
} catch (e) {
|
|
6481
|
-
return { kind: "unreachable", reason:
|
|
6517
|
+
return { kind: "unreachable", reason: e.name === "TimeoutError" ? "timed out" : e.message };
|
|
6482
6518
|
}
|
|
6483
6519
|
if (typeof advertised !== "string" || advertised === "") {
|
|
6484
6520
|
return { kind: "unreachable", reason: "it advertises no control endpoint" };
|
|
@@ -6954,11 +6990,14 @@ var DEFAULT_PORTAL_URL = "https://shadow.minnovate.ai";
|
|
|
6954
6990
|
function portalBase(env, flag) {
|
|
6955
6991
|
return (flag ?? env["GIT_PUBLISHER_PORTAL"] ?? DEFAULT_PORTAL_URL).replace(/\/+$/, "");
|
|
6956
6992
|
}
|
|
6993
|
+
var DISCOVER_TIMEOUT_MS = 1e4;
|
|
6957
6994
|
async function discoverEndpoint(portal, fetchImpl = fetch) {
|
|
6958
6995
|
const url2 = `${portal}/api/v1/config`;
|
|
6996
|
+
const bound = new AbortController();
|
|
6997
|
+
const timer = setTimeout(() => bound.abort(new DOMException("the request timed out", "TimeoutError")), DISCOVER_TIMEOUT_MS);
|
|
6959
6998
|
let body;
|
|
6960
6999
|
try {
|
|
6961
|
-
const response = await fetchImpl(url2);
|
|
7000
|
+
const response = await fetchImpl(url2, { signal: bound.signal });
|
|
6962
7001
|
if (!response.ok) {
|
|
6963
7002
|
throw new PublisherError("UNAVAILABLE", `could not ask ${portal} where to publish (it answered ${response.status})`, { retryable: true });
|
|
6964
7003
|
}
|
|
@@ -6968,6 +7007,8 @@ async function discoverEndpoint(portal, fetchImpl = fetch) {
|
|
|
6968
7007
|
throw e;
|
|
6969
7008
|
}
|
|
6970
7009
|
throw new PublisherError("NETWORK", `could not reach ${portal}: ${e instanceof Error ? e.message : String(e)}`, { retryable: true });
|
|
7010
|
+
} finally {
|
|
7011
|
+
clearTimeout(timer);
|
|
6971
7012
|
}
|
|
6972
7013
|
const endpoint = body?.publishingEndpoint;
|
|
6973
7014
|
if (endpoint === null || endpoint === void 0) {
|