sf-plugin-cms 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -14
- package/lib/{commands/cms/command-base.d.ts → command-base.d.ts} +6 -1
- package/lib/{commands/cms/command-base.js → command-base.js} +37 -0
- package/lib/command-base.js.map +1 -0
- package/lib/commands/cms/export/workspace.d.ts +12 -5
- package/lib/commands/cms/export/workspace.js +97 -12
- package/lib/commands/cms/export/workspace.js.map +1 -1
- package/lib/commands/cms/get/channel.d.ts +1 -1
- package/lib/commands/cms/get/channel.js +1 -1
- package/lib/commands/cms/get/channel.js.map +1 -1
- package/lib/commands/cms/get/content.d.ts +1 -1
- package/lib/commands/cms/get/content.js +1 -1
- package/lib/commands/cms/get/content.js.map +1 -1
- package/lib/commands/cms/get/variant.d.ts +1 -1
- package/lib/commands/cms/get/variant.js +1 -1
- package/lib/commands/cms/get/variant.js.map +1 -1
- package/lib/commands/cms/get/workspace.d.ts +1 -1
- package/lib/commands/cms/get/workspace.js +1 -1
- package/lib/commands/cms/get/workspace.js.map +1 -1
- package/lib/commands/cms/import/workspace.d.ts +7 -4
- package/lib/commands/cms/import/workspace.js +115 -36
- package/lib/commands/cms/import/workspace.js.map +1 -1
- package/lib/commands/cms/info.d.ts +11 -10
- package/lib/commands/cms/info.js +122 -9
- package/lib/commands/cms/info.js.map +1 -1
- package/lib/commands/cms/list/channel.d.ts +1 -1
- package/lib/commands/cms/list/channel.js +1 -1
- package/lib/commands/cms/list/channel.js.map +1 -1
- package/lib/commands/cms/list/workspace.d.ts +1 -1
- package/lib/commands/cms/list/workspace.js +1 -1
- package/lib/commands/cms/list/workspace.js.map +1 -1
- package/lib/contracts/info.d.ts +43 -0
- package/lib/contracts/info.js +69 -0
- package/lib/contracts/info.js.map +1 -0
- package/lib/contracts/shared.d.ts +81 -0
- package/lib/contracts/shared.js +218 -0
- package/lib/contracts/shared.js.map +1 -0
- package/lib/contracts/workspace-export.d.ts +91 -0
- package/lib/contracts/workspace-export.js +324 -0
- package/lib/contracts/workspace-export.js.map +1 -0
- package/lib/contracts/workspace-import.d.ts +46 -0
- package/lib/contracts/workspace-import.js +108 -0
- package/lib/contracts/workspace-import.js.map +1 -0
- package/lib/index.d.ts +1 -1
- package/lib/runtime-version.d.ts +2 -0
- package/lib/runtime-version.js +18 -0
- package/lib/runtime-version.js.map +1 -0
- package/lib/services/atomic-publish.d.ts +15 -0
- package/lib/services/atomic-publish.js +109 -0
- package/lib/services/atomic-publish.js.map +1 -0
- package/lib/services/bulk-export-workspaces.d.ts +25 -0
- package/lib/services/bulk-export-workspaces.js +273 -0
- package/lib/services/bulk-export-workspaces.js.map +1 -0
- package/lib/services/export-references.d.ts +21 -0
- package/lib/services/export-references.js +150 -0
- package/lib/services/export-references.js.map +1 -0
- package/lib/services/export-workspace.d.ts +15 -22
- package/lib/services/export-workspace.js +73 -7
- package/lib/services/export-workspace.js.map +1 -1
- package/lib/services/import-workspace.d.ts +10 -3
- package/lib/services/import-workspace.js +229 -101
- package/lib/services/import-workspace.js.map +1 -1
- package/lib/services/resolve-workspace.d.ts +5 -0
- package/lib/services/resolve-workspace.js +56 -47
- package/lib/services/resolve-workspace.js.map +1 -1
- package/messages/cms.export.workspace.md +22 -4
- package/messages/cms.import.workspace.md +8 -2
- package/messages/cms.info.md +21 -0
- package/package.json +16 -5
- package/lib/commands/cms/command-base.js.map +0 -1
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import { open, rename, rm } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
const windowsRenameRetryDelays = [10, 25, 50];
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
const runtimeReport = process.report.getReport();
|
|
7
|
+
const linuxLibc = runtimeReport.header?.glibcVersionRuntime === undefined ? 'musl' : 'gnu';
|
|
8
|
+
const nativeNoReplacePackages = {
|
|
9
|
+
darwin: {
|
|
10
|
+
arm64: '@skill-steward/rename-noreplace-darwin-arm64',
|
|
11
|
+
x64: '@skill-steward/rename-noreplace-darwin-x64',
|
|
12
|
+
},
|
|
13
|
+
linux: {
|
|
14
|
+
arm64: `@skill-steward/rename-noreplace-linux-arm64-${linuxLibc}`,
|
|
15
|
+
x64: `@skill-steward/rename-noreplace-linux-x64-${linuxLibc}`,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
function errorCode(error) {
|
|
19
|
+
return typeof error === 'object' &&
|
|
20
|
+
error !== null &&
|
|
21
|
+
'code' in error &&
|
|
22
|
+
typeof error.code === 'string'
|
|
23
|
+
? error.code
|
|
24
|
+
: undefined;
|
|
25
|
+
}
|
|
26
|
+
function delay(milliseconds) {
|
|
27
|
+
return new Promise((resolve) => {
|
|
28
|
+
setTimeout(resolve, milliseconds);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
async function renameWithNarrowWindowsRetry(temporary, destination, options) {
|
|
32
|
+
const renamePath = options.renamePath ?? rename;
|
|
33
|
+
const wait = options.delay ?? delay;
|
|
34
|
+
for (let attempt = 0;; attempt += 1) {
|
|
35
|
+
try {
|
|
36
|
+
await renamePath(temporary, destination);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
const retryDelay = windowsRenameRetryDelays[attempt];
|
|
41
|
+
const code = errorCode(error);
|
|
42
|
+
if ((options.platform ?? process.platform) !== 'win32' ||
|
|
43
|
+
(code !== 'EPERM' && code !== 'EBUSY') ||
|
|
44
|
+
retryDelay === undefined) {
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
await wait(retryDelay);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export async function replaceFileByAtomicRename(temporary, destination, options = {}) {
|
|
52
|
+
await renameWithNarrowWindowsRetry(temporary, destination, options);
|
|
53
|
+
}
|
|
54
|
+
function nativeDirectoryPublisher() {
|
|
55
|
+
if (process.platform === 'win32')
|
|
56
|
+
return rename;
|
|
57
|
+
const packageName = nativeNoReplacePackages[process.platform]?.[process.arch];
|
|
58
|
+
if (packageName === undefined) {
|
|
59
|
+
throw new Error(`Atomic no-clobber directory publication is unsupported on ${process.platform}/${process.arch}`);
|
|
60
|
+
}
|
|
61
|
+
const binding = require(packageName);
|
|
62
|
+
const renameNoReplace = typeof binding === 'function' ? binding : binding.renameNoReplace;
|
|
63
|
+
if (renameNoReplace === undefined) {
|
|
64
|
+
throw new TypeError(`${packageName} does not export renameNoReplace`);
|
|
65
|
+
}
|
|
66
|
+
return async (temporary, destination) => {
|
|
67
|
+
const parent = path.dirname(temporary);
|
|
68
|
+
if (path.dirname(destination) !== parent) {
|
|
69
|
+
throw new Error('Atomic no-clobber publication requires sibling paths');
|
|
70
|
+
}
|
|
71
|
+
const directory = await open(parent, 'r');
|
|
72
|
+
try {
|
|
73
|
+
renameNoReplace(directory.fd, path.basename(temporary), path.basename(destination));
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
await directory.close();
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export async function publishDirectoryNoClobber(temporary, destination, options = {}) {
|
|
81
|
+
const publishPath = options.publishPath ?? options.renamePath ?? nativeDirectoryPublisher();
|
|
82
|
+
await renameWithNarrowWindowsRetry(temporary, destination, {
|
|
83
|
+
...options,
|
|
84
|
+
renamePath: publishPath,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
export async function cleanupOwnedPath(ownedPath, primaryError, options = {}) {
|
|
88
|
+
try {
|
|
89
|
+
await (options.removePath ?? rm)(ownedPath, { force: true, recursive: true });
|
|
90
|
+
}
|
|
91
|
+
catch (cleanupError) {
|
|
92
|
+
try {
|
|
93
|
+
if (typeof primaryError === 'object' &&
|
|
94
|
+
primaryError !== null &&
|
|
95
|
+
Object.isExtensible(primaryError)) {
|
|
96
|
+
Object.defineProperty(primaryError, 'cleanupError', {
|
|
97
|
+
configurable: true,
|
|
98
|
+
enumerable: false,
|
|
99
|
+
value: cleanupError,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Preserve the primary publication error even when diagnostics cannot be attached.
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
throw primaryError;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=atomic-publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomic-publish.js","sourceRoot":"","sources":["../../src/services/atomic-publish.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Connection } from '@salesforce/core';
|
|
2
|
+
import { type CmsEnvelope } from '../contracts/shared.js';
|
|
3
|
+
import { type WorkspaceExportSetResult } from '../contracts/workspace-export.js';
|
|
4
|
+
import type { JsonRequestOptions } from '../transport/json-request.js';
|
|
5
|
+
export type CanonicalWorkspaceType = 'Content' | 'Marketing';
|
|
6
|
+
export type BulkWorkspaceExportOptions = JsonRequestOptions & {
|
|
7
|
+
apiVersion?: string;
|
|
8
|
+
generatedAt?: string;
|
|
9
|
+
pluginVersion?: string;
|
|
10
|
+
sourceOrgId?: string;
|
|
11
|
+
};
|
|
12
|
+
type RequestConnection = Pick<Connection, 'request'>;
|
|
13
|
+
type PreparedWorkspace = {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
type: CanonicalWorkspaceType;
|
|
17
|
+
destination: string;
|
|
18
|
+
};
|
|
19
|
+
export declare function normalizeWorkspaceType(value?: unknown): CanonicalWorkspaceType;
|
|
20
|
+
export declare function preflightBulkWorkspaceExport(connection: RequestConnection, outputDirectory: string, workspaceType?: CanonicalWorkspaceType, options?: JsonRequestOptions): Promise<{
|
|
21
|
+
discoveredCount: number;
|
|
22
|
+
selected: PreparedWorkspace[];
|
|
23
|
+
}>;
|
|
24
|
+
export declare function exportAllWorkspaces(connection: RequestConnection, outputDirectory: string, workspaceType: CanonicalWorkspaceType, options?: BulkWorkspaceExportOptions): Promise<CmsEnvelope<WorkspaceExportSetResult>>;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { mkdir, stat } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { assertCmsEnvelope, MAX_DIAGNOSTICS_PER_KIND, sanitizeDiagnostics, } from '../contracts/shared.js';
|
|
5
|
+
import { assertWorkspaceExportSetResult, WORKSPACE_EXPORT_MANIFEST_CONTRACT, WORKSPACE_EXPORT_SET_CONTRACT, } from '../contracts/workspace-export.js';
|
|
6
|
+
import { getPluginVersion } from '../runtime-version.js';
|
|
7
|
+
import { redactSecrets } from '../transport/redact-secrets.js';
|
|
8
|
+
import { exportWorkspace, safeWorkspaceDirectoryName } from './export-workspace.js';
|
|
9
|
+
import { getWorkspace } from './read.js';
|
|
10
|
+
import { enumerateWorkspaces } from './resolve-workspace.js';
|
|
11
|
+
function isRecord(value) {
|
|
12
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
13
|
+
}
|
|
14
|
+
function nonemptyString(value) {
|
|
15
|
+
return typeof value === 'string' && value.length > 0;
|
|
16
|
+
}
|
|
17
|
+
function folded(value) {
|
|
18
|
+
return value.normalize('NFKC').toLocaleLowerCase('en-US');
|
|
19
|
+
}
|
|
20
|
+
function actualWorkspaceType(workspace) {
|
|
21
|
+
const spaceType = workspace.spaceType;
|
|
22
|
+
if (typeof spaceType === 'string')
|
|
23
|
+
return normalizeWorkspaceType(spaceType);
|
|
24
|
+
if (isRecord(spaceType) && typeof spaceType.apiName === 'string') {
|
|
25
|
+
return normalizeWorkspaceType(spaceType.apiName);
|
|
26
|
+
}
|
|
27
|
+
return normalizeWorkspaceType();
|
|
28
|
+
}
|
|
29
|
+
export function normalizeWorkspaceType(value) {
|
|
30
|
+
if (typeof value === 'string') {
|
|
31
|
+
const normalized = value.toLocaleLowerCase('en-US');
|
|
32
|
+
if (normalized === 'marketing')
|
|
33
|
+
return 'Marketing';
|
|
34
|
+
if (normalized === 'content')
|
|
35
|
+
return 'Content';
|
|
36
|
+
}
|
|
37
|
+
throw new Error('Workspace type must be Marketing or Content.');
|
|
38
|
+
}
|
|
39
|
+
async function exists(candidate) {
|
|
40
|
+
try {
|
|
41
|
+
await stat(candidate);
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (isRecord(error) && error.code === 'ENOENT')
|
|
46
|
+
return false;
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async function assertParentCompatible(parent) {
|
|
51
|
+
let cursor = path.resolve(parent);
|
|
52
|
+
for (;;) {
|
|
53
|
+
try {
|
|
54
|
+
const information = await stat(cursor);
|
|
55
|
+
if (!information.isDirectory()) {
|
|
56
|
+
throw new Error(`Bulk output parent is not a directory: ${cursor}`);
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (!isRecord(error) || error.code !== 'ENOENT')
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
const next = path.dirname(cursor);
|
|
65
|
+
if (next === cursor)
|
|
66
|
+
throw new Error(`Bulk output parent is not usable: ${parent}`);
|
|
67
|
+
cursor = next;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function normalizedError(error) {
|
|
71
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
72
|
+
return (redactSecrets(message)
|
|
73
|
+
.replaceAll(/[\r\n]+/gu, ' ')
|
|
74
|
+
.trim() || 'Workspace export failed.');
|
|
75
|
+
}
|
|
76
|
+
function portableOutputPath(value) {
|
|
77
|
+
const portable = value.split(path.sep).join('/');
|
|
78
|
+
if (/^[A-Za-z]:/u.test(portable) || portable.startsWith('/'))
|
|
79
|
+
return path.basename(value);
|
|
80
|
+
return portable.startsWith('./') ? portable : `./${portable}`;
|
|
81
|
+
}
|
|
82
|
+
function relativeArtifactPath(outputDirectory, destination) {
|
|
83
|
+
return path.relative(outputDirectory, destination).split(path.sep).join('/');
|
|
84
|
+
}
|
|
85
|
+
function hashExportSet(result) {
|
|
86
|
+
return `export-set:${createHash('sha256').update(JSON.stringify(result)).digest('hex')}`;
|
|
87
|
+
}
|
|
88
|
+
export async function preflightBulkWorkspaceExport(connection, outputDirectory, workspaceType, options = {}) {
|
|
89
|
+
const listed = await enumerateWorkspaces(connection, options);
|
|
90
|
+
const canonical = [];
|
|
91
|
+
const canonicalNames = new Map();
|
|
92
|
+
for (const summary of listed) {
|
|
93
|
+
const workspace = await getWorkspace(connection, summary.id, options);
|
|
94
|
+
if (workspace.id !== summary.id || !nonemptyString(workspace.name)) {
|
|
95
|
+
throw new Error(`Canonical workspace ${summary.id} returned a malformed or mismatched ID/name.`);
|
|
96
|
+
}
|
|
97
|
+
const nameKey = folded(workspace.name);
|
|
98
|
+
const existingNameId = canonicalNames.get(nameKey);
|
|
99
|
+
if (existingNameId !== undefined && existingNameId !== summary.id) {
|
|
100
|
+
throw new Error(`Workspace names for IDs ${existingNameId} and ${summary.id} differ only by case or Unicode normalization and are ambiguous.`);
|
|
101
|
+
}
|
|
102
|
+
canonicalNames.set(nameKey, summary.id);
|
|
103
|
+
const type = actualWorkspaceType(workspace);
|
|
104
|
+
if (workspaceType !== undefined && type !== workspaceType)
|
|
105
|
+
continue;
|
|
106
|
+
canonical.push({
|
|
107
|
+
id: summary.id,
|
|
108
|
+
name: workspace.name,
|
|
109
|
+
type,
|
|
110
|
+
destination: path.join(outputDirectory, safeWorkspaceDirectoryName(workspace.name)),
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
canonical.sort((left, right) => left.id.localeCompare(right.id, 'en-US'));
|
|
114
|
+
await assertParentCompatible(outputDirectory);
|
|
115
|
+
const destinations = new Map();
|
|
116
|
+
for (const workspace of canonical) {
|
|
117
|
+
if (await exists(workspace.destination)) {
|
|
118
|
+
throw new Error(`Export destination already exists: ${workspace.destination}`);
|
|
119
|
+
}
|
|
120
|
+
const destinationKey = folded(path.resolve(workspace.destination));
|
|
121
|
+
const existing = destinations.get(destinationKey);
|
|
122
|
+
if (existing !== undefined) {
|
|
123
|
+
throw new Error(`Workspace destinations collide after sanitization: ${existing.id} (${existing.name}) and ${workspace.id} (${workspace.name}).`);
|
|
124
|
+
}
|
|
125
|
+
destinations.set(destinationKey, workspace);
|
|
126
|
+
}
|
|
127
|
+
return { discoveredCount: listed.length, selected: canonical };
|
|
128
|
+
}
|
|
129
|
+
export async function exportAllWorkspaces(connection, outputDirectory, workspaceType, options = {}) {
|
|
130
|
+
const generatedAt = options.generatedAt ?? new Date().toISOString();
|
|
131
|
+
const pluginVersion = options.pluginVersion ?? getPluginVersion();
|
|
132
|
+
const sourceOrgId = options.sourceOrgId ?? 'unknown-org';
|
|
133
|
+
const preflight = await preflightBulkWorkspaceExport(connection, outputDirectory, workspaceType, options);
|
|
134
|
+
if (preflight.selected.length > 0)
|
|
135
|
+
await mkdir(outputDirectory, { recursive: true });
|
|
136
|
+
const workspaces = [];
|
|
137
|
+
const externalReferenceCorrelations = [];
|
|
138
|
+
for (const workspace of preflight.selected) {
|
|
139
|
+
const artifactPath = relativeArtifactPath(outputDirectory, workspace.destination);
|
|
140
|
+
try {
|
|
141
|
+
const exported = await exportWorkspace(connection, workspace.id, workspace.destination, {
|
|
142
|
+
...options,
|
|
143
|
+
generatedAt,
|
|
144
|
+
pluginVersion,
|
|
145
|
+
sourceOrgId,
|
|
146
|
+
});
|
|
147
|
+
const partial = exported.manifest.completeness === 'partial';
|
|
148
|
+
for (const reference of exported.manifest.externalReferences) {
|
|
149
|
+
if (reference.resolution !== 'included' || reference.kind !== 'cms.content')
|
|
150
|
+
continue;
|
|
151
|
+
externalReferenceCorrelations.push({
|
|
152
|
+
sourceWorkspaceId: workspace.id,
|
|
153
|
+
sourceReference: reference.portableKey.value,
|
|
154
|
+
referenceKind: reference.kind,
|
|
155
|
+
referenceId: reference.referenceId,
|
|
156
|
+
packageManifestSha256: exported.manifestSha256,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
const warnings = partial
|
|
160
|
+
? exported.manifest.warnings.map(({ code, message }) => ({ code, message }))
|
|
161
|
+
: [];
|
|
162
|
+
workspaces.push({
|
|
163
|
+
source: {
|
|
164
|
+
kind: 'cms.workspace',
|
|
165
|
+
sourceId: workspace.id,
|
|
166
|
+
name: workspace.name,
|
|
167
|
+
workspaceType: workspace.type,
|
|
168
|
+
},
|
|
169
|
+
status: partial ? 'partial' : 'success',
|
|
170
|
+
artifact: {
|
|
171
|
+
path: artifactPath,
|
|
172
|
+
manifestPath: `${artifactPath}/manifest.json`,
|
|
173
|
+
manifestContract: WORKSPACE_EXPORT_MANIFEST_CONTRACT,
|
|
174
|
+
manifestContractVersion: '1.0.0',
|
|
175
|
+
manifestSha256: exported.manifestSha256,
|
|
176
|
+
},
|
|
177
|
+
diagnostics: { warnings, errors: [] },
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
workspaces.push({
|
|
182
|
+
source: {
|
|
183
|
+
kind: 'cms.workspace',
|
|
184
|
+
sourceId: workspace.id,
|
|
185
|
+
name: workspace.name,
|
|
186
|
+
workspaceType: workspace.type,
|
|
187
|
+
},
|
|
188
|
+
status: 'failed',
|
|
189
|
+
artifact: null,
|
|
190
|
+
diagnostics: {
|
|
191
|
+
warnings: [],
|
|
192
|
+
errors: [{ code: 'WORKSPACE_EXPORT_FAILED', message: normalizedError(error) }],
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
externalReferenceCorrelations.sort((left, right) => [
|
|
198
|
+
left.sourceWorkspaceId,
|
|
199
|
+
left.sourceReference,
|
|
200
|
+
left.referenceKind,
|
|
201
|
+
left.referenceId,
|
|
202
|
+
left.packageManifestSha256,
|
|
203
|
+
]
|
|
204
|
+
.join('\u0000')
|
|
205
|
+
.localeCompare([
|
|
206
|
+
right.sourceWorkspaceId,
|
|
207
|
+
right.sourceReference,
|
|
208
|
+
right.referenceKind,
|
|
209
|
+
right.referenceId,
|
|
210
|
+
right.packageManifestSha256,
|
|
211
|
+
].join('\u0000')));
|
|
212
|
+
const result = {
|
|
213
|
+
workspaceType,
|
|
214
|
+
outputDirectory: portableOutputPath(outputDirectory),
|
|
215
|
+
selection: {
|
|
216
|
+
mode: 'all',
|
|
217
|
+
discoveredCount: preflight.discoveredCount,
|
|
218
|
+
selectedCount: workspaces.length,
|
|
219
|
+
},
|
|
220
|
+
summary: {
|
|
221
|
+
succeededCount: workspaces.filter(({ status }) => status === 'success').length,
|
|
222
|
+
partialCount: workspaces.filter(({ status }) => status === 'partial').length,
|
|
223
|
+
failedCount: workspaces.filter(({ status }) => status === 'failed').length,
|
|
224
|
+
},
|
|
225
|
+
externalReferenceCorrelations,
|
|
226
|
+
workspaces,
|
|
227
|
+
};
|
|
228
|
+
let status = 'success';
|
|
229
|
+
if (result.summary.failedCount === workspaces.length && workspaces.length > 0)
|
|
230
|
+
status = 'failed';
|
|
231
|
+
else if (result.summary.failedCount > 0 || result.summary.partialCount > 0)
|
|
232
|
+
status = 'partial';
|
|
233
|
+
const errors = aggregateDiagnostics(workspaces, 'errors');
|
|
234
|
+
const warnings = aggregateDiagnostics(workspaces, 'warnings');
|
|
235
|
+
const envelope = {
|
|
236
|
+
contract: WORKSPACE_EXPORT_SET_CONTRACT,
|
|
237
|
+
contractVersion: '1.0.0',
|
|
238
|
+
status,
|
|
239
|
+
metadata: {
|
|
240
|
+
operation: 'workspace.export.bulk',
|
|
241
|
+
plugin: { name: 'sf-plugin-cms', version: pluginVersion },
|
|
242
|
+
apiVersion: options.apiVersion ?? '67.0',
|
|
243
|
+
},
|
|
244
|
+
diagnostics: { warnings, errors },
|
|
245
|
+
provenance: {
|
|
246
|
+
producer: 'sf-plugin-cms',
|
|
247
|
+
sourceOrgId,
|
|
248
|
+
pluginVersion,
|
|
249
|
+
exportSetId: hashExportSet(result),
|
|
250
|
+
command: 'sf cms export workspace',
|
|
251
|
+
generatedAt,
|
|
252
|
+
},
|
|
253
|
+
result,
|
|
254
|
+
};
|
|
255
|
+
assertCmsEnvelope(envelope, assertWorkspaceExportSetResult);
|
|
256
|
+
return envelope;
|
|
257
|
+
}
|
|
258
|
+
function aggregateDiagnostics(workspaces, kind) {
|
|
259
|
+
const diagnostics = workspaces.flatMap(({ source, diagnostics: workspaceDiagnostics }) => workspaceDiagnostics[kind].map((diagnostic) => ({ ...diagnostic, scope: source.sourceId })));
|
|
260
|
+
if (diagnostics.length <= MAX_DIAGNOSTICS_PER_KIND) {
|
|
261
|
+
return sanitizeDiagnostics(diagnostics, `diagnostics.${kind}`);
|
|
262
|
+
}
|
|
263
|
+
const omitted = diagnostics.length - MAX_DIAGNOSTICS_PER_KIND + 1;
|
|
264
|
+
return sanitizeDiagnostics([
|
|
265
|
+
...diagnostics.slice(0, MAX_DIAGNOSTICS_PER_KIND - 1),
|
|
266
|
+
{
|
|
267
|
+
code: 'DIAGNOSTICS_TRUNCATED',
|
|
268
|
+
message: `${omitted} additional ${kind} omitted from aggregate diagnostics; per-workspace diagnostics remain complete.`,
|
|
269
|
+
retryable: false,
|
|
270
|
+
},
|
|
271
|
+
], `diagnostics.${kind}`);
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=bulk-export-workspaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulk-export-workspaces.js","sourceRoot":"","sources":["../../src/services/bulk-export-workspaces.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { OpaqueCmsReference } from '../contracts/shared.js';
|
|
2
|
+
import type { CmsRecord } from './read.js';
|
|
3
|
+
export type ExportReferenceWarning = {
|
|
4
|
+
code: 'REFERENCE_UNRESOLVED' | 'REFERENCE_UNSUPPORTED';
|
|
5
|
+
message: string;
|
|
6
|
+
variantIds: string[];
|
|
7
|
+
};
|
|
8
|
+
export type ExportReferenceInventory = {
|
|
9
|
+
dependencies: string[];
|
|
10
|
+
externalReferences: OpaqueCmsReference[];
|
|
11
|
+
itemReferenceIds: ReadonlyMap<string, string>;
|
|
12
|
+
warnings: ExportReferenceWarning[];
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Inventories only the CMS content identity fields retained in exported variant payloads.
|
|
16
|
+
* Unknown payload fields are deliberately not interpreted as relationships.
|
|
17
|
+
* @param {string} workspaceId - Canonical source CMS workspace identifier.
|
|
18
|
+
* @param {ReadonlyMap<string, CmsRecord>} details - Exported variants keyed by variant ID.
|
|
19
|
+
* @returns {ExportReferenceInventory} Deterministic included and unresolved reference evidence.
|
|
20
|
+
*/
|
|
21
|
+
export declare function inventoryExportReferences(workspaceId: string, details: ReadonlyMap<string, CmsRecord>): ExportReferenceInventory;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
function nonemptyString(value) {
|
|
3
|
+
return typeof value === 'string' && value.length > 0;
|
|
4
|
+
}
|
|
5
|
+
function referenceId(workspaceId, kind, sourceId) {
|
|
6
|
+
const identity = JSON.stringify({ kind, sourceId, workspaceId });
|
|
7
|
+
return `ref:${createHash('sha256').update(identity).digest('hex')}`;
|
|
8
|
+
}
|
|
9
|
+
function containsCmsContentBodyReference(value) {
|
|
10
|
+
if (Array.isArray(value))
|
|
11
|
+
return value.some((item_) => containsCmsContentBodyReference(item_));
|
|
12
|
+
if (typeof value !== 'object' || value === null)
|
|
13
|
+
return false;
|
|
14
|
+
const record = value;
|
|
15
|
+
if (typeof record.ref === 'object' &&
|
|
16
|
+
record.ref !== null &&
|
|
17
|
+
nonemptyString(record.ref.contentKey)) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
return Object.values(record).some((item_) => containsCmsContentBodyReference(item_));
|
|
21
|
+
}
|
|
22
|
+
function compareReferences(left, right) {
|
|
23
|
+
return [left.kind, left.referenceId, left.portableKey.value]
|
|
24
|
+
.join('\u0000')
|
|
25
|
+
.localeCompare([right.kind, right.referenceId, right.portableKey.value].join('\u0000'));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Inventories only the CMS content identity fields retained in exported variant payloads.
|
|
29
|
+
* Unknown payload fields are deliberately not interpreted as relationships.
|
|
30
|
+
* @param {string} workspaceId - Canonical source CMS workspace identifier.
|
|
31
|
+
* @param {ReadonlyMap<string, CmsRecord>} details - Exported variants keyed by variant ID.
|
|
32
|
+
* @returns {ExportReferenceInventory} Deterministic included and unresolved reference evidence.
|
|
33
|
+
*/
|
|
34
|
+
export function inventoryExportReferences(workspaceId, details) {
|
|
35
|
+
const candidates = [];
|
|
36
|
+
const externalReferences = [];
|
|
37
|
+
const itemReferenceIds = new Map();
|
|
38
|
+
const warnings = [];
|
|
39
|
+
const includedById = new Map();
|
|
40
|
+
for (const [variantId, detail] of details) {
|
|
41
|
+
if ('references' in detail ||
|
|
42
|
+
'referencesList' in detail ||
|
|
43
|
+
containsCmsContentBodyReference(detail.contentBody)) {
|
|
44
|
+
const id = referenceId(workspaceId, 'cms.relationship', variantId);
|
|
45
|
+
externalReferences.push({
|
|
46
|
+
referenceId: id,
|
|
47
|
+
owner: 'cms',
|
|
48
|
+
kind: 'cms.relationship',
|
|
49
|
+
source: { workspaceId, sourceId: variantId },
|
|
50
|
+
portableKey: { scheme: 'cms-opaque-v1', value: variantId },
|
|
51
|
+
required: true,
|
|
52
|
+
resolution: 'unsupported',
|
|
53
|
+
});
|
|
54
|
+
warnings.push({
|
|
55
|
+
code: 'REFERENCE_UNSUPPORTED',
|
|
56
|
+
message: 'The exported CMS payload contains a relationship class without an evidenced portable resolver.',
|
|
57
|
+
variantIds: [variantId],
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (!nonemptyString(detail.contentKey))
|
|
61
|
+
continue;
|
|
62
|
+
candidates.push({
|
|
63
|
+
contentId: nonemptyString(detail.contentId) ? detail.contentId : undefined,
|
|
64
|
+
contentKey: detail.contentKey,
|
|
65
|
+
variantId,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
const idsByKey = new Map();
|
|
69
|
+
const keysById = new Map();
|
|
70
|
+
const incompleteKeys = new Set();
|
|
71
|
+
for (const candidate of candidates) {
|
|
72
|
+
if (candidate.contentId === undefined) {
|
|
73
|
+
incompleteKeys.add(candidate.contentKey);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const ids = idsByKey.get(candidate.contentKey) ?? new Set();
|
|
77
|
+
ids.add(candidate.contentId);
|
|
78
|
+
idsByKey.set(candidate.contentKey, ids);
|
|
79
|
+
const keys = keysById.get(candidate.contentId) ?? new Set();
|
|
80
|
+
keys.add(candidate.contentKey);
|
|
81
|
+
keysById.set(candidate.contentId, keys);
|
|
82
|
+
}
|
|
83
|
+
for (const candidate of candidates.toSorted((left, right) => left.variantId.localeCompare(right.variantId))) {
|
|
84
|
+
const conflicting = candidate.contentId !== undefined &&
|
|
85
|
+
((idsByKey.get(candidate.contentKey)?.size ?? 0) > 1 ||
|
|
86
|
+
incompleteKeys.has(candidate.contentKey) ||
|
|
87
|
+
(keysById.get(candidate.contentId)?.size ?? 0) > 1);
|
|
88
|
+
if (conflicting) {
|
|
89
|
+
const id = referenceId(workspaceId, 'cms.unknown', candidate.variantId);
|
|
90
|
+
externalReferences.push({
|
|
91
|
+
referenceId: id,
|
|
92
|
+
owner: 'cms',
|
|
93
|
+
kind: 'cms.unknown',
|
|
94
|
+
source: { workspaceId, sourceId: candidate.variantId },
|
|
95
|
+
portableKey: { scheme: 'cms-opaque-v1', value: candidate.contentKey },
|
|
96
|
+
required: true,
|
|
97
|
+
resolution: 'unsupported',
|
|
98
|
+
});
|
|
99
|
+
warnings.push({
|
|
100
|
+
code: 'REFERENCE_UNSUPPORTED',
|
|
101
|
+
message: 'A CMS content reference has conflicting retained identity evidence.',
|
|
102
|
+
variantIds: [candidate.variantId],
|
|
103
|
+
});
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (candidate.contentId === undefined) {
|
|
107
|
+
const id = referenceId(workspaceId, 'cms.unknown', candidate.variantId);
|
|
108
|
+
externalReferences.push({
|
|
109
|
+
referenceId: id,
|
|
110
|
+
owner: 'cms',
|
|
111
|
+
kind: 'cms.unknown',
|
|
112
|
+
source: { workspaceId, sourceId: candidate.variantId },
|
|
113
|
+
portableKey: { scheme: 'cms-opaque-v1', value: candidate.contentKey },
|
|
114
|
+
required: true,
|
|
115
|
+
resolution: 'unresolved',
|
|
116
|
+
});
|
|
117
|
+
warnings.push({
|
|
118
|
+
code: 'REFERENCE_UNRESOLVED',
|
|
119
|
+
message: 'A CMS content reference lacks retained canonical content identity.',
|
|
120
|
+
variantIds: [candidate.variantId],
|
|
121
|
+
});
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const id = referenceId(workspaceId, 'cms.content', candidate.contentId);
|
|
125
|
+
itemReferenceIds.set(candidate.variantId, id);
|
|
126
|
+
if (!includedById.has(candidate.contentId)) {
|
|
127
|
+
includedById.set(candidate.contentId, {
|
|
128
|
+
referenceId: id,
|
|
129
|
+
owner: 'cms',
|
|
130
|
+
kind: 'cms.content',
|
|
131
|
+
source: { workspaceId, sourceId: candidate.contentId },
|
|
132
|
+
portableKey: { scheme: 'cms-opaque-v1', value: candidate.contentKey },
|
|
133
|
+
required: true,
|
|
134
|
+
resolution: 'included',
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
externalReferences.push(...includedById.values());
|
|
139
|
+
externalReferences.sort(compareReferences);
|
|
140
|
+
warnings.sort((left, right) => [left.code, left.variantIds.join('\u0000')]
|
|
141
|
+
.join('\u0000')
|
|
142
|
+
.localeCompare([right.code, right.variantIds.join('\u0000')].join('\u0000')));
|
|
143
|
+
return {
|
|
144
|
+
dependencies: [],
|
|
145
|
+
externalReferences,
|
|
146
|
+
itemReferenceIds,
|
|
147
|
+
warnings,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=export-references.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-references.js","sourceRoot":"","sources":["../../src/services/export-references.ts"],"names":[],"mappings":"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"}
|