swallowkit 1.0.2 → 1.1.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/dist/cli/commands/create-migration.d.ts +3 -0
- package/dist/cli/commands/create-migration.d.ts.map +1 -0
- package/dist/cli/commands/create-migration.js +16 -0
- package/dist/cli/commands/create-migration.js.map +1 -0
- package/dist/cli/commands/index.d.ts +2 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +5 -1
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +2 -0
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/migrations.d.ts +3 -0
- package/dist/cli/commands/migrations.d.ts.map +1 -0
- package/dist/cli/commands/migrations.js +22 -0
- package/dist/cli/commands/migrations.js.map +1 -0
- package/dist/cli/commands/provision.d.ts +1 -1
- package/dist/cli/commands/provision.d.ts.map +1 -1
- package/dist/cli/commands/provision.js +95 -185
- package/dist/cli/commands/provision.js.map +1 -1
- package/dist/cli/commands/scaffold.d.ts.map +1 -1
- package/dist/cli/commands/scaffold.js +6 -130
- package/dist/cli/commands/scaffold.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/operations/migration-generator.d.ts +10 -0
- package/dist/core/operations/migration-generator.d.ts.map +1 -0
- package/dist/core/operations/migration-generator.js +194 -0
- package/dist/core/operations/migration-generator.js.map +1 -0
- package/dist/core/operations/provision-operations.d.ts +19 -0
- package/dist/core/operations/provision-operations.d.ts.map +1 -1
- package/dist/core/operations/provision-operations.js +299 -30
- package/dist/core/operations/provision-operations.js.map +1 -1
- package/dist/core/project/capabilities.js +1 -1
- package/dist/core/project/capabilities.js.map +1 -1
- package/dist/core/project/infra.d.ts +4 -0
- package/dist/core/project/infra.d.ts.map +1 -1
- package/dist/core/project/infra.js +19 -1
- package/dist/core/project/infra.js.map +1 -1
- package/dist/core/project/migrations.d.ts +53 -0
- package/dist/core/project/migrations.d.ts.map +1 -0
- package/dist/core/project/migrations.js +262 -0
- package/dist/core/project/migrations.js.map +1 -0
- package/dist/core/project/workflows.d.ts.map +1 -1
- package/dist/core/project/workflows.js +7 -3
- package/dist/core/project/workflows.js.map +1 -1
- package/dist/core/scaffold/native-schema-generator.d.ts.map +1 -1
- package/dist/core/scaffold/native-schema-generator.js +61 -13
- package/dist/core/scaffold/native-schema-generator.js.map +1 -1
- package/dist/machine/index.d.ts.map +1 -1
- package/dist/machine/index.js +6 -0
- package/dist/machine/index.js.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +11 -2
- package/dist/mcp/index.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/agent-loop-phase34.test.ts +139 -0
- package/src/__tests__/init.test.ts +8 -0
- package/src/__tests__/migration.test.ts +116 -0
- package/src/__tests__/plan-apply.test.ts +41 -11
- package/src/__tests__/scaffold.test.ts +7 -4
- package/src/cli/commands/create-migration.ts +13 -0
- package/src/cli/commands/index.ts +2 -0
- package/src/cli/commands/init.ts +2 -0
- package/src/cli/commands/migrations.ts +20 -0
- package/src/cli/commands/provision.ts +115 -184
- package/src/cli/commands/scaffold.ts +6 -145
- package/src/cli/index.ts +4 -0
- package/src/core/operations/migration-generator.ts +188 -0
- package/src/core/operations/provision-operations.ts +391 -44
- package/src/core/project/capabilities.ts +1 -1
- package/src/core/project/infra.ts +23 -1
- package/src/core/project/migrations.ts +274 -0
- package/src/core/project/workflows.ts +7 -3
- package/src/core/scaffold/native-schema-generator.ts +69 -13
- package/src/machine/index.ts +7 -1
- package/src/mcp/index.ts +8 -2
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export declare const MIGRATION_MANIFEST_VERSION = 1;
|
|
2
|
+
export declare const MIGRATION_MANIFEST_PATH: string;
|
|
3
|
+
export interface MigrationBaselineFile {
|
|
4
|
+
path: string;
|
|
5
|
+
checksum: string;
|
|
6
|
+
}
|
|
7
|
+
export interface MigrationBaseline {
|
|
8
|
+
version: 0;
|
|
9
|
+
legacy: boolean;
|
|
10
|
+
files: MigrationBaselineFile[];
|
|
11
|
+
checksum: string;
|
|
12
|
+
}
|
|
13
|
+
export interface InfrastructureMigration {
|
|
14
|
+
version: number;
|
|
15
|
+
slug: string;
|
|
16
|
+
template: string;
|
|
17
|
+
parameters?: string;
|
|
18
|
+
source: "model" | "custom";
|
|
19
|
+
sourceModel?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface MigrationManifest {
|
|
22
|
+
schemaVersion: 1;
|
|
23
|
+
projectId: string;
|
|
24
|
+
baseline: MigrationBaseline;
|
|
25
|
+
migrations: InfrastructureMigration[];
|
|
26
|
+
}
|
|
27
|
+
export interface ResolvedMigration extends InfrastructureMigration {
|
|
28
|
+
checksum: string;
|
|
29
|
+
cumulativeChecksum: string;
|
|
30
|
+
}
|
|
31
|
+
export interface MigrationState {
|
|
32
|
+
schemaVersion: 1;
|
|
33
|
+
version: number;
|
|
34
|
+
checksum: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function computeBaselineChecksum(files: MigrationBaselineFile[]): string;
|
|
37
|
+
export declare function findBaselineDrift(manifest: MigrationManifest, projectRoot?: string): string[];
|
|
38
|
+
export declare function collectLegacyBaselineFiles(projectRoot?: string): MigrationBaselineFile[];
|
|
39
|
+
export declare function createMigrationManifest(projectRoot?: string, options?: {
|
|
40
|
+
legacy?: boolean;
|
|
41
|
+
projectId?: string;
|
|
42
|
+
}): MigrationManifest;
|
|
43
|
+
export declare function saveMigrationManifest(manifest: MigrationManifest, projectRoot?: string): void;
|
|
44
|
+
export declare function replaceMigrationManifest(manifest: MigrationManifest, projectRoot?: string): void;
|
|
45
|
+
export declare function loadMigrationManifest(projectRoot?: string): MigrationManifest;
|
|
46
|
+
export declare function validateMigrationManifest(manifest: MigrationManifest, projectRoot?: string): void;
|
|
47
|
+
export declare function resolveMigrations(manifest: MigrationManifest, projectRoot?: string): ResolvedMigration[];
|
|
48
|
+
export declare function checksumAtVersion(manifest: MigrationManifest, version: number, projectRoot?: string): string;
|
|
49
|
+
export declare function getMigrationTagKey(projectId: string): string;
|
|
50
|
+
export declare function encodeMigrationState(state: MigrationState): string;
|
|
51
|
+
export declare function decodeMigrationState(value: string): MigrationState;
|
|
52
|
+
export declare function selectPendingMigrations(manifest: MigrationManifest, remoteState: MigrationState, projectRoot?: string): ResolvedMigration[];
|
|
53
|
+
//# sourceMappingURL=migrations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../src/core/project/migrations.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAC5C,eAAO,MAAM,uBAAuB,QAAoD,CAAC;AAEzF,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,qBAAqB,EAAE,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,CAAC,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,UAAU,EAAE,uBAAuB,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,iBAAkB,SAAQ,uBAAuB;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,CAAC,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAgCD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAE9E;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,WAAW,GAAE,MAAsB,GAAG,MAAM,EAAE,CAO5G;AAED,wBAAgB,0BAA0B,CAAC,WAAW,GAAE,MAAsB,GAAG,qBAAqB,EAAE,CAoBvG;AAED,wBAAgB,uBAAuB,CACrC,WAAW,GAAE,MAAsB,EACnC,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACrD,iBAAiB,CAanB;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,WAAW,GAAE,MAAsB,GAAG,IAAI,CAO5G;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,WAAW,GAAE,MAAsB,GAAG,IAAI,CAO/G;AAED,wBAAgB,qBAAqB,CAAC,WAAW,GAAE,MAAsB,GAAG,iBAAiB,CAa5F;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,WAAW,GAAE,MAAsB,GAAG,IAAI,CAsDhH;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,WAAW,GAAE,MAAsB,GAAG,iBAAiB,EAAE,CAYvH;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAE,MAAsB,GAAG,MAAM,CAK3H;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAG5D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAKlE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAIlE;AAED,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,iBAAiB,EAC3B,WAAW,EAAE,cAAc,EAC3B,WAAW,GAAE,MAAsB,GAClC,iBAAiB,EAAE,CAUrB"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.MIGRATION_MANIFEST_PATH = exports.MIGRATION_MANIFEST_VERSION = void 0;
|
|
37
|
+
exports.computeBaselineChecksum = computeBaselineChecksum;
|
|
38
|
+
exports.findBaselineDrift = findBaselineDrift;
|
|
39
|
+
exports.collectLegacyBaselineFiles = collectLegacyBaselineFiles;
|
|
40
|
+
exports.createMigrationManifest = createMigrationManifest;
|
|
41
|
+
exports.saveMigrationManifest = saveMigrationManifest;
|
|
42
|
+
exports.replaceMigrationManifest = replaceMigrationManifest;
|
|
43
|
+
exports.loadMigrationManifest = loadMigrationManifest;
|
|
44
|
+
exports.validateMigrationManifest = validateMigrationManifest;
|
|
45
|
+
exports.resolveMigrations = resolveMigrations;
|
|
46
|
+
exports.checksumAtVersion = checksumAtVersion;
|
|
47
|
+
exports.getMigrationTagKey = getMigrationTagKey;
|
|
48
|
+
exports.encodeMigrationState = encodeMigrationState;
|
|
49
|
+
exports.decodeMigrationState = decodeMigrationState;
|
|
50
|
+
exports.selectPendingMigrations = selectPendingMigrations;
|
|
51
|
+
const crypto = __importStar(require("crypto"));
|
|
52
|
+
const fs = __importStar(require("fs"));
|
|
53
|
+
const path = __importStar(require("path"));
|
|
54
|
+
const errors_1 = require("../../machine/errors");
|
|
55
|
+
const file_session_1 = require("../operations/file-session");
|
|
56
|
+
exports.MIGRATION_MANIFEST_VERSION = 1;
|
|
57
|
+
exports.MIGRATION_MANIFEST_PATH = path.join("infra", "migrations", "manifest.json");
|
|
58
|
+
function fail(code, message, details) {
|
|
59
|
+
throw new errors_1.MachineCommandError(code, message, details, "blocked");
|
|
60
|
+
}
|
|
61
|
+
function normalizeRelativePath(value) {
|
|
62
|
+
const normalized = value.replace(/\\/g, "/");
|
|
63
|
+
if (path.posix.isAbsolute(normalized) || normalized === ".." || normalized.startsWith("../") || normalized.includes("/../")) {
|
|
64
|
+
fail("invalid-migration-manifest", `Migration path must stay inside the project: ${value}`);
|
|
65
|
+
}
|
|
66
|
+
return normalized;
|
|
67
|
+
}
|
|
68
|
+
function readRequiredFile(projectRoot, relativePath) {
|
|
69
|
+
const normalized = normalizeRelativePath(relativePath);
|
|
70
|
+
const absolutePath = path.resolve(projectRoot, normalized);
|
|
71
|
+
const rootWithSeparator = `${path.resolve(projectRoot)}${path.sep}`;
|
|
72
|
+
if (!absolutePath.startsWith(rootWithSeparator) || !fs.existsSync(absolutePath) || !fs.statSync(absolutePath).isFile()) {
|
|
73
|
+
fail("migration-file-not-found", `Migration file not found: ${normalized}`);
|
|
74
|
+
}
|
|
75
|
+
const realPath = fs.realpathSync(absolutePath);
|
|
76
|
+
if (!realPath.startsWith(rootWithSeparator)) {
|
|
77
|
+
fail("invalid-migration-manifest", `Migration file resolves outside the project: ${normalized}`);
|
|
78
|
+
}
|
|
79
|
+
return fs.readFileSync(absolutePath, "utf-8");
|
|
80
|
+
}
|
|
81
|
+
function checksumObject(value) {
|
|
82
|
+
return (0, file_session_1.hashContent)(JSON.stringify(value));
|
|
83
|
+
}
|
|
84
|
+
function computeBaselineChecksum(files) {
|
|
85
|
+
return checksumObject([...files].sort((left, right) => left.path.localeCompare(right.path)));
|
|
86
|
+
}
|
|
87
|
+
function findBaselineDrift(manifest, projectRoot = process.cwd()) {
|
|
88
|
+
return manifest.baseline.files
|
|
89
|
+
.filter((file) => {
|
|
90
|
+
const absolutePath = path.join(projectRoot, normalizeRelativePath(file.path));
|
|
91
|
+
return !fs.existsSync(absolutePath) || (0, file_session_1.hashContent)(fs.readFileSync(absolutePath, "utf-8")) !== file.checksum;
|
|
92
|
+
})
|
|
93
|
+
.map((file) => file.path);
|
|
94
|
+
}
|
|
95
|
+
function collectLegacyBaselineFiles(projectRoot = process.cwd()) {
|
|
96
|
+
const infraRoot = path.join(projectRoot, "infra");
|
|
97
|
+
if (!fs.existsSync(path.join(infraRoot, "main.bicep"))) {
|
|
98
|
+
fail("infra-not-found", 'infra/main.bicep not found. Run this command from a SwallowKit project.');
|
|
99
|
+
}
|
|
100
|
+
const files = [];
|
|
101
|
+
const visit = (directory) => {
|
|
102
|
+
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
103
|
+
const absolutePath = path.join(directory, entry.name);
|
|
104
|
+
if (entry.isDirectory()) {
|
|
105
|
+
if (entry.name !== "migrations")
|
|
106
|
+
visit(absolutePath);
|
|
107
|
+
}
|
|
108
|
+
else if (entry.isFile() && (entry.name.endsWith(".bicep") || entry.name.endsWith(".json"))) {
|
|
109
|
+
const relativePath = path.relative(projectRoot, absolutePath).replace(/\\/g, "/");
|
|
110
|
+
files.push({ path: relativePath, checksum: (0, file_session_1.hashContent)(fs.readFileSync(absolutePath, "utf-8")) });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
visit(infraRoot);
|
|
115
|
+
return files.sort((left, right) => left.path.localeCompare(right.path));
|
|
116
|
+
}
|
|
117
|
+
function createMigrationManifest(projectRoot = process.cwd(), options = {}) {
|
|
118
|
+
const files = collectLegacyBaselineFiles(projectRoot);
|
|
119
|
+
return {
|
|
120
|
+
schemaVersion: exports.MIGRATION_MANIFEST_VERSION,
|
|
121
|
+
projectId: options.projectId ?? crypto.randomUUID(),
|
|
122
|
+
baseline: {
|
|
123
|
+
version: 0,
|
|
124
|
+
legacy: options.legacy ?? false,
|
|
125
|
+
files,
|
|
126
|
+
checksum: computeBaselineChecksum(files),
|
|
127
|
+
},
|
|
128
|
+
migrations: [],
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function saveMigrationManifest(manifest, projectRoot = process.cwd()) {
|
|
132
|
+
const manifestPath = path.join(projectRoot, exports.MIGRATION_MANIFEST_PATH);
|
|
133
|
+
if (fs.existsSync(manifestPath)) {
|
|
134
|
+
fail("migration-manifest-exists", `${exports.MIGRATION_MANIFEST_PATH} already exists.`);
|
|
135
|
+
}
|
|
136
|
+
fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
137
|
+
fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf-8");
|
|
138
|
+
}
|
|
139
|
+
function replaceMigrationManifest(manifest, projectRoot = process.cwd()) {
|
|
140
|
+
validateMigrationManifest(manifest, projectRoot);
|
|
141
|
+
const manifestPath = path.join(projectRoot, exports.MIGRATION_MANIFEST_PATH);
|
|
142
|
+
const temporaryPath = `${manifestPath}.tmp-${process.pid}`;
|
|
143
|
+
fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
144
|
+
fs.writeFileSync(temporaryPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf-8");
|
|
145
|
+
fs.renameSync(temporaryPath, manifestPath);
|
|
146
|
+
}
|
|
147
|
+
function loadMigrationManifest(projectRoot = process.cwd()) {
|
|
148
|
+
const manifestPath = path.join(projectRoot, exports.MIGRATION_MANIFEST_PATH);
|
|
149
|
+
if (!fs.existsSync(manifestPath)) {
|
|
150
|
+
fail("migration-manifest-not-found", `${exports.MIGRATION_MANIFEST_PATH} not found. Initialize migrations first.`);
|
|
151
|
+
}
|
|
152
|
+
let manifest;
|
|
153
|
+
try {
|
|
154
|
+
manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
fail("invalid-migration-manifest", `${exports.MIGRATION_MANIFEST_PATH} is not valid JSON.`);
|
|
158
|
+
}
|
|
159
|
+
validateMigrationManifest(manifest, projectRoot);
|
|
160
|
+
return manifest;
|
|
161
|
+
}
|
|
162
|
+
function validateMigrationManifest(manifest, projectRoot = process.cwd()) {
|
|
163
|
+
if (!manifest || typeof manifest !== "object" ||
|
|
164
|
+
manifest.schemaVersion !== exports.MIGRATION_MANIFEST_VERSION ||
|
|
165
|
+
typeof manifest.projectId !== "string" || !manifest.projectId ||
|
|
166
|
+
!manifest.baseline || typeof manifest.baseline !== "object" ||
|
|
167
|
+
manifest.baseline.version !== 0 || typeof manifest.baseline.legacy !== "boolean" ||
|
|
168
|
+
!Array.isArray(manifest.baseline.files) || typeof manifest.baseline.checksum !== "string" ||
|
|
169
|
+
!Array.isArray(manifest.migrations)) {
|
|
170
|
+
fail("invalid-migration-manifest", "Unsupported or incomplete migration manifest.");
|
|
171
|
+
}
|
|
172
|
+
for (const file of manifest.baseline.files) {
|
|
173
|
+
if (!file || typeof file.path !== "string" || !/^[a-f0-9]{64}$/.test(file.checksum)) {
|
|
174
|
+
fail("invalid-migration-manifest", "Migration baseline contains an invalid file record.");
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const baselineFiles = manifest.baseline.files.map((file) => ({
|
|
178
|
+
path: normalizeRelativePath(file.path),
|
|
179
|
+
checksum: file.checksum,
|
|
180
|
+
}));
|
|
181
|
+
if (new Set(baselineFiles.map((file) => file.path)).size !== baselineFiles.length) {
|
|
182
|
+
fail("invalid-migration-manifest", "Migration baseline contains duplicate paths.");
|
|
183
|
+
}
|
|
184
|
+
if (computeBaselineChecksum(baselineFiles) !== manifest.baseline.checksum) {
|
|
185
|
+
fail("migration-checksum-mismatch", "The migration baseline inventory was modified.");
|
|
186
|
+
}
|
|
187
|
+
const sorted = [...manifest.migrations].sort((left, right) => left.version - right.version);
|
|
188
|
+
for (let index = 0; index < sorted.length; index += 1) {
|
|
189
|
+
const migration = sorted[index];
|
|
190
|
+
if (!migration || !Number.isSafeInteger(migration.version) || typeof migration.slug !== "string" || typeof migration.template !== "string") {
|
|
191
|
+
fail("invalid-migration-manifest", "Migration manifest contains an invalid entry.");
|
|
192
|
+
}
|
|
193
|
+
const expectedVersion = index + 1;
|
|
194
|
+
if (migration.version !== expectedVersion || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(migration.slug)) {
|
|
195
|
+
fail("invalid-migration-manifest", `Migration versions must be contiguous and slugs must be kebab-case (expected version ${expectedVersion}).`);
|
|
196
|
+
}
|
|
197
|
+
if (migration.source !== "model" && migration.source !== "custom") {
|
|
198
|
+
fail("invalid-migration-manifest", `Migration ${migration.version} has an invalid source.`);
|
|
199
|
+
}
|
|
200
|
+
const template = normalizeRelativePath(migration.template);
|
|
201
|
+
if (!template.startsWith("infra/migrations/") || !template.endsWith(".bicep")) {
|
|
202
|
+
fail("invalid-migration-manifest", `Migration template must be a .bicep file under infra/migrations: ${template}`);
|
|
203
|
+
}
|
|
204
|
+
readRequiredFile(projectRoot, template);
|
|
205
|
+
if (migration.parameters) {
|
|
206
|
+
const parameters = normalizeRelativePath(migration.parameters);
|
|
207
|
+
if (!parameters.startsWith("infra/migrations/") || !parameters.endsWith(".json")) {
|
|
208
|
+
fail("invalid-migration-manifest", `Migration parameters must be JSON under infra/migrations: ${parameters}`);
|
|
209
|
+
}
|
|
210
|
+
readRequiredFile(projectRoot, parameters);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function resolveMigrations(manifest, projectRoot = process.cwd()) {
|
|
215
|
+
validateMigrationManifest(manifest, projectRoot);
|
|
216
|
+
let cumulativeChecksum = manifest.baseline.checksum;
|
|
217
|
+
return [...manifest.migrations]
|
|
218
|
+
.sort((left, right) => left.version - right.version)
|
|
219
|
+
.map((migration) => {
|
|
220
|
+
const templateContent = readRequiredFile(projectRoot, migration.template);
|
|
221
|
+
const parametersContent = migration.parameters ? readRequiredFile(projectRoot, migration.parameters) : null;
|
|
222
|
+
const checksum = checksumObject({ migration, templateContent, parametersContent });
|
|
223
|
+
cumulativeChecksum = checksumObject({ previous: cumulativeChecksum, version: migration.version, checksum });
|
|
224
|
+
return { ...migration, checksum, cumulativeChecksum };
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
function checksumAtVersion(manifest, version, projectRoot = process.cwd()) {
|
|
228
|
+
if (version === 0)
|
|
229
|
+
return manifest.baseline.checksum;
|
|
230
|
+
const migration = resolveMigrations(manifest, projectRoot).find((item) => item.version === version);
|
|
231
|
+
if (!migration)
|
|
232
|
+
fail("migration-version-not-found", `Migration version ${version} does not exist locally.`);
|
|
233
|
+
return migration.cumulativeChecksum;
|
|
234
|
+
}
|
|
235
|
+
function getMigrationTagKey(projectId) {
|
|
236
|
+
const projectHash = crypto.createHash("sha256").update(projectId).digest("hex").slice(0, 12);
|
|
237
|
+
return `swallowkit-migration-${projectHash}`;
|
|
238
|
+
}
|
|
239
|
+
function encodeMigrationState(state) {
|
|
240
|
+
if (state.schemaVersion !== 1 || !Number.isSafeInteger(state.version) || state.version < 0 || !/^[a-f0-9]{64}$/.test(state.checksum)) {
|
|
241
|
+
fail("invalid-migration-state", "Cannot encode an invalid migration state.");
|
|
242
|
+
}
|
|
243
|
+
return `1:${state.version}:${state.checksum}`;
|
|
244
|
+
}
|
|
245
|
+
function decodeMigrationState(value) {
|
|
246
|
+
const match = /^1:(0|[1-9]\d*):([a-f0-9]{64})$/.exec(value);
|
|
247
|
+
if (!match)
|
|
248
|
+
fail("invalid-migration-state", "The Azure migration state tag is invalid.");
|
|
249
|
+
return { schemaVersion: 1, version: Number(match[1]), checksum: match[2] };
|
|
250
|
+
}
|
|
251
|
+
function selectPendingMigrations(manifest, remoteState, projectRoot = process.cwd()) {
|
|
252
|
+
const latestVersion = manifest.migrations.length;
|
|
253
|
+
if (remoteState.version > latestVersion) {
|
|
254
|
+
fail("migration-state-ahead", `Azure is at migration ${remoteState.version}, but local latest is ${latestVersion}.`);
|
|
255
|
+
}
|
|
256
|
+
const expectedChecksum = checksumAtVersion(manifest, remoteState.version, projectRoot);
|
|
257
|
+
if (remoteState.checksum !== expectedChecksum) {
|
|
258
|
+
fail("migration-checksum-mismatch", `Azure migration ${remoteState.version} does not match the local history.`);
|
|
259
|
+
}
|
|
260
|
+
return resolveMigrations(manifest, projectRoot).filter((migration) => migration.version > remoteState.version);
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=migrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../../src/core/project/migrations.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../../src/core/project/workflows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,WAAW,WAAW;IAC1B,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../../src/core/project/workflows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,WAAW,WAAW;IAC1B,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,CAgO/D;AAED,eAAO,MAAM,aAAa,QAAwC,CAAC;AACnE,eAAO,MAAM,UAAU,QAAiC,CAAC;AAEzD,uDAAuD;AACvD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAS9E;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAS9F;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAS7E"}
|
|
@@ -198,7 +198,7 @@ Stop and ask a human when:
|
|
|
198
198
|
skillDescription: "Provision Azure resources (Static Web Apps, Functions, Cosmos DB) for a SwallowKit project using the two-phase plan/apply flow with a mandatory human approval gate. Use when asked to deploy infrastructure, provision Azure, create resource groups, or run Bicep deployments.",
|
|
199
199
|
content: `# Workflow: Provision Azure resources
|
|
200
200
|
|
|
201
|
-
Goal:
|
|
201
|
+
Goal: bootstrap Azure once, then apply only pending versioned infrastructure migrations with an explicit human approval gate.
|
|
202
202
|
|
|
203
203
|
## Rules
|
|
204
204
|
|
|
@@ -207,6 +207,8 @@ Goal: deploy the Bicep infrastructure with an explicit human approval gate.
|
|
|
207
207
|
- Never pass \`--approve\` to \`apply provision\` unless a human explicitly
|
|
208
208
|
instructed you to provision in this session.
|
|
209
209
|
- Inspect infra locally first — no \`az\` calls are needed for inspection.
|
|
210
|
+
- Never edit an applied migration. Create a corrective migration instead.
|
|
211
|
+
- Never use \`--reconcile\` for an ordinary model or resource addition.
|
|
210
212
|
|
|
211
213
|
## Steps
|
|
212
214
|
|
|
@@ -215,8 +217,10 @@ Goal: deploy the Bicep infrastructure with an explicit human approval gate.
|
|
|
215
217
|
- review parameters, modules, outputs, and container wiring warnings.
|
|
216
218
|
2. Compute the provisioning plan (no resources are created):
|
|
217
219
|
\`${runCmd} swallowkit machine plan provision -g <resource-group> --location <region>\`
|
|
218
|
-
|
|
219
|
-
|
|
220
|
+
- the plan reports \`bootstrap\`, \`migrate\`, \`noop\`, or \`adoption-required\`.
|
|
221
|
+
- it lists only pending migrations and the exact \`az\` commands that would run.
|
|
222
|
+
- for an older untagged environment, first run \`${runCmd} swallowkit migrations init --legacy-baseline\`, then plan with \`--adopt-existing --baseline 0 --what-if\`.
|
|
223
|
+
- only intentional baseline changes use \`--reconcile --what-if\`; this can reset template-managed settings.
|
|
220
224
|
3. Present the plan to the human and wait for explicit approval.
|
|
221
225
|
4. Only after approval:
|
|
222
226
|
\`${runCmd} swallowkit machine apply provision --plan <planId> --approve\`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflows.js","sourceRoot":"","sources":["../../../src/core/project/workflows.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuBH,
|
|
1
|
+
{"version":3,"file":"workflows.js","sourceRoot":"","sources":["../../../src/core/project/workflows.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-schema-generator.d.ts","sourceRoot":"","sources":["../../../src/core/scaffold/native-schema-generator.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,SAAS,EAAe,MAAM,gBAAgB,CAAC;AAYxD,eAAO,MAAM,yBAAyB,WAAW,CAAC;AAClD,eAAO,MAAM,iCAAiC,4CAA4C,CAAC;AA4C3F,wBAAgB,oCAAoC,IAAI,MAAM,CAe7D;AAED,wBAAgB,oCAAoC,IAAI,MAAM,CAE7D;
|
|
1
|
+
{"version":3,"file":"native-schema-generator.d.ts","sourceRoot":"","sources":["../../../src/core/scaffold/native-schema-generator.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,SAAS,EAAe,MAAM,gBAAgB,CAAC;AAYxD,eAAO,MAAM,yBAAyB,WAAW,CAAC;AAClD,eAAO,MAAM,iCAAiC,4CAA4C,CAAC;AA4C3F,wBAAgB,oCAAoC,IAAI,MAAM,CAe7D;AAED,wBAAgB,oCAAoC,IAAI,MAAM,CAE7D;AA4ED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAErF;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAErF;AAED,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAkB3F;AAED,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAkB3F;AA0kBD;;;GAGG;AACH,wBAAsB,6BAA6B,CACjD,MAAM,EAAE,SAAS,EAAE,EACnB,SAAS,EAAE,SAAS,EACpB,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,YAAY,CAAC,EACvD,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAmDf;AA8DD,wBAAsB,+BAA+B,CACnD,MAAM,EAAE,SAAS,EAAE,EACnB,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,YAAY,CAAC,EACvD,OAAO,GAAE,oBAAyD,GACjE,OAAO,CAAC,IAAI,CAAC,CAqCf"}
|
|
@@ -113,6 +113,53 @@ function toPascalIdentifier(value) {
|
|
|
113
113
|
}
|
|
114
114
|
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
115
115
|
}
|
|
116
|
+
const CSHARP_RESERVED_IDENTIFIERS = new Set([
|
|
117
|
+
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked",
|
|
118
|
+
"class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else",
|
|
119
|
+
"enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach",
|
|
120
|
+
"goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long",
|
|
121
|
+
"namespace", "new", "null", "object", "operator", "out", "override", "params", "private",
|
|
122
|
+
"protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof",
|
|
123
|
+
"stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try",
|
|
124
|
+
"typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void",
|
|
125
|
+
"volatile", "while",
|
|
126
|
+
]);
|
|
127
|
+
function toCSharpEnumMemberBase(value) {
|
|
128
|
+
const encoded = Array.from(value)
|
|
129
|
+
.map((character) => {
|
|
130
|
+
if (/^[A-Za-z0-9_-]$/.test(character))
|
|
131
|
+
return character;
|
|
132
|
+
if (/^\s$/.test(character))
|
|
133
|
+
return "-";
|
|
134
|
+
return `-U${character.codePointAt(0).toString(16).toUpperCase()}-`;
|
|
135
|
+
})
|
|
136
|
+
.join("");
|
|
137
|
+
let identifier = toPascalIdentifier(encoded).replace(/[^A-Za-z0-9_]/g, "");
|
|
138
|
+
if (!identifier)
|
|
139
|
+
identifier = "Value";
|
|
140
|
+
if (/^[0-9]/.test(identifier))
|
|
141
|
+
identifier = `Value${identifier}`;
|
|
142
|
+
if (CSHARP_RESERVED_IDENTIFIERS.has(identifier))
|
|
143
|
+
identifier = `Value${identifier}`;
|
|
144
|
+
return identifier;
|
|
145
|
+
}
|
|
146
|
+
function buildCSharpEnumMemberMap(values, enumType) {
|
|
147
|
+
const uniqueValues = [...new Set(values)];
|
|
148
|
+
const bases = uniqueValues.map((value) => ({ value, base: toCSharpEnumMemberBase(value) }));
|
|
149
|
+
const baseCounts = new Map();
|
|
150
|
+
for (const entry of bases)
|
|
151
|
+
baseCounts.set(entry.base, (baseCounts.get(entry.base) ?? 0) + 1);
|
|
152
|
+
return bases.map(({ value, base }) => {
|
|
153
|
+
let name = base;
|
|
154
|
+
if ((baseCounts.get(base) ?? 0) > 1 || name === enumType) {
|
|
155
|
+
name = `${base}_${Buffer.from(value, "utf-8").toString("hex").toUpperCase() || "Empty"}`;
|
|
156
|
+
}
|
|
157
|
+
return { value, name };
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
function csharpStringLiteral(value) {
|
|
161
|
+
return JSON.stringify(value);
|
|
162
|
+
}
|
|
116
163
|
function isDateLikeField(field) {
|
|
117
164
|
return field.type === "date" || (field.type === "string" && field.name.toLowerCase().endsWith("at"));
|
|
118
165
|
}
|
|
@@ -252,21 +299,21 @@ namespace SwallowKitBackendModels.Client
|
|
|
252
299
|
}
|
|
253
300
|
`;
|
|
254
301
|
}
|
|
255
|
-
function buildCSharpEnumMembers(
|
|
256
|
-
return
|
|
257
|
-
.map((
|
|
302
|
+
function buildCSharpEnumMembers(members) {
|
|
303
|
+
return members
|
|
304
|
+
.map((member, index) => ` ${member.name} = ${index + 1}`)
|
|
258
305
|
.join(",\n\n");
|
|
259
306
|
}
|
|
260
|
-
function buildCSharpEnumFromStringCases(field, nullable) {
|
|
307
|
+
function buildCSharpEnumFromStringCases(field, members, nullable) {
|
|
261
308
|
const enumType = `${toPascalIdentifier(field.name)}Enum`;
|
|
262
|
-
return
|
|
263
|
-
.map((
|
|
309
|
+
return members
|
|
310
|
+
.map((member) => ` if (value.Equals(${csharpStringLiteral(member.value)}, StringComparison.Ordinal))\n return ${enumType}.${member.name};`)
|
|
264
311
|
.join("\n\n") + (nullable ? `\n\n return null;` : `\n\n throw new NotImplementedException($"Could not convert value to type ${enumType}: '{value}'");`);
|
|
265
312
|
}
|
|
266
|
-
function buildCSharpEnumToJsonCases(field) {
|
|
313
|
+
function buildCSharpEnumToJsonCases(field, members) {
|
|
267
314
|
const enumType = `${toPascalIdentifier(field.name)}Enum`;
|
|
268
|
-
return
|
|
269
|
-
.map((
|
|
315
|
+
return members
|
|
316
|
+
.map((member) => ` if (value == ${enumType}.${member.name})\n return ${csharpStringLiteral(member.value)};`)
|
|
270
317
|
.join("\n\n");
|
|
271
318
|
}
|
|
272
319
|
function generateLegacyCompatibleCSharpModelSource(model) {
|
|
@@ -285,28 +332,29 @@ function generateLegacyCompatibleCSharpModelSource(model) {
|
|
|
285
332
|
.filter((field) => field.enumValues?.length)
|
|
286
333
|
.map((field) => {
|
|
287
334
|
const enumType = `${toPascalIdentifier(field.name)}Enum`;
|
|
335
|
+
const enumMembers = buildCSharpEnumMemberMap(field.enumValues, enumType);
|
|
288
336
|
return ` /// <summary>
|
|
289
337
|
/// Defines ${toPascalIdentifier(field.name)}
|
|
290
338
|
/// </summary>
|
|
291
339
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
|
292
340
|
public enum ${enumType}
|
|
293
341
|
{
|
|
294
|
-
${buildCSharpEnumMembers(
|
|
342
|
+
${buildCSharpEnumMembers(enumMembers)}
|
|
295
343
|
}
|
|
296
344
|
|
|
297
345
|
public static ${enumType} ${enumType}FromString(string value)
|
|
298
346
|
{
|
|
299
|
-
${buildCSharpEnumFromStringCases(field, false)}
|
|
347
|
+
${buildCSharpEnumFromStringCases(field, enumMembers, false)}
|
|
300
348
|
}
|
|
301
349
|
|
|
302
350
|
public static ${enumType}? ${enumType}FromStringOrDefault(string value)
|
|
303
351
|
{
|
|
304
|
-
${buildCSharpEnumFromStringCases(field, true)}
|
|
352
|
+
${buildCSharpEnumFromStringCases(field, enumMembers, true)}
|
|
305
353
|
}
|
|
306
354
|
|
|
307
355
|
public static string ${enumType}ToJsonValue(${enumType}? value)
|
|
308
356
|
{
|
|
309
|
-
${buildCSharpEnumToJsonCases(field)}
|
|
357
|
+
${buildCSharpEnumToJsonCases(field, enumMembers)}
|
|
310
358
|
|
|
311
359
|
throw new NotImplementedException($"Value could not be handled: '{value}'");
|
|
312
360
|
}`;
|