@cogenta/cli 0.4.0 → 0.6.0
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/CHANGELOG.md +3856 -0
- package/dist/admin-assets/assets/index-CxZHGwVA.css +1 -0
- package/dist/admin-assets/assets/index-fYXyHpn8.js +1090 -0
- package/dist/admin-assets/assets/vips-_dmTUXFO.wasm +0 -0
- package/dist/admin-assets/assets/vips-es6-DrQTTS8Q.js +7 -0
- package/dist/admin-assets/branding/logo-cogenta-dark.png +0 -0
- package/dist/admin-assets/branding/logo-cogenta-icon.png +0 -0
- package/dist/admin-assets/branding/logo-cogenta-light.png +0 -0
- package/dist/admin-assets/branding/logo-cogenta-small.png +0 -0
- package/dist/admin-assets/branding/logo-cogenta-transparent.png +0 -0
- package/dist/admin-assets/branding/logo-cogenta.png +0 -0
- package/dist/admin-assets/favicon.png +0 -0
- package/dist/admin-assets/fonts/jetbrains-mono-var.woff2 +0 -0
- package/dist/admin-assets/fonts/space-grotesk-var.woff2 +0 -0
- package/dist/admin-assets/index.html +3 -2
- package/dist/bin.js +6 -0
- package/dist/bin.js.map +1 -1
- package/dist/commands/admin-assets.d.ts +1 -0
- package/dist/commands/admin-assets.d.ts.map +1 -1
- package/dist/commands/admin-assets.js +19 -1
- package/dist/commands/admin-assets.js.map +1 -1
- package/dist/commands/agent-runtime.d.ts +151 -0
- package/dist/commands/agent-runtime.d.ts.map +1 -0
- package/dist/commands/agent-runtime.js +519 -0
- package/dist/commands/agent-runtime.js.map +1 -0
- package/dist/commands/assistant.d.ts +89 -3
- package/dist/commands/assistant.d.ts.map +1 -1
- package/dist/commands/assistant.js +206 -39
- package/dist/commands/assistant.js.map +1 -1
- package/dist/commands/audit-integrity-alert.d.ts +23 -0
- package/dist/commands/audit-integrity-alert.d.ts.map +1 -0
- package/dist/commands/audit-integrity-alert.js +33 -0
- package/dist/commands/audit-integrity-alert.js.map +1 -0
- package/dist/commands/backup.d.ts +78 -0
- package/dist/commands/backup.d.ts.map +1 -0
- package/dist/commands/backup.js +238 -0
- package/dist/commands/backup.js.map +1 -0
- package/dist/commands/channels.d.ts +47 -0
- package/dist/commands/channels.d.ts.map +1 -0
- package/dist/commands/channels.js +277 -0
- package/dist/commands/channels.js.map +1 -0
- package/dist/commands/default-logo.d.ts +27 -0
- package/dist/commands/default-logo.d.ts.map +1 -0
- package/dist/commands/default-logo.js +30 -0
- package/dist/commands/default-logo.js.map +1 -0
- package/dist/commands/doctor.d.ts +5 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +74 -2
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/export.d.ts +22 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +182 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/forms-page.d.ts +75 -0
- package/dist/commands/forms-page.d.ts.map +1 -0
- package/dist/commands/forms-page.js +191 -0
- package/dist/commands/forms-page.js.map +1 -0
- package/dist/commands/import.d.ts.map +1 -1
- package/dist/commands/import.js +13 -1
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/mcp.d.ts +35 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +277 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/roles.d.ts +22 -0
- package/dist/commands/roles.d.ts.map +1 -0
- package/dist/commands/roles.js +79 -0
- package/dist/commands/roles.js.map +1 -0
- package/dist/commands/search-page.d.ts +15 -0
- package/dist/commands/search-page.d.ts.map +1 -1
- package/dist/commands/search-page.js +22 -16
- package/dist/commands/search-page.js.map +1 -1
- package/dist/commands/seo.d.ts +92 -4
- package/dist/commands/seo.d.ts.map +1 -1
- package/dist/commands/seo.js +168 -4
- package/dist/commands/seo.js.map +1 -1
- package/dist/commands/serve.d.ts +439 -7
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +3498 -181
- package/dist/commands/serve.js.map +1 -1
- package/dist/commands/site-plan.d.ts +27 -1
- package/dist/commands/site-plan.d.ts.map +1 -1
- package/dist/commands/site-plan.js +71 -4
- package/dist/commands/site-plan.js.map +1 -1
- package/dist/commands/term-archive-page.d.ts +94 -0
- package/dist/commands/term-archive-page.d.ts.map +1 -0
- package/dist/commands/term-archive-page.js +195 -0
- package/dist/commands/term-archive-page.js.map +1 -0
- package/dist/commands/theme-css.d.ts +22 -7
- package/dist/commands/theme-css.d.ts.map +1 -1
- package/dist/commands/theme-css.js +33 -8
- package/dist/commands/theme-css.js.map +1 -1
- package/dist/commands/theme-registry.d.ts +94 -0
- package/dist/commands/theme-registry.d.ts.map +1 -0
- package/dist/commands/theme-registry.js +130 -0
- package/dist/commands/theme-registry.js.map +1 -0
- package/dist/commands/theme-render.d.ts +330 -9
- package/dist/commands/theme-render.d.ts.map +1 -1
- package/dist/commands/theme-render.js +932 -66
- package/dist/commands/theme-render.js.map +1 -1
- package/dist/commands/theme-wiring.d.ts +107 -0
- package/dist/commands/theme-wiring.d.ts.map +1 -0
- package/dist/commands/theme-wiring.js +295 -0
- package/dist/commands/theme-wiring.js.map +1 -0
- package/dist/commands/tools.d.ts +71 -0
- package/dist/commands/tools.d.ts.map +1 -0
- package/dist/commands/tools.js +330 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/commands/update.d.ts +25 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +193 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +146 -4
- package/dist/index.js.map +1 -1
- package/dist/invite-mail.d.ts +39 -0
- package/dist/invite-mail.d.ts.map +1 -0
- package/dist/invite-mail.js +39 -0
- package/dist/invite-mail.js.map +1 -0
- package/dist/update/apply.d.ts +54 -0
- package/dist/update/apply.d.ts.map +1 -0
- package/dist/update/apply.js +77 -0
- package/dist/update/apply.js.map +1 -0
- package/dist/update/changelog-risk.d.ts +20 -0
- package/dist/update/changelog-risk.d.ts.map +1 -0
- package/dist/update/changelog-risk.js +55 -0
- package/dist/update/changelog-risk.js.map +1 -0
- package/dist/update/check.d.ts +60 -0
- package/dist/update/check.d.ts.map +1 -0
- package/dist/update/check.js +56 -0
- package/dist/update/check.js.map +1 -0
- package/dist/update/contract-risk.d.ts +55 -0
- package/dist/update/contract-risk.d.ts.map +1 -0
- package/dist/update/contract-risk.js +75 -0
- package/dist/update/contract-risk.js.map +1 -0
- package/dist/update/history.d.ts +30 -0
- package/dist/update/history.d.ts.map +1 -0
- package/dist/update/history.js +38 -0
- package/dist/update/history.js.map +1 -0
- package/dist/update/index.d.ts +28 -0
- package/dist/update/index.d.ts.map +1 -0
- package/dist/update/index.js +11 -0
- package/dist/update/index.js.map +1 -0
- package/dist/update/list-restore-points.d.ts +20 -0
- package/dist/update/list-restore-points.d.ts.map +1 -0
- package/dist/update/list-restore-points.js +35 -0
- package/dist/update/list-restore-points.js.map +1 -0
- package/dist/update/npm-registry.d.ts +11 -0
- package/dist/update/npm-registry.d.ts.map +1 -0
- package/dist/update/npm-registry.js +74 -0
- package/dist/update/npm-registry.js.map +1 -0
- package/dist/update/restore-point.d.ts +26 -0
- package/dist/update/restore-point.d.ts.map +1 -0
- package/dist/update/restore-point.js +23 -0
- package/dist/update/restore-point.js.map +1 -0
- package/dist/update/tar.d.ts +27 -0
- package/dist/update/tar.d.ts.map +1 -0
- package/dist/update/tar.js +56 -0
- package/dist/update/tar.js.map +1 -0
- package/dist/update/version-compare.d.ts +17 -0
- package/dist/update/version-compare.d.ts.map +1 -0
- package/dist/update/version-compare.js +42 -0
- package/dist/update/version-compare.js.map +1 -0
- package/dist/version.d.ts +13 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +18 -0
- package/dist/version.js.map +1 -0
- package/package.json +33 -16
- package/dist/admin-assets/assets/index-C9a7O_Xs.css +0 -1
- package/dist/admin-assets/assets/index-DXvMgWvn.js +0 -74
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type ContractRiskAssessment } from './contract-risk.js';
|
|
2
|
+
import { type UpdateBump } from './version-compare.js';
|
|
3
|
+
/**
|
|
4
|
+
* `cogenta update check` / `GET /api/updates/status` (L22 task 9, point 1):
|
|
5
|
+
* "compare la version installée à la dernière publiée sur npm —
|
|
6
|
+
* `@cogenta/core` et `@cogenta/cli` sont déjà la source de vérité de
|
|
7
|
+
* version."
|
|
8
|
+
*
|
|
9
|
+
* "Installed" here means each package's own self-reported version
|
|
10
|
+
* (`getCoreVersion`/`getCliVersion`, both lazily computed with
|
|
11
|
+
* `readOwnPackageVersion` in `@cogenta/core` — see that function's own
|
|
12
|
+
* comment for why this is never a top-level constant) — whichever
|
|
13
|
+
* `@cogenta/core`/`@cogenta/cli` this very process actually
|
|
14
|
+
* loaded, not a guess read from `node_modules` by path (which would answer
|
|
15
|
+
* a different, less certain question on a hoisted or symlinked install).
|
|
16
|
+
* Scoped to exactly these two packages, deliberately, not every `@cogenta/*`
|
|
17
|
+
* dependency a site happens to carry (`@cogenta/theme-canonical`, any
|
|
18
|
+
* installed plugin…) — see this module's caller for why.
|
|
19
|
+
*
|
|
20
|
+
* Point 4's contract-risk check ("avant d'appliquer : notifier le risque")
|
|
21
|
+
* runs here too, not only inside `apply.ts` — an admin (or `cogenta update
|
|
22
|
+
* check`) needs to see the risk *before* deciding to confirm, so `check()`
|
|
23
|
+
* already fetches it for every package that actually has an update
|
|
24
|
+
* available (never for one that does not — no reason to download a tarball
|
|
25
|
+
* nobody would apply). `includeContractRisk: false` skips it for a caller
|
|
26
|
+
* that only wants the fast version comparison.
|
|
27
|
+
*/
|
|
28
|
+
export interface PackageUpdateStatus {
|
|
29
|
+
readonly name: string;
|
|
30
|
+
readonly installed: string;
|
|
31
|
+
/** `null` only when the registry check for this specific package failed — never when it simply reports no update. */
|
|
32
|
+
readonly latest: string | null;
|
|
33
|
+
readonly bump: UpdateBump;
|
|
34
|
+
readonly updateAvailable: boolean;
|
|
35
|
+
/** Set only when `latest` is `null`. */
|
|
36
|
+
readonly checkError: string | undefined;
|
|
37
|
+
/** `null` when there is no update to assess, or `includeContractRisk` was `false`. See `contract-risk.ts` for how honestly limited this signal is. */
|
|
38
|
+
readonly contractRisk: ContractRiskAssessment | null;
|
|
39
|
+
}
|
|
40
|
+
export interface UpdateCheckReport {
|
|
41
|
+
readonly checkedAt: string;
|
|
42
|
+
readonly packages: readonly PackageUpdateStatus[];
|
|
43
|
+
readonly updateAvailable: boolean;
|
|
44
|
+
readonly highestBump: UpdateBump;
|
|
45
|
+
/** `true` when any package's `contractRisk` actually found a warning — the one field a "should I click apply" UI decision boils down to. */
|
|
46
|
+
readonly contractRiskDetected: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface CheckForUpdatesInput {
|
|
49
|
+
/** `{ name, installed }` for each package to check — `check.ts` itself has no opinion on which packages that is; `cogenta update`/`update-router.ts` pass `@cogenta/core`/`@cogenta/cli`. */
|
|
50
|
+
readonly packages: readonly {
|
|
51
|
+
readonly name: string;
|
|
52
|
+
readonly installed: string;
|
|
53
|
+
}[];
|
|
54
|
+
readonly fetchImpl?: typeof fetch;
|
|
55
|
+
readonly now?: () => Date;
|
|
56
|
+
/** Default `true`. `false` skips the tarball fetch/scan entirely — a faster, network-lighter check with no risk signal. */
|
|
57
|
+
readonly includeContractRisk?: boolean;
|
|
58
|
+
}
|
|
59
|
+
export declare function checkForUpdates(input: CheckForUpdatesInput): Promise<UpdateCheckReport>;
|
|
60
|
+
//# sourceMappingURL=check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/update/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAEpF,OAAO,EAAgC,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEpF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,qHAAqH;IACrH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;IACjC,wCAAwC;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,sJAAsJ;IACtJ,QAAQ,CAAC,YAAY,EAAE,sBAAsB,GAAG,IAAI,CAAA;CACrD;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,EAAE,SAAS,mBAAmB,EAAE,CAAA;IACjD,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;IACjC,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAA;IAChC,4IAA4I;IAC5I,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAA;CACvC;AAED,MAAM,WAAW,oBAAoB;IACnC,6LAA6L;IAC7L,QAAQ,CAAC,QAAQ,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACnF,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;IACzB,2HAA2H;IAC3H,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAA;CACvC;AAED,wBAAsB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA0D7F"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { assessContractRisk } from './contract-risk.js';
|
|
2
|
+
import { fetchNpmPackageSummary } from './npm-registry.js';
|
|
3
|
+
import { classifyBump, higherRiskBump } from './version-compare.js';
|
|
4
|
+
export async function checkForUpdates(input) {
|
|
5
|
+
const now = input.now ?? (() => new Date());
|
|
6
|
+
const fetchImpl = input.fetchImpl ?? fetch;
|
|
7
|
+
const includeContractRisk = input.includeContractRisk ?? true;
|
|
8
|
+
const packages = [];
|
|
9
|
+
for (const { name, installed } of input.packages) {
|
|
10
|
+
try {
|
|
11
|
+
const summary = await fetchNpmPackageSummary(name, fetchImpl);
|
|
12
|
+
const bump = classifyBump(installed, summary.latest);
|
|
13
|
+
const updateAvailable = bump !== 'none' && bump !== 'unknown';
|
|
14
|
+
let contractRisk = null;
|
|
15
|
+
const tarballUrl = summary.tarballUrl[summary.latest];
|
|
16
|
+
if (includeContractRisk && updateAvailable && tarballUrl !== undefined) {
|
|
17
|
+
contractRisk = await assessContractRisk({
|
|
18
|
+
packageName: name,
|
|
19
|
+
fromVersion: installed,
|
|
20
|
+
toVersion: summary.latest,
|
|
21
|
+
tarballUrl,
|
|
22
|
+
fetchImpl,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
packages.push({
|
|
26
|
+
name,
|
|
27
|
+
installed,
|
|
28
|
+
latest: summary.latest,
|
|
29
|
+
bump,
|
|
30
|
+
updateAvailable,
|
|
31
|
+
checkError: undefined,
|
|
32
|
+
contractRisk,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
packages.push({
|
|
37
|
+
name,
|
|
38
|
+
installed,
|
|
39
|
+
latest: null,
|
|
40
|
+
bump: 'unknown',
|
|
41
|
+
updateAvailable: false,
|
|
42
|
+
checkError: error instanceof Error ? error.message : String(error),
|
|
43
|
+
contractRisk: null,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const highestBump = packages.reduce((highest, pkg) => higherRiskBump(highest, pkg.bump === 'unknown' ? 'none' : pkg.bump), 'none');
|
|
48
|
+
return {
|
|
49
|
+
checkedAt: now().toISOString(),
|
|
50
|
+
packages,
|
|
51
|
+
updateAvailable: packages.some((pkg) => pkg.updateAvailable),
|
|
52
|
+
highestBump,
|
|
53
|
+
contractRiskDetected: packages.some((pkg) => (pkg.contractRisk?.warnings.length ?? 0) > 0),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/update/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA+B,MAAM,oBAAoB,CAAA;AACpF,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAmB,MAAM,sBAAsB,CAAA;AA2DpF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAA2B;IAC/D,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,GAAS,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;IACjD,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAA;IAC1C,MAAM,mBAAmB,GAAG,KAAK,CAAC,mBAAmB,IAAI,IAAI,CAAA;IAE7D,MAAM,QAAQ,GAA0B,EAAE,CAAA;IAC1C,KAAK,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;YAC7D,MAAM,IAAI,GAAG,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;YACpD,MAAM,eAAe,GAAG,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,SAAS,CAAA;YAE7D,IAAI,YAAY,GAAkC,IAAI,CAAA;YACtD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;YACrD,IAAI,mBAAmB,IAAI,eAAe,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;gBACvE,YAAY,GAAG,MAAM,kBAAkB,CAAC;oBACtC,WAAW,EAAE,IAAI;oBACjB,WAAW,EAAE,SAAS;oBACtB,SAAS,EAAE,OAAO,CAAC,MAAM;oBACzB,UAAU;oBACV,SAAS;iBACV,CAAC,CAAA;YACJ,CAAC;YAED,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI;gBACJ,SAAS;gBACT,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,IAAI;gBACJ,eAAe;gBACf,UAAU,EAAE,SAAS;gBACrB,YAAY;aACb,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI;gBACJ,SAAS;gBACT,MAAM,EAAE,IAAI;gBACZ,IAAI,EAAE,SAAS;gBACf,eAAe,EAAE,KAAK;gBACtB,UAAU,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;gBAClE,YAAY,EAAE,IAAI;aACnB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CACjC,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EACrF,MAAM,CACP,CAAA;IAED,OAAO;QACL,SAAS,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE;QAC9B,QAAQ;QACR,eAAe,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,eAAe,CAAC;QAC5D,WAAW;QACX,oBAAoB,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;KAC3F,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
import { type ContractRiskWarning } from './changelog-risk.js';
|
|
3
|
+
/**
|
|
4
|
+
* "Avant d'appliquer : notifier le risque si la mise à jour touche un
|
|
5
|
+
* contrat A/B/C/D/E" (L22 task 9, point 4) — read honestly, this is the
|
|
6
|
+
* hardest, least reliable part of the whole feature, and this module is
|
|
7
|
+
* built to be honest about that rather than to overclaim.
|
|
8
|
+
*
|
|
9
|
+
* **What is actually detectable, and since when.** A changeset's own prose
|
|
10
|
+
* lives in `.changeset/*.md` only until a release consumes it into the
|
|
11
|
+
* publishing package's `CHANGELOG.md` — after that, the `.changeset` file is
|
|
12
|
+
* deleted and `CHANGELOG.md` is the only surviving copy. Nothing about that
|
|
13
|
+
* text is ever sent to npm's registry API itself (no "breaking: true" field
|
|
14
|
+
* exists on a package version there); the only way to read it from an
|
|
15
|
+
* installed site, with no access to this repository's own git history, is to
|
|
16
|
+
* fetch the target version's own **published tarball** and read
|
|
17
|
+
* `CHANGELOG.md` out of it directly — which is exactly what this module does
|
|
18
|
+
* (`tar.ts`'s minimal reader, over `dist.tarball` from the npm registry,
|
|
19
|
+
* never a third-party CDN).
|
|
20
|
+
*
|
|
21
|
+
* **The one honest catch.** Before this task, `@cogenta/core` and
|
|
22
|
+
* `@cogenta/cli`'s `package.json` `"files"` was `["dist"]` — `CHANGELOG.md`
|
|
23
|
+
* was never actually included in the published npm tarball at all (verified
|
|
24
|
+
* with a real `npm pack` during this task). This task adds it to `"files"`
|
|
25
|
+
* for both packages, but that only takes effect for versions published
|
|
26
|
+
* **from now on**. Every version already on npm when this ships (`0.1.x`
|
|
27
|
+
* through `0.4.0` at the time of writing) has no `CHANGELOG.md` in its
|
|
28
|
+
* tarball, so this reports `available: false` for those, honestly, rather
|
|
29
|
+
* than inventing a "no risk found" that would really mean "could not look."
|
|
30
|
+
*
|
|
31
|
+
* **Even once it can read a CHANGELOG.md, this is a keyword scan of prose,
|
|
32
|
+
* not a structured signal** (`changelog-risk.ts`'s `FROZEN_CONTRACT_PATTERN`)
|
|
33
|
+
* — deliberately broad, so it can miss an unusually-worded note and it can
|
|
34
|
+
* also flag one that turns out to be harmless. It is a strong hint an admin
|
|
35
|
+
* reviews before confirming, never a guarantee, and the UI/CLI say so.
|
|
36
|
+
*/
|
|
37
|
+
export interface ContractRiskAssessment {
|
|
38
|
+
readonly packageName: string;
|
|
39
|
+
/** `false` when no CHANGELOG.md could be read for the target version at all — an honest "could not determine," never treated as "no risk." */
|
|
40
|
+
readonly available: boolean;
|
|
41
|
+
readonly reason: string | undefined;
|
|
42
|
+
/** Every version between the installed one (exclusive) and the target (inclusive) whose changelog section this could actually read. */
|
|
43
|
+
readonly scannedVersions: readonly string[];
|
|
44
|
+
readonly warnings: readonly ContractRiskWarning[];
|
|
45
|
+
}
|
|
46
|
+
export interface AssessContractRiskInput {
|
|
47
|
+
readonly packageName: string;
|
|
48
|
+
readonly fromVersion: string;
|
|
49
|
+
readonly toVersion: string;
|
|
50
|
+
readonly tarballUrl: string;
|
|
51
|
+
readonly fetchImpl?: typeof fetch;
|
|
52
|
+
}
|
|
53
|
+
export declare function assessContractRisk(input: AssessContractRiskInput): Promise<ContractRiskAssessment>;
|
|
54
|
+
export declare function contractRiskUnknownError(packageName: string, reason: string): CogentaError;
|
|
55
|
+
//# sourceMappingURL=contract-risk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-risk.d.ts","sourceRoot":"","sources":["../../src/update/contract-risk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAE5C,OAAO,EACL,KAAK,mBAAmB,EAGzB,MAAM,qBAAqB,CAAA;AAG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,8IAA8I;IAC9I,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,uIAAuI;IACvI,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3C,QAAQ,CAAC,QAAQ,EAAE,SAAS,mBAAmB,EAAE,CAAA;CAClD;AAQD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CAClC;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,sBAAsB,CAAC,CAmDjC;AAWD,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAO1F"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
import { compareVersions, parseVersion } from '@cogenta/plugins';
|
|
3
|
+
import { sectionsMentioningContractRisk, splitChangelogSections, } from './changelog-risk.js';
|
|
4
|
+
import { findPackageFile, readTarGz } from './tar.js';
|
|
5
|
+
const MAX_TARBALL_BYTES = 20 * 1024 * 1024;
|
|
6
|
+
function unavailable(packageName, reason) {
|
|
7
|
+
return { packageName, available: false, reason, scannedVersions: [], warnings: [] };
|
|
8
|
+
}
|
|
9
|
+
export async function assessContractRisk(input) {
|
|
10
|
+
const { packageName, fromVersion, toVersion, tarballUrl } = input;
|
|
11
|
+
const fetchImpl = input.fetchImpl ?? fetch;
|
|
12
|
+
let response;
|
|
13
|
+
try {
|
|
14
|
+
response = await fetchImpl(tarballUrl, { signal: AbortSignal.timeout(15_000) });
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
return unavailable(packageName, `could not download the package tarball: ${String(error)}`);
|
|
18
|
+
}
|
|
19
|
+
if (!response.ok) {
|
|
20
|
+
return unavailable(packageName, `the package tarball responded with HTTP ${response.status}`);
|
|
21
|
+
}
|
|
22
|
+
const contentLength = response.headers.get('content-length');
|
|
23
|
+
if (contentLength !== null && Number(contentLength) > MAX_TARBALL_BYTES) {
|
|
24
|
+
return unavailable(packageName, 'the package tarball is larger than this check accepts');
|
|
25
|
+
}
|
|
26
|
+
let bytes;
|
|
27
|
+
try {
|
|
28
|
+
bytes = await response.arrayBuffer();
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
return unavailable(packageName, `could not read the package tarball: ${String(error)}`);
|
|
32
|
+
}
|
|
33
|
+
if (bytes.byteLength > MAX_TARBALL_BYTES) {
|
|
34
|
+
return unavailable(packageName, 'the package tarball is larger than this check accepts');
|
|
35
|
+
}
|
|
36
|
+
let changelog;
|
|
37
|
+
try {
|
|
38
|
+
const entries = readTarGz(Buffer.from(bytes));
|
|
39
|
+
changelog = findPackageFile(entries, 'CHANGELOG.md');
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
return unavailable(packageName, `could not read the package tarball: ${String(error)}`);
|
|
43
|
+
}
|
|
44
|
+
if (changelog === null) {
|
|
45
|
+
return unavailable(packageName, 'this version carries no CHANGELOG.md in its published tarball');
|
|
46
|
+
}
|
|
47
|
+
const sections = splitChangelogSections(changelog.toString('utf8'));
|
|
48
|
+
const inRange = sections.filter((section) => isInRange(section.version, fromVersion, toVersion));
|
|
49
|
+
const warnings = sectionsMentioningContractRisk(inRange);
|
|
50
|
+
return {
|
|
51
|
+
packageName,
|
|
52
|
+
available: true,
|
|
53
|
+
reason: undefined,
|
|
54
|
+
scannedVersions: inRange.map((section) => section.version),
|
|
55
|
+
warnings,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** `fromVersion < version <= toVersion`, via `@cogenta/plugins`'s own comparator — unparseable versions (a pre-release tag this parser does not understand) are excluded rather than guessed at. */
|
|
59
|
+
function isInRange(version, fromVersion, toVersion) {
|
|
60
|
+
const v = parseVersion(version);
|
|
61
|
+
const from = parseVersion(fromVersion);
|
|
62
|
+
const to = parseVersion(toVersion);
|
|
63
|
+
if (v === null || from === null || to === null)
|
|
64
|
+
return false;
|
|
65
|
+
return compareVersions(v, from) > 0 && compareVersions(v, to) <= 0;
|
|
66
|
+
}
|
|
67
|
+
export function contractRiskUnknownError(packageName, reason) {
|
|
68
|
+
return new CogentaError({
|
|
69
|
+
code: 'UPDATE_CHECK_FAILED',
|
|
70
|
+
message: `Could not determine whether updating "${packageName}" touches a frozen contract: ${reason}`,
|
|
71
|
+
hint: 'Review the target version manually before applying, or retry once network access to registry.npmjs.org is available.',
|
|
72
|
+
details: { packageName, reason },
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=contract-risk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-risk.js","sourceRoot":"","sources":["../../src/update/contract-risk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { AuditEntry, AuditLog } from '@cogenta/auth';
|
|
2
|
+
/**
|
|
3
|
+
* "Historique des mises à jour et des points de restauration, consultable
|
|
4
|
+
* depuis le même écran" (L22 task 9, point 5).
|
|
5
|
+
*
|
|
6
|
+
* Never a new table: an update check/apply is one more kind of entry in the
|
|
7
|
+
* audit log every other administrative action already writes to — same
|
|
8
|
+
* pattern `scheduled_task.run` uses in `serve.ts`. The *restore point* half
|
|
9
|
+
* of the history is not duplicated here either — it is exactly `cogenta
|
|
10
|
+
* backup list`'s own answer (`@cogenta/export`'s `readBackupManifest` over
|
|
11
|
+
* the `.cogenta/backups` directory), since `restore-point.ts` writes restore
|
|
12
|
+
* points through the very same `createSiteBackup` function backups already
|
|
13
|
+
* use, just tagged with an `update-` filename prefix. The router/CLI layer
|
|
14
|
+
* that serves "history" to the admin screen combines both reads; this module
|
|
15
|
+
* only owns the audit half.
|
|
16
|
+
*/
|
|
17
|
+
export declare const UPDATE_CHECKED_ACTION = "system.update.checked";
|
|
18
|
+
export declare const UPDATE_APPLIED_ACTION = "system.update.applied";
|
|
19
|
+
export declare const UPDATE_APPLY_FAILED_ACTION = "system.update.apply_failed";
|
|
20
|
+
export interface UpdateHistoryEntryInput {
|
|
21
|
+
readonly actorId: string | null;
|
|
22
|
+
readonly actorRoles: readonly string[];
|
|
23
|
+
readonly action: typeof UPDATE_CHECKED_ACTION | typeof UPDATE_APPLIED_ACTION | typeof UPDATE_APPLY_FAILED_ACTION;
|
|
24
|
+
/** Never a secret, never a full npm install log — package names, versions, bump, restore point path, whether contract risk was flagged. */
|
|
25
|
+
readonly diff: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
export declare function recordUpdateHistory(auditLog: AuditLog, entry: UpdateHistoryEntryInput): Promise<AuditEntry>;
|
|
28
|
+
/** Every update-related audit entry, most recent first — the update-system slice of `AuditLog.list()`. */
|
|
29
|
+
export declare function listUpdateHistory(auditLog: AuditLog, limit?: number): Promise<readonly AuditEntry[]>;
|
|
30
|
+
//# sourceMappingURL=history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/update/history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAEzD;;;;;;;;;;;;;;GAcG;AAEH,eAAO,MAAM,qBAAqB,0BAA0B,CAAA;AAC5D,eAAO,MAAM,qBAAqB,0BAA0B,CAAA;AAC5D,eAAO,MAAM,0BAA0B,+BAA+B,CAAA;AAEtE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;IACtC,QAAQ,CAAC,MAAM,EACX,OAAO,qBAAqB,GAC5B,OAAO,qBAAqB,GAC5B,OAAO,0BAA0B,CAAA;IACrC,2IAA2I;IAC3I,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACvC;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,UAAU,CAAC,CAOrB;AAED,0GAA0G;AAC1G,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,QAAQ,EAClB,KAAK,SAAK,GACT,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAShC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Historique des mises à jour et des points de restauration, consultable
|
|
3
|
+
* depuis le même écran" (L22 task 9, point 5).
|
|
4
|
+
*
|
|
5
|
+
* Never a new table: an update check/apply is one more kind of entry in the
|
|
6
|
+
* audit log every other administrative action already writes to — same
|
|
7
|
+
* pattern `scheduled_task.run` uses in `serve.ts`. The *restore point* half
|
|
8
|
+
* of the history is not duplicated here either — it is exactly `cogenta
|
|
9
|
+
* backup list`'s own answer (`@cogenta/export`'s `readBackupManifest` over
|
|
10
|
+
* the `.cogenta/backups` directory), since `restore-point.ts` writes restore
|
|
11
|
+
* points through the very same `createSiteBackup` function backups already
|
|
12
|
+
* use, just tagged with an `update-` filename prefix. The router/CLI layer
|
|
13
|
+
* that serves "history" to the admin screen combines both reads; this module
|
|
14
|
+
* only owns the audit half.
|
|
15
|
+
*/
|
|
16
|
+
export const UPDATE_CHECKED_ACTION = 'system.update.checked';
|
|
17
|
+
export const UPDATE_APPLIED_ACTION = 'system.update.applied';
|
|
18
|
+
export const UPDATE_APPLY_FAILED_ACTION = 'system.update.apply_failed';
|
|
19
|
+
export function recordUpdateHistory(auditLog, entry) {
|
|
20
|
+
return auditLog.record({
|
|
21
|
+
actorId: entry.actorId,
|
|
22
|
+
actorRoles: entry.actorRoles,
|
|
23
|
+
action: entry.action,
|
|
24
|
+
diff: entry.diff,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/** Every update-related audit entry, most recent first — the update-system slice of `AuditLog.list()`. */
|
|
28
|
+
export async function listUpdateHistory(auditLog, limit = 50) {
|
|
29
|
+
const [checked, applied, failed] = await Promise.all([
|
|
30
|
+
auditLog.list({ action: UPDATE_CHECKED_ACTION, limit }),
|
|
31
|
+
auditLog.list({ action: UPDATE_APPLIED_ACTION, limit }),
|
|
32
|
+
auditLog.list({ action: UPDATE_APPLY_FAILED_ACTION, limit }),
|
|
33
|
+
]);
|
|
34
|
+
return [...checked, ...applied, ...failed]
|
|
35
|
+
.sort((a, b) => (a.at < b.at ? 1 : a.at > b.at ? -1 : 0))
|
|
36
|
+
.slice(0, limit);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/update/history.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAA;AAC5D,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAA;AAC5D,MAAM,CAAC,MAAM,0BAA0B,GAAG,4BAA4B,CAAA;AAatE,MAAM,UAAU,mBAAmB,CACjC,QAAkB,EAClB,KAA8B;IAE9B,OAAO,QAAQ,CAAC,MAAM,CAAC;QACrB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC,CAAA;AACJ,CAAC;AAED,0GAA0G;AAC1G,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAkB,EAClB,KAAK,GAAG,EAAE;IAEV,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACnD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,KAAK,EAAE,CAAC;QACvD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,KAAK,EAAE,CAAC;QACvD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,0BAA0B,EAAE,KAAK,EAAE,CAAC;KAC7D,CAAC,CAAA;IACF,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC;SACvC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACxD,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;AACpB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The update system (L22 task 9) — checking npm for a newer
|
|
3
|
+
* `@cogenta/core`/`@cogenta/cli`, applying one with a mandatory restore
|
|
4
|
+
* point first, and the honest, best-effort contract-risk warning that goes
|
|
5
|
+
* with it. See each module's own doc comment for the reasoning; this file
|
|
6
|
+
* is only the barrel.
|
|
7
|
+
*/
|
|
8
|
+
export type { ApplyUpdateInput, ApplyUpdateResult, RunPackageInstall, RunPackageInstallInput, RunPackageInstallResult, } from './apply.js';
|
|
9
|
+
export { applyUpdate, runNpmInstall } from './apply.js';
|
|
10
|
+
export type { ChangelogSection, ContractRiskWarning } from './changelog-risk.js';
|
|
11
|
+
export { sectionsMentioningContractRisk, splitChangelogSections } from './changelog-risk.js';
|
|
12
|
+
export type { CheckForUpdatesInput, PackageUpdateStatus, UpdateCheckReport } from './check.js';
|
|
13
|
+
export { checkForUpdates } from './check.js';
|
|
14
|
+
export type { AssessContractRiskInput, ContractRiskAssessment } from './contract-risk.js';
|
|
15
|
+
export { assessContractRisk, contractRiskUnknownError } from './contract-risk.js';
|
|
16
|
+
export type { UpdateHistoryEntryInput } from './history.js';
|
|
17
|
+
export { listUpdateHistory, recordUpdateHistory, UPDATE_APPLIED_ACTION, UPDATE_APPLY_FAILED_ACTION, UPDATE_CHECKED_ACTION, } from './history.js';
|
|
18
|
+
export type { RestorePointSummary } from './list-restore-points.js';
|
|
19
|
+
export { listRestorePoints } from './list-restore-points.js';
|
|
20
|
+
export type { NpmPackageSummary } from './npm-registry.js';
|
|
21
|
+
export { fetchNpmPackageSummary } from './npm-registry.js';
|
|
22
|
+
export type { CreateUpdateRestorePointOptions, UpdateRestorePoint } from './restore-point.js';
|
|
23
|
+
export { createUpdateRestorePoint } from './restore-point.js';
|
|
24
|
+
export type { TarEntry } from './tar.js';
|
|
25
|
+
export { findPackageFile, readTarEntries, readTarGz } from './tar.js';
|
|
26
|
+
export type { AutoUpdatePolicy, UpdateBump } from './version-compare.js';
|
|
27
|
+
export { AUTO_UPDATE_POLICIES, classifyBump, higherRiskBump, policyAllows, } from './version-compare.js';
|
|
28
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/update/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AACvD,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAChF,OAAO,EAAE,8BAA8B,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAC5F,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9F,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,YAAY,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AACzF,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AACjF,YAAY,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AAC3D,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAC1D,YAAY,EAAE,+BAA+B,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC7F,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AAC7D,YAAY,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACrE,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACxE,OAAO,EACL,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,YAAY,GACb,MAAM,sBAAsB,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { applyUpdate, runNpmInstall } from './apply.js';
|
|
2
|
+
export { sectionsMentioningContractRisk, splitChangelogSections } from './changelog-risk.js';
|
|
3
|
+
export { checkForUpdates } from './check.js';
|
|
4
|
+
export { assessContractRisk, contractRiskUnknownError } from './contract-risk.js';
|
|
5
|
+
export { listUpdateHistory, recordUpdateHistory, UPDATE_APPLIED_ACTION, UPDATE_APPLY_FAILED_ACTION, UPDATE_CHECKED_ACTION, } from './history.js';
|
|
6
|
+
export { listRestorePoints } from './list-restore-points.js';
|
|
7
|
+
export { fetchNpmPackageSummary } from './npm-registry.js';
|
|
8
|
+
export { createUpdateRestorePoint } from './restore-point.js';
|
|
9
|
+
export { findPackageFile, readTarEntries, readTarGz } from './tar.js';
|
|
10
|
+
export { AUTO_UPDATE_POLICIES, classifyBump, higherRiskBump, policyAllows, } from './version-compare.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/update/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAEvD,OAAO,EAAE,8BAA8B,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAE5F,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE5C,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AAEjF,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAE5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAE1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AAE7D,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAErE,OAAO,EACL,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,YAAY,GACb,MAAM,sBAAsB,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The restore-point half of "historique des mises à jour et des points de
|
|
3
|
+
* restauration" (L22 task 9, point 5) — exactly `cogenta backup list`'s own
|
|
4
|
+
* directory scan (`.cogenta/backups`), reused rather than re-implemented,
|
|
5
|
+
* with one addition: `triggeredByUpdate` is read straight off the filename
|
|
6
|
+
* prefix `restore-point.ts` writes (`update-…zip` vs. `backup-…zip`), so the
|
|
7
|
+
* admin's history view can show *which* restore points exist because an
|
|
8
|
+
* update took them automatically, without a second manifest field.
|
|
9
|
+
*/
|
|
10
|
+
export interface RestorePointSummary {
|
|
11
|
+
readonly path: string;
|
|
12
|
+
readonly createdAt: string;
|
|
13
|
+
readonly rows: number;
|
|
14
|
+
readonly tables: number;
|
|
15
|
+
readonly checksum: string;
|
|
16
|
+
readonly encrypted: boolean;
|
|
17
|
+
readonly triggeredByUpdate: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function listRestorePoints(dir: string): Promise<readonly RestorePointSummary[]>;
|
|
20
|
+
//# sourceMappingURL=list-restore-points.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-restore-points.d.ts","sourceRoot":"","sources":["../../src/update/list-restore-points.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAA;CACpC;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,mBAAmB,EAAE,CAAC,CA6B5F"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { readdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { readBackupManifest } from '@cogenta/export';
|
|
4
|
+
export async function listRestorePoints(dir) {
|
|
5
|
+
let files;
|
|
6
|
+
try {
|
|
7
|
+
files = (await readdir(dir)).filter((name) => name.endsWith('.zip'));
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
// No backup directory yet — nothing has ever been backed up.
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
const summaries = [];
|
|
14
|
+
for (const file of files) {
|
|
15
|
+
try {
|
|
16
|
+
const manifest = await readBackupManifest(join(dir, file));
|
|
17
|
+
summaries.push({
|
|
18
|
+
path: join(dir, file),
|
|
19
|
+
createdAt: manifest.createdAt,
|
|
20
|
+
rows: manifest.tables.reduce((sum, table) => sum + table.rows, 0),
|
|
21
|
+
tables: manifest.tables.length,
|
|
22
|
+
checksum: manifest.checksum,
|
|
23
|
+
encrypted: manifest.encrypted,
|
|
24
|
+
triggeredByUpdate: file.startsWith('update-'),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// A manifest that fails to read (corrupted, mid-write) is skipped
|
|
29
|
+
// rather than crashing the whole history view — `cogenta backup list`
|
|
30
|
+
// makes the same choice for the same reason.
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return summaries.sort((a, b) => (a.createdAt < b.createdAt ? 1 : -1));
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=list-restore-points.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-restore-points.js","sourceRoot":"","sources":["../../src/update/list-restore-points.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAsBpD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,GAAW;IACjD,IAAI,KAAwB,CAAA;IAC5B,IAAI,CAAC;QACH,KAAK,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;QAC7D,OAAO,EAAE,CAAA;IACX,CAAC;IAED,MAAM,SAAS,GAA0B,EAAE,CAAA;IAC3C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAA;YAC1D,SAAS,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC;gBACrB,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;gBACjE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM;gBAC9B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,iBAAiB,EAAE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;aAC9C,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,kEAAkE;YAClE,sEAAsE;YACtE,6CAA6C;QAC/C,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACvE,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface NpmPackageSummary {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
/** `dist-tags.latest` — the version `npm install <name>` would resolve to today. */
|
|
4
|
+
readonly latest: string;
|
|
5
|
+
/** Every version the registry lists, in whatever order it returned them (usually publish order). */
|
|
6
|
+
readonly versions: readonly string[];
|
|
7
|
+
/** `dist.tarball` per version — only present for a version this response actually described. */
|
|
8
|
+
readonly tarballUrl: Readonly<Record<string, string>>;
|
|
9
|
+
}
|
|
10
|
+
export declare function fetchNpmPackageSummary(packageName: string, fetchImpl?: typeof fetch): Promise<NpmPackageSummary>;
|
|
11
|
+
//# sourceMappingURL=npm-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm-registry.d.ts","sourceRoot":"","sources":["../../src/update/npm-registry.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,oGAAoG;IACpG,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,gGAAgG;IAChG,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACtD;AAoBD,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,OAAO,KAAa,GAC9B,OAAO,CAAC,iBAAiB,CAAC,CA0C5B"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
/**
|
|
3
|
+
* The one piece of real network access `cogenta update` needs: "what is the
|
|
4
|
+
* newest published version of this package, and where is its tarball" — the
|
|
5
|
+
* npm registry's own abbreviated packument
|
|
6
|
+
* (`Accept: application/vnd.npm.install-v1+json`), which is a small fraction
|
|
7
|
+
* of the full packument (no per-version readme, no full dependency graph)
|
|
8
|
+
* but still carries `dist-tags.latest` and, per version, `dist.tarball` —
|
|
9
|
+
* exactly what `contract-risk.ts` needs to fetch one tarball and read its
|
|
10
|
+
* `CHANGELOG.md`.
|
|
11
|
+
*
|
|
12
|
+
* `registry.npmjs.org` only — never a CDN mirror (unpkg, jsdelivr…), which
|
|
13
|
+
* would be a second external host this optional feature depends on for no
|
|
14
|
+
* real gain. Every caller degrades to "could not check" on failure (R1's
|
|
15
|
+
* spirit: checking for an update is optional infrastructure, never something
|
|
16
|
+
* the rest of the CMS needs to run).
|
|
17
|
+
*/
|
|
18
|
+
const REGISTRY_BASE = 'https://registry.npmjs.org';
|
|
19
|
+
const FETCH_TIMEOUT_MS = 10_000;
|
|
20
|
+
function registryUrl(packageName) {
|
|
21
|
+
// A scoped name (`@cogenta/core`) needs the whole name percent-encoded as
|
|
22
|
+
// one segment — `encodeURIComponent` turns `/` into `%2F`, which is what
|
|
23
|
+
// the registry expects for a scoped package's single-segment route.
|
|
24
|
+
return `${REGISTRY_BASE}/${encodeURIComponent(packageName)}`;
|
|
25
|
+
}
|
|
26
|
+
function checkFailed(packageName, reason, cause) {
|
|
27
|
+
const npmPage = `https://www.npmjs.com/package/${packageName}`;
|
|
28
|
+
return new CogentaError({
|
|
29
|
+
code: 'UPDATE_CHECK_FAILED',
|
|
30
|
+
message: `Could not check npm for the latest version of "${packageName}": ${reason}`,
|
|
31
|
+
hint: `This needs outbound network access to registry.npmjs.org. Everything else in this admin works without it (R1) — try again later, or check manually at ${npmPage}.`,
|
|
32
|
+
cause,
|
|
33
|
+
details: { packageName },
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
export async function fetchNpmPackageSummary(packageName, fetchImpl = fetch) {
|
|
37
|
+
let response;
|
|
38
|
+
try {
|
|
39
|
+
response = await fetchImpl(registryUrl(packageName), {
|
|
40
|
+
headers: { accept: 'application/vnd.npm.install-v1+json' },
|
|
41
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
throw checkFailed(packageName, 'the request failed', error);
|
|
46
|
+
}
|
|
47
|
+
if (response.status === 404) {
|
|
48
|
+
throw checkFailed(packageName, 'npm has no package by this name');
|
|
49
|
+
}
|
|
50
|
+
if (!response.ok) {
|
|
51
|
+
throw checkFailed(packageName, `npm responded with HTTP ${response.status}`);
|
|
52
|
+
}
|
|
53
|
+
let body;
|
|
54
|
+
try {
|
|
55
|
+
body = await response.json();
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
throw checkFailed(packageName, 'the response was not valid JSON', error);
|
|
59
|
+
}
|
|
60
|
+
const record = body;
|
|
61
|
+
const latest = record['dist-tags']?.latest;
|
|
62
|
+
if (typeof latest !== 'string' || latest === '') {
|
|
63
|
+
throw checkFailed(packageName, 'the response carried no "dist-tags.latest"');
|
|
64
|
+
}
|
|
65
|
+
const versions = record.versions ?? {};
|
|
66
|
+
const tarballUrl = {};
|
|
67
|
+
for (const [version, meta] of Object.entries(versions)) {
|
|
68
|
+
const tarball = meta.dist?.tarball;
|
|
69
|
+
if (typeof tarball === 'string' && tarball !== '')
|
|
70
|
+
tarballUrl[version] = tarball;
|
|
71
|
+
}
|
|
72
|
+
return { name: packageName, latest, versions: Object.keys(versions), tarballUrl };
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=npm-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm-registry.js","sourceRoot":"","sources":["../../src/update/npm-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAE5C;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,aAAa,GAAG,4BAA4B,CAAA;AAClD,MAAM,gBAAgB,GAAG,MAAM,CAAA;AAY/B,SAAS,WAAW,CAAC,WAAmB;IACtC,0EAA0E;IAC1E,yEAAyE;IACzE,oEAAoE;IACpE,OAAO,GAAG,aAAa,IAAI,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAA;AAC9D,CAAC;AAED,SAAS,WAAW,CAAC,WAAmB,EAAE,MAAc,EAAE,KAAe;IACvE,MAAM,OAAO,GAAG,iCAAiC,WAAW,EAAE,CAAA;IAC9D,OAAO,IAAI,YAAY,CAAC;QACtB,IAAI,EAAE,qBAAqB;QAC3B,OAAO,EAAE,kDAAkD,WAAW,MAAM,MAAM,EAAE;QACpF,IAAI,EAAE,yJAAyJ,OAAO,GAAG;QACzK,KAAK;QACL,OAAO,EAAE,EAAE,WAAW,EAAE;KACzB,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,WAAmB,EACnB,SAAS,GAAiB,KAAK;IAE/B,IAAI,QAAkB,CAAA;IACtB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE;YACnD,OAAO,EAAE,EAAE,MAAM,EAAE,qCAAqC,EAAE;YAC1D,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,gBAAgB,CAAC;SAC9C,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,WAAW,CAAC,WAAW,EAAE,oBAAoB,EAAE,KAAK,CAAC,CAAA;IAC7D,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,WAAW,CAAC,WAAW,EAAE,iCAAiC,CAAC,CAAA;IACnE,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,WAAW,CAAC,WAAW,EAAE,2BAA2B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IAC9E,CAAC;IAED,IAAI,IAAa,CAAA;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,WAAW,CAAC,WAAW,EAAE,iCAAiC,EAAE,KAAK,CAAC,CAAA;IAC1E,CAAC;IAED,MAAM,MAAM,GAAG,IAGd,CAAA;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC1C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QAChD,MAAM,WAAW,CAAC,WAAW,EAAE,4CAA4C,CAAC,CAAA;IAC9E,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAA;IACtC,MAAM,UAAU,GAA2B,EAAE,CAAA;IAC7C,KAAK,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,CAAA;QAClC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,EAAE;YAAE,UAAU,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA;IAClF,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAA;AACnF,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type Logger } from '@cogenta/core';
|
|
2
|
+
/**
|
|
3
|
+
* "Un point de restauration obligatoire avant toute mise à jour" (L22 task
|
|
4
|
+
* 9, point 2) — this is the *entire* implementation: one call into
|
|
5
|
+
* `createSiteBackup`, the exact function `cogenta backup create` itself
|
|
6
|
+
* calls, tagged with the `update-` filename prefix so it shows up
|
|
7
|
+
* identifiably in `cogenta backup list` and in the admin's own history view
|
|
8
|
+
* without a second backup format or a second directory. Never a smaller,
|
|
9
|
+
* update-specific backup — a restore point has to be able to put the whole
|
|
10
|
+
* site back, and `createSiteBackup` already is that.
|
|
11
|
+
*/
|
|
12
|
+
export interface CreateUpdateRestorePointOptions {
|
|
13
|
+
readonly cwd?: string;
|
|
14
|
+
readonly env?: Record<string, string | undefined>;
|
|
15
|
+
readonly logger?: Logger;
|
|
16
|
+
readonly dir?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface UpdateRestorePoint {
|
|
19
|
+
readonly path: string;
|
|
20
|
+
readonly createdAt: string;
|
|
21
|
+
readonly tableCount: number;
|
|
22
|
+
readonly rowCount: number;
|
|
23
|
+
readonly checksum: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function createUpdateRestorePoint(options: CreateUpdateRestorePointOptions): Promise<UpdateRestorePoint>;
|
|
26
|
+
//# sourceMappingURL=restore-point.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restore-point.d.ts","sourceRoot":"","sources":["../../src/update/restore-point.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,eAAe,CAAA;AAGzD;;;;;;;;;GASG;AAEH,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACjD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,kBAAkB,CAAC,CAkB7B"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
import { createSiteBackup } from '../commands/backup.js';
|
|
3
|
+
export async function createUpdateRestorePoint(options) {
|
|
4
|
+
try {
|
|
5
|
+
const { path, manifest } = await createSiteBackup({ ...options, filenamePrefix: 'update-' });
|
|
6
|
+
return {
|
|
7
|
+
path,
|
|
8
|
+
createdAt: manifest.createdAt,
|
|
9
|
+
tableCount: manifest.tables.length,
|
|
10
|
+
rowCount: manifest.tables.reduce((sum, table) => sum + table.rows, 0),
|
|
11
|
+
checksum: manifest.checksum,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
throw new CogentaError({
|
|
16
|
+
code: 'UPDATE_RESTORE_POINT_FAILED',
|
|
17
|
+
message: 'Could not create a restore point before the update — nothing was changed.',
|
|
18
|
+
hint: 'This update was refused rather than applied without a safety net. Check the underlying error, free up disk space if that is the cause, and try again.',
|
|
19
|
+
cause: error,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=restore-point.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restore-point.js","sourceRoot":"","sources":["../../src/update/restore-point.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAe,MAAM,eAAe,CAAA;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AA4BxD,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,OAAwC;IAExC,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,gBAAgB,CAAC,EAAE,GAAG,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC,CAAA;QAC5F,OAAO;YACL,IAAI;YACJ,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM;YAClC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACrE,QAAQ,EAAE,QAAQ,CAAC,QAAQ;SAC5B,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,YAAY,CAAC;YACrB,IAAI,EAAE,6BAA6B;YACnC,OAAO,EAAE,2EAA2E;YACpF,IAAI,EAAE,uJAAuJ;YAC7J,KAAK,EAAE,KAAK;SACb,CAAC,CAAA;IACJ,CAAC;AACH,CAAC"}
|