@t1mmen/srtd 0.0.0-next-20251227000343

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.
Files changed (96) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +363 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +50 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/apply.d.ts +2 -0
  7. package/dist/commands/apply.js +105 -0
  8. package/dist/commands/apply.js.map +1 -0
  9. package/dist/commands/build.d.ts +2 -0
  10. package/dist/commands/build.js +134 -0
  11. package/dist/commands/build.js.map +1 -0
  12. package/dist/commands/clear.d.ts +2 -0
  13. package/dist/commands/clear.js +161 -0
  14. package/dist/commands/clear.js.map +1 -0
  15. package/dist/commands/init.d.ts +2 -0
  16. package/dist/commands/init.js +91 -0
  17. package/dist/commands/init.js.map +1 -0
  18. package/dist/commands/menu.d.ts +4 -0
  19. package/dist/commands/menu.js +76 -0
  20. package/dist/commands/menu.js.map +1 -0
  21. package/dist/commands/promote.d.ts +2 -0
  22. package/dist/commands/promote.js +181 -0
  23. package/dist/commands/promote.js.map +1 -0
  24. package/dist/commands/register.d.ts +2 -0
  25. package/dist/commands/register.js +192 -0
  26. package/dist/commands/register.js.map +1 -0
  27. package/dist/commands/watch.d.ts +14 -0
  28. package/dist/commands/watch.js +190 -0
  29. package/dist/commands/watch.js.map +1 -0
  30. package/dist/constants.d.ts +1 -0
  31. package/dist/constants.js +2 -0
  32. package/dist/constants.js.map +1 -0
  33. package/dist/services/DatabaseService.d.ts +113 -0
  34. package/dist/services/DatabaseService.js +343 -0
  35. package/dist/services/DatabaseService.js.map +1 -0
  36. package/dist/services/FileSystemService.d.ts +100 -0
  37. package/dist/services/FileSystemService.js +237 -0
  38. package/dist/services/FileSystemService.js.map +1 -0
  39. package/dist/services/MigrationBuilder.d.ts +106 -0
  40. package/dist/services/MigrationBuilder.js +193 -0
  41. package/dist/services/MigrationBuilder.js.map +1 -0
  42. package/dist/services/Orchestrator.d.ts +155 -0
  43. package/dist/services/Orchestrator.js +622 -0
  44. package/dist/services/Orchestrator.js.map +1 -0
  45. package/dist/services/StateService.d.ts +169 -0
  46. package/dist/services/StateService.js +463 -0
  47. package/dist/services/StateService.js.map +1 -0
  48. package/dist/types.d.ts +48 -0
  49. package/dist/types.js +2 -0
  50. package/dist/types.js.map +1 -0
  51. package/dist/ui/badge.d.ts +14 -0
  52. package/dist/ui/badge.js +28 -0
  53. package/dist/ui/badge.js.map +1 -0
  54. package/dist/ui/branding.d.ts +9 -0
  55. package/dist/ui/branding.js +35 -0
  56. package/dist/ui/branding.js.map +1 -0
  57. package/dist/ui/index.d.ts +4 -0
  58. package/dist/ui/index.js +5 -0
  59. package/dist/ui/index.js.map +1 -0
  60. package/dist/ui/results.d.ts +10 -0
  61. package/dist/ui/results.js +62 -0
  62. package/dist/ui/results.js.map +1 -0
  63. package/dist/ui/spinner.d.ts +5 -0
  64. package/dist/ui/spinner.js +8 -0
  65. package/dist/ui/spinner.js.map +1 -0
  66. package/dist/utils/config.d.ts +12 -0
  67. package/dist/utils/config.js +67 -0
  68. package/dist/utils/config.js.map +1 -0
  69. package/dist/utils/createEmptyBuildLog.d.ts +1 -0
  70. package/dist/utils/createEmptyBuildLog.js +10 -0
  71. package/dist/utils/createEmptyBuildLog.js.map +1 -0
  72. package/dist/utils/ensureDirectories.d.ts +4 -0
  73. package/dist/utils/ensureDirectories.js +23 -0
  74. package/dist/utils/ensureDirectories.js.map +1 -0
  75. package/dist/utils/fileExists.d.ts +1 -0
  76. package/dist/utils/fileExists.js +11 -0
  77. package/dist/utils/fileExists.js.map +1 -0
  78. package/dist/utils/findProjectRoot.d.ts +1 -0
  79. package/dist/utils/findProjectRoot.js +25 -0
  80. package/dist/utils/findProjectRoot.js.map +1 -0
  81. package/dist/utils/getErrorMessage.d.ts +9 -0
  82. package/dist/utils/getErrorMessage.js +14 -0
  83. package/dist/utils/getErrorMessage.js.map +1 -0
  84. package/dist/utils/getNextTimestamp.d.ts +2 -0
  85. package/dist/utils/getNextTimestamp.js +12 -0
  86. package/dist/utils/getNextTimestamp.js.map +1 -0
  87. package/dist/utils/isWipTemplate.d.ts +1 -0
  88. package/dist/utils/isWipTemplate.js +6 -0
  89. package/dist/utils/isWipTemplate.js.map +1 -0
  90. package/dist/utils/logger.d.ts +9 -0
  91. package/dist/utils/logger.js +12 -0
  92. package/dist/utils/logger.js.map +1 -0
  93. package/dist/utils/safeCreate.d.ts +1 -0
  94. package/dist/utils/safeCreate.js +16 -0
  95. package/dist/utils/safeCreate.js.map +1 -0
  96. package/package.json +106 -0
