@t1mmen/srtd
Version:
Supabase Repeatable Template Definitions (srtd): 🪄 Live-reloading SQL templates for Supabase DX. Make your database changes reviewable and migrations maintainable! 🚀
159 lines • 7.19 kB
JavaScript
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
if (value !== null && value !== void 0) {
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
var dispose, inner;
if (async) {
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
dispose = value[Symbol.asyncDispose];
}
if (dispose === void 0) {
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
dispose = value[Symbol.dispose];
if (async) inner = dispose;
}
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
env.stack.push({ value: value, dispose: dispose, async: async });
}
else if (async) {
env.stack.push({ async: true });
}
return value;
};
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
return function (env) {
function fail(e) {
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
env.hasError = true;
}
var r, s = 0;
function next() {
while (r = env.stack.pop()) {
try {
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
if (r.dispose) {
var result = r.dispose.call(r.value);
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
}
else s |= 1;
}
catch (e) {
fail(e);
}
}
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
if (env.hasError) throw env.error;
}
return next();
};
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
});
import chalk from 'chalk';
// src/commands/build.ts
import { Command } from 'commander';
import figures from 'figures';
import { formatFatalError, output, writeJson } from '../output/index.js';
import { Orchestrator } from '../services/Orchestrator.js';
import { displayValidationWarnings } from '../ui/displayWarnings.js';
import { renderBranding, renderErrorDisplay } from '../ui/index.js';
import { getConfig } from '../utils/config.js';
import { findProjectRoot } from '../utils/findProjectRoot.js';
import { getErrorMessage } from '../utils/getErrorMessage.js';
import { toTemplateResults } from '../utils/resultTransformer.js';
export const buildCommand = new Command('build')
.description('Build migrations from templates')
.option('-f, --force', 'Force building of all templates, irrespective of changes')
.option('-a, --apply', 'Apply the built templates')
.option('-b, --bundle', 'Bundle all templates into a single migration')
.option('--no-deps', 'Disable automatic dependency ordering')
.option('--json', 'Output results as JSON')
.action(async (options) => {
let exitCode = 0;
try {
const env_1 = { stack: [], error: void 0, hasError: false };
try {
// Render header only if not invoked from menu and not in JSON mode
if (!process.env.__SRTD_FROM_MENU__ && !options.json) {
const parts = ['Build'];
if (options.force)
parts.push('(forced)');
if (options.bundle)
parts.push('(bundled)');
renderBranding({ subtitle: parts.join(' ') });
}
// Initialize Orchestrator
const projectRoot = await findProjectRoot();
const { config, warnings: configWarnings } = await getConfig(projectRoot);
const orchestrator = __addDisposableResource(env_1, await Orchestrator.create(projectRoot, config, {
silent: true,
configWarnings,
}), true);
// Display validation warnings (skip in JSON mode)
if (!options.json) {
displayValidationWarnings(orchestrator.getValidationWarnings());
}
// Execute build operation
const buildResult = await orchestrator.build({
force: options.force,
bundle: options.bundle,
silent: true,
respectDependencies: options.deps,
});
let result = buildResult;
// If apply flag is set, also apply the templates
if (options.apply) {
const applyResult = await orchestrator.apply({
force: options.force,
silent: true,
});
// Merge results
result = {
errors: [...buildResult.errors, ...applyResult.errors],
applied: applyResult.applied,
built: buildResult.built,
skipped: [...buildResult.skipped, ...applyResult.skipped],
};
}
// Transform results to unified TemplateResult format using shared transformer
const context = { command: 'build', forced: options.force, json: options.json };
const results = toTemplateResults(result, (name) => orchestrator.getTemplateInfo(name), context, { wipIndicator: config.wipIndicator });
// Output results (JSON or human-readable based on context.json flag)
output({ results, context });
// Render errors if any (skip in JSON mode - errors are included in JSON output)
if (result.errors.length > 0 && !options.json) {
const errorItems = result.errors.map(err => ({
template: err.file,
message: err.error,
hint: err.hint,
}));
renderErrorDisplay({ errors: errorItems });
}
exitCode = result.errors.length > 0 ? 1 : 0;
}
catch (e_1) {
env_1.error = e_1;
env_1.hasError = true;
}
finally {
const result_1 = __disposeResources(env_1);
if (result_1)
await result_1;
}
}
catch (error) {
if (options.json) {
writeJson(formatFatalError('build', getErrorMessage(error)));
}
else {
console.log();
console.log(chalk.red(`${figures.cross} Error building templates:`));
console.log(chalk.red(getErrorMessage(error)));
}
exitCode = 1;
}
// Exit AFTER the using block has completed, ensuring dispose() runs
process.exit(exitCode);
});
//# sourceMappingURL=build.js.map