@currentjs/gen 0.1.1

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 (55) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +56 -0
  3. package/README.md +686 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.js +143 -0
  6. package/dist/commands/commit.d.ts +1 -0
  7. package/dist/commands/commit.js +153 -0
  8. package/dist/commands/createApp.d.ts +1 -0
  9. package/dist/commands/createApp.js +64 -0
  10. package/dist/commands/createModule.d.ts +1 -0
  11. package/dist/commands/createModule.js +121 -0
  12. package/dist/commands/diff.d.ts +1 -0
  13. package/dist/commands/diff.js +164 -0
  14. package/dist/commands/generateAll.d.ts +4 -0
  15. package/dist/commands/generateAll.js +305 -0
  16. package/dist/commands/infer.d.ts +1 -0
  17. package/dist/commands/infer.js +179 -0
  18. package/dist/generators/controllerGenerator.d.ts +20 -0
  19. package/dist/generators/controllerGenerator.js +280 -0
  20. package/dist/generators/domainModelGenerator.d.ts +33 -0
  21. package/dist/generators/domainModelGenerator.js +175 -0
  22. package/dist/generators/serviceGenerator.d.ts +39 -0
  23. package/dist/generators/serviceGenerator.js +379 -0
  24. package/dist/generators/storeGenerator.d.ts +31 -0
  25. package/dist/generators/storeGenerator.js +191 -0
  26. package/dist/generators/templateGenerator.d.ts +11 -0
  27. package/dist/generators/templateGenerator.js +143 -0
  28. package/dist/generators/templates/appTemplates.d.ts +27 -0
  29. package/dist/generators/templates/appTemplates.js +1621 -0
  30. package/dist/generators/templates/controllerTemplates.d.ts +43 -0
  31. package/dist/generators/templates/controllerTemplates.js +82 -0
  32. package/dist/generators/templates/index.d.ts +5 -0
  33. package/dist/generators/templates/index.js +21 -0
  34. package/dist/generators/templates/serviceTemplates.d.ts +15 -0
  35. package/dist/generators/templates/serviceTemplates.js +54 -0
  36. package/dist/generators/templates/storeTemplates.d.ts +9 -0
  37. package/dist/generators/templates/storeTemplates.js +260 -0
  38. package/dist/generators/templates/validationTemplates.d.ts +25 -0
  39. package/dist/generators/templates/validationTemplates.js +66 -0
  40. package/dist/generators/templates/viewTemplates.d.ts +16 -0
  41. package/dist/generators/templates/viewTemplates.js +359 -0
  42. package/dist/generators/validationGenerator.d.ts +24 -0
  43. package/dist/generators/validationGenerator.js +199 -0
  44. package/dist/utils/cliUtils.d.ts +6 -0
  45. package/dist/utils/cliUtils.js +71 -0
  46. package/dist/utils/colors.d.ts +26 -0
  47. package/dist/utils/colors.js +80 -0
  48. package/dist/utils/commitUtils.d.ts +46 -0
  49. package/dist/utils/commitUtils.js +377 -0
  50. package/dist/utils/constants.d.ts +52 -0
  51. package/dist/utils/constants.js +64 -0
  52. package/dist/utils/generationRegistry.d.ts +25 -0
  53. package/dist/utils/generationRegistry.js +192 -0
  54. package/howto.md +556 -0
  55. package/package.json +44 -0