@@ -0,0 +1,48 @@
1
+ export interface TemplateBuildState {
2
+ lastBuildHash?: string;
3
+ lastBuildDate?: string;
4
+ lastBuildError?: string;
5
+ lastMigrationFile?: string;
6
+ lastAppliedHash?: string;
7
+ lastAppliedDate?: string;
8
+ lastAppliedError?: string;
9
+ }
10
+ export interface BuildLog {
11
+ version: string;
12
+ lastTimestamp: string;
13
+ templates: {
14
+ [templatePath: string]: TemplateBuildState;
15
+ };
16
+ }
17
+ export interface MigrationError {
18
+ file: string;
19
+ error: string;
20
+ templateName: string;
21
+ }
22
+ export interface CLIConfig {
23
+ filter: string;
24
+ wipIndicator: string;
25
+ wrapInTransaction: boolean;
26
+ banner: string;
27
+ footer: string;
28
+ templateDir: string;
29
+ migrationDir: string;
30
+ migrationPrefix?: string;
31
+ buildLog: string;
32
+ localBuildLog: string;
33
+ pgConnection: string;
34
+ }
35
+ export interface ProcessedTemplateResult {
36
+ errors: MigrationError[];
37
+ applied: string[];
38
+ built: string[];
39
+ skipped: string[];
40
+ }
41
+ export interface TemplateStatus {
42
+ name: string;
43
+ path: string;
44
+ currentHash: string;
45
+ migrationHash: string | null;
46
+ buildState: TemplateBuildState;
47
+ wip: boolean;
48
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ type BadgeColor = 'red' | 'green' | 'yellow' | 'blue' | 'magenta' | 'cyan' | 'white' | 'gray';
2
+ /**
3
+ * Renders a colored stat badge inline.
4
+ */
5
+ export declare function renderStatBadge(label: string, value: number, color: BadgeColor): string;
6
+ /**
7
+ * Renders multiple stat badges on a single line.
8
+ */
9
+ export declare function renderStatBadges(stats: Array<{
10
+ label: string;
11
+ value: number;
12
+ color: BadgeColor;
13
+ }>): string;
14
+ export {};
@@ -0,0 +1,28 @@
1
+ import chalk from 'chalk';
2
+ const bgColorMap = {
3
+ red: text => chalk.bgRed.black(text),
4
+ green: text => chalk.bgGreen.black(text),
5
+ yellow: text => chalk.bgYellow.black(text),
6
+ blue: text => chalk.bgBlue.black(text),
7
+ magenta: text => chalk.bgMagenta.black(text),
8
+ cyan: text => chalk.bgCyan.black(text),
9
+ white: text => chalk.bgWhite.black(text),
10
+ gray: text => chalk.bgGray.black(text),
11
+ };
12
+ /**
13
+ * Renders a colored stat badge inline.
14
+ */
15
+ export function renderStatBadge(label, value, color) {
16
+ const colorFn = bgColorMap[color] || bgColorMap.white;
17
+ return colorFn(` ${label}: ${value} `);
18
+ }
19
+ /**
20
+ * Renders multiple stat badges on a single line.
21
+ */
22
+ export function renderStatBadges(stats) {
23
+ return stats
24
+ .filter(s => s.value > 0)
25
+ .map(s => renderStatBadge(s.label, s.value, s.color))
26
+ .join(' ');
27
+ }
28
+ //# sourceMappingURL=badge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.js","sourceRoot":"","sources":["../../src/ui/badge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,UAAU,GAAiD;IAC/D,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC;IACpC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;IACxC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;IAC1C,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;IACtC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;IAC5C,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;IACtC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;IACxC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;CACvC,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,KAAa,EAAE,KAAiB;IAC7E,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC;IACtD,OAAO,OAAO,CAAC,IAAI,KAAK,KAAK,KAAK,GAAG,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAiE;IAEjE,OAAO,KAAK;SACT,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;SACxB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;SACpD,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { DatabaseService } from '../services/DatabaseService.js';
2
+ export interface BrandingOptions {
3
+ subtitle?: string;
4
+ }
5
+ /**
6
+ * Renders the srtd branding header with connection status badge.
7
+ * @see {@link DatabaseService.testConnection} - Database connection check
8
+ */
9
+ export declare function renderBranding(options?: BrandingOptions, dbService?: DatabaseService): Promise<void>;
@@ -0,0 +1,35 @@
1
+ import chalk from 'chalk';
2
+ import packageJson from '../../package.json' with { type: 'json' };
3
+ /**
4
+ * Renders the srtd branding header with connection status badge.
5
+ * @see {@link DatabaseService.testConnection} - Database connection check
6
+ */
7
+ export async function renderBranding(options = {}, dbService) {
8
+ const { subtitle } = options;
9
+ // Check database connection status
10
+ let isConnected = false;
11
+ if (dbService) {
12
+ try {
13
+ isConnected = await dbService.testConnection();
14
+ }
15
+ catch {
16
+ isConnected = false;
17
+ }
18
+ }
19
+ console.log();
20
+ // Render badge
21
+ const badge = isConnected ? chalk.bgGreen.white(' srtd ') : chalk.bgYellow.white(' srtd ');
22
+ // Render subtitle or main title
23
+ let title;
24
+ if (subtitle) {
25
+ title = subtitle;
26
+ }
27
+ else {
28
+ title = `${chalk.green.bold('S')}upabase ${chalk.green.bold('R')}epeatable ${chalk.green.bold('T')}emplate ${chalk.green.bold('D')}efinitions`;
29
+ }
30
+ // Version
31
+ const version = chalk.dim(` v${packageJson.version}`);
32
+ console.log(`${badge} ${title}${version}`);
33
+ console.log();
34
+ }
35
+ //# sourceMappingURL=branding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branding.js","sourceRoot":"","sources":["../../src/ui/branding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,WAAW,MAAM,oBAAoB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAOnE;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,UAA2B,EAAE,EAC7B,SAA2B;IAE3B,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAE7B,mCAAmC;IACnC,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,CAAC;YACH,WAAW,GAAG,MAAM,SAAS,CAAC,cAAc,EAAE,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,eAAe;IACf,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAE3F,gCAAgC;IAChC,IAAI,KAAa,CAAC;IAClB,IAAI,QAAQ,EAAE,CAAC;QACb,KAAK,GAAG,QAAQ,CAAC;IACnB,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC;IACjJ,CAAC;IAED,UAAU;IACV,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAEtD,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,IAAI,KAAK,GAAG,OAAO,EAAE,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { renderBranding, type BrandingOptions } from './branding.js';
2
+ export { renderStatBadge, renderStatBadges } from './badge.js';
3
+ export { createSpinner } from './spinner.js';
4
+ export { renderResults, type ResultsOptions } from './results.js';
@@ -0,0 +1,5 @@
1
+ export { renderBranding } from './branding.js';
2
+ export { renderStatBadge, renderStatBadges } from './badge.js';
3
+ export { createSpinner } from './spinner.js';
4
+ export { renderResults } from './results.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAwB,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAuB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ProcessedTemplateResult } from '../types.js';
2
+ export interface ResultsOptions {
3
+ showBuild?: boolean;
4
+ showApply?: boolean;
5
+ }
6
+ /**
7
+ * Renders processing results with sections and stat badges.
8
+ * @see {@link ProcessedTemplateResult} - Result structure from Orchestrator
9
+ */
10
+ export declare function renderResults(result: ProcessedTemplateResult, options?: ResultsOptions): void;
@@ -0,0 +1,62 @@
1
+ import chalk from 'chalk';
2
+ import figures from 'figures';
3
+ import { renderStatBadges } from './badge.js';
4
+ /**
5
+ * Renders a section of results (built, applied, skipped items).
6
+ */
7
+ function renderSection(items, label, variant) {
8
+ if (items.length === 0)
9
+ return;
10
+ const icon = variant === 'build' ? figures.tick : variant === 'apply' ? figures.play : figures.pointerSmall;
11
+ const maxItems = 30;
12
+ const itemsToShow = items.slice(0, maxItems);
13
+ const overflow = items.length > maxItems ? items.length - maxItems : 0;
14
+ const colorFn = variant === 'skip' ? chalk.yellow : chalk.green;
15
+ // Section label
16
+ console.log(chalk.bold(`${label}:`));
17
+ // Items
18
+ for (const item of itemsToShow) {
19
+ console.log(` ${colorFn(`${icon} ${item}`)}`);
20
+ }
21
+ // Overflow indicator
22
+ if (overflow > 0) {
23
+ console.log(chalk.dim(` ... and ${overflow} more`));
24
+ }
25
+ console.log();
26
+ }
27
+ /**
28
+ * Renders processing results with sections and stat badges.
29
+ * @see {@link ProcessedTemplateResult} - Result structure from Orchestrator
30
+ */
31
+ export function renderResults(result, options = {}) {
32
+ const { showBuild = true, showApply = false } = options;
33
+ console.log();
34
+ // Render sections
35
+ renderSection(result.skipped, 'Skipped', 'skip');
36
+ if (showBuild) {
37
+ renderSection(result.built, 'Built', 'build');
38
+ }
39
+ if (showApply) {
40
+ renderSection(result.applied, 'Applied', 'apply');
41
+ }
42
+ // Render errors
43
+ if (result.errors.length > 0) {
44
+ console.log(chalk.red('Errors:'));
45
+ for (const error of result.errors) {
46
+ console.log(chalk.red(` ${figures.cross} ${error.templateName}: ${error.error}`));
47
+ }
48
+ console.log();
49
+ }
50
+ // Render stat badges
51
+ const badges = renderStatBadges([
52
+ { label: 'Skipped', value: result.skipped.length, color: 'yellow' },
53
+ { label: 'Errors', value: result.errors.length, color: 'red' },
54
+ { label: 'Built', value: result.built.length, color: 'green' },
55
+ { label: 'Applied', value: result.applied.length, color: 'green' },
56
+ ]);
57
+ if (badges) {
58
+ console.log(badges);
59
+ console.log();
60
+ }
61
+ }
62
+ //# sourceMappingURL=results.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"results.js","sourceRoot":"","sources":["../../src/ui/results.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type Ora } from 'ora';
2
+ /**
3
+ * Creates a new spinner with the dots style.
4
+ */
5
+ export declare function createSpinner(text: string): Ora;
@@ -0,0 +1,8 @@
1
+ import ora from 'ora';
2
+ /**
3
+ * Creates a new spinner with the dots style.
4
+ */
5
+ export function createSpinner(text) {
6
+ return ora({ text, spinner: 'dots' });
7
+ }
8
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA,OAAO,GAAiB,MAAM,KAAK,CAAC;AAEpC;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { CLIConfig } from '../types.js';
2
+ /**
3
+ * Get config for a specific directory.
4
+ * Caches per directory to support multi-project scenarios.
5
+ */
6
+ export declare function getConfig(dir?: string): Promise<CLIConfig>;
7
+ /**
8
+ * Clear the config cache (useful for testing)
9
+ */
10
+ export declare function clearConfigCache(): void;
11
+ export declare function saveConfig(baseDir: string, config: Partial<CLIConfig>): Promise<void>;
12
+ export declare function resetConfig(baseDir: string): Promise<void>;
@@ -0,0 +1,67 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { CONFIG_FILE } from '../constants.js';
4
+ import { logger } from './logger.js';
5
+ const defaultConfig = {
6
+ wipIndicator: '.wip',
7
+ migrationPrefix: 'srtd',
8
+ filter: '**/*.sql',
9
+ banner: 'You very likely **DO NOT** want to manually edit this generated file.',
10
+ footer: '',
11
+ wrapInTransaction: true,
12
+ templateDir: 'supabase/migrations-templates',
13
+ migrationDir: 'supabase/migrations',
14
+ buildLog: 'supabase/migrations-templates/.srtd.buildlog.json',
15
+ localBuildLog: 'supabase/migrations-templates/.srtd.buildlog.local.json',
16
+ pgConnection: 'postgresql://postgres:postgres@localhost:54322/postgres',
17
+ };
18
+ /**
19
+ * Per-directory config cache to support multiple projects in same process
20
+ */
21
+ const configCache = new Map();
22
+ /**
23
+ * Get config for a specific directory.
24
+ * Caches per directory to support multi-project scenarios.
25
+ */
26
+ export async function getConfig(dir = process.cwd()) {
27
+ const resolvedDir = path.resolve(dir);
28
+ const cached = configCache.get(resolvedDir);
29
+ if (cached)
30
+ return cached;
31
+ let config;
32
+ try {
33
+ const configPath = path.join(resolvedDir, CONFIG_FILE);
34
+ const content = await fs.readFile(configPath, 'utf-8');
35
+ config = { ...defaultConfig, ...JSON.parse(content) };
36
+ }
37
+ catch {
38
+ config = { ...defaultConfig };
39
+ }
40
+ configCache.set(resolvedDir, config);
41
+ return config;
42
+ }
43
+ /**
44
+ * Clear the config cache (useful for testing)
45
+ */
46
+ export function clearConfigCache() {
47
+ configCache.clear();
48
+ }
49
+ export async function saveConfig(baseDir, config) {
50
+ const resolvedDir = path.resolve(baseDir);
51
+ const configPath = path.join(resolvedDir, CONFIG_FILE);
52
+ const finalConfig = { ...defaultConfig, ...config };
53
+ // Add newline at the end to satisfy linters
54
+ await fs.writeFile(configPath, `${JSON.stringify(finalConfig, null, 2)}\n`).catch(e => {
55
+ logger.error(`Failed to save config: ${e.message}`);
56
+ });
57
+ configCache.set(resolvedDir, finalConfig);
58
+ }
59
+ export async function resetConfig(baseDir) {
60
+ const resolvedDir = path.resolve(baseDir);
61
+ configCache.delete(resolvedDir);
62
+ await fs.unlink(path.join(resolvedDir, CONFIG_FILE)).catch(() => {
63
+ /* ignore */
64
+ });
65
+ await saveConfig(resolvedDir, {});
66
+ }
67
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function createEmptyBuildLog(filepath: string): Promise<boolean>;
@@ -0,0 +1,10 @@
1
+ import { safeCreate } from './safeCreate.js';
2
+ export async function createEmptyBuildLog(filepath) {
3
+ const initial = {
4
+ version: '1.0',
5
+ lastTimestamp: '',
6
+ templates: {},
7
+ };
8
+ return safeCreate(filepath, JSON.stringify(initial, null, 2));
9
+ }
10
+ //# sourceMappingURL=createEmptyBuildLog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createEmptyBuildLog.js","sourceRoot":"","sources":["../../src/utils/createEmptyBuildLog.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,QAAgB;IACxD,MAAM,OAAO,GAAG;QACd,OAAO,EAAE,KAAK;QACd,aAAa,EAAE,EAAE;QACjB,SAAS,EAAE,EAAE;KACK,CAAC;IACrB,OAAO,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function ensureDirectories(baseDir: string): Promise<{
2
+ templateDir: boolean;
3
+ migrationDir: boolean;
4
+ }>;
@@ -0,0 +1,23 @@
1
+ // utils/ensureDirectories.ts
2
+ import fs from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { getConfig } from './config.js';
5
+ import { fileExists } from './fileExists.js';
6
+ export async function ensureDirectories(baseDir) {
7
+ const config = await getConfig(baseDir);
8
+ const templatePath = path.join(baseDir, config.templateDir);
9
+ const migrationPath = path.join(baseDir, config.migrationDir);
10
+ const templateExists = await fileExists(templatePath);
11
+ const migrationExists = await fileExists(migrationPath);
12
+ if (!templateExists) {
13
+ await fs.mkdir(templatePath, { recursive: true });
14
+ }
15
+ if (!migrationExists) {
16
+ await fs.mkdir(migrationPath, { recursive: true });
17
+ }
18
+ return {
19
+ templateDir: !templateExists,
20
+ migrationDir: !migrationExists,
21
+ };
22
+ }
23
+ //# sourceMappingURL=ensureDirectories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensureDirectories.js","sourceRoot":"","sources":["../../src/utils/ensureDirectories.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAe;IAEf,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IAC5D,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IAE9D,MAAM,cAAc,GAAG,MAAM,UAAU,CAAC,YAAY,CAAC,CAAC;IACtD,MAAM,eAAe,GAAG,MAAM,UAAU,CAAC,aAAa,CAAC,CAAC;IAExD,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,OAAO;QACL,WAAW,EAAE,CAAC,cAAc;QAC5B,YAAY,EAAE,CAAC,eAAe;KAC/B,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function fileExists(filepath: string): Promise<boolean>;
@@ -0,0 +1,11 @@
1
+ import fs from 'node:fs/promises';
2
+ export async function fileExists(filepath) {
3
+ try {
4
+ await fs.access(filepath);
5
+ return true;
6
+ }
7
+ catch {
8
+ return false;
9
+ }
10
+ }
11
+ //# sourceMappingURL=fileExists.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileExists.js","sourceRoot":"","sources":["../../src/utils/fileExists.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function findProjectRoot(startDir?: string): Promise<string>;
@@ -0,0 +1,25 @@
1
+ import path from 'node:path';
2
+ import { fileExists } from './fileExists.js';
3
+ async function isProjectDir(dir) {
4
+ // Check for srtd config files
5
+ if (await fileExists(path.join(dir, 'srtd.config.json')))
6
+ return true;
7
+ // Check for package.json
8
+ if (await fileExists(path.join(dir, 'package.json')))
9
+ return true;
10
+ // Check for supabase directory
11
+ if (await fileExists(path.join(dir, 'supabase')))
12
+ return true;
13
+ return false;
14
+ }
15
+ export async function findProjectRoot(startDir) {
16
+ let currentDir = startDir || process.cwd();
17
+ while (currentDir !== path.parse(currentDir).root) {
18
+ if (await isProjectDir(currentDir)) {
19
+ return currentDir;
20
+ }
21
+ currentDir = path.dirname(currentDir);
22
+ }
23
+ throw new Error('Could not find project root. Are you in a Supabase project directory?');
24
+ }
25
+ //# sourceMappingURL=findProjectRoot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findProjectRoot.js","sourceRoot":"","sources":["../../src/utils/findProjectRoot.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,KAAK,UAAU,YAAY,CAAC,GAAW;IACrC,8BAA8B;IAC9B,IAAI,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtE,yBAAyB;IACzB,IAAI,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAElE,+BAA+B;IAC/B,IAAI,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAE9D,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAiB;IACrD,IAAI,UAAU,GAAG,QAAQ,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAE3C,OAAO,UAAU,KAAK,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;QAClD,IAAI,MAAM,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC;YACnC,OAAO,UAAU,CAAC;QACpB,CAAC;QACD,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;AAC3F,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Extracts error message from unknown error type.
3
+ * Handles Error instances and arbitrary values.
4
+ */
5
+ export declare function getErrorMessage(error: unknown): string;
6
+ /**
7
+ * Checks if an error is an Inquirer prompt exit (Ctrl+C).
8
+ */
9
+ export declare function isPromptExit(error: unknown): boolean;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Extracts error message from unknown error type.
3
+ * Handles Error instances and arbitrary values.
4
+ */
5
+ export function getErrorMessage(error) {
6
+ return error instanceof Error ? error.message : String(error);
7
+ }
8
+ /**
9
+ * Checks if an error is an Inquirer prompt exit (Ctrl+C).
10
+ */
11
+ export function isPromptExit(error) {
12
+ return error instanceof Error && error.name === 'ExitPromptError';
13
+ }
14
+ //# sourceMappingURL=getErrorMessage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getErrorMessage.js","sourceRoot":"","sources":["../../src/utils/getErrorMessage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,OAAO,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,CAAC;AACpE,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { BuildLog } from '../types.js';
2
+ export declare function getNextTimestamp(buildLog: BuildLog): Promise<string>;
@@ -0,0 +1,12 @@
1
+ export async function getNextTimestamp(buildLog) {
2
+ const now = new Date();
3
+ const timestamp = now.toISOString().replace(/\D/g, '').slice(0, 14);
4
+ if (timestamp <= buildLog.lastTimestamp) {
5
+ const nextTimestamp = (BigInt(buildLog.lastTimestamp) + 1n).toString();
6
+ buildLog.lastTimestamp = nextTimestamp;
7
+ return nextTimestamp;
8
+ }
9
+ buildLog.lastTimestamp = timestamp;
10
+ return timestamp;
11
+ }
12
+ //# sourceMappingURL=getNextTimestamp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getNextTimestamp.js","sourceRoot":"","sources":["../../src/utils/getNextTimestamp.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAkB;IACvD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,SAAS,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEpE,IAAI,SAAS,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;QACxC,MAAM,aAAa,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACvE,QAAQ,CAAC,aAAa,GAAG,aAAa,CAAC;QACvC,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,QAAQ,CAAC,aAAa,GAAG,SAAS,CAAC;IACnC,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function isWipTemplate(templatePath: string, baseDir?: string): Promise<boolean>;
@@ -0,0 +1,6 @@
1
+ import { getConfig } from './config.js';
2
+ export async function isWipTemplate(templatePath, baseDir) {
3
+ const config = await getConfig(baseDir);
4
+ return templatePath.includes(config.wipIndicator);
5
+ }
6
+ //# sourceMappingURL=isWipTemplate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isWipTemplate.js","sourceRoot":"","sources":["../../src/utils/isWipTemplate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,YAAoB,EAAE,OAAgB;IACxE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IACxC,OAAO,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare const logger: {
2
+ info: (msg: string) => void;
3
+ success: (msg: string) => void;
4
+ warn: (msg: string) => void;
5
+ error: (msg: string) => void;
6
+ skip: (msg: string) => void;
7
+ debug: (msg: string) => false | void | "" | undefined;
8
+ };
9
+ export type LogLevel = keyof typeof logger;
@@ -0,0 +1,12 @@
1
+ // utils/logger.ts
2
+ import chalk from 'chalk';
3
+ import figures from 'figures';
4
+ export const logger = {
5
+ info: (msg) => console.log(`${figures.info} ${msg}`),
6
+ success: (msg) => console.log(`${figures.tick} ${chalk.green(msg)}`),
7
+ warn: (msg) => console.log(`${figures.warning} ${chalk.yellow(msg)}`),
8
+ error: (msg) => console.log(`${figures.cross} ${chalk.red(msg)}`),
9
+ skip: (msg) => console.log(`${figures.pointerSmall} ${chalk.dim(msg)}`),
10
+ debug: (msg) => process.env.DEBUG && process.env.DEBUG === 'true' && console.log(` 🔍 ${chalk.white(msg)}`),
11
+ };
12
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAClB,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;IAC5D,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC5E,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IAC7E,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;IACzE,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,YAAY,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;IAC/E,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE,CACrB,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;CAC/F,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function safeCreate(filepath: string, content: string): Promise<boolean>;
@@ -0,0 +1,16 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { fileExists } from './fileExists.js';
4
+ export async function safeCreate(filepath, content) {
5
+ // Create directory structure if needed
6
+ const dir = path.dirname(filepath);
7
+ await fs.mkdir(dir, { recursive: true });
8
+ if (await fileExists(filepath)) {
9
+ // If file exists, overwrite it rather than skipping
10
+ await fs.writeFile(filepath, content);
11
+ return true;
12
+ }
13
+ await fs.writeFile(filepath, content);
14
+ return true;
15
+ }
16
+ //# sourceMappingURL=safeCreate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safeCreate.js","sourceRoot":"","sources":["../../src/utils/safeCreate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB,EAAE,OAAe;IAChE,uCAAuC;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzC,IAAI,MAAM,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/B,oDAAoD;QACpD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACtC,OAAO,IAAI,CAAC;AACd,CAAC"}