47 lines
1.9 KiB
TypeScript
47 lines
1.9 KiB
TypeScript
import { assertPublicFileTarget } from '../fleet/private-config.js';
|
|
import { db } from '../db/index.js';
|
|
import { blobSize, getFileBlob } from '../db/file-blobs.js';
|
|
import type { LaunchRecipePlan } from '../fleet/launch-recipes.js';
|
|
import type { StagedFileChange } from '../fleet/staged-files.js';
|
|
|
|
/** Build the replacement with the exact requested additions, updates and removals. */
|
|
export function applyActivationFiles(
|
|
recipe: LaunchRecipePlan,
|
|
operationId: string,
|
|
includeContent = false
|
|
): void {
|
|
const changes = db()
|
|
.prepare(
|
|
`SELECT f.*, ${blobSize('f.content_hash')} AS size, v.version FROM staged_file_changes f
|
|
JOIN provisioning_sources s ON s.kind=f.source_kind AND s.source_id=f.source_id AND s.server=f.server
|
|
LEFT JOIN script_versions v ON v.id=f.script_version_id
|
|
WHERE s.operation_id=? AND f.state='pending' ORDER BY f.id`
|
|
)
|
|
.all(operationId) as (StagedFileChange & {
|
|
content_hash: string | null;
|
|
size: number;
|
|
version: number | null;
|
|
})[];
|
|
for (const change of changes) {
|
|
assertPublicFileTarget(change.server, change.kind, change.rel_path);
|
|
if (change.kind !== 'script' && change.kind !== 'config' && change.kind !== 'plugin')
|
|
throw new Error('File activation requires a runtime file kind.');
|
|
recipe.files = recipe.files.filter(
|
|
(file) => file.kind !== change.kind || file.path !== change.rel_path
|
|
);
|
|
if (!change.content_hash) continue;
|
|
recipe.files.push({
|
|
kind: change.kind,
|
|
name: change.rel_path,
|
|
path: change.rel_path,
|
|
versionId: change.script_version_id,
|
|
version: change.version,
|
|
sha256: change.content_hash,
|
|
size: change.size,
|
|
...(includeContent
|
|
? { content: getFileBlob(change.content_hash)!.toString('base64') }
|
|
: {})
|
|
});
|
|
}
|
|
}
|