@limlabs/limo
Version:
Infrastructure as Code generator
138 lines (137 loc) • 6.49 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateMigrationHistory = exports.getUnappliedMigrations = exports.getMigrationFiles = exports.getMigrationHistory = exports.ensureMigrations = exports.exportMigration = exports.parseMigration = exports.migrationSchema = exports.extraOptionTypes = exports.codeModTypes = exports.operationTypes = void 0;
const js_yaml_1 = __importDefault(require("js-yaml"));
const zod_1 = __importDefault(require("zod"));
const path_1 = __importDefault(require("path"));
const fs_1 = require("fs");
const promises_1 = require("fs/promises");
const yaml_1 = require("../yaml");
const process_1 = require("process");
exports.operationTypes = [
"addComponents",
"removeComponents",
"installComponents",
"addInstance",
"removeInstance",
"initResourceGroup",
"removeResourceGroup",
"applyResourceGroupChanges",
"undoResourceGroupChanges",
"configureFramework",
"runCodeMod"
];
exports.codeModTypes = ["configureNext"];
exports.extraOptionTypes = [...exports.codeModTypes];
exports.migrationSchema = zod_1.default.object({
id: zod_1.default.string(),
up: zod_1.default.array(zod_1.default.object({
type: zod_1.default.enum(exports.operationTypes),
options: zod_1.default
.object({
type: zod_1.default.enum(exports.extraOptionTypes).optional(),
args: zod_1.default.record(zod_1.default.string(), zod_1.default.string().or(zod_1.default.record(zod_1.default.string(), zod_1.default.any())))
})
.optional()
})),
down: zod_1.default
.array(zod_1.default.object({
type: zod_1.default.enum(exports.operationTypes),
options: zod_1.default
.object({
type: zod_1.default.enum(exports.extraOptionTypes).optional(),
args: zod_1.default.record(zod_1.default.string(), zod_1.default.string().or(zod_1.default.record(zod_1.default.string(), zod_1.default.any())))
})
.optional()
}))
.optional()
});
const parseMigration = (yamlString) => {
const base = js_yaml_1.default.load(yamlString);
const parsed = exports.migrationSchema.safeParse(base);
if (!parsed.success) {
throw new Error(parsed.error.errors.join(", "));
}
return parsed.data;
};
exports.parseMigration = parseMigration;
const exportMigration = (migration, path) => __awaiter(void 0, void 0, void 0, function* () {
const migrationHistory = yield getMigrationHistory();
if (migrationHistory.migrations.includes(migration.id)) {
throw new Error(`Migration ${migration.id} already exists`);
}
const newMigration = (0, yaml_1.jsonToYaml)(migration);
yield (0, promises_1.writeFile)(path, newMigration);
});
exports.exportMigration = exportMigration;
function ensureMigrations() {
return __awaiter(this, void 0, void 0, function* () {
yield (0, promises_1.mkdir)(path_1.default.join("infrastructure", "migrations"), {
recursive: true
});
const historyPath = path_1.default.join("infrastructure", "migrations", "history.yaml");
if (!(0, fs_1.existsSync)(historyPath)) {
yield (0, promises_1.writeFile)(historyPath, (0, yaml_1.jsonToYaml)({ migrations: [] }));
}
});
}
exports.ensureMigrations = ensureMigrations;
function getMigrationHistory() {
return __awaiter(this, void 0, void 0, function* () {
const historyPath = path_1.default.join("infrastructure", "migrations", "history.yaml");
const history = yield (0, promises_1.readFile)(historyPath, "utf8");
const yamlHistory = (0, yaml_1.parseYaml)(history);
return yamlHistory;
});
}
exports.getMigrationHistory = getMigrationHistory;
function getMigrationFiles() {
return __awaiter(this, void 0, void 0, function* () {
const migrationsPath = path_1.default.join("infrastructure", "migrations");
const files = yield (0, promises_1.readdir)(migrationsPath);
return files.filter((file) => file.endsWith(".yaml") && !file.endsWith("history.yaml"));
});
}
exports.getMigrationFiles = getMigrationFiles;
function getUnappliedMigrations() {
return __awaiter(this, void 0, void 0, function* () {
const history = yield getMigrationHistory();
const migrationFiles = (yield getMigrationFiles()).sort();
const migrationPath = path_1.default.join((0, process_1.cwd)(), "infrastructure", "migrations");
const migrations = migrationFiles.map((file) => {
const migrationYaml = (0, fs_1.readFileSync)(path_1.default.join(migrationPath, file), "utf-8");
return (0, exports.parseMigration)(migrationYaml);
});
return migrations.filter((migration) => !history.migrations.includes(migration.id));
});
}
exports.getUnappliedMigrations = getUnappliedMigrations;
function updateMigrationHistory(migrationId, apply = true) {
return __awaiter(this, void 0, void 0, function* () {
const historyPath = path_1.default.join("infrastructure", "migrations", "history.yaml");
const history = yield getMigrationHistory();
if (history.migrations.includes(migrationId)) {
if (apply) {
throw new Error(`Migration ${migrationId} already applied`);
}
history.migrations = history.migrations.filter((id) => id !== migrationId);
}
else {
history.migrations.push(migrationId);
}
yield (0, promises_1.writeFile)(historyPath, (0, yaml_1.jsonToYaml)(history));
});
}
exports.updateMigrationHistory = updateMigrationHistory;