@lesliechan721/aw 0.1.0-beta.7 → 0.1.0-beta.8
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/authoring/scripts/init-plugin.mjs +4 -33
- package/dist/authoring/scripts/init-plugin.mjs.map +1 -1
- package/dist/authoring/scripts/lib/plugin-version-check.mjs +1 -1
- package/dist/authoring/scripts/plugin-status.mjs +8 -11
- package/dist/authoring/scripts/plugin-status.mjs.map +1 -1
- package/dist/authoring/scripts/remove-plugin.mjs +1 -0
- package/dist/authoring/scripts/remove-plugin.mjs.map +1 -1
- package/dist/authoring/scripts/validate-plugin.mjs +104 -54
- package/dist/authoring/scripts/validate-plugin.mjs.map +1 -1
- package/dist/scripts/codex-eval-app-server.d.ts +2 -0
- package/dist/scripts/codex-eval-app-server.js +107 -1
- package/dist/scripts/codex-eval-app-server.js.map +1 -1
- package/dist/scripts/eval-plugin-skills.js +5 -2
- package/dist/scripts/eval-plugin-skills.js.map +1 -1
- package/dist/scripts/plugin-eval-contract.d.ts +5 -1
- package/dist/scripts/plugin-eval-contract.js +54 -4
- package/dist/scripts/plugin-eval-contract.js.map +1 -1
- package/dist/scripts/plugin-staging.d.ts +6 -7
- package/dist/scripts/plugin-staging.js +11 -23
- package/dist/scripts/plugin-staging.js.map +1 -1
- package/dist/scripts/test-plugin-scripts.js +2 -33
- package/dist/scripts/test-plugin-scripts.js.map +1 -1
- package/dist/src/adapters/helpers.js +2 -2
- package/dist/src/adapters/helpers.js.map +1 -1
- package/dist/src/authoring/workspace-commands.d.ts +17 -2
- package/dist/src/authoring/workspace-commands.js +21 -4
- package/dist/src/authoring/workspace-commands.js.map +1 -1
- package/dist/src/commands/aw-capabilities.d.ts +78 -0
- package/dist/src/commands/aw-capabilities.js +259 -0
- package/dist/src/commands/aw-capabilities.js.map +1 -0
- package/dist/src/commands/catalog-context.d.ts +52 -0
- package/dist/src/commands/catalog-context.js +156 -0
- package/dist/src/commands/catalog-context.js.map +1 -0
- package/dist/src/commands/catalog-dev-source.d.ts +112 -0
- package/dist/src/commands/catalog-dev-source.js +481 -0
- package/dist/src/commands/catalog-dev-source.js.map +1 -0
- package/dist/src/commands/catalog-generation.d.ts +26 -0
- package/dist/src/commands/catalog-generation.js +14 -0
- package/dist/src/commands/catalog-generation.js.map +1 -0
- package/dist/src/commands/catalog-publication-inspection.d.ts +1 -1
- package/dist/src/commands/catalog-publication-inspection.js +4 -5
- package/dist/src/commands/catalog-publication-inspection.js.map +1 -1
- package/dist/src/commands/catalog-publication-target.d.ts +17 -0
- package/dist/src/commands/catalog-publication-target.js +60 -0
- package/dist/src/commands/catalog-publication-target.js.map +1 -0
- package/dist/src/commands/catalog-publish.d.ts +8 -1
- package/dist/src/commands/catalog-publish.js +25 -2
- package/dist/src/commands/catalog-publish.js.map +1 -1
- package/dist/src/commands/catalog-source.d.ts +23 -1
- package/dist/src/commands/catalog-source.js +126 -40
- package/dist/src/commands/catalog-source.js.map +1 -1
- package/dist/src/commands/catalog-status.d.ts +18 -2
- package/dist/src/commands/catalog-status.js +122 -18
- package/dist/src/commands/catalog-status.js.map +1 -1
- package/dist/src/commands/init.js +1 -1
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/offline-cleanup-evidence.d.ts +23 -0
- package/dist/src/commands/offline-cleanup-evidence.js +38 -0
- package/dist/src/commands/offline-cleanup-evidence.js.map +1 -0
- package/dist/src/commands/options.d.ts +1 -0
- package/dist/src/commands/options.js +1 -0
- package/dist/src/commands/options.js.map +1 -1
- package/dist/src/commands/plugin-capabilities.js +1 -1
- package/dist/src/commands/plugin-capabilities.js.map +1 -1
- package/dist/src/commands/rebuild-command.d.ts +19 -7
- package/dist/src/commands/rebuild-command.js +415 -205
- package/dist/src/commands/rebuild-command.js.map +1 -1
- package/dist/src/commands/rebuild-integration.d.ts +10 -3
- package/dist/src/commands/rebuild-integration.js +71 -76
- package/dist/src/commands/rebuild-integration.js.map +1 -1
- package/dist/src/commands/rebuild-operations.d.ts +0 -8
- package/dist/src/commands/rebuild-operations.js +17 -115
- package/dist/src/commands/rebuild-operations.js.map +1 -1
- package/dist/src/commands/runtime.js +21 -34
- package/dist/src/commands/runtime.js.map +1 -1
- package/dist/src/commands/{status-v4.d.ts → status-v5.d.ts} +67 -21
- package/dist/src/commands/{status-v4.js → status-v5.js} +260 -30
- package/dist/src/commands/status-v5.js.map +1 -0
- package/dist/src/commands/wizard.d.ts +2 -2
- package/dist/src/commands/wizard.js +2 -2
- package/dist/src/commands/wizard.js.map +1 -1
- package/dist/src/commands/write-commands.js +73 -17
- package/dist/src/commands/write-commands.js.map +1 -1
- package/dist/src/constants.d.ts +6 -1
- package/dist/src/constants.js +6 -1
- package/dist/src/constants.js.map +1 -1
- package/dist/src/generators/local-plugin.js +57 -3
- package/dist/src/generators/local-plugin.js.map +1 -1
- package/dist/src/index.d.ts +4 -1
- package/dist/src/index.js +562 -85
- package/dist/src/index.js.map +1 -1
- package/dist/src/output/model.d.ts +1 -34
- package/dist/src/output/model.js +1 -144
- package/dist/src/output/model.js.map +1 -1
- package/dist/src/output/rebuild-progress.js +0 -3
- package/dist/src/output/rebuild-progress.js.map +1 -1
- package/dist/src/portable/commands.d.ts +4 -0
- package/dist/src/portable/commands.js +61 -4
- package/dist/src/portable/commands.js.map +1 -1
- package/dist/src/portable/materializer.d.ts +3 -0
- package/dist/src/portable/materializer.js +61 -10
- package/dist/src/portable/materializer.js.map +1 -1
- package/dist/src/tui/catalog-generation.d.ts +56 -0
- package/dist/src/tui/catalog-generation.js +244 -0
- package/dist/src/tui/catalog-generation.js.map +1 -0
- package/dist/src/tui/console-app-v4.d.ts +1 -1
- package/dist/src/tui/console-app-v4.js +446 -126
- package/dist/src/tui/console-app-v4.js.map +1 -1
- package/dist/src/tui/controller-runtime.d.ts +8 -2
- package/dist/src/tui/controller-runtime.js +606 -92
- package/dist/src/tui/controller-runtime.js.map +1 -1
- package/dist/src/tui/controller.d.ts +71 -6
- package/dist/src/tui/controller.js +377 -83
- package/dist/src/tui/controller.js.map +1 -1
- package/dist/src/tui/index.d.ts +1 -0
- package/dist/src/tui/index.js +1 -0
- package/dist/src/tui/index.js.map +1 -1
- package/dist/src/tui/input-display.d.ts +8 -0
- package/dist/src/tui/input-display.js +36 -0
- package/dist/src/tui/input-display.js.map +1 -0
- package/dist/src/tui/model.d.ts +27 -7
- package/dist/src/tui/model.js +273 -65
- package/dist/src/tui/model.js.map +1 -1
- package/dist/src/tui/router.d.ts +26 -0
- package/dist/src/tui/router.js.map +1 -1
- package/dist/src/tui/source-ref-presets.d.ts +3 -0
- package/dist/src/tui/source-ref-presets.js +11 -0
- package/dist/src/tui/source-ref-presets.js.map +1 -0
- package/dist/src/tui/views.js +31 -3
- package/dist/src/tui/views.js.map +1 -1
- package/dist/src/types.d.ts +90 -6
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/agent-version.d.ts +3 -0
- package/dist/src/utils/agent-version.js +13 -5
- package/dist/src/utils/agent-version.js.map +1 -1
- package/dist/src/utils/aw-home-mutation-lock.d.ts +1 -0
- package/dist/src/utils/aw-home-mutation-lock.js +32 -4
- package/dist/src/utils/aw-home-mutation-lock.js.map +1 -1
- package/dist/src/utils/bundle-integrity.d.ts +0 -1
- package/dist/src/utils/bundle-integrity.js +0 -25
- package/dist/src/utils/bundle-integrity.js.map +1 -1
- package/dist/src/utils/bundle-layout.js +8 -6
- package/dist/src/utils/bundle-layout.js.map +1 -1
- package/dist/src/utils/catalog-digests.js +13 -2
- package/dist/src/utils/catalog-digests.js.map +1 -1
- package/dist/src/utils/catalog-generation-error.d.ts +12 -0
- package/dist/src/utils/catalog-generation-error.js +16 -0
- package/dist/src/utils/catalog-generation-error.js.map +1 -0
- package/dist/src/utils/catalog-generation-resolver.d.ts +13 -0
- package/dist/src/utils/catalog-generation-resolver.js +129 -0
- package/dist/src/utils/catalog-generation-resolver.js.map +1 -0
- package/dist/src/utils/catalog-generation-service.d.ts +52 -0
- package/dist/src/utils/catalog-generation-service.js +620 -0
- package/dist/src/utils/catalog-generation-service.js.map +1 -0
- package/dist/src/utils/catalog-generation-state.d.ts +13 -0
- package/dist/src/utils/catalog-generation-state.js +201 -0
- package/dist/src/utils/catalog-generation-state.js.map +1 -0
- package/dist/src/utils/catalog-generation-store.d.ts +44 -0
- package/dist/src/utils/catalog-generation-store.js +387 -0
- package/dist/src/utils/catalog-generation-store.js.map +1 -0
- package/dist/src/utils/catalog-manifest-v5.d.ts +5 -0
- package/dist/src/utils/{catalog-manifest-v4.js → catalog-manifest-v5.js} +39 -35
- package/dist/src/utils/{catalog-manifest-v4.js.map → catalog-manifest-v5.js.map} +1 -1
- package/dist/src/utils/catalog-operation-context.d.ts +28 -0
- package/dist/src/utils/catalog-operation-context.js +242 -0
- package/dist/src/utils/catalog-operation-context.js.map +1 -0
- package/dist/src/utils/catalog-public-error.d.ts +7 -3
- package/dist/src/utils/catalog-public-error.js +20 -4
- package/dist/src/utils/catalog-public-error.js.map +1 -1
- package/dist/src/utils/catalog-snapshot.d.ts +5 -3
- package/dist/src/utils/catalog-snapshot.js +11 -3
- package/dist/src/utils/catalog-snapshot.js.map +1 -1
- package/dist/src/utils/catalog-source-cache.d.ts +1 -1
- package/dist/src/utils/catalog-source-cache.js +37 -12
- package/dist/src/utils/catalog-source-cache.js.map +1 -1
- package/dist/src/utils/catalog-source-identity.d.ts +1 -0
- package/dist/src/utils/catalog-source-identity.js +21 -2
- package/dist/src/utils/catalog-source-identity.js.map +1 -1
- package/dist/src/utils/catalog-sources.d.ts +1 -0
- package/dist/src/utils/catalog-sources.js +30 -11
- package/dist/src/utils/catalog-sources.js.map +1 -1
- package/dist/src/utils/codex-config.js +4 -4
- package/dist/src/utils/codex-config.js.map +1 -1
- package/dist/src/utils/codex-manager.d.ts +33 -0
- package/dist/src/utils/codex-manager.js +656 -0
- package/dist/src/utils/codex-manager.js.map +1 -0
- package/dist/src/utils/codex-skill-staging.d.ts +2 -0
- package/dist/src/utils/codex-skill-staging.js.map +1 -1
- package/dist/src/utils/dynamic-skill-tree.d.ts +4 -0
- package/dist/src/utils/dynamic-skill-tree.js +35 -5
- package/dist/src/utils/dynamic-skill-tree.js.map +1 -1
- package/dist/src/utils/git-catalog-provider.js +10 -25
- package/dist/src/utils/git-catalog-provider.js.map +1 -1
- package/dist/src/utils/lifecycle-active-store.d.ts +0 -28
- package/dist/src/utils/lifecycle-active-store.js +35 -247
- package/dist/src/utils/lifecycle-active-store.js.map +1 -1
- package/dist/src/utils/multi-source-catalog.d.ts +3 -0
- package/dist/src/utils/multi-source-catalog.js +120 -10
- package/dist/src/utils/multi-source-catalog.js.map +1 -1
- package/dist/src/utils/native-cli.d.ts +15 -6
- package/dist/src/utils/native-cli.js +31 -39
- package/dist/src/utils/native-cli.js.map +1 -1
- package/dist/src/utils/orphan-marketplace-cleanup.js +0 -3
- package/dist/src/utils/orphan-marketplace-cleanup.js.map +1 -1
- package/dist/src/utils/ownership.d.ts +10 -1
- package/dist/src/utils/ownership.js +52 -24
- package/dist/src/utils/ownership.js.map +1 -1
- package/dist/src/utils/path-catalog-provider.js +12 -8
- package/dist/src/utils/path-catalog-provider.js.map +1 -1
- package/dist/src/utils/plugin-config-write.js +18 -35
- package/dist/src/utils/plugin-config-write.js.map +1 -1
- package/dist/src/utils/plugin-config.d.ts +1 -12
- package/dist/src/utils/plugin-config.js +107 -226
- package/dist/src/utils/plugin-config.js.map +1 -1
- package/dist/src/utils/plugin-scripts.d.ts +1 -1
- package/dist/src/utils/plugin-scripts.js +1 -1
- package/dist/src/utils/plugin-scripts.js.map +1 -1
- package/dist/src/utils/state-paths.js +7 -2
- package/dist/src/utils/state-paths.js.map +1 -1
- package/dist/src/utils/target-eligibility.d.ts +7 -2
- package/dist/src/utils/target-eligibility.js +6 -3
- package/dist/src/utils/target-eligibility.js.map +1 -1
- package/package.json +4 -3
- package/dist/authoring/scripts/check-plugin-versions.d.mts +0 -2
- package/dist/authoring/scripts/check-plugin-versions.mjs +0 -5
- package/dist/authoring/scripts/check-plugin-versions.mjs.map +0 -1
- package/dist/src/commands/status-v4.js.map +0 -1
- package/dist/src/commands/status.d.ts +0 -93
- package/dist/src/commands/status.js +0 -442
- package/dist/src/commands/status.js.map +0 -1
- package/dist/src/utils/active-marketplace-runtime-lock.d.ts +0 -12
- package/dist/src/utils/active-marketplace-runtime-lock.js +0 -133
- package/dist/src/utils/active-marketplace-runtime-lock.js.map +0 -1
- package/dist/src/utils/catalog-manifest-v3.d.ts +0 -2
- package/dist/src/utils/catalog-manifest-v3.js +0 -3
- package/dist/src/utils/catalog-manifest-v3.js.map +0 -1
- package/dist/src/utils/catalog-manifest-v4.d.ts +0 -5
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CatalogGenerationStateFileV1 } from '../types.js';
|
|
2
|
+
export declare function validateCatalogGenerationState(value: unknown): CatalogGenerationStateFileV1;
|
|
3
|
+
export declare function createEmptyCatalogGenerationState(): CatalogGenerationStateFileV1;
|
|
4
|
+
export declare function resolveCatalogGenerationStatePath(env?: NodeJS.ProcessEnv): string;
|
|
5
|
+
export declare function readCatalogGenerationState(env?: NodeJS.ProcessEnv): Promise<CatalogGenerationStateFileV1>;
|
|
6
|
+
export declare function withCatalogGenerationStateTransaction<T>(options: {
|
|
7
|
+
env?: NodeJS.ProcessEnv;
|
|
8
|
+
beforeReplace?: (next: CatalogGenerationStateFileV1) => Promise<void> | void;
|
|
9
|
+
action: (current: CatalogGenerationStateFileV1) => Promise<{
|
|
10
|
+
state: CatalogGenerationStateFileV1;
|
|
11
|
+
result: T;
|
|
12
|
+
}>;
|
|
13
|
+
}): Promise<T>;
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import { CATALOG_GENERATIONS_FILE, CATALOG_GENERATIONS_SCHEMA_VERSION, } from '../constants.js';
|
|
4
|
+
import { CatalogGenerationError } from './catalog-generation-error.js';
|
|
5
|
+
import { createCatalogGenerationKey } from './catalog-generation-store.js';
|
|
6
|
+
import { CATALOG_SOURCE_ID_PATTERN } from './catalog-sources.js';
|
|
7
|
+
import { parseStrictSemVer } from './manifest.js';
|
|
8
|
+
import { atomicReplaceConfigFile } from './plugin-config.js';
|
|
9
|
+
import { resolveAwHome } from './state-paths.js';
|
|
10
|
+
const SHA256_DIGEST_PATTERN = /^sha256:[0-9a-f]{64}$/u;
|
|
11
|
+
const RESOLVED_COMMIT_PATTERN = /^(?:[0-9a-f]{40}|[0-9a-f]{64}|path:sha256:[0-9a-f]{64})$/u;
|
|
12
|
+
function stateError(message, cause) {
|
|
13
|
+
return new CatalogGenerationError({
|
|
14
|
+
code: 'catalogGenerationStateInvalid',
|
|
15
|
+
message: `${message} Repair or remove catalog-generations.json, then refresh configured sources. This state never authorizes plugin deletion.`,
|
|
16
|
+
cause,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function isRecord(value) {
|
|
20
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
21
|
+
}
|
|
22
|
+
function assertAllowedKeys(value, fieldName, allowed) {
|
|
23
|
+
const unexpected = Object.keys(value).find((key) => !allowed.includes(key));
|
|
24
|
+
if (unexpected)
|
|
25
|
+
throw stateError(`Invalid ${fieldName}: unknown field "${unexpected}".`);
|
|
26
|
+
}
|
|
27
|
+
function parseDate(value, fieldName) {
|
|
28
|
+
if (typeof value !== 'string' || Number.isNaN(Date.parse(value))) {
|
|
29
|
+
throw stateError(`Invalid ${fieldName}: expected an ISO date.`);
|
|
30
|
+
}
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
function parsePointer(value, fieldName, candidate) {
|
|
34
|
+
if (!isRecord(value))
|
|
35
|
+
throw stateError(`Invalid ${fieldName}: expected an object.`);
|
|
36
|
+
const baseKeys = [
|
|
37
|
+
'sourceConfigFingerprint', 'catalogVersion', 'channel', 'requestedRef', 'resolvedCommit', 'manifestDigest',
|
|
38
|
+
'snapshotDigest', 'generationKey', 'activatedAt',
|
|
39
|
+
];
|
|
40
|
+
assertAllowedKeys(value, fieldName, candidate ? [...baseKeys, 'candidateKind', 'downloadedAt'] : baseKeys);
|
|
41
|
+
if (typeof value.sourceConfigFingerprint !== 'string'
|
|
42
|
+
|| !SHA256_DIGEST_PATTERN.test(value.sourceConfigFingerprint)
|
|
43
|
+
|| typeof value.catalogVersion !== 'string'
|
|
44
|
+
|| (value.channel !== 'latest' && value.channel !== 'beta')
|
|
45
|
+
|| typeof value.requestedRef !== 'string'
|
|
46
|
+
|| value.requestedRef.length === 0
|
|
47
|
+
|| typeof value.resolvedCommit !== 'string'
|
|
48
|
+
|| !RESOLVED_COMMIT_PATTERN.test(value.resolvedCommit)
|
|
49
|
+
|| typeof value.manifestDigest !== 'string'
|
|
50
|
+
|| !SHA256_DIGEST_PATTERN.test(value.manifestDigest)
|
|
51
|
+
|| typeof value.snapshotDigest !== 'string'
|
|
52
|
+
|| !SHA256_DIGEST_PATTERN.test(value.snapshotDigest)
|
|
53
|
+
|| typeof value.generationKey !== 'string'
|
|
54
|
+
|| !/^[0-9a-f]{64}\/[0-9a-f]{64}$/u.test(value.generationKey))
|
|
55
|
+
throw stateError(`Invalid ${fieldName}.`);
|
|
56
|
+
try {
|
|
57
|
+
parseStrictSemVer(value.catalogVersion, `${fieldName}.catalogVersion`);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
throw stateError(`Invalid ${fieldName}.catalogVersion.`, error);
|
|
61
|
+
}
|
|
62
|
+
const pointer = {
|
|
63
|
+
sourceConfigFingerprint: value.sourceConfigFingerprint,
|
|
64
|
+
catalogVersion: value.catalogVersion,
|
|
65
|
+
channel: value.channel,
|
|
66
|
+
requestedRef: value.requestedRef,
|
|
67
|
+
resolvedCommit: value.resolvedCommit,
|
|
68
|
+
manifestDigest: value.manifestDigest,
|
|
69
|
+
snapshotDigest: value.snapshotDigest,
|
|
70
|
+
generationKey: value.generationKey,
|
|
71
|
+
...(value.activatedAt === undefined
|
|
72
|
+
? {}
|
|
73
|
+
: { activatedAt: parseDate(value.activatedAt, `${fieldName}.activatedAt`) }),
|
|
74
|
+
};
|
|
75
|
+
if (!candidate)
|
|
76
|
+
return pointer;
|
|
77
|
+
if ((value.candidateKind !== 'upgrade' && value.candidateKind !== 'refChange')
|
|
78
|
+
|| value.activatedAt !== undefined)
|
|
79
|
+
throw stateError(`Invalid ${fieldName} candidate fields.`);
|
|
80
|
+
return {
|
|
81
|
+
...pointer,
|
|
82
|
+
candidateKind: value.candidateKind,
|
|
83
|
+
downloadedAt: parseDate(value.downloadedAt, `${fieldName}.downloadedAt`),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function parseLastCheck(value, fieldName) {
|
|
87
|
+
if (!isRecord(value))
|
|
88
|
+
throw stateError(`Invalid ${fieldName}: expected an object.`);
|
|
89
|
+
assertAllowedKeys(value, fieldName, ['checkedAt', 'state', 'remoteCommit', 'errorCode']);
|
|
90
|
+
const states = new Set([
|
|
91
|
+
'upToDate', 'activeReady', 'candidateReady', 'failed',
|
|
92
|
+
'immutableViolation', 'channelRollback',
|
|
93
|
+
]);
|
|
94
|
+
if (typeof value.state !== 'string'
|
|
95
|
+
|| !states.has(value.state)
|
|
96
|
+
|| (value.remoteCommit !== undefined
|
|
97
|
+
&& (typeof value.remoteCommit !== 'string'
|
|
98
|
+
|| !RESOLVED_COMMIT_PATTERN.test(value.remoteCommit)))
|
|
99
|
+
|| (value.errorCode !== undefined
|
|
100
|
+
&& (typeof value.errorCode !== 'string' || value.errorCode.length === 0)))
|
|
101
|
+
throw stateError(`Invalid ${fieldName}.`);
|
|
102
|
+
return {
|
|
103
|
+
checkedAt: parseDate(value.checkedAt, `${fieldName}.checkedAt`),
|
|
104
|
+
state: value.state,
|
|
105
|
+
...(value.remoteCommit ? { remoteCommit: value.remoteCommit } : {}),
|
|
106
|
+
...(value.errorCode ? { errorCode: value.errorCode } : {}),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function parseSourceState(value, fieldName) {
|
|
110
|
+
if (!isRecord(value))
|
|
111
|
+
throw stateError(`Invalid ${fieldName}: expected an object.`);
|
|
112
|
+
assertAllowedKeys(value, fieldName, [
|
|
113
|
+
'logicalIdentity', 'refreshPolicy', 'active', 'candidate', 'lastCheck',
|
|
114
|
+
]);
|
|
115
|
+
if (typeof value.logicalIdentity !== 'string'
|
|
116
|
+
|| value.logicalIdentity.trim() === ''
|
|
117
|
+
|| (value.refreshPolicy !== 'startup' && value.refreshPolicy !== 'manual'))
|
|
118
|
+
throw stateError(`Invalid ${fieldName} identity or refresh policy.`);
|
|
119
|
+
const active = value.active === undefined
|
|
120
|
+
? undefined
|
|
121
|
+
: parsePointer(value.active, `${fieldName}.active`, false);
|
|
122
|
+
const candidate = value.candidate === undefined
|
|
123
|
+
? undefined
|
|
124
|
+
: parsePointer(value.candidate, `${fieldName}.candidate`, true);
|
|
125
|
+
for (const [pointerName, pointer] of [['active', active], ['candidate', candidate]]) {
|
|
126
|
+
if (pointer && pointer.generationKey !== createCatalogGenerationKey(value.logicalIdentity, pointer.snapshotDigest))
|
|
127
|
+
throw stateError(`Invalid ${fieldName}.${pointerName} generation identity.`);
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
logicalIdentity: value.logicalIdentity,
|
|
131
|
+
refreshPolicy: value.refreshPolicy,
|
|
132
|
+
...(active ? { active } : {}),
|
|
133
|
+
...(candidate ? { candidate } : {}),
|
|
134
|
+
...(value.lastCheck === undefined
|
|
135
|
+
? {}
|
|
136
|
+
: { lastCheck: parseLastCheck(value.lastCheck, `${fieldName}.lastCheck`) }),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
export function validateCatalogGenerationState(value) {
|
|
140
|
+
if (!isRecord(value))
|
|
141
|
+
throw stateError('Invalid Catalog generation state: expected an object.');
|
|
142
|
+
assertAllowedKeys(value, 'Catalog generation state', ['schemaVersion', 'sources']);
|
|
143
|
+
if (value.schemaVersion !== CATALOG_GENERATIONS_SCHEMA_VERSION || !isRecord(value.sources)) {
|
|
144
|
+
throw stateError('Invalid Catalog generation state schema.');
|
|
145
|
+
}
|
|
146
|
+
const sources = {};
|
|
147
|
+
for (const sourceId of Object.keys(value.sources).sort()) {
|
|
148
|
+
if (!CATALOG_SOURCE_ID_PATTERN.test(sourceId)) {
|
|
149
|
+
throw stateError(`Invalid Catalog generation source ID "${sourceId}".`);
|
|
150
|
+
}
|
|
151
|
+
sources[sourceId] = parseSourceState(value.sources[sourceId], `Catalog generation state.sources.${sourceId}`);
|
|
152
|
+
}
|
|
153
|
+
return { schemaVersion: 1, sources };
|
|
154
|
+
}
|
|
155
|
+
export function createEmptyCatalogGenerationState() {
|
|
156
|
+
return { schemaVersion: 1, sources: {} };
|
|
157
|
+
}
|
|
158
|
+
export function resolveCatalogGenerationStatePath(env = process.env) {
|
|
159
|
+
return path.join(resolveAwHome(env), CATALOG_GENERATIONS_FILE);
|
|
160
|
+
}
|
|
161
|
+
async function readStateAt(filePath) {
|
|
162
|
+
const stat = await fs.lstat(filePath).catch((error) => {
|
|
163
|
+
if (error.code === 'ENOENT')
|
|
164
|
+
return null;
|
|
165
|
+
throw error;
|
|
166
|
+
});
|
|
167
|
+
if (!stat)
|
|
168
|
+
return createEmptyCatalogGenerationState();
|
|
169
|
+
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
170
|
+
throw stateError('Catalog generation state path is not a regular file.');
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
return validateCatalogGenerationState(await fs.readJson(filePath));
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
if (error instanceof CatalogGenerationError)
|
|
177
|
+
throw error;
|
|
178
|
+
throw stateError('Catalog generation state is unreadable.', error);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
export async function readCatalogGenerationState(env = process.env) {
|
|
182
|
+
return readStateAt(resolveCatalogGenerationStatePath(env));
|
|
183
|
+
}
|
|
184
|
+
export async function withCatalogGenerationStateTransaction(options) {
|
|
185
|
+
const env = options.env ?? process.env;
|
|
186
|
+
const awHome = resolveAwHome(env);
|
|
187
|
+
const filePath = resolveCatalogGenerationStatePath(env);
|
|
188
|
+
const current = await readStateAt(filePath);
|
|
189
|
+
const output = await options.action(current);
|
|
190
|
+
const next = validateCatalogGenerationState(output.state);
|
|
191
|
+
if (JSON.stringify(next) !== JSON.stringify(current)) {
|
|
192
|
+
await options.beforeReplace?.(next);
|
|
193
|
+
await atomicReplaceConfigFile({
|
|
194
|
+
filePath,
|
|
195
|
+
allowedRoot: awHome,
|
|
196
|
+
content: `${JSON.stringify(next, null, 2)}\n`,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return output.result;
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=catalog-generation-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-generation-state.js","sourceRoot":"","sources":["../../../src/utils/catalog-generation-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { CatalogGenerationMetadataV1, CatalogSourceResolution } from '../types.js';
|
|
2
|
+
export interface CatalogGenerationLocation {
|
|
3
|
+
awHomeDir: string;
|
|
4
|
+
storeRootDir: string;
|
|
5
|
+
logicalIdentityDirectory: string;
|
|
6
|
+
generationDir: string;
|
|
7
|
+
metadataPath: string;
|
|
8
|
+
snapshotRoot: string;
|
|
9
|
+
generationKey: string;
|
|
10
|
+
}
|
|
11
|
+
export interface PreparedCatalogGeneration {
|
|
12
|
+
stagingDir: string;
|
|
13
|
+
location: CatalogGenerationLocation;
|
|
14
|
+
metadata: CatalogGenerationMetadataV1;
|
|
15
|
+
}
|
|
16
|
+
export interface PublishedCatalogGeneration {
|
|
17
|
+
generationDir: string;
|
|
18
|
+
snapshotRoot: string;
|
|
19
|
+
metadata: CatalogGenerationMetadataV1;
|
|
20
|
+
}
|
|
21
|
+
export declare function createCatalogGenerationKey(logicalIdentity: string, snapshotDigest: string): string;
|
|
22
|
+
export declare function resolveCatalogGenerationLocation(options: {
|
|
23
|
+
logicalIdentity: string;
|
|
24
|
+
snapshotDigest: string;
|
|
25
|
+
env?: NodeJS.ProcessEnv;
|
|
26
|
+
}): CatalogGenerationLocation;
|
|
27
|
+
export declare function prepareCatalogGeneration(options: {
|
|
28
|
+
resolution: CatalogSourceResolution;
|
|
29
|
+
cliVersion: string;
|
|
30
|
+
env?: NodeJS.ProcessEnv;
|
|
31
|
+
now?: () => Date;
|
|
32
|
+
signal?: AbortSignal;
|
|
33
|
+
}): Promise<PreparedCatalogGeneration>;
|
|
34
|
+
export declare function publishPreparedCatalogGeneration(prepared: PreparedCatalogGeneration): Promise<PublishedCatalogGeneration>;
|
|
35
|
+
export declare function discardPreparedCatalogGeneration(prepared: PreparedCatalogGeneration): Promise<void>;
|
|
36
|
+
export declare function readCatalogGeneration(options: {
|
|
37
|
+
logicalIdentity: string;
|
|
38
|
+
snapshotDigest: string;
|
|
39
|
+
env?: NodeJS.ProcessEnv;
|
|
40
|
+
}): Promise<PublishedCatalogGeneration>;
|
|
41
|
+
export declare function listCatalogGenerationsForIdentity(options: {
|
|
42
|
+
logicalIdentity: string;
|
|
43
|
+
env?: NodeJS.ProcessEnv;
|
|
44
|
+
}): Promise<PublishedCatalogGeneration[]>;
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import { CATALOG_GENERATION_METADATA_FILE, CATALOG_GENERATIONS_DIRECTORY, } from '../constants.js';
|
|
5
|
+
import { CatalogGenerationError } from './catalog-generation-error.js';
|
|
6
|
+
import { validateCatalogSnapshotTransport } from './catalog-snapshot.js';
|
|
7
|
+
import { normalizeAwCapabilities, parseStrictSemVer } from './manifest.js';
|
|
8
|
+
import { canonicalizePathThroughExistingAncestorSync, ensureRegularDirectoryPath, resolveAwHome, } from './state-paths.js';
|
|
9
|
+
const SHA256_DIGEST_PATTERN = /^sha256:([0-9a-f]{64})$/u;
|
|
10
|
+
const HEX_DIGEST_PATTERN = /^[0-9a-f]{64}$/u;
|
|
11
|
+
function sha256Hex(value) {
|
|
12
|
+
return crypto.createHash('sha256').update(value).digest('hex');
|
|
13
|
+
}
|
|
14
|
+
function digestHex(value, fieldName) {
|
|
15
|
+
const match = SHA256_DIGEST_PATTERN.exec(value);
|
|
16
|
+
if (!match) {
|
|
17
|
+
throw new CatalogGenerationError({
|
|
18
|
+
code: 'catalogGenerationMetadataInvalid',
|
|
19
|
+
message: `Invalid ${fieldName}: expected a SHA-256 digest. Remove the damaged generation and refresh the source.`,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return match[1];
|
|
23
|
+
}
|
|
24
|
+
export function createCatalogGenerationKey(logicalIdentity, snapshotDigest) {
|
|
25
|
+
if (typeof logicalIdentity !== 'string' || logicalIdentity.trim() === '') {
|
|
26
|
+
throw new CatalogGenerationError({
|
|
27
|
+
code: 'catalogGenerationMetadataInvalid',
|
|
28
|
+
message: 'Invalid Catalog logical identity. Rebuild or republish the Catalog snapshot, then refresh the source.',
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return `${sha256Hex(logicalIdentity)}/${digestHex(snapshotDigest, 'Catalog snapshot digest')}`;
|
|
32
|
+
}
|
|
33
|
+
export function resolveCatalogGenerationLocation(options) {
|
|
34
|
+
const awHomeDir = canonicalizePathThroughExistingAncestorSync(resolveAwHome(options.env ?? process.env));
|
|
35
|
+
const storeRootDir = path.join(awHomeDir, CATALOG_GENERATIONS_DIRECTORY);
|
|
36
|
+
const generationKey = createCatalogGenerationKey(options.logicalIdentity, options.snapshotDigest);
|
|
37
|
+
const [logicalIdentityHex, snapshotDigestHex] = generationKey.split('/');
|
|
38
|
+
const logicalIdentityDirectory = path.join(storeRootDir, logicalIdentityHex);
|
|
39
|
+
const generationDir = path.join(logicalIdentityDirectory, snapshotDigestHex);
|
|
40
|
+
return {
|
|
41
|
+
awHomeDir,
|
|
42
|
+
storeRootDir,
|
|
43
|
+
logicalIdentityDirectory,
|
|
44
|
+
generationDir,
|
|
45
|
+
metadataPath: path.join(generationDir, CATALOG_GENERATION_METADATA_FILE),
|
|
46
|
+
snapshotRoot: path.join(generationDir, 'snapshot'),
|
|
47
|
+
generationKey,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function isStrictObject(value, keys) {
|
|
51
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
52
|
+
return false;
|
|
53
|
+
const actual = Object.keys(value).sort();
|
|
54
|
+
const expected = [...keys].sort();
|
|
55
|
+
return actual.length === expected.length
|
|
56
|
+
&& actual.every((key, index) => key === expected[index]);
|
|
57
|
+
}
|
|
58
|
+
function parseGenerationMetadata(value) {
|
|
59
|
+
if (!isStrictObject(value, [
|
|
60
|
+
'schemaVersion',
|
|
61
|
+
'logicalIdentity',
|
|
62
|
+
'catalogVersion',
|
|
63
|
+
'channel',
|
|
64
|
+
'manifestDigest',
|
|
65
|
+
'snapshotDigest',
|
|
66
|
+
'generationKey',
|
|
67
|
+
'requiredAwCapabilities',
|
|
68
|
+
'publishedAt',
|
|
69
|
+
])) {
|
|
70
|
+
throw new CatalogGenerationError({
|
|
71
|
+
code: 'catalogGenerationMetadataInvalid',
|
|
72
|
+
message: 'Invalid Catalog generation metadata. Remove the damaged generation and refresh the source.',
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (value.schemaVersion !== 1
|
|
76
|
+
|| typeof value.logicalIdentity !== 'string'
|
|
77
|
+
|| value.logicalIdentity.trim() === ''
|
|
78
|
+
|| typeof value.catalogVersion !== 'string'
|
|
79
|
+
|| !Array.isArray(value.requiredAwCapabilities)
|
|
80
|
+
|| value.requiredAwCapabilities.some((capability) => typeof capability !== 'string')
|
|
81
|
+
|| (value.channel !== 'latest' && value.channel !== 'beta')
|
|
82
|
+
|| typeof value.manifestDigest !== 'string'
|
|
83
|
+
|| !SHA256_DIGEST_PATTERN.test(value.manifestDigest)
|
|
84
|
+
|| typeof value.snapshotDigest !== 'string'
|
|
85
|
+
|| !SHA256_DIGEST_PATTERN.test(value.snapshotDigest)
|
|
86
|
+
|| typeof value.generationKey !== 'string'
|
|
87
|
+
|| !/^[0-9a-f]{64}\/[0-9a-f]{64}$/u.test(value.generationKey)
|
|
88
|
+
|| typeof value.publishedAt !== 'string'
|
|
89
|
+
|| Number.isNaN(Date.parse(value.publishedAt))) {
|
|
90
|
+
throw new CatalogGenerationError({
|
|
91
|
+
code: 'catalogGenerationMetadataInvalid',
|
|
92
|
+
message: 'Invalid Catalog generation metadata. Remove the damaged generation and refresh the source.',
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
parseStrictSemVer(value.catalogVersion, 'Catalog generation catalogVersion');
|
|
97
|
+
if (JSON.stringify(normalizeAwCapabilities(value.requiredAwCapabilities))
|
|
98
|
+
!== JSON.stringify(value.requiredAwCapabilities)) {
|
|
99
|
+
throw new Error('Catalog generation required capabilities are not normalized.');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
throw new CatalogGenerationError({
|
|
104
|
+
code: 'catalogGenerationMetadataInvalid',
|
|
105
|
+
message: 'Invalid Catalog generation version metadata. Remove the damaged generation and refresh the source.',
|
|
106
|
+
cause: error,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (value.generationKey !== createCatalogGenerationKey(value.logicalIdentity, value.snapshotDigest)) {
|
|
110
|
+
throw new CatalogGenerationError({
|
|
111
|
+
code: 'catalogGenerationMetadataInvalid',
|
|
112
|
+
message: 'Catalog generation metadata does not match its content identity. Remove the damaged generation and refresh the source.',
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
117
|
+
async function readCatalogLogicalIdentity(snapshotRoot) {
|
|
118
|
+
const markerPath = path.join(snapshotRoot, '.aw-generated.json');
|
|
119
|
+
const stat = await fs.lstat(markerPath).catch((error) => {
|
|
120
|
+
if (error.code === 'ENOENT')
|
|
121
|
+
return null;
|
|
122
|
+
throw error;
|
|
123
|
+
});
|
|
124
|
+
if (!stat?.isFile() || stat.isSymbolicLink()) {
|
|
125
|
+
throw new CatalogGenerationError({
|
|
126
|
+
code: 'catalogGenerationMetadataInvalid',
|
|
127
|
+
message: 'Catalog snapshot has no valid generated marker. Rebuild or republish the Catalog, then refresh the source.',
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
const marker = await fs.readJson(markerPath);
|
|
131
|
+
if (!isStrictObject(marker, ['schemaVersion', 'kind', 'workspaceIdentity', 'sourceIdentity'])
|
|
132
|
+
|| marker.schemaVersion !== 1
|
|
133
|
+
|| marker.kind !== 'catalog'
|
|
134
|
+
|| typeof marker.workspaceIdentity !== 'string'
|
|
135
|
+
|| marker.workspaceIdentity.trim() === ''
|
|
136
|
+
|| typeof marker.sourceIdentity !== 'string'
|
|
137
|
+
|| !SHA256_DIGEST_PATTERN.test(marker.sourceIdentity)) {
|
|
138
|
+
throw new CatalogGenerationError({
|
|
139
|
+
code: 'catalogGenerationMetadataInvalid',
|
|
140
|
+
message: 'Catalog snapshot generated marker is invalid. Rebuild or republish the Catalog, then refresh the source.',
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return marker.workspaceIdentity;
|
|
144
|
+
}
|
|
145
|
+
async function assertRegularGenerationDirectory(directory) {
|
|
146
|
+
const stat = await fs.lstat(directory).catch((error) => {
|
|
147
|
+
if (error.code === 'ENOENT')
|
|
148
|
+
return null;
|
|
149
|
+
throw error;
|
|
150
|
+
});
|
|
151
|
+
if (!stat?.isDirectory() || stat.isSymbolicLink()) {
|
|
152
|
+
throw new CatalogGenerationError({
|
|
153
|
+
code: 'catalogGenerationMetadataInvalid',
|
|
154
|
+
message: 'Catalog generation directory is missing or unsafe. Refresh the source after repairing the generation store.',
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async function validateGenerationDirectory(options) {
|
|
159
|
+
const metadata = await readGenerationMetadataAt(options);
|
|
160
|
+
const snapshotRoot = path.join(options.generationDir, 'snapshot');
|
|
161
|
+
let validation;
|
|
162
|
+
try {
|
|
163
|
+
validation = await validateCatalogSnapshotTransport(snapshotRoot);
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
throw new CatalogGenerationError({
|
|
167
|
+
code: 'catalogGenerationMetadataInvalid',
|
|
168
|
+
message: 'Catalog generation snapshot is damaged. Remove the damaged generation and refresh the source.',
|
|
169
|
+
cause: error,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
if (validation.manifest.catalogVersion !== metadata.catalogVersion
|
|
173
|
+
|| validation.manifest.channel !== metadata.channel
|
|
174
|
+
|| JSON.stringify(validation.manifest.requires.aw.capabilities ?? [])
|
|
175
|
+
!== JSON.stringify(metadata.requiredAwCapabilities)
|
|
176
|
+
|| validation.manifestDigest !== metadata.manifestDigest
|
|
177
|
+
|| validation.snapshotDigest !== metadata.snapshotDigest
|
|
178
|
+
|| await readCatalogLogicalIdentity(snapshotRoot) !== metadata.logicalIdentity) {
|
|
179
|
+
throw new CatalogGenerationError({
|
|
180
|
+
code: 'catalogGenerationIdentityMismatch',
|
|
181
|
+
message: 'Catalog generation snapshot does not match its immutable metadata. Remove the damaged generation and refresh the source.',
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
return { generationDir: options.generationDir, snapshotRoot, metadata };
|
|
185
|
+
}
|
|
186
|
+
async function readGenerationMetadataAt(options) {
|
|
187
|
+
await assertRegularGenerationDirectory(options.generationDir);
|
|
188
|
+
const metadataPath = path.join(options.generationDir, CATALOG_GENERATION_METADATA_FILE);
|
|
189
|
+
const metadataStat = await fs.lstat(metadataPath).catch((error) => {
|
|
190
|
+
if (error.code === 'ENOENT')
|
|
191
|
+
return null;
|
|
192
|
+
throw error;
|
|
193
|
+
});
|
|
194
|
+
if (!metadataStat?.isFile() || metadataStat.isSymbolicLink()) {
|
|
195
|
+
throw new CatalogGenerationError({
|
|
196
|
+
code: 'catalogGenerationMetadataInvalid',
|
|
197
|
+
message: 'Catalog generation metadata file is missing or unsafe. Remove the damaged generation and refresh the source.',
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
let metadata;
|
|
201
|
+
try {
|
|
202
|
+
metadata = parseGenerationMetadata(await fs.readJson(metadataPath));
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
if (error instanceof CatalogGenerationError)
|
|
206
|
+
throw error;
|
|
207
|
+
throw new CatalogGenerationError({
|
|
208
|
+
code: 'catalogGenerationMetadataInvalid',
|
|
209
|
+
message: 'Catalog generation metadata is unreadable. Remove the damaged generation and refresh the source.',
|
|
210
|
+
cause: error,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
if (metadata.logicalIdentity !== options.logicalIdentity
|
|
214
|
+
|| metadata.snapshotDigest !== options.snapshotDigest) {
|
|
215
|
+
throw new CatalogGenerationError({
|
|
216
|
+
code: 'catalogGenerationIdentityMismatch',
|
|
217
|
+
message: 'Catalog generation directory identity does not match its metadata. Remove the damaged generation and refresh the source.',
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
return metadata;
|
|
221
|
+
}
|
|
222
|
+
export async function prepareCatalogGeneration(options) {
|
|
223
|
+
options.signal?.throwIfAborted();
|
|
224
|
+
const awHomeDir = canonicalizePathThroughExistingAncestorSync(resolveAwHome(options.env ?? process.env));
|
|
225
|
+
const storeRootDir = path.join(awHomeDir, CATALOG_GENERATIONS_DIRECTORY);
|
|
226
|
+
await ensureRegularDirectoryPath(storeRootDir, 'Catalog generation store');
|
|
227
|
+
const stagingDir = path.join(storeRootDir, `.staging-${crypto.randomUUID()}.tmp`);
|
|
228
|
+
try {
|
|
229
|
+
await fs.mkdir(stagingDir);
|
|
230
|
+
const snapshotRoot = path.join(stagingDir, 'snapshot');
|
|
231
|
+
await fs.copy(options.resolution.rootDir, snapshotRoot, {
|
|
232
|
+
dereference: false,
|
|
233
|
+
preserveTimestamps: true,
|
|
234
|
+
filter: () => {
|
|
235
|
+
options.signal?.throwIfAborted();
|
|
236
|
+
return true;
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
options.signal?.throwIfAborted();
|
|
240
|
+
const validation = await validateCatalogSnapshotTransport(snapshotRoot);
|
|
241
|
+
options.signal?.throwIfAborted();
|
|
242
|
+
if (validation.manifestDigest !== options.resolution.manifestDigest
|
|
243
|
+
|| validation.snapshotDigest !== options.resolution.snapshotDigest
|
|
244
|
+
|| validation.manifest.catalogVersion !== options.resolution.manifest.catalogVersion
|
|
245
|
+
|| validation.manifest.channel !== options.resolution.manifest.channel) {
|
|
246
|
+
throw new CatalogGenerationError({
|
|
247
|
+
code: 'catalogGenerationPublishFailed',
|
|
248
|
+
sourceId: options.resolution.sourceId,
|
|
249
|
+
message: `Catalog source "${options.resolution.sourceId}" changed before generation publication. Refresh the source again.`,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
const logicalIdentity = await readCatalogLogicalIdentity(snapshotRoot);
|
|
253
|
+
const location = resolveCatalogGenerationLocation({
|
|
254
|
+
logicalIdentity,
|
|
255
|
+
snapshotDigest: validation.snapshotDigest,
|
|
256
|
+
env: options.env,
|
|
257
|
+
});
|
|
258
|
+
const metadata = {
|
|
259
|
+
schemaVersion: 1,
|
|
260
|
+
logicalIdentity,
|
|
261
|
+
catalogVersion: validation.manifest.catalogVersion,
|
|
262
|
+
channel: validation.manifest.channel,
|
|
263
|
+
manifestDigest: validation.manifestDigest,
|
|
264
|
+
snapshotDigest: validation.snapshotDigest,
|
|
265
|
+
generationKey: location.generationKey,
|
|
266
|
+
requiredAwCapabilities: normalizeAwCapabilities(validation.manifest.requires.aw.capabilities ?? []),
|
|
267
|
+
publishedAt: (options.now?.() ?? new Date()).toISOString(),
|
|
268
|
+
};
|
|
269
|
+
await fs.writeFile(path.join(stagingDir, CATALOG_GENERATION_METADATA_FILE), `${JSON.stringify(metadata, null, 2)}\n`, { flag: 'wx', mode: 0o600 });
|
|
270
|
+
options.signal?.throwIfAborted();
|
|
271
|
+
await validateGenerationDirectory({
|
|
272
|
+
generationDir: stagingDir,
|
|
273
|
+
logicalIdentity,
|
|
274
|
+
snapshotDigest: validation.snapshotDigest,
|
|
275
|
+
});
|
|
276
|
+
options.signal?.throwIfAborted();
|
|
277
|
+
return { stagingDir, location, metadata };
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
await fs.remove(stagingDir).catch(() => undefined);
|
|
281
|
+
if (error instanceof CatalogGenerationError)
|
|
282
|
+
throw error;
|
|
283
|
+
throw new CatalogGenerationError({
|
|
284
|
+
code: 'catalogGenerationPublishFailed',
|
|
285
|
+
sourceId: options.resolution.sourceId,
|
|
286
|
+
message: `Cannot prepare Catalog generation for source "${options.resolution.sourceId}". Refresh the source again after repairing the snapshot.`,
|
|
287
|
+
cause: error,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
export async function publishPreparedCatalogGeneration(prepared) {
|
|
292
|
+
await ensureRegularDirectoryPath(prepared.location.logicalIdentityDirectory, 'Catalog logical identity directory');
|
|
293
|
+
const existing = await fs.lstat(prepared.location.generationDir).catch((error) => {
|
|
294
|
+
if (error.code === 'ENOENT')
|
|
295
|
+
return null;
|
|
296
|
+
throw error;
|
|
297
|
+
});
|
|
298
|
+
if (existing) {
|
|
299
|
+
const published = await validateGenerationDirectory({
|
|
300
|
+
generationDir: prepared.location.generationDir,
|
|
301
|
+
logicalIdentity: prepared.metadata.logicalIdentity,
|
|
302
|
+
snapshotDigest: prepared.metadata.snapshotDigest,
|
|
303
|
+
});
|
|
304
|
+
await fs.remove(prepared.stagingDir).catch(() => undefined);
|
|
305
|
+
return published;
|
|
306
|
+
}
|
|
307
|
+
try {
|
|
308
|
+
await fs.rename(prepared.stagingDir, prepared.location.generationDir);
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
const code = error.code;
|
|
312
|
+
if (code === 'EEXIST' || code === 'ENOTEMPTY') {
|
|
313
|
+
const published = await validateGenerationDirectory({
|
|
314
|
+
generationDir: prepared.location.generationDir,
|
|
315
|
+
logicalIdentity: prepared.metadata.logicalIdentity,
|
|
316
|
+
snapshotDigest: prepared.metadata.snapshotDigest,
|
|
317
|
+
});
|
|
318
|
+
await fs.remove(prepared.stagingDir).catch(() => undefined);
|
|
319
|
+
return published;
|
|
320
|
+
}
|
|
321
|
+
throw new CatalogGenerationError({
|
|
322
|
+
code: 'catalogGenerationPublishFailed',
|
|
323
|
+
message: 'Cannot atomically publish the prepared Catalog generation. The previous Active generation is unchanged; refresh the source again.',
|
|
324
|
+
cause: error,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
return {
|
|
328
|
+
generationDir: prepared.location.generationDir,
|
|
329
|
+
snapshotRoot: prepared.location.snapshotRoot,
|
|
330
|
+
metadata: prepared.metadata,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
export async function discardPreparedCatalogGeneration(prepared) {
|
|
334
|
+
await fs.remove(prepared.stagingDir).catch(() => undefined);
|
|
335
|
+
}
|
|
336
|
+
export async function readCatalogGeneration(options) {
|
|
337
|
+
const location = resolveCatalogGenerationLocation(options);
|
|
338
|
+
return validateGenerationDirectory({
|
|
339
|
+
generationDir: location.generationDir,
|
|
340
|
+
logicalIdentity: options.logicalIdentity,
|
|
341
|
+
snapshotDigest: options.snapshotDigest,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
export async function listCatalogGenerationsForIdentity(options) {
|
|
345
|
+
const placeholderDigest = `sha256:${'0'.repeat(64)}`;
|
|
346
|
+
const location = resolveCatalogGenerationLocation({
|
|
347
|
+
logicalIdentity: options.logicalIdentity,
|
|
348
|
+
snapshotDigest: placeholderDigest,
|
|
349
|
+
env: options.env,
|
|
350
|
+
});
|
|
351
|
+
const directoryStat = await fs.lstat(location.logicalIdentityDirectory).catch((error) => {
|
|
352
|
+
if (error.code === 'ENOENT')
|
|
353
|
+
return null;
|
|
354
|
+
throw error;
|
|
355
|
+
});
|
|
356
|
+
if (!directoryStat)
|
|
357
|
+
return [];
|
|
358
|
+
if (!directoryStat.isDirectory() || directoryStat.isSymbolicLink()) {
|
|
359
|
+
throw new CatalogGenerationError({
|
|
360
|
+
code: 'catalogGenerationMetadataInvalid',
|
|
361
|
+
message: 'Catalog logical identity store is unsafe. Repair it before refreshing the source.',
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
const names = (await fs.readdir(location.logicalIdentityDirectory)).sort();
|
|
365
|
+
const generations = [];
|
|
366
|
+
for (const name of names) {
|
|
367
|
+
if (!HEX_DIGEST_PATTERN.test(name)) {
|
|
368
|
+
throw new CatalogGenerationError({
|
|
369
|
+
code: 'catalogGenerationMetadataInvalid',
|
|
370
|
+
message: 'Catalog logical identity store contains an invalid entry. Remove the damaged entry before refreshing the source.',
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
const generationDir = path.join(location.logicalIdentityDirectory, name);
|
|
374
|
+
const metadata = await readGenerationMetadataAt({
|
|
375
|
+
generationDir,
|
|
376
|
+
logicalIdentity: options.logicalIdentity,
|
|
377
|
+
snapshotDigest: `sha256:${name}`,
|
|
378
|
+
});
|
|
379
|
+
generations.push({
|
|
380
|
+
generationDir,
|
|
381
|
+
snapshotRoot: path.join(generationDir, 'snapshot'),
|
|
382
|
+
metadata,
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
return generations;
|
|
386
|
+
}
|
|
387
|
+
//# sourceMappingURL=catalog-generation-store.js.map
|