@@ -0,0 +1,26 @@
1
+ export type ColorizeFn = (text: string | number) => string;
2
+ export declare const colors: {
3
+ enabled: boolean;
4
+ dim: ColorizeFn;
5
+ bold: ColorizeFn;
6
+ italic: ColorizeFn;
7
+ underline: ColorizeFn;
8
+ inverse: ColorizeFn;
9
+ black: ColorizeFn;
10
+ red: ColorizeFn;
11
+ green: ColorizeFn;
12
+ yellow: ColorizeFn;
13
+ blue: ColorizeFn;
14
+ magenta: ColorizeFn;
15
+ cyan: ColorizeFn;
16
+ white: ColorizeFn;
17
+ gray: ColorizeFn;
18
+ brightRed: ColorizeFn;
19
+ brightGreen: ColorizeFn;
20
+ brightYellow: ColorizeFn;
21
+ brightBlue: ColorizeFn;
22
+ brightMagenta: ColorizeFn;
23
+ brightCyan: ColorizeFn;
24
+ brightWhite: ColorizeFn;
25
+ };
26
+ export declare function stripAnsi(input: string): string;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /* Simple ANSI color utilities with TTY/NO_COLOR/FOREG_COLOR detection */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.colors = void 0;
5
+ exports.stripAnsi = stripAnsi;
6
+ function isColorSupported() {
7
+ const force = process.env.FORCE_COLOR;
8
+ if (force && force !== '0')
9
+ return true;
10
+ if (force === '0')
11
+ return false;
12
+ if (process.env.NO_COLOR)
13
+ return false;
14
+ // Prefer stdout TTY; fall back to true in CI with FORCE_COLOR
15
+ return !!process.stdout && !!process.stdout.isTTY;
16
+ }
17
+ const enabled = isColorSupported();
18
+ function createStyle(openCode, closeCode) {
19
+ const open = `\u001b[${openCode}m`;
20
+ const close = `\u001b[${closeCode}m`;
21
+ return (text) => {
22
+ const value = String(text);
23
+ if (!enabled)
24
+ return value;
25
+ return open + value + close;
26
+ };
27
+ }
28
+ const dim = createStyle(2, 22);
29
+ const bold = createStyle(1, 22);
30
+ const italic = createStyle(3, 23);
31
+ const underline = createStyle(4, 24);
32
+ const inverse = createStyle(7, 27);
33
+ const black = createStyle(30, 39);
34
+ const red = createStyle(31, 39);
35
+ const green = createStyle(32, 39);
36
+ const yellow = createStyle(33, 39);
37
+ const blue = createStyle(34, 39);
38
+ const magenta = createStyle(35, 39);
39
+ const cyan = createStyle(36, 39);
40
+ const white = createStyle(37, 39);
41
+ const gray = createStyle(90, 39);
42
+ const brightRed = createStyle(91, 39);
43
+ const brightGreen = createStyle(92, 39);
44
+ const brightYellow = createStyle(93, 39);
45
+ const brightBlue = createStyle(94, 39);
46
+ const brightMagenta = createStyle(95, 39);
47
+ const brightCyan = createStyle(96, 39);
48
+ const brightWhite = createStyle(97, 39);
49
+ exports.colors = {
50
+ enabled,
51
+ // modifiers
52
+ dim,
53
+ bold,
54
+ italic,
55
+ underline,
56
+ inverse,
57
+ // base colors
58
+ black,
59
+ red,
60
+ green,
61
+ yellow,
62
+ blue,
63
+ magenta,
64
+ cyan,
65
+ white,
66
+ gray,
67
+ // bright variants
68
+ brightRed,
69
+ brightGreen,
70
+ brightYellow,
71
+ brightBlue,
72
+ brightMagenta,
73
+ brightCyan,
74
+ brightWhite
75
+ };
76
+ function stripAnsi(input) {
77
+ // eslint-disable-next-line no-control-regex
78
+ const ansiRegex = /[\u001b\u009b][[\]()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
79
+ return input.replace(ansiRegex, '');
80
+ }
@@ -0,0 +1,46 @@
1
+ export type DiffHunk = {
2
+ oldStart: number;
3
+ oldLines: number;
4
+ newStart: number;
5
+ newLines: number;
6
+ oldContent: string[];
7
+ newContent: string[];
8
+ ctxBeforeOld?: string[];
9
+ ctxAfterOld?: string[];
10
+ };
11
+ type StoredCommit = {
12
+ createdAt?: string;
13
+ files: Array<{
14
+ file: string;
15
+ status: 'modified';
16
+ oldHash?: string;
17
+ newHash?: string;
18
+ diff?: string;
19
+ format?: 'hunks-v1';
20
+ baseHash?: string;
21
+ resultHash?: string;
22
+ hunks?: DiffHunk[];
23
+ meta?: Record<string, any>;
24
+ }>;
25
+ };
26
+ export declare function loadAllCommitRecords(rootDir: string): Array<{
27
+ createdAt: number;
28
+ file: string;
29
+ record: StoredCommit['files'][number];
30
+ }>;
31
+ export declare function computeLineDiff(oldStr: string, newStr: string): string;
32
+ export declare function applyDiffToBase(base: string, diff: string): string | null;
33
+ export declare function computeHunks(oldStr: string, newStr: string): DiffHunk[];
34
+ export declare function applyHunksToBase(base: string, hunks: DiffHunk[]): string | null;
35
+ /**
36
+ * Try to apply hunks to an arbitrary base using contextual search.
37
+ * - If oldContent exists, locate it and replace by newContent.
38
+ * - If oldLines === 0 (pure insertion), use ctxBeforeOld/ctxAfterOld anchors to place newContent.
39
+ * Returns null if cannot apply cleanly.
40
+ */
41
+ export declare function applyHunksToAnyBase(base: string, hunks: DiffHunk[]): string | null;
42
+ export declare function tryApplyCommitsToGenerated(fileAbsPath: string, generatedContent: string): {
43
+ applied: boolean;
44
+ content: string;
45
+ };
46
+ export {};
@@ -0,0 +1,377 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.loadAllCommitRecords = loadAllCommitRecords;
37
+ exports.computeLineDiff = computeLineDiff;
38
+ exports.applyDiffToBase = applyDiffToBase;
39
+ exports.computeHunks = computeHunks;
40
+ exports.applyHunksToBase = applyHunksToBase;
41
+ exports.applyHunksToAnyBase = applyHunksToAnyBase;
42
+ exports.tryApplyCommitsToGenerated = tryApplyCommitsToGenerated;
43
+ const fs = __importStar(require("fs"));
44
+ const path = __importStar(require("path"));
45
+ const generationRegistry_1 = require("./generationRegistry");
46
+ function parseCommitTimestamp(name) {
47
+ // commit-YYYY-MM-DDTHH-MM-SS-sssZ.json
48
+ const match = name.match(/commit-(.*)\.json$/);
49
+ if (!match)
50
+ return 0;
51
+ const iso = match[1].replace(/-/g, ':');
52
+ // restore last hyphens: not exact; fallback to Date.parse of createdAt inside file
53
+ return 0;
54
+ }
55
+ function loadAllCommitRecords(rootDir) {
56
+ const commitsDir = path.join(rootDir, 'commits');
57
+ if (!fs.existsSync(commitsDir))
58
+ return [];
59
+ const files = fs.readdirSync(commitsDir).filter(f => f.endsWith('.json'));
60
+ const results = [];
61
+ files.forEach(f => {
62
+ const abs = path.join(commitsDir, f);
63
+ try {
64
+ const data = JSON.parse(fs.readFileSync(abs, 'utf8'));
65
+ const ts = data.createdAt ? Date.parse(data.createdAt) : parseCommitTimestamp(f);
66
+ data.files.forEach(rec => {
67
+ results.push({ createdAt: ts || 0, file: rec.file, record: rec });
68
+ });
69
+ }
70
+ catch {
71
+ // ignore broken commit files
72
+ }
73
+ });
74
+ // sort by createdAt ascending
75
+ results.sort((a, b) => a.createdAt - b.createdAt);
76
+ return results;
77
+ }
78
+ function parseDiff(diff) {
79
+ return diff.split(/\r?\n/).map(line => {
80
+ const type = line[0];
81
+ const content = line.length > 1 && line[1] === ' ' ? line.slice(2) : line.slice(1);
82
+ return { type: type === ' ' || type === '+' || type === '-' ? type : ' ', line: content };
83
+ });
84
+ }
85
+ function computeLineDiff(oldStr, newStr) {
86
+ const oldLines = oldStr.split(/\r?\n/);
87
+ const newLines = newStr.split(/\r?\n/);
88
+ const n = oldLines.length;
89
+ const m = newLines.length;
90
+ const dp = Array.from({ length: n + 1 }, () => Array(m + 1).fill(0));
91
+ for (let i = n - 1; i >= 0; i -= 1) {
92
+ for (let j = m - 1; j >= 0; j -= 1) {
93
+ if (oldLines[i] === newLines[j])
94
+ dp[i][j] = dp[i + 1][j + 1] + 1;
95
+ else
96
+ dp[i][j] = Math.max(dp[i + 1][j], dp[i][j + 1]);
97
+ }
98
+ }
99
+ const result = [];
100
+ let i = 0;
101
+ let j = 0;
102
+ while (i < n && j < m) {
103
+ if (oldLines[i] === newLines[j]) {
104
+ result.push({ type: ' ', line: oldLines[i] });
105
+ i += 1;
106
+ j += 1;
107
+ }
108
+ else if (dp[i + 1][j] >= dp[i][j + 1]) {
109
+ result.push({ type: '-', line: oldLines[i] });
110
+ i += 1;
111
+ }
112
+ else {
113
+ result.push({ type: '+', line: newLines[j] });
114
+ j += 1;
115
+ }
116
+ }
117
+ while (i < n) {
118
+ result.push({ type: '-', line: oldLines[i] });
119
+ i += 1;
120
+ }
121
+ while (j < m) {
122
+ result.push({ type: '+', line: newLines[j] });
123
+ j += 1;
124
+ }
125
+ const lines = result.map(op => `${op.type} ${op.line}`);
126
+ return lines.join('\n');
127
+ }
128
+ function applyDiffToBase(base, diff) {
129
+ const baseLines = base.split(/\r?\n/);
130
+ const ops = parseDiff(diff);
131
+ const result = [];
132
+ let i = 0;
133
+ for (const op of ops) {
134
+ if (op.type === ' ') {
135
+ if (baseLines[i] !== op.line) {
136
+ return null; // context mismatch
137
+ }
138
+ result.push(op.line);
139
+ i += 1;
140
+ }
141
+ else if (op.type === '+') {
142
+ if (baseLines[i] !== op.line) {
143
+ return null; // base content deviates
144
+ }
145
+ // skip this line in result (removed compared to base)
146
+ i += 1;
147
+ }
148
+ else if (op.type === '-') {
149
+ // insert user-only line
150
+ result.push(op.line);
151
+ }
152
+ }
153
+ // any remaining base lines are unexpected; consider they should have been represented
154
+ if (i < baseLines.length) {
155
+ // append remaining lines only if ops end with matching context; otherwise fail
156
+ result.push(...baseLines.slice(i));
157
+ }
158
+ return result.join('\n');
159
+ }
160
+ function lcsMatrix(a, b) {
161
+ const n = a.length;
162
+ const m = b.length;
163
+ const dp = Array.from({ length: n + 1 }, () => Array(m + 1).fill(0));
164
+ for (let i = n - 1; i >= 0; i -= 1) {
165
+ for (let j = m - 1; j >= 0; j -= 1) {
166
+ if (a[i] === b[j])
167
+ dp[i][j] = dp[i + 1][j + 1] + 1;
168
+ else
169
+ dp[i][j] = Math.max(dp[i + 1][j], dp[i][j + 1]);
170
+ }
171
+ }
172
+ return dp;
173
+ }
174
+ function computeHunks(oldStr, newStr) {
175
+ var _a, _b;
176
+ const a = oldStr.split(/\r?\n/);
177
+ const b = newStr.split(/\r?\n/);
178
+ const dp = lcsMatrix(a, b);
179
+ const hunks = [];
180
+ let i = 0;
181
+ let j = 0;
182
+ let pending = null;
183
+ while (i < a.length && j < b.length) {
184
+ if (a[i] === b[j]) {
185
+ if (pending) {
186
+ hunks.push(pending);
187
+ pending = null;
188
+ }
189
+ i += 1;
190
+ j += 1;
191
+ }
192
+ else if (((_a = dp[i + 1]) === null || _a === void 0 ? void 0 : _a[j]) >= ((_b = dp[i]) === null || _b === void 0 ? void 0 : _b[j + 1])) {
193
+ // deletion from old (i advanced)
194
+ if (!pending) {
195
+ pending = { oldStart: i, oldLines: 0, newStart: j, newLines: 0, oldContent: [], newContent: [] };
196
+ }
197
+ pending.oldLines += 1;
198
+ pending.oldContent.push(a[i]);
199
+ i += 1;
200
+ }
201
+ else {
202
+ // insertion to new (j advanced)
203
+ if (!pending) {
204
+ pending = { oldStart: i, oldLines: 0, newStart: j, newLines: 0, oldContent: [], newContent: [] };
205
+ }
206
+ pending.newLines += 1;
207
+ pending.newContent.push(b[j]);
208
+ j += 1;
209
+ }
210
+ }
211
+ // tail remainders
212
+ if (i < a.length || j < b.length) {
213
+ const tail = {
214
+ oldStart: i,
215
+ oldLines: a.length - i,
216
+ newStart: j,
217
+ newLines: b.length - j,
218
+ oldContent: a.slice(i),
219
+ newContent: b.slice(j)
220
+ };
221
+ if (tail.oldLines > 0 || tail.newLines > 0) {
222
+ if (pending) {
223
+ // merge if adjacent
224
+ if (pending.oldStart + pending.oldLines === tail.oldStart && pending.newStart + pending.newLines === tail.newStart) {
225
+ pending.oldLines += tail.oldLines;
226
+ pending.newLines += tail.newLines;
227
+ pending.oldContent.push(...tail.oldContent);
228
+ pending.newContent.push(...tail.newContent);
229
+ }
230
+ else {
231
+ hunks.push(pending);
232
+ hunks.push(tail);
233
+ pending = null;
234
+ }
235
+ }
236
+ else {
237
+ pending = tail;
238
+ }
239
+ }
240
+ }
241
+ if (pending)
242
+ hunks.push(pending);
243
+ // Attach lightweight context (up to 3 lines) around old segments to help rebase
244
+ const CONTEXT = 3;
245
+ return hunks.map(h => {
246
+ const beforeStart = Math.max(0, h.oldStart - CONTEXT);
247
+ const before = a.slice(beforeStart, h.oldStart);
248
+ const afterEnd = h.oldStart + h.oldLines + CONTEXT;
249
+ const after = a.slice(h.oldStart + h.oldLines, Math.min(a.length, afterEnd));
250
+ return { ...h, ctxBeforeOld: before, ctxAfterOld: after };
251
+ });
252
+ }
253
+ function applyHunksToBase(base, hunks) {
254
+ const baseLines = base.split(/\r?\n/);
255
+ let offset = 0;
256
+ for (const h of hunks) {
257
+ const start = h.oldStart + offset;
258
+ const end = start + h.oldLines;
259
+ if (start < 0 || start > baseLines.length || end < 0 || end > baseLines.length) {
260
+ return null;
261
+ }
262
+ baseLines.splice(start, h.oldLines, ...h.newContent);
263
+ offset += h.newContent.length - h.oldLines;
264
+ }
265
+ return baseLines.join('\n');
266
+ }
267
+ function findSubsequence(haystack, needle, fromIndex = 0) {
268
+ if (needle.length === 0)
269
+ return fromIndex;
270
+ for (let i = fromIndex; i <= haystack.length - needle.length; i += 1) {
271
+ let ok = true;
272
+ for (let j = 0; j < needle.length; j += 1) {
273
+ if (haystack[i + j] !== needle[j]) {
274
+ ok = false;
275
+ break;
276
+ }
277
+ }
278
+ if (ok)
279
+ return i;
280
+ }
281
+ return -1;
282
+ }
283
+ /**
284
+ * Try to apply hunks to an arbitrary base using contextual search.
285
+ * - If oldContent exists, locate it and replace by newContent.
286
+ * - If oldLines === 0 (pure insertion), use ctxBeforeOld/ctxAfterOld anchors to place newContent.
287
+ * Returns null if cannot apply cleanly.
288
+ */
289
+ function applyHunksToAnyBase(base, hunks) {
290
+ let baseLines = base.split(/\r?\n/);
291
+ let searchFrom = 0;
292
+ for (const h of hunks) {
293
+ if (h.oldLines > 0 && h.oldContent.length > 0) {
294
+ // Try to find exact oldContent sequence
295
+ let idx = findSubsequence(baseLines, h.oldContent, searchFrom);
296
+ if (idx === -1 && h.ctxBeforeOld && h.ctxBeforeOld.length > 0) {
297
+ // Try to locate by ctxBefore then expect oldContent after
298
+ const beforeIdx = findSubsequence(baseLines, h.ctxBeforeOld, Math.max(0, searchFrom - h.ctxBeforeOld.length));
299
+ if (beforeIdx !== -1) {
300
+ idx = findSubsequence(baseLines, h.oldContent, beforeIdx + h.ctxBeforeOld.length);
301
+ }
302
+ }
303
+ if (idx === -1 && h.ctxAfterOld && h.ctxAfterOld.length > 0) {
304
+ // Try to locate by ctxAfter before it
305
+ const afterIdx = findSubsequence(baseLines, h.ctxAfterOld, searchFrom);
306
+ if (afterIdx !== -1) {
307
+ // Scan backwards window before afterIdx
308
+ const windowStart = Math.max(0, afterIdx - h.oldLines - h.ctxBeforeOld.length);
309
+ idx = findSubsequence(baseLines.slice(windowStart, afterIdx), h.oldContent);
310
+ if (idx !== -1)
311
+ idx += windowStart;
312
+ }
313
+ }
314
+ if (idx === -1)
315
+ return null;
316
+ baseLines.splice(idx, h.oldLines, ...h.newContent);
317
+ searchFrom = idx + h.newContent.length;
318
+ }
319
+ else {
320
+ // Insertion-only hunk: place using context anchors
321
+ let insertAt = h.newStart; // fallback
322
+ if (h.ctxBeforeOld && h.ctxBeforeOld.length > 0) {
323
+ const beforeIdx = findSubsequence(baseLines, h.ctxBeforeOld, Math.max(0, searchFrom - h.ctxBeforeOld.length));
324
+ if (beforeIdx !== -1)
325
+ insertAt = beforeIdx + h.ctxBeforeOld.length;
326
+ }
327
+ else if (h.ctxAfterOld && h.ctxAfterOld.length > 0) {
328
+ const afterIdx = findSubsequence(baseLines, h.ctxAfterOld, searchFrom);
329
+ if (afterIdx !== -1)
330
+ insertAt = afterIdx;
331
+ }
332
+ if (insertAt < 0 || insertAt > baseLines.length)
333
+ insertAt = baseLines.length;
334
+ baseLines.splice(insertAt, 0, ...h.newContent);
335
+ searchFrom = insertAt + h.newContent.length;
336
+ }
337
+ }
338
+ return baseLines.join('\n');
339
+ }
340
+ function tryApplyCommitsToGenerated(fileAbsPath, generatedContent) {
341
+ const root = process.cwd();
342
+ const rel = path.relative(root, path.resolve(fileAbsPath));
343
+ const baseHash = (0, generationRegistry_1.computeContentHash)(generatedContent);
344
+ // Prefer registry snapshot if present and compatible
345
+ const registry = (0, generationRegistry_1.loadRegistry)();
346
+ const regEntry = registry[rel];
347
+ if (regEntry && regEntry.diffFormat === 'hunks-v1' && regEntry.diffHunks) {
348
+ // If baseHash matches, use fast exact apply; else attempt contextual apply
349
+ const appliedViaRegistry = regEntry.diffBaseHash === baseHash
350
+ ? applyHunksToBase(generatedContent, regEntry.diffHunks)
351
+ : applyHunksToAnyBase(generatedContent, regEntry.diffHunks);
352
+ if (appliedViaRegistry != null) {
353
+ return { applied: true, content: appliedViaRegistry };
354
+ }
355
+ }
356
+ // Fallback to commit files if registry snapshot not usable
357
+ const all = loadAllCommitRecords(root).filter(r => r.file === rel && r.record.status === 'modified');
358
+ if (all.length === 0)
359
+ return { applied: false, content: generatedContent };
360
+ // Prefer hunks format
361
+ const hunksCandidates = all.filter(r => r.record.format === 'hunks-v1' && r.record.baseHash === baseHash && r.record.hunks);
362
+ if (hunksCandidates.length > 0) {
363
+ const latest = hunksCandidates[hunksCandidates.length - 1].record;
364
+ const applied = applyHunksToBase(generatedContent, latest.hunks);
365
+ if (applied != null)
366
+ return { applied: true, content: applied };
367
+ }
368
+ // Fallback to legacy line diff
369
+ const legacyCandidates = all.filter(r => r.record.newHash === baseHash && r.record.diff);
370
+ if (legacyCandidates.length > 0) {
371
+ const latest = legacyCandidates[legacyCandidates.length - 1].record;
372
+ const applied = applyDiffToBase(generatedContent, latest.diff);
373
+ if (applied != null)
374
+ return { applied: true, content: applied };
375
+ }
376
+ return { applied: false, content: generatedContent };
377
+ }
@@ -0,0 +1,52 @@
1
+ export declare const FILE_EXTENSIONS: {
2
+ readonly YAML: ".yaml";
3
+ readonly TYPESCRIPT: ".ts";
4
+ readonly JAVASCRIPT: ".js";
5
+ readonly JSON: ".json";
6
+ };
7
+ export declare const COMMON_FILES: {
8
+ readonly APP_YAML: "app.yaml";
9
+ readonly APP_TS: "app.ts";
10
+ readonly REGISTRY_JSON: "registry.json";
11
+ readonly STORE_INTERFACE: "StoreInterface.ts";
12
+ };
13
+ export declare const GENERATOR_MARKERS: {
14
+ readonly CONTROLLERS_START: "// currentjs:controllers:start";
15
+ readonly CONTROLLERS_END: "// currentjs:controllers:end";
16
+ };
17
+ export declare const PATH_PATTERNS: {
18
+ readonly MODULES_PREFIX: "modules/";
19
+ readonly MODULES_RELATIVE: "./modules/";
20
+ readonly MODULES_DIRECTIVE: "@modules/";
21
+ readonly SRC_MODULES: "src/modules/";
22
+ readonly INFRASTRUCTURE: "infrastructure";
23
+ readonly APPLICATION: "application";
24
+ readonly DOMAIN: "domain";
25
+ readonly ENTITIES: "entities";
26
+ readonly STORES: "stores";
27
+ readonly SERVICES: "services";
28
+ readonly CONTROLLERS: "controllers";
29
+ };
30
+ export declare const DEFAULTS: {
31
+ readonly SERVER_PORT: 3000;
32
+ readonly SERVER_HOST: "localhost";
33
+ readonly PAGINATION_LIMIT: 10;
34
+ readonly PAGINATION_PAGE: 1;
35
+ };
36
+ export declare const MODULE_STRUCTURE: {
37
+ readonly DOMAIN_ENTITIES: "domain/entities";
38
+ readonly APPLICATION_SERVICES: "application/services";
39
+ readonly INFRASTRUCTURE_STORES: "infrastructure/stores";
40
+ readonly INFRASTRUCTURE_CONTROLLERS: "infrastructure/controllers";
41
+ };
42
+ export declare const SERVER: {
43
+ readonly BASE_URL: "http://localhost:3000";
44
+ readonly START_MESSAGE: "Server started on http://localhost:3000";
45
+ };
46
+ export declare const GENERATOR_SUFFIXES: {
47
+ readonly STORE: "Store";
48
+ readonly SERVICE: "Service";
49
+ readonly CONTROLLER: "Controller";
50
+ readonly API_CONTROLLER: "ApiController";
51
+ readonly WEB_CONTROLLER: "WebController";
52
+ };
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ // Common constants used across the generator
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.GENERATOR_SUFFIXES = exports.SERVER = exports.MODULE_STRUCTURE = exports.DEFAULTS = exports.PATH_PATTERNS = exports.GENERATOR_MARKERS = exports.COMMON_FILES = exports.FILE_EXTENSIONS = void 0;
5
+ // File extensions
6
+ exports.FILE_EXTENSIONS = {
7
+ YAML: '.yaml',
8
+ TYPESCRIPT: '.ts',
9
+ JAVASCRIPT: '.js',
10
+ JSON: '.json'
11
+ };
12
+ // Common file names
13
+ exports.COMMON_FILES = {
14
+ APP_YAML: 'app.yaml',
15
+ APP_TS: 'app.ts',
16
+ REGISTRY_JSON: 'registry.json',
17
+ STORE_INTERFACE: 'StoreInterface.ts'
18
+ };
19
+ // Generator markers
20
+ exports.GENERATOR_MARKERS = {
21
+ CONTROLLERS_START: '// currentjs:controllers:start',
22
+ CONTROLLERS_END: '// currentjs:controllers:end'
23
+ };
24
+ // Path patterns
25
+ exports.PATH_PATTERNS = {
26
+ MODULES_PREFIX: 'modules/',
27
+ MODULES_RELATIVE: './modules/',
28
+ MODULES_DIRECTIVE: '@modules/',
29
+ SRC_MODULES: 'src/modules/',
30
+ INFRASTRUCTURE: 'infrastructure',
31
+ APPLICATION: 'application',
32
+ DOMAIN: 'domain',
33
+ ENTITIES: 'entities',
34
+ STORES: 'stores',
35
+ SERVICES: 'services',
36
+ CONTROLLERS: 'controllers'
37
+ };
38
+ // Default values
39
+ exports.DEFAULTS = {
40
+ SERVER_PORT: 3000,
41
+ SERVER_HOST: 'localhost',
42
+ PAGINATION_LIMIT: 10,
43
+ PAGINATION_PAGE: 1
44
+ };
45
+ // Module structure paths
46
+ exports.MODULE_STRUCTURE = {
47
+ DOMAIN_ENTITIES: 'domain/entities',
48
+ APPLICATION_SERVICES: 'application/services',
49
+ INFRASTRUCTURE_STORES: 'infrastructure/stores',
50
+ INFRASTRUCTURE_CONTROLLERS: 'infrastructure/controllers'
51
+ };
52
+ // Server URLs and messages
53
+ exports.SERVER = {
54
+ BASE_URL: `http://${exports.DEFAULTS.SERVER_HOST}:${exports.DEFAULTS.SERVER_PORT}`,
55
+ START_MESSAGE: `Server started on http://${exports.DEFAULTS.SERVER_HOST}:${exports.DEFAULTS.SERVER_PORT}`
56
+ };
57
+ // Generator suffixes
58
+ exports.GENERATOR_SUFFIXES = {
59
+ STORE: 'Store',
60
+ SERVICE: 'Service',
61
+ CONTROLLER: 'Controller',
62
+ API_CONTROLLER: 'ApiController',
63
+ WEB_CONTROLLER: 'WebController'
64
+ };
@@ -0,0 +1,25 @@
1
+ import { type DiffHunk } from './commitUtils';
2
+ type RegistryEntry = {
3
+ hash: string;
4
+ updatedAt: string;
5
+ diffFormat?: 'hunks-v1';
6
+ diffBaseHash?: string;
7
+ diffResultHash?: string;
8
+ diffHunks?: DiffHunk[];
9
+ diffUpdatedAt?: string;
10
+ };
11
+ type RegistryData = Record<string, RegistryEntry>;
12
+ export declare function initGenerationRegistry(rootDir: string): void;
13
+ export declare function computeContentHash(contents: string): string;
14
+ export declare function loadRegistry(): RegistryData;
15
+ export declare function saveRegistry(data: RegistryData): void;
16
+ export declare function getStoredHash(filePath: string): string | undefined;
17
+ export declare function updateStoredHash(filePath: string, hash: string): void;
18
+ export declare function updateStoredHunks(filePath: string, hunks: DiffHunk[], baseHash?: string, resultHash?: string): void;
19
+ export declare function writeGeneratedFile(filePath: string, contents: string, options?: {
20
+ force?: boolean;
21
+ silent?: boolean;
22
+ skipOnConflict?: boolean;
23
+ }): Promise<'written' | 'skipped' | 'unchanged'>;
24
+ export declare function ensureCommitsDir(): string;
25
+ export {};