@t1mmen/srtd 0.4.2 → 0.4.4

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 (65) hide show
  1. package/README.md +1 -1
  2. package/dist/__tests__/apply.test.js +2 -2
  3. package/dist/__tests__/build.test.js +4 -4
  4. package/dist/__tests__/build.test.js.map +1 -1
  5. package/dist/__tests__/clear.test.d.ts +1 -0
  6. package/dist/__tests__/clear.test.js +11 -0
  7. package/dist/__tests__/clear.test.js.map +1 -0
  8. package/dist/__tests__/init.test.d.ts +1 -0
  9. package/dist/__tests__/init.test.js +28 -0
  10. package/dist/__tests__/init.test.js.map +1 -0
  11. package/dist/__tests__/register.test.d.ts +1 -0
  12. package/dist/__tests__/register.test.js +9 -0
  13. package/dist/__tests__/register.test.js.map +1 -0
  14. package/dist/__tests__/vitest.setup.js +2 -1
  15. package/dist/__tests__/vitest.setup.js.map +1 -1
  16. package/dist/__tests__/watch.test.js +3 -6
  17. package/dist/__tests__/watch.test.js.map +1 -1
  18. package/dist/commands/_app.js +1 -9
  19. package/dist/commands/_app.js.map +1 -1
  20. package/dist/commands/apply.js +3 -5
  21. package/dist/commands/apply.js.map +1 -1
  22. package/dist/commands/build.js +5 -6
  23. package/dist/commands/build.js.map +1 -1
  24. package/dist/commands/clear.js +12 -5
  25. package/dist/commands/clear.js.map +1 -1
  26. package/dist/commands/index.js +6 -12
  27. package/dist/commands/index.js.map +1 -1
  28. package/dist/commands/register.d.ts +1 -1
  29. package/dist/commands/register.js +62 -16
  30. package/dist/commands/register.js.map +1 -1
  31. package/dist/commands/watch.js +25 -28
  32. package/dist/commands/watch.js.map +1 -1
  33. package/dist/components/Branding.js +1 -1
  34. package/dist/components/Branding.js.map +1 -1
  35. package/dist/components/ProcessingResults.js +26 -14
  36. package/dist/components/ProcessingResults.js.map +1 -1
  37. package/dist/components/Quittable.js +6 -4
  38. package/dist/components/Quittable.js.map +1 -1
  39. package/dist/components/StatBadge.d.ts +6 -0
  40. package/dist/components/StatBadge.js +14 -0
  41. package/dist/components/StatBadge.js.map +1 -0
  42. package/dist/components/TimeSince.js +9 -5
  43. package/dist/components/TimeSince.js.map +1 -1
  44. package/dist/hooks/useDatabaseConnection.js +2 -1
  45. package/dist/hooks/useDatabaseConnection.js.map +1 -1
  46. package/dist/hooks/useFullscreen.d.ts +1 -0
  47. package/dist/hooks/useFullscreen.js +18 -0
  48. package/dist/hooks/useFullscreen.js.map +1 -0
  49. package/dist/hooks/useTemplateProcessor.js +0 -6
  50. package/dist/hooks/useTemplateProcessor.js.map +1 -1
  51. package/dist/lib/templateManager.js +41 -26
  52. package/dist/lib/templateManager.js.map +1 -1
  53. package/dist/lib/templateManager.test.js +821 -505
  54. package/dist/lib/templateManager.test.js.map +1 -1
  55. package/dist/utils/applyMigrations.test.js +4 -1
  56. package/dist/utils/applyMigrations.test.js.map +1 -1
  57. package/dist/utils/databaseConnection.js +21 -19
  58. package/dist/utils/databaseConnection.js.map +1 -1
  59. package/dist/utils/databaseConnection.test.js +1 -4
  60. package/dist/utils/databaseConnection.test.js.map +1 -1
  61. package/dist/utils/logger.js +6 -5
  62. package/dist/utils/logger.js.map +1 -1
  63. package/dist/utils/registerTemplate.js +1 -2
  64. package/dist/utils/registerTemplate.js.map +1 -1
  65. package/package.json +2 -1
@@ -56,27 +56,22 @@ import { default as path, join, relative } from 'node:path';
56
56
  import { afterEach, beforeEach, describe, expect, it } from 'vitest';
57
57
  import { TEST_FN_PREFIX } from '../__tests__/vitest.setup.js';
58
58
  import { calculateMD5 } from '../utils/calculateMD5.js';
59
- import { connect, disconnect } from '../utils/databaseConnection.js';
59
+ import { connect } from '../utils/databaseConnection.js';
60
60
  import { ensureDirectories } from '../utils/ensureDirectories.js';
61
61
  import { TemplateManager } from './templateManager.js';
62
- const waitForCondition = async (condition, timeout = 5000, interval = 100) => {
63
- const start = Date.now();
64
- while (Date.now() - start < timeout) {
65
- if (await condition())
66
- return true;
67
- await new Promise(resolve => setTimeout(resolve, interval));
68
- }
69
- return false;
70
- };
62
+ const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));
71
63
  describe('TemplateManager', () => {
72
64
  const testContext = {
73
- timestamp: Date.now(),
74
- testDir: '',
75
- testFunctionName: '',
65
+ testId: 0,
66
+ testDir: tmpdir(),
67
+ testFunctionName: TEST_FN_PREFIX,
68
+ templateCounter: 0,
76
69
  };
77
70
  beforeEach(async () => {
78
- testContext.testDir = join(tmpdir(), `srtd-test-${testContext.timestamp}`);
79
- testContext.testFunctionName = `${TEST_FN_PREFIX}${testContext.timestamp}`;
71
+ testContext.testId = Math.floor(Math.random() * 1000000);
72
+ testContext.testDir = join(tmpdir(), `srtd-test`);
73
+ testContext.testFunctionName = `${TEST_FN_PREFIX}`;
74
+ testContext.templateCounter = 0;
80
75
  await ensureDirectories(testContext.testDir);
81
76
  const client = await connect();
82
77
  try {
@@ -106,190 +101,316 @@ describe('TemplateManager', () => {
106
101
  client.release();
107
102
  }
108
103
  await fs.rm(testContext.testDir, { recursive: true, force: true });
109
- disconnect();
110
104
  });
105
+ // Helper to generate unique template names
106
+ const getNextTemplateName = (prefix = 'template') => {
107
+ testContext.templateCounter++;
108
+ return `${prefix}_${testContext.testId}_${testContext.templateCounter}`;
109
+ };
111
110
  const createTemplate = async (name, content, dir) => {
112
111
  const fullPath = dir
113
112
  ? join(testContext.testDir, 'test-templates', dir, name)
114
113
  : join(testContext.testDir, 'test-templates', name);
115
- await fs.mkdir(path.dirname(fullPath), { recursive: true });
116
- await fs.writeFile(fullPath, content);
117
- return fullPath;
114
+ try {
115
+ await fs.mkdir(path.dirname(fullPath), { recursive: true });
116
+ await fs.writeFile(fullPath, content);
117
+ return fullPath;
118
+ }
119
+ catch (error) {
120
+ console.error('Error creating template:', error);
121
+ throw error;
122
+ }
118
123
  };
119
- const createTemplateWithFunc = async (name, funcSuffix = '', dir) => {
124
+ const createTemplateWithFunc = async (prefix, funcSuffix = '', dir) => {
125
+ const name = `${getNextTemplateName(prefix)}.sql`;
120
126
  const funcName = `${testContext.testFunctionName}${funcSuffix}`;
121
127
  const content = `CREATE OR REPLACE FUNCTION ${funcName}() RETURNS void AS $$ BEGIN NULL; END; $$ LANGUAGE plpgsql;`;
122
128
  return createTemplate(name, content, dir);
123
129
  };
124
130
  it('should create migration file when template changes', async () => {
125
- await createTemplateWithFunc(`test-${testContext.timestamp}.sql`, '_file_change');
126
- const manager = await TemplateManager.create(testContext.testDir);
127
- await manager.processTemplates({ generateFiles: true });
128
- const migrations = await fs.readdir(join(testContext.testDir, 'test-migrations'));
129
- const relevantMigrations = migrations.filter(m => m.includes(`test-${testContext.timestamp}`));
130
- expect(relevantMigrations).toHaveLength(1);
131
+ const env_1 = { stack: [], error: void 0, hasError: false };
132
+ try {
133
+ await createTemplateWithFunc('basic', '_file_change');
134
+ const manager = __addDisposableResource(env_1, await TemplateManager.create(testContext.testDir), false);
135
+ await manager.processTemplates({ generateFiles: true });
136
+ const migrations = await fs.readdir(join(testContext.testDir, 'test-migrations'));
137
+ expect(migrations.length).toBe(1);
138
+ }
139
+ catch (e_1) {
140
+ env_1.error = e_1;
141
+ env_1.hasError = true;
142
+ }
143
+ finally {
144
+ __disposeResources(env_1);
145
+ }
131
146
  });
132
147
  it('should not allow building WIP templates', async () => {
133
- await createTemplateWithFunc(`test-${testContext.timestamp}.wip.sql`, '_wip_wont_build');
134
- const manager = await TemplateManager.create(testContext.testDir);
135
- await manager.processTemplates({ generateFiles: true });
136
- const migrations = await fs.readdir(join(testContext.testDir, 'test-migrations'));
137
- expect(migrations.filter(m => m.includes(`test-${testContext.timestamp}`))).toHaveLength(0);
148
+ const env_2 = { stack: [], error: void 0, hasError: false };
149
+ try {
150
+ await createTemplateWithFunc('file.wip', '_wip_wont_build');
151
+ const manager = __addDisposableResource(env_2, await TemplateManager.create(testContext.testDir), false);
152
+ await manager.processTemplates({ generateFiles: true });
153
+ const migrations = await fs.readdir(join(testContext.testDir, 'test-migrations'));
154
+ expect(migrations.filter(m => m.includes(`wip`))).toHaveLength(0);
155
+ }
156
+ catch (e_2) {
157
+ env_2.error = e_2;
158
+ env_2.hasError = true;
159
+ }
160
+ finally {
161
+ __disposeResources(env_2);
162
+ }
138
163
  });
139
164
  it('should maintain separate build and local logs', async () => {
140
- const templatePath = join(testContext.testDir, 'test-templates', `test-${testContext.timestamp}.sql`);
141
- const templateContent = `CREATE FUNCTION ${testContext.testFunctionName}() RETURNS void AS $$ BEGIN NULL; END; $$ LANGUAGE plpgsql;`;
142
- await fs.writeFile(templatePath, templateContent);
143
- const manager = await TemplateManager.create(testContext.testDir);
144
- // Build writes to build log
145
- await manager.processTemplates({ generateFiles: true });
146
- const buildLog = JSON.parse(await fs.readFile(join(testContext.testDir, '.buildlog-test.json'), 'utf-8'));
147
- const relPath = relative(testContext.testDir, templatePath);
148
- expect(buildLog.templates[relPath].lastBuildHash).toBeDefined();
149
- // Apply writes to local log
150
- await manager.processTemplates({ apply: true });
151
- const localLog = JSON.parse(await fs.readFile(join(testContext.testDir, '.buildlog-test.local.json'), 'utf-8'));
152
- expect(localLog.templates[relPath].lastAppliedHash).toBeDefined();
165
+ const env_3 = { stack: [], error: void 0, hasError: false };
166
+ try {
167
+ const templatePath = join(testContext.testDir, 'test-templates', `template_${testContext.testId}_1.sql`);
168
+ const templateContent = `CREATE FUNCTION ${testContext.testFunctionName}() RETURNS void AS $$ BEGIN NULL; END; $$ LANGUAGE plpgsql;`;
169
+ await fs.writeFile(templatePath, templateContent);
170
+ const manager = __addDisposableResource(env_3, await TemplateManager.create(testContext.testDir), false);
171
+ // Build writes to build log
172
+ await manager.processTemplates({ generateFiles: true });
173
+ const buildLog = JSON.parse(await fs.readFile(join(testContext.testDir, '.buildlog-test.json'), 'utf-8'));
174
+ const relPath = relative(testContext.testDir, templatePath);
175
+ expect(buildLog.templates[relPath].lastBuildHash).toBeDefined();
176
+ // Apply writes to local log
177
+ await manager.processTemplates({ apply: true });
178
+ const localLog = JSON.parse(await fs.readFile(join(testContext.testDir, '.buildlog-test.local.json'), 'utf-8'));
179
+ expect(localLog.templates[relPath].lastAppliedHash).toBeDefined();
180
+ }
181
+ catch (e_3) {
182
+ env_3.error = e_3;
183
+ env_3.hasError = true;
184
+ }
185
+ finally {
186
+ __disposeResources(env_3);
187
+ }
153
188
  });
154
189
  it('should track template state correctly', async () => {
155
- const templatePath = join(testContext.testDir, 'test-templates', `test-${testContext.timestamp}.sql`);
156
- const templateContent = `CREATE FUNCTION ${testContext.testFunctionName}() RETURNS void AS $$ BEGIN NULL; END; $$ LANGUAGE plpgsql;`;
157
- await fs.writeFile(templatePath, templateContent);
158
- const manager = await TemplateManager.create(testContext.testDir);
159
- // Initially no state
160
- let status = await manager.getTemplateStatus(templatePath);
161
- expect(status.buildState.lastBuildHash).toBeUndefined();
162
- expect(status.buildState.lastAppliedHash).toBeUndefined();
163
- // After build
164
- await manager.processTemplates({ generateFiles: true });
165
- status = await manager.getTemplateStatus(templatePath);
166
- expect(status.buildState.lastBuildHash).toBeDefined();
167
- expect(status.buildState.lastBuildDate).toBeDefined();
168
- // After apply
169
- await manager.processTemplates({ apply: true });
170
- status = await manager.getTemplateStatus(templatePath);
171
- expect(status.buildState.lastAppliedHash).toBeDefined();
172
- expect(status.buildState.lastAppliedDate).toBeDefined();
190
+ const env_4 = { stack: [], error: void 0, hasError: false };
191
+ try {
192
+ const templatePath = join(testContext.testDir, 'test-templates', `template_${testContext.testId}_1.sql`);
193
+ const templateContent = `CREATE FUNCTION ${testContext.testFunctionName}() RETURNS void AS $$ BEGIN NULL; END; $$ LANGUAGE plpgsql;`;
194
+ await fs.writeFile(templatePath, templateContent);
195
+ const manager = __addDisposableResource(env_4, await TemplateManager.create(testContext.testDir), false);
196
+ // Initially no state
197
+ let status = await manager.getTemplateStatus(templatePath);
198
+ expect(status.buildState.lastBuildHash).toBeUndefined();
199
+ expect(status.buildState.lastAppliedHash).toBeUndefined();
200
+ // After build
201
+ await manager.processTemplates({ generateFiles: true });
202
+ status = await manager.getTemplateStatus(templatePath);
203
+ expect(status.buildState.lastBuildHash).toBeDefined();
204
+ expect(status.buildState.lastBuildDate).toBeDefined();
205
+ // After apply
206
+ await manager.processTemplates({ apply: true });
207
+ status = await manager.getTemplateStatus(templatePath);
208
+ expect(status.buildState.lastAppliedHash).toBeDefined();
209
+ expect(status.buildState.lastAppliedDate).toBeDefined();
210
+ }
211
+ catch (e_4) {
212
+ env_4.error = e_4;
213
+ env_4.hasError = true;
214
+ }
215
+ finally {
216
+ __disposeResources(env_4);
217
+ }
173
218
  });
174
219
  it('should handle rapid template changes', async () => {
175
- const templatePath = join(testContext.testDir, 'test-templates', `test-${testContext.timestamp}.sql`);
176
- const baseContent = `CREATE OR REPLACE FUNCTION ${testContext.testFunctionName}() RETURNS void AS $$ BEGIN NULL; END; $$ LANGUAGE plpgsql;`;
177
- await fs.writeFile(templatePath, baseContent);
178
- const manager = await TemplateManager.create(testContext.testDir);
179
- const changes = [];
180
- manager.on('templateChanged', async (template) => {
181
- changes.push(template.currentHash);
182
- });
183
- const watcher = await manager.watch();
184
- await new Promise(resolve => setTimeout(resolve, 100));
185
- // Make rapid changes
186
- for (let i = 0; i < 5; i++) {
187
- await fs.writeFile(templatePath, `${baseContent}\n-- Change ${i}`);
188
- await new Promise(resolve => setTimeout(resolve, 51));
189
- }
190
- await new Promise(resolve => setTimeout(resolve, 500));
191
- watcher.close();
192
- expect(changes.length).toBeGreaterThanOrEqual(1);
193
- expect(new Set(changes).size).toBe(changes.length); // All changes should be unique
220
+ const env_5 = { stack: [], error: void 0, hasError: false };
221
+ try {
222
+ const templatePath = join(testContext.testDir, 'test-templates', `template_${testContext.testId}_1.sql`);
223
+ const baseContent = `CREATE OR REPLACE FUNCTION ${testContext.testFunctionName}() RETURNS void AS $$ BEGIN NULL; END; $$ LANGUAGE plpgsql;`;
224
+ await fs.writeFile(templatePath, baseContent);
225
+ const manager = __addDisposableResource(env_5, await TemplateManager.create(testContext.testDir), false);
226
+ const changes = [];
227
+ manager.on('templateChanged', async (template) => {
228
+ changes.push(template.currentHash);
229
+ });
230
+ const watcher = await manager.watch();
231
+ await wait(100);
232
+ // Make rapid changes
233
+ for (let i = 0; i < 5; i++) {
234
+ await fs.writeFile(templatePath, `${baseContent}\n-- Change ${i}`);
235
+ await wait(100);
236
+ }
237
+ await wait(500);
238
+ watcher.close();
239
+ expect(changes.length).toBeGreaterThanOrEqual(1);
240
+ expect(new Set(changes).size).toBe(changes.length); // All changes should be unique
241
+ }
242
+ catch (e_5) {
243
+ env_5.error = e_5;
244
+ env_5.hasError = true;
245
+ }
246
+ finally {
247
+ __disposeResources(env_5);
248
+ }
194
249
  }, 10000);
195
250
  it('should apply WIP templates directly to database', async () => {
196
- const templatePath = join(testContext.testDir, 'test-templates', `test-${testContext.timestamp}.wip.sql`);
197
- const templateContent = `CREATE FUNCTION ${testContext.testFunctionName}() RETURNS void AS $$ BEGIN NULL; END; $$ LANGUAGE plpgsql;`;
198
- await fs.writeFile(templatePath, templateContent);
199
- const manager = await TemplateManager.create(testContext.testDir);
200
- const result = await manager.processTemplates({ apply: true });
201
- expect(result.errors).toHaveLength(0);
202
- const client = await connect();
251
+ const env_6 = { stack: [], error: void 0, hasError: false };
203
252
  try {
204
- const res = await client.query(`SELECT COUNT(*) FROM pg_proc WHERE proname = $1`, [
205
- testContext.testFunctionName,
206
- ]);
207
- expect(Number.parseInt(res.rows[0].count)).toBe(1);
253
+ const templatePath = join(testContext.testDir, 'test-templates', `template_${testContext.testId}_1.wip.sql`);
254
+ const templateContent = `CREATE FUNCTION ${testContext.testFunctionName}() RETURNS void AS $$ BEGIN NULL; END; $$ LANGUAGE plpgsql;`;
255
+ await fs.writeFile(templatePath, templateContent);
256
+ const manager = __addDisposableResource(env_6, await TemplateManager.create(testContext.testDir), false);
257
+ const result = await manager.processTemplates({ apply: true });
258
+ expect(result.errors).toHaveLength(0);
259
+ const client = await connect();
260
+ try {
261
+ const res = await client.query(`SELECT COUNT(*) FROM pg_proc WHERE proname = $1`, [
262
+ testContext.testFunctionName,
263
+ ]);
264
+ expect(Number.parseInt(res.rows[0].count)).toBe(1);
265
+ }
266
+ finally {
267
+ client.release();
268
+ }
269
+ }
270
+ catch (e_6) {
271
+ env_6.error = e_6;
272
+ env_6.hasError = true;
208
273
  }
209
274
  finally {
210
- client.release();
275
+ __disposeResources(env_6);
211
276
  }
212
277
  });
213
278
  it('should handle sequential template operations', async () => {
214
- const templates = await Promise.all([...Array(5)].map(async (_, i) => createTemplateWithFunc(`sequencetest-${i}-${testContext.timestamp}.sql`, `_sequence_test_${i}`)));
215
- const manager = await TemplateManager.create(testContext.testDir);
216
- const client = await connect();
279
+ const env_7 = { stack: [], error: void 0, hasError: false };
217
280
  try {
218
- // Start transaction for isolation
219
- await client.query('BEGIN');
220
- // Apply templates and verify each one
221
- for (const [index, _] of templates.entries()) {
222
- const result = await manager.processTemplates({ apply: true });
281
+ const tmpls = await Promise.all([...Array(5)].map((_, i) => createTemplateWithFunc(`sequencetest_${i}`, `_sequence_test_${i}`)));
282
+ expect(tmpls).toHaveLength(5);
283
+ const manager = __addDisposableResource(env_7, await TemplateManager.create(testContext.testDir), false);
284
+ const client = await connect();
285
+ await wait(100);
286
+ try {
287
+ // Start transaction
288
+ await client.query('BEGIN');
289
+ const result = await manager.processTemplates({ apply: true, force: true });
290
+ // Add retry logic for verification
291
+ const verifyFunctions = async (retries = 3, delay = 200) => {
292
+ try {
293
+ const allFunctions = await client.query(`SELECT proname FROM pg_proc WHERE proname LIKE $1`, [`${testContext.testFunctionName}_sequence_test_%`]);
294
+ expect(allFunctions.rows).toHaveLength(5);
295
+ }
296
+ catch (error) {
297
+ console.log('Flakey test failed verifying functions:', error, 'retries', retries);
298
+ if (retries === 0)
299
+ throw error;
300
+ await wait(delay);
301
+ await verifyFunctions(retries - 1, delay * 2);
302
+ }
303
+ };
304
+ await verifyFunctions();
305
+ await client.query('COMMIT');
223
306
  expect(result.errors).toHaveLength(0);
224
- // Wait for function to appear with retry logic
225
- const functionExists = await waitForCondition(async () => {
226
- const res = await client.query(`SELECT proname FROM pg_proc WHERE proname = $1`, [
227
- `${testContext.testFunctionName}_sequence_test_${index}`,
228
- ]);
229
- return res.rows.length === 1;
230
- });
231
- expect(functionExists).toBe(true);
307
+ expect(result.applied).toHaveLength(5);
308
+ }
309
+ catch (error) {
310
+ await client.query('ROLLBACK');
311
+ throw error;
312
+ }
313
+ finally {
314
+ client.release();
232
315
  }
233
- // Verify final state
234
- const allFunctions = await client.query(`SELECT proname FROM pg_proc WHERE proname LIKE $1`, [
235
- `${testContext.testFunctionName}_sequence_test_%`,
236
- ]);
237
- expect(allFunctions.rows).toHaveLength(5);
238
316
  }
239
- catch (error) {
240
- console.error('Test failed:', error);
241
- throw error;
317
+ catch (e_7) {
318
+ env_7.error = e_7;
319
+ env_7.hasError = true;
242
320
  }
243
321
  finally {
244
- // Cleanup
245
- await client.query('ROLLBACK');
246
- client.release();
322
+ __disposeResources(env_7);
247
323
  }
248
324
  });
249
325
  it('should generate unique timestamps for multiple templates', async () => {
250
- const templates = await Promise.all([...Array(10)].map((_, i) => createTemplateWithFunc(`timestamptest-${i}-${testContext.timestamp}.sql`, `_unique_timestamps_${i}`)));
251
- const manager = await TemplateManager.create(testContext.testDir);
252
- await manager.processTemplates({ generateFiles: true });
253
- const migrations = await fs.readdir(join(testContext.testDir, 'test-migrations'));
254
- const timestamps = migrations.map(m => m.split('_')[0]);
255
- const uniqueTimestamps = new Set(timestamps);
256
- expect(uniqueTimestamps.size).toBe(templates.length);
257
- expect(timestamps).toEqual([...timestamps].sort());
326
+ const env_8 = { stack: [], error: void 0, hasError: false };
327
+ try {
328
+ const templates = await Promise.all([...Array(10)].map((_, i) => createTemplateWithFunc(`timestamptest_${i}`, `_unique_timestamps_${i}`)));
329
+ const manager = __addDisposableResource(env_8, await TemplateManager.create(testContext.testDir), false);
330
+ await manager.processTemplates({ generateFiles: true });
331
+ const migrations = await fs.readdir(join(testContext.testDir, 'test-migrations'));
332
+ const timestamps = migrations.map(m => m.split('_')[0]);
333
+ const uniqueTimestamps = new Set(timestamps);
334
+ expect(uniqueTimestamps.size).toBe(templates.length);
335
+ expect(timestamps).toEqual([...timestamps].sort());
336
+ }
337
+ catch (e_8) {
338
+ env_8.error = e_8;
339
+ env_8.hasError = true;
340
+ }
341
+ finally {
342
+ __disposeResources(env_8);
343
+ }
258
344
  });
259
345
  it('should handle mix of working and broken templates', async () => {
260
- await createTemplateWithFunc(`a-test-good-${testContext.timestamp}.sql`, '_good_and_broken_mix');
261
- await createTemplate(`a-test-bad-${testContext.timestamp}.sql`, 'INVALID SQL SYNTAX;');
262
- const manager = await TemplateManager.create(testContext.testDir);
263
- const result = await manager.processTemplates({ apply: true });
264
- expect(result.errors).toHaveLength(1);
265
- expect(result.applied).toHaveLength(1);
266
- const client = await connect();
346
+ const env_9 = { stack: [], error: void 0, hasError: false };
267
347
  try {
268
- const res = await client.query(`SELECT COUNT(*) FROM pg_proc WHERE proname = $1`, [
269
- `${testContext.testFunctionName}_good_and_broken_mix`,
270
- ]);
271
- expect(Number.parseInt(res.rows[0].count)).toBe(1);
348
+ await createTemplateWithFunc(`a-test-good`, '_good_and_broken_mix');
349
+ await createTemplate(`a-test-bad.sql`, 'INVALID SQL SYNTAX;');
350
+ const manager = __addDisposableResource(env_9, await TemplateManager.create(testContext.testDir), false);
351
+ const result = await manager.processTemplates({ apply: true });
352
+ expect(result.errors).toHaveLength(1);
353
+ expect(result.applied).toHaveLength(1);
354
+ const client = await connect();
355
+ try {
356
+ const res = await client.query(`SELECT COUNT(*) FROM pg_proc WHERE proname = $1`, [
357
+ `${testContext.testFunctionName}_good_and_broken_mix`,
358
+ ]);
359
+ expect(Number.parseInt(res.rows[0].count)).toBe(1);
360
+ }
361
+ finally {
362
+ client.release();
363
+ }
364
+ }
365
+ catch (e_9) {
366
+ env_9.error = e_9;
367
+ env_9.hasError = true;
272
368
  }
273
369
  finally {
274
- client.release();
370
+ __disposeResources(env_9);
275
371
  }
276
372
  });
277
373
  it('should handle database errors gracefully', async () => {
278
- const manager = await TemplateManager.create(testContext.testDir);
279
- await createTemplate(`test-error-${testContext.timestamp}.sql`, 'SELECT 1/0;'); // Division by zero error
280
- const result = await manager.processTemplates({ apply: true });
281
- expect(result.errors).toHaveLength(1);
282
- expect(result.errors[0]?.error).toMatch(/division by zero/i);
374
+ const env_10 = { stack: [], error: void 0, hasError: false };
375
+ try {
376
+ const manager = __addDisposableResource(env_10, await TemplateManager.create(testContext.testDir), false);
377
+ await createTemplate(`test-error.sql`, 'SELECT 1/0;'); // Division by zero error
378
+ const result = await manager.processTemplates({ apply: true });
379
+ expect(result.errors).toHaveLength(1);
380
+ expect(result.errors[0]?.error).toMatch(/division by zero/i);
381
+ }
382
+ catch (e_10) {
383
+ env_10.error = e_10;
384
+ env_10.hasError = true;
385
+ }
386
+ finally {
387
+ __disposeResources(env_10);
388
+ }
283
389
  });
284
390
  it('should handle file system errors', async () => {
285
- const errorPath = join(testContext.testDir, 'test-templates', `test-error-${testContext.timestamp}.sql`);
391
+ const errorPath = join(testContext.testDir, 'test-templates', `test-error.sql`);
286
392
  try {
287
- await createTemplate(`test-error-${testContext.timestamp}.sql`, 'SELECT 1;');
288
- await fs.chmod(errorPath, 0o000);
289
- const manager = await TemplateManager.create(testContext.testDir);
290
- await manager.processTemplates({ generateFiles: true });
291
- // Cleanup for afterEach
292
- await fs.chmod(errorPath, 0o644);
393
+ const env_11 = { stack: [], error: void 0, hasError: false };
394
+ try {
395
+ await createTemplate(`test-error.sql`, 'SELECT 1;');
396
+ await fs.chmod(errorPath, 0o000);
397
+ const manager = __addDisposableResource(env_11, await TemplateManager.create(testContext.testDir), false);
398
+ try {
399
+ await manager.processTemplates({ generateFiles: true });
400
+ }
401
+ catch (error) {
402
+ expect(error).toBeDefined();
403
+ }
404
+ // Cleanup for afterEach
405
+ await fs.chmod(errorPath, 0o644);
406
+ }
407
+ catch (e_11) {
408
+ env_11.error = e_11;
409
+ env_11.hasError = true;
410
+ }
411
+ finally {
412
+ __disposeResources(env_11);
413
+ }
293
414
  }
294
415
  catch (error) {
295
416
  expect(error).toBeDefined();
@@ -303,17 +424,30 @@ describe('TemplateManager', () => {
303
424
  }
304
425
  });
305
426
  it('should handle large batches of templates', async () => {
306
- // Create 50 templates
307
- await Promise.all([...Array(50)].map((_, i) => createTemplateWithFunc(`test-${i}-${testContext.timestamp}.sql`, `_large_batch_${i}`)));
308
- const manager = await TemplateManager.create(testContext.testDir);
309
- const result = await manager.processTemplates({ generateFiles: true });
310
- expect(result.errors).toHaveLength(0);
311
- const migrations = await fs.readdir(join(testContext.testDir, 'test-migrations'));
312
- expect(migrations.length).toBe(50);
427
+ const env_12 = { stack: [], error: void 0, hasError: false };
428
+ try {
429
+ // Create 50 templates
430
+ await Promise.all([...Array(50)].map((_, i) => createTemplateWithFunc(`test_${i}`, `_large_batch_${i}`)));
431
+ const manager = __addDisposableResource(env_12, await TemplateManager.create(testContext.testDir), false);
432
+ const result = await manager.processTemplates({ generateFiles: true });
433
+ expect(result.errors).toHaveLength(0);
434
+ const migrations = await fs.readdir(join(testContext.testDir, 'test-migrations'));
435
+ expect(migrations.length).toBe(50);
436
+ }
437
+ catch (e_12) {
438
+ env_12.error = e_12;
439
+ env_12.hasError = true;
440
+ }
441
+ finally {
442
+ __disposeResources(env_12);
443
+ }
313
444
  });
314
445
  it('should handle templates with complex SQL', async () => {
315
- const complexSQL = `
316
- CREATE OR REPLACE FUNCTION ${testContext.testFunctionName}(
446
+ const env_13 = { stack: [], error: void 0, hasError: false };
447
+ try {
448
+ const testFunctionName = `${testContext.testFunctionName}_complex`;
449
+ const complexSQL = `
450
+ CREATE OR REPLACE FUNCTION ${testFunctionName}(
317
451
  param1 integer DEFAULT 100,
318
452
  OUT result1 integer,
319
453
  OUT result2 text
@@ -337,413 +471,595 @@ describe('TemplateManager', () => {
337
471
  END;
338
472
  $$ LANGUAGE plpgsql;
339
473
  `;
340
- await createTemplate(`test-complex-${testContext.timestamp}.sql`, complexSQL);
341
- const manager = await TemplateManager.create(testContext.testDir);
342
- const result = await manager.processTemplates({ apply: true });
343
- expect(result.errors).toHaveLength(0);
344
- const client = await connect();
345
- try {
346
- const res = await client.query(`
474
+ await createTemplate(`test-complex.sql`, complexSQL);
475
+ const manager = __addDisposableResource(env_13, await TemplateManager.create(testContext.testDir), false);
476
+ const result = await manager.processTemplates({ apply: true });
477
+ expect(result.errors).toHaveLength(0);
478
+ const client = await connect();
479
+ try {
480
+ const res = await client.query(`
347
481
  SELECT proname, pronargs, prorettype::regtype::text as return_type
348
482
  FROM pg_proc
349
483
  WHERE proname = $1
350
- `, [testContext.testFunctionName]);
351
- expect(res.rows).toHaveLength(1);
352
- expect(res.rows[0].return_type).toBe('record');
484
+ `, [testFunctionName]);
485
+ expect(res.rows).toHaveLength(1);
486
+ expect(res.rows[0].return_type).toBe('record');
487
+ }
488
+ finally {
489
+ client.release();
490
+ }
491
+ }
492
+ catch (e_13) {
493
+ env_13.error = e_13;
494
+ env_13.hasError = true;
353
495
  }
354
496
  finally {
355
- client.release();
497
+ __disposeResources(env_13);
356
498
  }
357
499
  });
358
500
  it('should maintain template state across manager instances', async () => {
359
- const template = await createTemplateWithFunc(`test-${testContext.timestamp}.sql`, 'maintain_state');
360
- // First manager instance
361
- const manager1 = await TemplateManager.create(testContext.testDir);
362
- await manager1.processTemplates({ generateFiles: true });
363
- // Second manager instance should see the state
364
- const manager2 = await TemplateManager.create(testContext.testDir);
365
- const status = await manager2.getTemplateStatus(template);
366
- expect(status.buildState.lastBuildHash).toBeDefined();
501
+ const env_14 = { stack: [], error: void 0, hasError: false };
502
+ try {
503
+ const template = await createTemplateWithFunc(`test`, 'maintain_state');
504
+ // First manager instance
505
+ const manager1 = __addDisposableResource(env_14, await TemplateManager.create(testContext.testDir), false);
506
+ await manager1.processTemplates({ generateFiles: true });
507
+ // Second manager instance should see the state
508
+ const manager2 = __addDisposableResource(env_14, await TemplateManager.create(testContext.testDir), false);
509
+ const status = await manager2.getTemplateStatus(template);
510
+ expect(status.buildState.lastBuildHash).toBeDefined();
511
+ }
512
+ catch (e_14) {
513
+ env_14.error = e_14;
514
+ env_14.hasError = true;
515
+ }
516
+ finally {
517
+ __disposeResources(env_14);
518
+ }
367
519
  });
368
520
  it('should handle template additions in watch mode', async () => {
369
- const manager = await TemplateManager.create(testContext.testDir);
370
- const changes = [];
371
- manager.on('templateChanged', template => {
372
- changes.push(template.name);
373
- });
374
- const watcher = await manager.watch();
375
- // Add new template after watch started
376
- await createTemplateWithFunc(`test-new-${testContext.timestamp}.sql`, '_watch_addition');
377
- await new Promise(resolve => setTimeout(resolve, 150));
378
- watcher.close();
379
- expect(changes).toContain(`test-new-${testContext.timestamp}`);
521
+ const env_15 = { stack: [], error: void 0, hasError: false };
522
+ try {
523
+ const manager = __addDisposableResource(env_15, await TemplateManager.create(testContext.testDir), false);
524
+ const changes = [];
525
+ manager.on('templateChanged', template => {
526
+ changes.push(template.name);
527
+ });
528
+ const watcher = await manager.watch();
529
+ // Add new template after watch started
530
+ await createTemplateWithFunc('new', '_watch_addition');
531
+ await wait(150);
532
+ watcher.close();
533
+ expect(changes).toContain(`new_${testContext.testId}_1`);
534
+ }
535
+ catch (e_15) {
536
+ env_15.error = e_15;
537
+ env_15.hasError = true;
538
+ }
539
+ finally {
540
+ __disposeResources(env_15);
541
+ }
380
542
  });
381
543
  it('should handle templates in deep subdirectories', async () => {
382
- // Create nested directory structure
383
- const depth = 5;
384
- const templatePaths = [];
385
- for (let i = 1; i <= depth; i++) {
386
- const dir = [...Array(i)].map((_, idx) => `level${idx + 1}`).join('/');
387
- const templatePath = await createTemplateWithFunc(`depth-test-${i}-${testContext.timestamp}.sql`, `_depth_${i}`, dir);
388
- templatePaths.push(templatePath);
389
- }
390
- const manager = await TemplateManager.create(testContext.testDir);
391
- const changes = [];
392
- manager.on('templateChanged', template => {
393
- changes.push(template.name);
394
- });
395
- const watcher = await manager.watch();
396
- await new Promise(resolve => setTimeout(resolve, depth * 100 * 1.1));
397
- watcher.close();
398
- expect(changes.length).toBe(depth);
399
- // Verify each template was detected
400
- for (let i = 1; i <= depth; i++) {
401
- expect(changes).toContain(`depth-test-${i}-${testContext.timestamp}`);
544
+ const env_16 = { stack: [], error: void 0, hasError: false };
545
+ try {
546
+ // Create nested directory structure
547
+ const depth = 5;
548
+ const templatePaths = [];
549
+ for (let i = 1; i <= depth; i++) {
550
+ const dir = [...Array(i)].map((_, idx) => `level${idx + 1}`).join('/');
551
+ const templatePath = await createTemplateWithFunc(`depth-test_${i}`, `_depth_${i}`, dir);
552
+ templatePaths.push(templatePath);
553
+ }
554
+ const manager = __addDisposableResource(env_16, await TemplateManager.create(testContext.testDir), false);
555
+ const changes = [];
556
+ manager.on('templateChanged', template => {
557
+ changes.push(template.name);
558
+ });
559
+ const watcher = await manager.watch();
560
+ await wait(depth * 100 * 1.1);
561
+ watcher.close();
562
+ expect(changes.length).toBe(depth);
563
+ // Verify each template was detected
564
+ for (let i = 1; i <= depth; i++) {
565
+ expect(changes).toContain(`depth-test_${i}_${testContext.testId}_${i}`);
566
+ }
567
+ }
568
+ catch (e_16) {
569
+ env_16.error = e_16;
570
+ env_16.hasError = true;
571
+ }
572
+ finally {
573
+ __disposeResources(env_16);
402
574
  }
403
575
  });
404
576
  it('should only watch SQL files', async () => {
405
- const manager = await TemplateManager.create(testContext.testDir);
406
- const changes = [];
407
- manager.on('templateChanged', template => {
408
- changes.push(template.name);
409
- });
410
- const watcher = await manager.watch();
411
- await new Promise(resolve => setTimeout(resolve, 100));
412
- // Create various file types
413
- await fs.writeFile(join(testContext.testDir, 'test-templates/test.txt'), 'not sql');
414
- await fs.writeFile(join(testContext.testDir, 'test-templates/test.md'), 'not sql');
415
- await createTemplateWithFunc(`test-sql-${testContext.timestamp}.sql`, '_watch_sql_only');
416
- await new Promise(resolve => setTimeout(resolve, 500));
417
- watcher.close();
418
- expect(changes).toHaveLength(1);
419
- expect(changes[0]).toBe(`test-sql-${testContext.timestamp}`);
577
+ const env_17 = { stack: [], error: void 0, hasError: false };
578
+ try {
579
+ const manager = __addDisposableResource(env_17, await TemplateManager.create(testContext.testDir), false);
580
+ const changes = [];
581
+ manager.on('templateChanged', template => {
582
+ changes.push(template.name);
583
+ });
584
+ const watcher = await manager.watch();
585
+ await wait(100);
586
+ // Create various file types
587
+ await fs.writeFile(join(testContext.testDir, 'test-templates/test.txt'), 'not sql');
588
+ await fs.writeFile(join(testContext.testDir, 'test-templates/test.md'), 'not sql');
589
+ await createTemplateWithFunc(`sql`, '_watch_sql_only');
590
+ await wait(500);
591
+ watcher.close();
592
+ expect(changes).toHaveLength(1);
593
+ expect(changes[0]).toBe(`sql_${testContext.testId}_1`);
594
+ }
595
+ catch (e_17) {
596
+ env_17.error = e_17;
597
+ env_17.hasError = true;
598
+ }
599
+ finally {
600
+ __disposeResources(env_17);
601
+ }
420
602
  });
421
603
  it('should handle multiple template changes simultaneously', async () => {
422
- const manager = await TemplateManager.create(testContext.testDir);
423
- const changes = new Set();
424
- const count = 5;
425
- manager.on('templateChanged', template => {
426
- changes.add(template.name);
427
- });
428
- const watcher = await manager.watch();
429
- await new Promise(resolve => setTimeout(resolve, 100));
430
- // Create multiple templates simultaneously
431
- await Promise.all([
432
- createTemplateWithFunc(`rapid_test-1-${testContext.timestamp}.sql`, '_batch_changes_1'),
433
- createTemplateWithFunc(`rapid_test-2-${testContext.timestamp}.sql`, '_batch_changes_2'),
434
- createTemplateWithFunc(`rapid_test-3-${testContext.timestamp}.sql`, '_batch_changes_3'),
435
- createTemplateWithFunc(`rapid_test-4-${testContext.timestamp}.sql`, '_batch_changes_4', 'deep'),
436
- createTemplateWithFunc(`rapid_test-5-${testContext.timestamp}.sql`, '_batch_changes_5', 'deep/nested'),
437
- ]);
438
- // Give enough time for all changes to be detected
439
- await new Promise(resolve => setTimeout(resolve, count * 100 * 1.1));
440
- watcher.close();
441
- expect(changes.size).toBe(count); // Should detect all 5 templates
442
- for (let i = 1; i <= count; i++) {
443
- expect(changes.has(`rapid_test-${i}-${testContext.timestamp}`)).toBe(true);
444
- }
445
- // Verify all templates were processed
446
- const client = await connect();
604
+ const env_18 = { stack: [], error: void 0, hasError: false };
447
605
  try {
606
+ const client = await connect();
607
+ const manager = __addDisposableResource(env_18, await TemplateManager.create(testContext.testDir), false);
608
+ const changes = new Set();
609
+ const count = 5;
610
+ const watcher = await manager.watch();
611
+ await wait(100);
612
+ manager.on('templateChanged', template => {
613
+ changes.add(template.name);
614
+ });
615
+ // Create multiple templates simultaneously
616
+ try {
617
+ await createTemplateWithFunc(`rapid_test_1`, '_batch_changes_1');
618
+ await createTemplateWithFunc(`rapid_test_2`, '_batch_changes_2');
619
+ await createTemplateWithFunc(`rapid_test_3`, '_batch_changes_3');
620
+ await createTemplateWithFunc(`rapid_test_4`, '_batch_changes_4', 'deep');
621
+ await createTemplateWithFunc(`rapid_test_5`, '_batch_changes_5', 'deep/nested');
622
+ }
623
+ catch (error) {
624
+ console.error('Error creating templates:', error);
625
+ throw error;
626
+ }
627
+ // Give enough time for all changes to be detected
628
+ await wait(count * 100 * 1.1);
629
+ watcher.close();
630
+ expect(changes.size).toBe(count); // Should detect all 5 templates
448
631
  for (let i = 1; i <= count; i++) {
449
- const res = await client.query(`SELECT proname FROM pg_proc WHERE proname = $1`, [
450
- `${testContext.testFunctionName}_batch_changes_${i}`,
632
+ expect(changes.has(`rapid_test_${i}_${testContext.testId}_${i}`)).toBe(true);
633
+ }
634
+ // Verify all templates were processed
635
+ await wait(100);
636
+ try {
637
+ const res = await client.query(`SELECT proname FROM pg_proc WHERE proname LIKE $1`, [
638
+ `${testContext.testFunctionName}_batch_changes_%`,
451
639
  ]);
452
- expect(res.rows).toHaveLength(1);
640
+ // expect(res).toBe('');
641
+ expect(res.rows).toHaveLength(count);
642
+ }
643
+ catch (error) {
644
+ console.error('Error querying functions:', error);
645
+ }
646
+ finally {
647
+ client.release();
453
648
  }
454
649
  }
650
+ catch (e_18) {
651
+ env_18.error = e_18;
652
+ env_18.hasError = true;
653
+ }
455
654
  finally {
456
- client.release();
655
+ __disposeResources(env_18);
457
656
  }
458
657
  }, 15000);
459
658
  it('should handle rapid bulk template creation realistically', async () => {
460
- const TEMPLATE_COUNT = 50;
461
- const manager = await TemplateManager.create(testContext.testDir);
462
- const processed = new Set();
463
- const failed = new Set();
464
- const inProgress = new Set();
465
- const events = [];
466
- let resolveProcessing;
467
- const processingComplete = new Promise(resolve => {
468
- resolveProcessing = resolve;
469
- });
470
- manager.on('templateChanged', ({ name }) => {
471
- events.push({ event: 'changed', template: name, time: Date.now() });
472
- inProgress.add(name);
473
- });
474
- manager.on('templateApplied', ({ name }) => {
475
- events.push({ event: 'applied', template: name, time: Date.now() });
476
- processed.add(name);
477
- inProgress.delete(name);
478
- if (processed.size + failed.size === TEMPLATE_COUNT) {
479
- resolveProcessing();
480
- }
481
- });
482
- manager.on('templateError', ({ template: { name }, error }) => {
483
- events.push({ event: 'error', template: name, time: Date.now() });
484
- failed.add(name);
485
- inProgress.delete(name);
486
- console.error('Template error:', { name, error });
487
- if (processed.size + failed.size === TEMPLATE_COUNT) {
488
- resolveProcessing();
489
- }
490
- });
491
- const watcher = await manager.watch();
492
- // Create all templates
493
- await Promise.all(Array.from({ length: TEMPLATE_COUNT }, (_, i) => createTemplateWithFunc(`bulk_created_template_${i + 1}.sql`, `_bulk_${i + 1}`)));
494
- await processingComplete;
495
- watcher.close();
496
- expect(processed.size + failed.size).toBe(TEMPLATE_COUNT);
497
- expect(inProgress.size).toBe(0);
498
- expect(failed.size).toBe(0);
659
+ const env_19 = { stack: [], error: void 0, hasError: false };
660
+ try {
661
+ const TEMPLATE_COUNT = 50;
662
+ const manager = __addDisposableResource(env_19, await TemplateManager.create(testContext.testDir), false);
663
+ const processed = new Set();
664
+ const failed = new Set();
665
+ const inProgress = new Set();
666
+ const events = [];
667
+ let resolveProcessing;
668
+ const processingComplete = new Promise(resolve => {
669
+ resolveProcessing = resolve;
670
+ });
671
+ manager.on('templateChanged', ({ name }) => {
672
+ events.push({ event: 'changed', template: name, time: Date.now() });
673
+ inProgress.add(name);
674
+ });
675
+ manager.on('templateApplied', ({ name }) => {
676
+ events.push({ event: 'applied', template: name, time: Date.now() });
677
+ processed.add(name);
678
+ inProgress.delete(name);
679
+ if (processed.size + failed.size === TEMPLATE_COUNT) {
680
+ resolveProcessing();
681
+ }
682
+ });
683
+ manager.on('templateError', ({ template: { name }, error }) => {
684
+ events.push({ event: 'error', template: name, time: Date.now() });
685
+ failed.add(name);
686
+ inProgress.delete(name);
687
+ console.error('Template error:', { name, error });
688
+ if (processed.size + failed.size === TEMPLATE_COUNT) {
689
+ resolveProcessing();
690
+ }
691
+ });
692
+ const watcher = await manager.watch();
693
+ // Create all templates
694
+ await Promise.all(Array.from({ length: TEMPLATE_COUNT }, (_, i) => createTemplateWithFunc(`bulk_${i + 1}`, `_bulk_${i + 1}`)));
695
+ await processingComplete;
696
+ watcher.close();
697
+ expect(processed.size + failed.size).toBe(TEMPLATE_COUNT);
698
+ expect(inProgress.size).toBe(0);
699
+ expect(failed.size).toBe(0);
700
+ }
701
+ catch (e_19) {
702
+ env_19.error = e_19;
703
+ env_19.hasError = true;
704
+ }
705
+ finally {
706
+ __disposeResources(env_19);
707
+ }
499
708
  });
500
709
  it('should cleanup resources when disposed', async () => {
501
- const manager = await TemplateManager.create(testContext.testDir);
502
- const changes = [];
503
- manager.on('templateChanged', template => {
504
- changes.push(template.name);
505
- });
506
- await manager.watch();
507
- // Create template before disposal
508
- await createTemplateWithFunc(`test-before-dispose-${testContext.timestamp}.sql`, 'before_dispose');
509
- await new Promise(resolve => setTimeout(resolve, 100));
510
- // Dispose and verify cleanup
511
- manager[Symbol.dispose]();
512
- // Try creating template after disposal
513
- await createTemplateWithFunc(`test-after-dispose-${testContext.timestamp}.sql`, 'after_dispose');
514
- await new Promise(resolve => setTimeout(resolve, 100));
515
- expect(changes).toHaveLength(1);
516
- expect(changes[0]).toBe(`test-before-dispose-${testContext.timestamp}`);
710
+ const env_20 = { stack: [], error: void 0, hasError: false };
711
+ try {
712
+ const manager = __addDisposableResource(env_20, await TemplateManager.create(testContext.testDir), false);
713
+ const changes = [];
714
+ manager.on('templateChanged', template => {
715
+ changes.push(template.name);
716
+ });
717
+ await manager.watch();
718
+ // Create template before disposal
719
+ await createTemplateWithFunc(`before-dispose`, 'before_dispose');
720
+ await wait(100);
721
+ // Dispose and verify cleanup
722
+ manager[Symbol.dispose]();
723
+ // Try creating template after disposal
724
+ await createTemplateWithFunc(`after-dispose`, 'after_dispose');
725
+ await wait(100);
726
+ expect(changes).toHaveLength(1);
727
+ expect(changes[0]).toBe(`before-dispose_${testContext.testId}_1`);
728
+ }
729
+ catch (e_20) {
730
+ env_20.error = e_20;
731
+ env_20.hasError = true;
732
+ }
733
+ finally {
734
+ __disposeResources(env_20);
735
+ }
517
736
  });
518
737
  it('should auto-cleanup with using statement', async () => {
519
738
  const changes = [];
520
739
  await (async () => {
521
- const env_1 = { stack: [], error: void 0, hasError: false };
740
+ const env_21 = { stack: [], error: void 0, hasError: false };
522
741
  try {
523
- const manager = __addDisposableResource(env_1, await TemplateManager.create(testContext.testDir), false);
742
+ const manager = __addDisposableResource(env_21, await TemplateManager.create(testContext.testDir), false);
524
743
  manager.on('templateChanged', template => {
525
744
  changes.push(template.name);
526
745
  });
527
746
  await manager.watch();
528
- await createTemplateWithFunc(`test-during-scope-${testContext.timestamp}.sql`, 'during_scope');
529
- await new Promise(resolve => setTimeout(resolve, 100));
747
+ await createTemplateWithFunc(`during-scope`, 'during_scope');
748
+ await wait(100);
530
749
  }
531
- catch (e_1) {
532
- env_1.error = e_1;
533
- env_1.hasError = true;
750
+ catch (e_21) {
751
+ env_21.error = e_21;
752
+ env_21.hasError = true;
534
753
  }
535
754
  finally {
536
- __disposeResources(env_1);
755
+ __disposeResources(env_21);
537
756
  }
538
757
  })();
539
758
  // After scope exit, create another template
540
- await createTemplateWithFunc(`test-after-scope-${testContext.timestamp}.sql`, 'after_scope');
541
- await new Promise(resolve => setTimeout(resolve, 100));
759
+ await createTemplateWithFunc(`after-scope`, 'after_scope');
760
+ await wait(100);
761
+ expect(changes[0]).toBe(`during-scope_${testContext.testId}_1`);
542
762
  expect(changes).toHaveLength(1);
543
- expect(changes[0]).toBe(`test-during-scope-${testContext.timestamp}`);
544
763
  });
545
764
  it('should not process unchanged templates', async () => {
546
- const templatePath = await createTemplateWithFunc(`test-unchanged-${testContext.timestamp}.sql`, 'unchanged');
547
- const manager = await TemplateManager.create(testContext.testDir);
548
- await manager.watch();
549
- // First processing
550
- await manager.processTemplates({ apply: true });
551
- // Get the status after first processing
552
- const statusAfterFirstRun = await manager.getTemplateStatus(templatePath);
553
- const changes = [];
554
- manager.on('templateChanged', template => {
555
- changes.push(template.name);
556
- });
557
- // Process again without changes
558
- await manager.processTemplates({ apply: true });
559
- // Get status after second run
560
- const statusAfterSecondRun = await manager.getTemplateStatus(templatePath);
561
- expect(changes).toHaveLength(0);
562
- expect(statusAfterSecondRun.buildState.lastBuildHash).toBe(statusAfterFirstRun.buildState.lastBuildHash);
563
- expect(statusAfterSecondRun.buildState.lastAppliedHash).toBe(statusAfterFirstRun.buildState.lastAppliedHash);
765
+ const env_22 = { stack: [], error: void 0, hasError: false };
766
+ try {
767
+ const templatePath = await createTemplateWithFunc(`initial_will_remain_unchanged`, 'unchanged_tmpl');
768
+ const manager = __addDisposableResource(env_22, await TemplateManager.create(testContext.testDir), false);
769
+ await manager.watch();
770
+ // First processing
771
+ await manager.processTemplates({ apply: true });
772
+ // Get the status after first processing
773
+ const statusAfterFirstRun = await manager.getTemplateStatus(templatePath);
774
+ const changes = [];
775
+ manager.on('templateChanged', template => {
776
+ changes.push(template.name);
777
+ });
778
+ // Process again without changes
779
+ await manager.processTemplates({ apply: true });
780
+ // Get status after second run
781
+ const statusAfterSecondRun = await manager.getTemplateStatus(templatePath);
782
+ expect(changes).toHaveLength(0);
783
+ expect(statusAfterSecondRun.buildState.lastBuildHash).toBe(statusAfterFirstRun.buildState.lastBuildHash);
784
+ expect(statusAfterSecondRun.buildState.lastAppliedHash).toBe(statusAfterFirstRun.buildState.lastAppliedHash);
785
+ }
786
+ catch (e_22) {
787
+ env_22.error = e_22;
788
+ env_22.hasError = true;
789
+ }
790
+ finally {
791
+ __disposeResources(env_22);
792
+ }
564
793
  });
565
794
  it('should only process modified templates in batch', async () => {
566
- // Create two templates
567
- const template1 = await createTemplateWithFunc(`modified_tmpl_1-${testContext.timestamp}.sql`, 'mod_1');
568
- await createTemplateWithFunc(`modified_tmpl_2-${testContext.timestamp}.sql`, 'mod_2');
569
- const manager = await TemplateManager.create(testContext.testDir);
570
- // First processing of both
571
- await manager.processTemplates({ apply: true });
572
- const changes = [];
573
- manager.on('templateChanged', template => {
574
- changes.push(template.name);
575
- });
576
- // Modify only template1
577
- await fs.writeFile(template1, `${await fs.readFile(template1, 'utf-8')}\n-- Modified`);
578
- // Process both templates again
579
- await manager.processTemplates({ apply: true });
580
- expect(changes).toHaveLength(1);
581
- expect(changes[0]).toBe(`modified_tmpl_1-${testContext.timestamp}`);
795
+ const env_23 = { stack: [], error: void 0, hasError: false };
796
+ try {
797
+ // Create two templates
798
+ const template1 = await createTemplateWithFunc(`modified_tmpl_1`, 'mod_1');
799
+ await createTemplateWithFunc(`modified_tmpl_2`, 'mod_2');
800
+ const manager = __addDisposableResource(env_23, await TemplateManager.create(testContext.testDir), false);
801
+ // First processing of both
802
+ await manager.processTemplates({ apply: true });
803
+ const changes = [];
804
+ manager.on('templateChanged', template => {
805
+ changes.push(template.name);
806
+ });
807
+ // Modify only template1
808
+ try {
809
+ const tmpl1content = await fs.readFile(template1, 'utf-8');
810
+ await fs.writeFile(template1, `${tmpl1content}\n-- Modified`);
811
+ }
812
+ catch (error) {
813
+ console.error('Test: Error modifying template:', error);
814
+ throw error;
815
+ }
816
+ // Process both templates again
817
+ await manager.processTemplates({ apply: true });
818
+ expect(changes).toHaveLength(1);
819
+ expect(changes[0]).toBe(`modified_tmpl_1_${testContext.testId}_1`);
820
+ }
821
+ catch (e_23) {
822
+ env_23.error = e_23;
823
+ env_23.hasError = true;
824
+ }
825
+ finally {
826
+ __disposeResources(env_23);
827
+ }
582
828
  });
583
829
  it('should correctly update local buildlog on apply', async () => {
584
- const templatePath = await createTemplateWithFunc(`test-buildlog-${testContext.timestamp}.sql`, '_buildlog');
585
- const manager = await TemplateManager.create(testContext.testDir);
586
- const localBuildlogPath = join(testContext.testDir, '.buildlog-test.local.json');
587
- // Initial apply
588
- await manager.processTemplates({ apply: true });
589
- const initialLog = JSON.parse(await fs.readFile(localBuildlogPath, 'utf-8'));
590
- const relPath = relative(testContext.testDir, templatePath);
591
- const initialHash = initialLog.templates[relPath].lastAppliedHash;
592
- const initialContent = await fs.readFile(templatePath, 'utf-8');
593
- expect(initialHash).toBeDefined();
594
- // Modify template
595
- await fs.writeFile(templatePath, `${initialContent}\n-- Modified`);
596
- await new Promise(resolve => setTimeout(resolve, 100));
597
- const changedContent = await fs.readFile(templatePath, 'utf-8');
598
- // Second apply
599
- await manager.processTemplates({ apply: true });
600
- await new Promise(resolve => setTimeout(resolve, 100));
601
- const updatedLog = JSON.parse(await fs.readFile(localBuildlogPath, 'utf-8'));
602
- const newHash = updatedLog.templates[relPath].lastAppliedHash;
603
- const manualMd5 = await calculateMD5(changedContent);
604
- expect(newHash).toBeDefined();
605
- expect(newHash).toBe(manualMd5);
606
- expect(newHash).not.toBe(initialHash);
830
+ const env_24 = { stack: [], error: void 0, hasError: false };
831
+ try {
832
+ const templatePath = await createTemplateWithFunc(`buildlog`, '_buildlog');
833
+ const manager = __addDisposableResource(env_24, await TemplateManager.create(testContext.testDir), false);
834
+ const localBuildlogPath = join(testContext.testDir, '.buildlog-test.local.json');
835
+ // Initial apply
836
+ await manager.processTemplates({ apply: true });
837
+ const initialLog = JSON.parse(await fs.readFile(localBuildlogPath, 'utf-8'));
838
+ const relPath = relative(testContext.testDir, templatePath);
839
+ const initialHash = initialLog.templates[relPath].lastAppliedHash;
840
+ const initialContent = await fs.readFile(templatePath, 'utf-8');
841
+ expect(initialHash).toBeDefined();
842
+ // Modify template
843
+ await fs.writeFile(templatePath, `${initialContent}\n-- Modified`);
844
+ await wait(100);
845
+ const changedContent = await fs.readFile(templatePath, 'utf-8');
846
+ // Second apply
847
+ await manager.processTemplates({ apply: true });
848
+ await wait(100);
849
+ const updatedLog = JSON.parse(await fs.readFile(localBuildlogPath, 'utf-8'));
850
+ const newHash = updatedLog.templates[relPath].lastAppliedHash;
851
+ const manualMd5 = await calculateMD5(changedContent);
852
+ expect(newHash).toBeDefined();
853
+ expect(newHash).toBe(manualMd5);
854
+ expect(newHash).not.toBe(initialHash);
855
+ }
856
+ catch (e_24) {
857
+ env_24.error = e_24;
858
+ env_24.hasError = true;
859
+ }
860
+ finally {
861
+ __disposeResources(env_24);
862
+ }
607
863
  });
608
864
  it('should skip apply if template hash matches local buildlog', async () => {
609
- const templatePath = await createTemplateWithFunc(`test-skip-${testContext.timestamp}.sql`, '_skip_apply');
610
- const manager = await TemplateManager.create(testContext.testDir);
611
- const localBuildlogPath = join(testContext.testDir, '.buildlog-test.local.json');
612
- // Initial apply
613
- await manager.processTemplates({ apply: true });
614
- const initialLog = JSON.parse(await fs.readFile(localBuildlogPath, 'utf-8'));
615
- const relPath = relative(testContext.testDir, templatePath);
616
- const initialHash = initialLog.templates[relPath].lastAppliedHash;
617
- const initialDate = initialLog.templates[relPath].lastAppliedDate;
618
- // Wait a bit to ensure timestamp would be different
619
- await new Promise(resolve => setTimeout(resolve, 100));
620
- // Apply again without changes
621
- await manager.processTemplates({ apply: true });
622
- const updatedLog = JSON.parse(await fs.readFile(localBuildlogPath, 'utf-8'));
623
- // Hash and date should remain exactly the same since no changes were made
624
- expect(updatedLog.templates[relPath].lastAppliedHash).toBe(initialHash);
625
- expect(updatedLog.templates[relPath].lastAppliedDate).toBe(initialDate);
865
+ const env_25 = { stack: [], error: void 0, hasError: false };
866
+ try {
867
+ const templatePath = await createTemplateWithFunc(`skip`, '_skip_apply');
868
+ const manager = __addDisposableResource(env_25, await TemplateManager.create(testContext.testDir), false);
869
+ const localBuildlogPath = join(testContext.testDir, '.buildlog-test.local.json');
870
+ // Initial apply
871
+ await manager.processTemplates({ apply: true });
872
+ const initialLog = JSON.parse(await fs.readFile(localBuildlogPath, 'utf-8'));
873
+ const relPath = relative(testContext.testDir, templatePath);
874
+ const initialHash = initialLog.templates[relPath].lastAppliedHash;
875
+ const initialDate = initialLog.templates[relPath].lastAppliedDate;
876
+ // Wait a bit to ensure timestamp would be different
877
+ await wait(100);
878
+ // Apply again without changes
879
+ await manager.processTemplates({ apply: true });
880
+ const updatedLog = JSON.parse(await fs.readFile(localBuildlogPath, 'utf-8'));
881
+ // Hash and date should remain exactly the same since no changes were made
882
+ expect(updatedLog.templates[relPath].lastAppliedHash).toBe(initialHash);
883
+ expect(updatedLog.templates[relPath].lastAppliedDate).toBe(initialDate);
884
+ }
885
+ catch (e_25) {
886
+ env_25.error = e_25;
887
+ env_25.hasError = true;
888
+ }
889
+ finally {
890
+ __disposeResources(env_25);
891
+ }
626
892
  });
627
893
  it('should not reapply unchanged templates in watch mode', async () => {
628
- // Create multiple templates
629
- const templates = await Promise.all([
630
- createTemplateWithFunc(`watch-stable-1-${testContext.timestamp}.sql`, '_watch_1'),
631
- createTemplateWithFunc(`watch-stable-2-${testContext.timestamp}.sql`, '_watch_2'),
632
- ]);
633
- const manager = await TemplateManager.create(testContext.testDir);
634
- const applied = [];
635
- const changed = [];
636
- manager.on('templateChanged', template => {
637
- changed.push(template.name);
638
- });
639
- manager.on('templateApplied', template => {
640
- applied.push(template.name);
641
- });
642
- // First watch session
643
- const watcher1 = await manager.watch();
644
- await new Promise(resolve => setTimeout(resolve, 100));
645
- await watcher1.close();
646
- // Record initial state
647
- const initialApplied = [...applied];
648
- const initialChanged = [...changed];
649
- applied.length = 0;
650
- changed.length = 0;
651
- // Second watch session without any changes
652
- const watcher2 = await manager.watch();
653
- await new Promise(resolve => setTimeout(resolve, 100));
654
- await watcher2.close();
655
- expect(initialApplied).toHaveLength(2); // First run should apply both
656
- expect(initialChanged).toHaveLength(2); // First run should detect both
657
- expect(applied).toHaveLength(0); // Second run should apply none
658
- expect(changed).toHaveLength(0); // Second run should detect none
659
- // Verify the buildlog state
660
- const localBuildlogPath = join(testContext.testDir, '.buildlog-test.local.json');
661
- const buildLog = JSON.parse(await fs.readFile(localBuildlogPath, 'utf-8'));
662
- for (const templatePath of templates) {
663
- const relPath = relative(testContext.testDir, templatePath);
664
- const content = await fs.readFile(templatePath, 'utf-8');
665
- const hash = await calculateMD5(content);
666
- expect(buildLog.templates[relPath].lastAppliedHash).toBe(hash);
894
+ const env_26 = { stack: [], error: void 0, hasError: false };
895
+ try {
896
+ // Create multiple templates
897
+ const templates = await Promise.all([
898
+ createTemplateWithFunc(`watch-stable_1`, '_watch_1'),
899
+ createTemplateWithFunc(`watch-stable_2`, '_watch_2'),
900
+ ]);
901
+ const manager = __addDisposableResource(env_26, await TemplateManager.create(testContext.testDir), false);
902
+ const applied = [];
903
+ const changed = [];
904
+ manager.on('templateChanged', template => {
905
+ changed.push(template.name);
906
+ });
907
+ manager.on('templateApplied', template => {
908
+ applied.push(template.name);
909
+ });
910
+ // First watch session
911
+ const watcher1 = await manager.watch();
912
+ await wait(100);
913
+ await watcher1.close();
914
+ // Record initial state
915
+ const initialApplied = [...applied];
916
+ const initialChanged = [...changed];
917
+ applied.length = 0;
918
+ changed.length = 0;
919
+ // Second watch session without any changes
920
+ const watcher2 = await manager.watch();
921
+ await wait(100);
922
+ await watcher2.close();
923
+ expect(initialApplied).toHaveLength(2); // First run should apply both
924
+ expect(initialChanged).toHaveLength(2); // First run should detect both
925
+ expect(applied).toHaveLength(0); // Second run should apply none
926
+ expect(changed).toHaveLength(0); // Second run should detect none
927
+ // Verify the buildlog state
928
+ const localBuildlogPath = join(testContext.testDir, '.buildlog-test.local.json');
929
+ const buildLog = JSON.parse(await fs.readFile(localBuildlogPath, 'utf-8'));
930
+ for (const templatePath of templates) {
931
+ const relPath = relative(testContext.testDir, templatePath);
932
+ const content = await fs.readFile(templatePath, 'utf-8');
933
+ const hash = await calculateMD5(content);
934
+ expect(buildLog.templates[relPath].lastAppliedHash).toBe(hash);
935
+ }
936
+ }
937
+ catch (e_26) {
938
+ env_26.error = e_26;
939
+ env_26.hasError = true;
940
+ }
941
+ finally {
942
+ __disposeResources(env_26);
667
943
  }
668
944
  });
669
945
  it('should process unapplied templates on startup', async () => {
670
- // Create template but don't process it
671
- await createTemplateWithFunc(`startup-test-${testContext.timestamp}.sql`, '_startup_test');
672
- // Create a new manager instance
673
- const manager = await TemplateManager.create(testContext.testDir);
674
- const changes = [];
675
- const applied = [];
676
- manager.on('templateChanged', t => changes.push(t.name));
677
- manager.on('templateApplied', t => applied.push(t.name));
678
- // Start watching - this should process the template
679
- await manager.watch();
680
- await new Promise(resolve => setTimeout(resolve, 100));
681
- expect(changes).toHaveLength(1);
682
- expect(applied).toHaveLength(1);
683
- expect(changes[0]).toBe(`startup-test-${testContext.timestamp}`);
684
- expect(applied[0]).toBe(`startup-test-${testContext.timestamp}`);
946
+ const env_27 = { stack: [], error: void 0, hasError: false };
947
+ try {
948
+ // Create template but don't process it
949
+ await createTemplateWithFunc(`startup-test`, '_startup_test');
950
+ // Create a new manager instance
951
+ const manager = __addDisposableResource(env_27, await TemplateManager.create(testContext.testDir), false);
952
+ const changes = [];
953
+ const applied = [];
954
+ manager.on('templateChanged', t => changes.push(t.name));
955
+ manager.on('templateApplied', t => applied.push(t.name));
956
+ // Start watching - this should process the template
957
+ await manager.watch();
958
+ await wait(100);
959
+ expect(changes).toHaveLength(1);
960
+ expect(applied).toHaveLength(1);
961
+ expect(changes[0]).toBe(`startup-test_${testContext.testId}_1`);
962
+ expect(applied[0]).toBe(`startup-test_${testContext.testId}_1`);
963
+ }
964
+ catch (e_27) {
965
+ env_27.error = e_27;
966
+ env_27.hasError = true;
967
+ }
968
+ finally {
969
+ __disposeResources(env_27);
970
+ }
685
971
  });
686
972
  it('should handle error state transitions correctly', async () => {
687
- const templatePath = await createTemplateWithFunc(`error-state-${testContext.timestamp}.sql`, '_error_test');
688
- const manager = await TemplateManager.create(testContext.testDir);
689
- const states = [];
690
- manager.on('templateChanged', () => states.push({ type: 'changed' }));
691
- manager.on('templateApplied', () => states.push({ type: 'applied' }));
692
- manager.on('templateError', ({ error }) => states.push({ type: 'error', error: String(error) }));
693
- // First apply should succeed
694
- await manager.processTemplates({ apply: true });
695
- // Modify template to be invalid
696
- await fs.writeFile(templatePath, 'INVALID SQL;');
697
- await manager.processTemplates({ apply: true });
698
- // Fix template with valid SQL
699
- await fs.writeFile(templatePath, `CREATE OR REPLACE FUNCTION ${testContext.testFunctionName}() RETURNS void AS $$ BEGIN NULL; END; $$ LANGUAGE plpgsql;`);
700
- await manager.processTemplates({ apply: true });
701
- expect(states).toEqual([
702
- { type: 'changed' },
703
- { type: 'applied' },
704
- { type: 'changed' },
705
- { type: 'error', error: expect.stringMatching(/syntax error/) },
706
- { type: 'changed' },
707
- { type: 'applied' },
708
- ]);
973
+ const env_28 = { stack: [], error: void 0, hasError: false };
974
+ try {
975
+ const templatePath = await createTemplateWithFunc(`error-state`, '_error_test');
976
+ const manager = __addDisposableResource(env_28, await TemplateManager.create(testContext.testDir), false);
977
+ const states = [];
978
+ manager.on('templateChanged', () => states.push({ type: 'changed' }));
979
+ manager.on('templateApplied', () => states.push({ type: 'applied' }));
980
+ manager.on('templateError', ({ error }) => states.push({ type: 'error', error: String(error) }));
981
+ // First apply should succeed
982
+ await manager.processTemplates({ apply: true });
983
+ // Modify template to be invalid
984
+ await fs.writeFile(templatePath, 'INVALID SQL;');
985
+ await manager.processTemplates({ apply: true });
986
+ // Fix template with valid SQL
987
+ await fs.writeFile(templatePath, `CREATE OR REPLACE FUNCTION ${testContext.testFunctionName}() RETURNS void AS $$ BEGIN NULL; END; $$ LANGUAGE plpgsql;`);
988
+ await manager.processTemplates({ apply: true });
989
+ expect(states).toEqual([
990
+ { type: 'changed' },
991
+ { type: 'applied' },
992
+ { type: 'changed' },
993
+ { type: 'error', error: expect.stringMatching(/syntax error/) },
994
+ { type: 'changed' },
995
+ { type: 'applied' },
996
+ ]);
997
+ }
998
+ catch (e_28) {
999
+ env_28.error = e_28;
1000
+ env_28.hasError = true;
1001
+ }
1002
+ finally {
1003
+ __disposeResources(env_28);
1004
+ }
709
1005
  });
710
1006
  it('should maintain correct state through manager restarts', async () => {
711
- const templatePath = await createTemplateWithFunc(`restart-test-${testContext.timestamp}.sql`, 'restart_test');
712
- // First manager instance
713
- const manager1 = await TemplateManager.create(testContext.testDir);
714
- await manager1.processTemplates({ apply: true });
715
- // Get initial state
716
- const status1 = await manager1.getTemplateStatus(templatePath);
717
- const initialHash = status1.buildState.lastAppliedHash;
718
- // Modify template
719
- await fs.writeFile(templatePath, `${await fs.readFile(templatePath, 'utf-8')}\n-- Modified`);
720
- // Create new manager instance
721
- const manager2 = await TemplateManager.create(testContext.testDir);
722
- const changes = [];
723
- const applied = [];
724
- manager2.on('templateChanged', t => changes.push(t.name));
725
- manager2.on('templateApplied', t => applied.push(t.name));
726
- await manager2.watch();
727
- await new Promise(resolve => setTimeout(resolve, 100));
728
- // Verify state was maintained and change was detected
729
- const status2 = await manager2.getTemplateStatus(templatePath);
730
- expect(status2.buildState.lastAppliedHash).not.toBe(initialHash);
731
- expect(changes).toContain(`restart-test-${testContext.timestamp}`);
732
- expect(applied).toContain(`restart-test-${testContext.timestamp}`);
1007
+ const env_29 = { stack: [], error: void 0, hasError: false };
1008
+ try {
1009
+ const templatePath = await createTemplateWithFunc(`restart-test`, 'restart_test');
1010
+ // First manager instance
1011
+ const manager1 = __addDisposableResource(env_29, await TemplateManager.create(testContext.testDir), false);
1012
+ await manager1.processTemplates({ apply: true });
1013
+ // Get initial state
1014
+ const status1 = await manager1.getTemplateStatus(templatePath);
1015
+ const initialHash = status1.buildState.lastAppliedHash;
1016
+ // Modify template
1017
+ await fs.writeFile(templatePath, `${await fs.readFile(templatePath, 'utf-8')}\n-- Modified`);
1018
+ // Create new manager instance
1019
+ const manager2 = __addDisposableResource(env_29, await TemplateManager.create(testContext.testDir), false);
1020
+ const changes = [];
1021
+ const applied = [];
1022
+ manager2.on('templateChanged', t => changes.push(t.name));
1023
+ manager2.on('templateApplied', t => applied.push(t.name));
1024
+ await manager2.watch();
1025
+ await new Promise(resolve => setTimeout(resolve, 100));
1026
+ // Verify state was maintained and change was detected
1027
+ const status2 = await manager2.getTemplateStatus(templatePath);
1028
+ expect(status2.buildState.lastAppliedHash).not.toBe(initialHash);
1029
+ expect(changes).toContain(`restart-test_${testContext.testId}_1`);
1030
+ expect(applied).toContain(`restart-test_${testContext.testId}_1`);
1031
+ }
1032
+ catch (e_29) {
1033
+ env_29.error = e_29;
1034
+ env_29.hasError = true;
1035
+ }
1036
+ finally {
1037
+ __disposeResources(env_29);
1038
+ }
733
1039
  });
734
1040
  it('should properly format and propagate error messages', async () => {
735
- const templatePath = await createTemplateWithFunc(`error-format-${testContext.timestamp}.sql`, 'error_format');
736
- const manager = await TemplateManager.create(testContext.testDir);
737
- const errors = [];
738
- manager.on('templateError', err => errors.push(err));
739
- // Create invalid SQL
740
- await fs.writeFile(templatePath, 'SELECT * FROM nonexistent_table;');
741
- await manager.processTemplates({ apply: true });
742
- expect(errors).toHaveLength(1);
743
- const error = errors[0]?.error;
744
- expect(typeof error).toBe('string');
745
- expect(error).not.toMatch(/\[object Object\]/);
746
- expect(error).toMatch(/relation.*does not exist/i);
1041
+ const env_30 = { stack: [], error: void 0, hasError: false };
1042
+ try {
1043
+ const templatePath = await createTemplateWithFunc(`error-format`, 'error_format');
1044
+ const manager = __addDisposableResource(env_30, await TemplateManager.create(testContext.testDir), false);
1045
+ const errors = [];
1046
+ manager.on('templateError', err => errors.push(err));
1047
+ // Create invalid SQL
1048
+ await fs.writeFile(templatePath, 'SELECT * FROM nonexistent_table;');
1049
+ await manager.processTemplates({ apply: true });
1050
+ expect(errors).toHaveLength(1);
1051
+ const error = errors[0]?.error;
1052
+ expect(typeof error).toBe('string');
1053
+ expect(error).not.toMatch(/\[object Object\]/);
1054
+ expect(error).toMatch(/relation.*does not exist/i);
1055
+ }
1056
+ catch (e_30) {
1057
+ env_30.error = e_30;
1058
+ env_30.hasError = true;
1059
+ }
1060
+ finally {
1061
+ __disposeResources(env_30);
1062
+ }
747
1063
  });
748
1064
  });
749
1065
  //# sourceMappingURL=templateManager.test.js.map