@pattern-stack/codegen 0.17.2 → 0.18.0

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 (118) hide show
  1. package/README.md +106 -2
  2. package/dist/{chunk-65MO75WM.js → chunk-2VGVSL2D.js} +8 -8
  3. package/dist/{chunk-VNBC3VXM.js → chunk-3A34R6CI.js} +7 -7
  4. package/dist/{chunk-I6UXRJ3Q.js → chunk-43SBT72G.js} +4 -4
  5. package/dist/{chunk-7OVCARTQ.js → chunk-5RT7JGKT.js} +4 -4
  6. package/dist/{chunk-E6PLM6QG.js → chunk-7MMS36AN.js} +9 -9
  7. package/dist/{chunk-4MVGAMUA.js → chunk-BK5ICA2F.js} +4 -4
  8. package/dist/{chunk-VDL5CJ5C.js → chunk-C5E7H553.js} +7 -7
  9. package/dist/{chunk-IOQMMH6C.js → chunk-CFFTPWHM.js} +79 -4
  10. package/dist/chunk-CFFTPWHM.js.map +1 -0
  11. package/dist/{chunk-XKWOJZZ4.js → chunk-E45CSC33.js} +2 -2
  12. package/dist/{chunk-AZLUWG5S.js → chunk-EWYI5GGJ.js} +13 -13
  13. package/dist/{chunk-BHZP6LOV.js → chunk-IN3EWFB4.js} +4 -4
  14. package/dist/{chunk-CZQUOIDY.js → chunk-J7JMVS2B.js} +4 -4
  15. package/dist/{chunk-KSTZIULO.js → chunk-K2I6XIK5.js} +4 -4
  16. package/dist/{chunk-Z7PQCAVK.js → chunk-LQ6PYFU6.js} +4 -4
  17. package/dist/{chunk-T6SCOJF4.js → chunk-NXHL5YII.js} +4 -4
  18. package/dist/{chunk-ATVGYF3D.js → chunk-PKDS6QIJ.js} +7 -7
  19. package/dist/{chunk-OZEPJGMA.js → chunk-R4BPUUB5.js} +4 -4
  20. package/dist/{chunk-B34G6PHD.js → chunk-RKNW56RU.js} +8 -8
  21. package/dist/{chunk-R6F6KFIL.js → chunk-TBGTMALE.js} +4 -4
  22. package/dist/{chunk-GM3RMJIJ.js → chunk-VHAR2BGH.js} +4 -4
  23. package/dist/{chunk-CLWBNXKF.js → chunk-W2UIDI3R.js} +4 -4
  24. package/dist/{chunk-235ZMMJR.js → chunk-X6BP6LI5.js} +3 -3
  25. package/dist/{chunk-KZDHMZ45.js → chunk-YZLBU6O2.js} +10 -10
  26. package/dist/runtime/base-classes/index.js +24 -24
  27. package/dist/runtime/subsystems/analytics/analytics.module.js +2 -2
  28. package/dist/runtime/subsystems/analytics/index.js +4 -4
  29. package/dist/runtime/subsystems/auth/auth.module.js +2 -2
  30. package/dist/runtime/subsystems/auth/index.js +12 -12
  31. package/dist/runtime/subsystems/bridge/bridge-delivery-handler.js +2 -2
  32. package/dist/runtime/subsystems/bridge/bridge-delivery.drizzle-backend.js +3 -3
  33. package/dist/runtime/subsystems/bridge/bridge-outbox-drain-hook.js +6 -6
  34. package/dist/runtime/subsystems/bridge/bridge.module.js +17 -17
  35. package/dist/runtime/subsystems/bridge/event-flow.service.js +2 -2
  36. package/dist/runtime/subsystems/bridge/index.js +24 -24
  37. package/dist/runtime/subsystems/cache/cache.module.js +1 -1
  38. package/dist/runtime/subsystems/cache/index.js +3 -3
  39. package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js +3 -3
  40. package/dist/runtime/subsystems/events/event-bus.memory-backend.js +2 -2
  41. package/dist/runtime/subsystems/events/events.module.js +7 -7
  42. package/dist/runtime/subsystems/events/generated/bus.js +2 -2
  43. package/dist/runtime/subsystems/events/generated/index.js +2 -2
  44. package/dist/runtime/subsystems/events/index.js +10 -10
  45. package/dist/runtime/subsystems/index.js +90 -90
  46. package/dist/runtime/subsystems/integration/build-change-source.js +2 -2
  47. package/dist/runtime/subsystems/integration/index.js +36 -36
  48. package/dist/runtime/subsystems/integration/integration.module.js +4 -4
  49. package/dist/runtime/subsystems/jobs/index.js +29 -29
  50. package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.js +5 -5
  51. package/dist/runtime/subsystems/jobs/job-orchestrator.drizzle-backend.js +3 -3
  52. package/dist/runtime/subsystems/jobs/job-run-service.drizzle-backend.js +3 -3
  53. package/dist/runtime/subsystems/jobs/job-run-service.memory-backend.js +2 -2
  54. package/dist/runtime/subsystems/jobs/job-worker.js +3 -3
  55. package/dist/runtime/subsystems/jobs/job-worker.module.js +10 -10
  56. package/dist/runtime/subsystems/jobs/jobs-domain.module.js +8 -8
  57. package/dist/runtime/subsystems/observability/index.js +3 -3
  58. package/dist/runtime/subsystems/observability/observability.module.js +3 -3
  59. package/dist/runtime/subsystems/observability/observability.service.js +2 -2
  60. package/dist/runtime/subsystems/storage/index.js +4 -4
  61. package/dist/runtime/subsystems/storage/storage.module.js +2 -2
  62. package/dist/src/cli/index.js +1415 -252
  63. package/dist/src/cli/index.js.map +1 -1
  64. package/dist/src/index.d.ts +18 -0
  65. package/dist/src/index.js +12 -12
  66. package/package.json +1 -1
  67. package/src/config/locations.mjs +0 -6
  68. package/src/config/paths.mjs +0 -13
  69. package/templates/entity/new/prompt.js +12 -88
  70. package/dist/chunk-IOQMMH6C.js.map +0 -1
  71. package/templates/entity/new/frontend/_inject-entities-entry.ejs.t +0 -7
  72. package/templates/entity/new/frontend/_inject-entities-import.ejs.t +0 -7
  73. package/templates/entity/new/frontend/collections/_ensure-anchor-collections.ejs.t +0 -10
  74. package/templates/entity/new/frontend/collections/_inject-index.ejs.t +0 -9
  75. package/templates/entity/new/frontend/collections/_inject-schema-import.ejs.t +0 -9
  76. package/templates/entity/new/frontend/collections/collection.ejs.t +0 -86
  77. package/templates/entity/new/frontend/collections/collections-base.ejs.t +0 -35
  78. package/templates/entity/new/frontend/entity/collection.ejs.t +0 -173
  79. package/templates/entity/new/frontend/entity/combined.ejs.t +0 -505
  80. package/templates/entity/new/frontend/entity/fields.ejs.t +0 -105
  81. package/templates/entity/new/frontend/entity/hooks.ejs.t +0 -74
  82. package/templates/entity/new/frontend/entity/index.ejs.t +0 -22
  83. package/templates/entity/new/frontend/entity/mutation-hooks.ejs.t +0 -85
  84. package/templates/entity/new/frontend/entity/mutations.ejs.t +0 -39
  85. package/templates/entity/new/frontend/entity/types.ejs.t +0 -60
  86. package/templates/entity/new/frontend/generated/_inject-index-export.ejs.t +0 -7
  87. package/templates/entity/new/frontend/generated/_inject-index-import.ejs.t +0 -7
  88. package/templates/entity/new/frontend/generated/_inject-index-registry.ejs.t +0 -7
  89. package/templates/entity/new/frontend/store/_inject-collection-import.ejs.t +0 -9
  90. package/templates/entity/new/frontend/store/_inject-collections.ejs.t +0 -9
  91. package/templates/entity/new/frontend/store/_inject-entity.ejs.t +0 -9
  92. package/templates/entity/new/frontend/store/_inject-import.ejs.t +0 -9
  93. package/templates/entity/new/frontend/store/_inject-lookups.ejs.t +0 -9
  94. package/templates/entity/new/frontend/store/_inject-resolve.ejs.t +0 -10
  95. package/templates/entity/new/frontend/store/hooks.ejs.t +0 -73
  96. package/templates/entity/new/frontend/unified-entity.ejs.t +0 -29
  97. /package/dist/{chunk-65MO75WM.js.map → chunk-2VGVSL2D.js.map} +0 -0
  98. /package/dist/{chunk-VNBC3VXM.js.map → chunk-3A34R6CI.js.map} +0 -0
  99. /package/dist/{chunk-I6UXRJ3Q.js.map → chunk-43SBT72G.js.map} +0 -0
  100. /package/dist/{chunk-7OVCARTQ.js.map → chunk-5RT7JGKT.js.map} +0 -0
  101. /package/dist/{chunk-E6PLM6QG.js.map → chunk-7MMS36AN.js.map} +0 -0
  102. /package/dist/{chunk-4MVGAMUA.js.map → chunk-BK5ICA2F.js.map} +0 -0
  103. /package/dist/{chunk-VDL5CJ5C.js.map → chunk-C5E7H553.js.map} +0 -0
  104. /package/dist/{chunk-XKWOJZZ4.js.map → chunk-E45CSC33.js.map} +0 -0
  105. /package/dist/{chunk-AZLUWG5S.js.map → chunk-EWYI5GGJ.js.map} +0 -0
  106. /package/dist/{chunk-BHZP6LOV.js.map → chunk-IN3EWFB4.js.map} +0 -0
  107. /package/dist/{chunk-CZQUOIDY.js.map → chunk-J7JMVS2B.js.map} +0 -0
  108. /package/dist/{chunk-KSTZIULO.js.map → chunk-K2I6XIK5.js.map} +0 -0
  109. /package/dist/{chunk-Z7PQCAVK.js.map → chunk-LQ6PYFU6.js.map} +0 -0
  110. /package/dist/{chunk-T6SCOJF4.js.map → chunk-NXHL5YII.js.map} +0 -0
  111. /package/dist/{chunk-ATVGYF3D.js.map → chunk-PKDS6QIJ.js.map} +0 -0
  112. /package/dist/{chunk-OZEPJGMA.js.map → chunk-R4BPUUB5.js.map} +0 -0
  113. /package/dist/{chunk-B34G6PHD.js.map → chunk-RKNW56RU.js.map} +0 -0
  114. /package/dist/{chunk-R6F6KFIL.js.map → chunk-TBGTMALE.js.map} +0 -0
  115. /package/dist/{chunk-GM3RMJIJ.js.map → chunk-VHAR2BGH.js.map} +0 -0
  116. /package/dist/{chunk-CLWBNXKF.js.map → chunk-W2UIDI3R.js.map} +0 -0
  117. /package/dist/{chunk-235ZMMJR.js.map → chunk-X6BP6LI5.js.map} +0 -0
  118. /package/dist/{chunk-KZDHMZ45.js.map → chunk-YZLBU6O2.js.map} +0 -0
@@ -1,7 +0,0 @@
1
- ---
2
- inject: true
3
- to: "<%= frontendEnabled ? `${locations.frontendEntities.path}/index.ts` : '' %>"
4
- after: "// \\[CODEGEN:ENTITY_ENTRIES\\]"
5
- skip_if: "<%= plural %>,"
6
- ---
7
- <%= plural %>,
@@ -1,7 +0,0 @@
1
- ---
2
- inject: true
3
- to: "<%= frontendEnabled ? `${locations.frontendEntities.path}/index.ts` : '' %>"
4
- after: "// \\[CODEGEN:ENTITY_IMPORTS\\]"
5
- skip_if: "from './<%= name %>'"
6
- ---
7
- import { <%= plural %> } from './<%= name %>';
@@ -1,10 +0,0 @@
1
- ---
2
- to: "<%= frontendEnabled ? (generate.collections ? `${locations.frontendCollections.path}/collections.ts` : '') : '' %>"
3
- inject: true
4
- append: true
5
- skip_if: "// Codegen collections"
6
- ---
7
- <% if (generate.collections) { -%>
8
-
9
- // Codegen collections
10
- <% } -%>
@@ -1,9 +0,0 @@
1
- ---
2
- to: "<%= frontendEnabled ? (generate.collectionsIndex ? `${locations.frontendCollections.path}/index.ts` : '') : '' %>"
3
- inject: true
4
- after: "// Generated entity collections"
5
- skip_if: "from './collections'"
6
- ---
7
- <% if (generate.collectionsIndex) { -%>
8
- export * from './collections';
9
- <% } -%>
@@ -1,9 +0,0 @@
1
- ---
2
- to: "<%= frontendEnabled ? (generate.collections && !frontend.collections?.schemaPrefix ? `${locations.frontendCollections.path}/collections.ts` : '') : '' %>"
3
- inject: true
4
- after: "// Codegen schema imports"
5
- skip_if: <%= camelName %>Schema
6
- ---
7
- <% if (generate.collections && !frontend.collections?.schemaPrefix) { -%>
8
- <%= camelName %>Schema,
9
- <% } -%>
@@ -1,86 +0,0 @@
1
- ---
2
- to: "<%= frontendEnabled ? (generate.collections ? `${locations.frontendCollections.path}/collections.ts` : '') : '' %>"
3
- inject: true
4
- after: "// Codegen collections"
5
- skip_if: <%= camelName %>Collection
6
- ---
7
- <% if (generate.collections) { -%>
8
- <%
9
- // Determine the URL expression based on config
10
- const hasApiBaseUrl = !!frontend.sync.apiBaseUrlImport;
11
- // For the URL path, use API_BASE_URL if configured
12
- const shapeUrlExpr = hasApiBaseUrl
13
- ? '`${API_BASE_URL}/' + plural + '`'
14
- : '`' + frontend.sync.shapeUrl + '/' + plural + '`';
15
- // REST list endpoint for 'api' sync mode
16
- const apiUrlExpr = hasApiBaseUrl
17
- ? '`${API_BASE_URL}/' + plural + '`'
18
- : '`' + frontend.sync.apiUrl + '/' + plural + '`';
19
- const schemaPrefix = frontend.collections?.schemaPrefix ?? 'schema.';
20
- -%>
21
- <% if (frontend.sync.mode === 'api') { -%>
22
- export const <%= camelName %>Collection = createCollection(
23
- queryCollectionOptions({
24
- id: '<%= plural %>',
25
- queryKey: ['<%= plural %>'],
26
- queryClient,
27
- queryFn: async () => {
28
- const res = await fetch(<%- apiUrlExpr %><% if (frontend.auth.function) { %>, {
29
- headers: { Authorization: <%= frontend.auth.function %>() },
30
- }<% } %>);
31
- if (!res.ok) {
32
- throw new Error(`GET <%= plural %> → ${res.status} ${res.statusText}`);
33
- }
34
- return res.json();
35
- },
36
- getKey: (item) => item.id,
37
- schema: <%= schemaPrefix %><%= camelName %>Schema,
38
- }),
39
- );
40
- <% } else { -%>
41
- export const <%= camelName %>Collection = createCollection(
42
- electricCollectionOptions({
43
- id: '<%= plural %>',
44
- shapeOptions: {
45
- <% if (frontend.sync.useTableParam) { -%>
46
- url: new URL(
47
- '<%= frontend.sync.shapeUrl %>',
48
- window.location.origin,
49
- ).toString(),
50
- params: {
51
- table: '<%= plural %>',
52
- },
53
- <% } else { -%>
54
- <% if (frontend.sync.wrapInUrlConstructor !== false) { -%>
55
- url: new URL(
56
- <%- shapeUrlExpr %>,
57
- window.location.origin,
58
- ).toString(),
59
- <% } else { -%>
60
- url: <%- shapeUrlExpr %>,
61
- <% } -%>
62
- <% } -%>
63
- <% if (frontend.auth.function) { -%>
64
- headers: {
65
- Authorization: <%= frontend.auth.function %>(),
66
- },
67
- <% } -%>
68
- parser: {
69
- <% Object.entries(frontend.parsers).forEach(([type, fn]) => { -%>
70
- <%- type %>: <%- fn %>,
71
- <% }); -%>
72
- },
73
- <% if (frontend.sync.columnMapper) { -%>
74
- <% if (frontend.sync.columnMapperNeedsCall !== false) { -%>
75
- columnMapper: <%= frontend.sync.columnMapper %>(),
76
- <% } else { -%>
77
- columnMapper: <%= frontend.sync.columnMapper %>,
78
- <% } -%>
79
- <% } -%>
80
- },
81
- schema: <%= schemaPrefix %><%= camelName %>Schema,
82
- getKey: (item) => item.id,
83
- }),
84
- );
85
- <% } -%>
86
- <% } -%>
@@ -1,35 +0,0 @@
1
- ---
2
- to: <%= locations.frontendCollections.path %>/collections.ts
3
- skip_if: <%= !frontendEnabled %>
4
- force: false
5
- ---
6
- <% if (frontend.sync.mode === 'api') { -%>
7
- /**
8
- * REST-backed Collections (TanStack Query)
9
- * Generated by entity codegen - do not edit directly
10
- */
11
-
12
- import { queryCollectionOptions } from '@tanstack/query-db-collection';
13
- import { createCollection } from '@tanstack/react-db';
14
- import { queryClient } from '<%= frontend.sync.queryClientImport ?? './query-client' %>';
15
- <% } else { -%>
16
- /**
17
- * Electric SQL Collections
18
- * Generated by entity codegen - do not edit directly
19
- */
20
-
21
- import { electricCollectionOptions } from '@tanstack/electric-db-collection';
22
- import { createCollection } from '@tanstack/react-db';
23
- <% if (frontend.sync.columnMapper) { -%>
24
- import { <%= frontend.sync.columnMapper %> } from '@electric-sql/client';
25
- <% } -%>
26
- <% } -%>
27
- <% if (frontend.auth.function) { -%>
28
- import { <%= frontend.auth.function %> } from '<%= locations.frontendCollectionsAuth.import %>';
29
- <% } -%>
30
- <% if (frontend.sync.apiBaseUrlImport) { -%>
31
- import { API_BASE_URL } from '<%= frontend.sync.apiBaseUrlImport %>';
32
- <% } -%>
33
- import * as schema from '<%= locations.dbSchemaClient.import %>';
34
-
35
- // Codegen collections
@@ -1,173 +0,0 @@
1
- ---
2
- to: "<%= generate.structure === 'entity-first' ? `${locations.frontendGenerated.path}/${generate.fileNaming === 'plural' ? plural : name}/collection.ts` : generate.structure === 'concern-first' ? `${locations.frontendGenerated.path}/collections/${generate.fileNaming === 'plural' ? plural : name}.ts` : '' %>"
3
- skip_if: <%= !frontendEnabled || (generate.structure === 'monolithic') %>
4
- force: true
5
- ---
6
- <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
7
- /**
8
- * <%= className %> Collection
9
- * Generated by entity codegen - do not edit directly
10
- *
11
- * Real-time synced collection using Electric SQL
12
- */
13
-
14
- <% if (frontend.sync.columnMapper) { -%>
15
- import { <%= frontend.sync.columnMapper %> } from '@electric-sql/client';
16
- <% } -%>
17
- import { <%= camelName %>Schema } from '<%= locations.dbEntities.import %><% if (!locations.dbEntities.barrelExport) { %>/<%= name %><% } %>';
18
- <% if (exposeTrpc) { -%>
19
- import { trpc } from '<%= locations.trpcClient.import %>';
20
- <% } -%>
21
- import { electricCollectionOptions } from '@tanstack/electric-db-collection';
22
- import { createCollection } from '@tanstack/react-db';
23
- <% if (frontend.auth.function) { -%>
24
- import { <%= frontend.auth.function %> } from '<%= locations.frontendCollectionsAuth.import %>';
25
- <% } -%>
26
- <% if (frontend.sync.apiBaseUrlImport) { -%>
27
- import { API_BASE_URL } from '<%= frontend.sync.apiBaseUrlImport %>';
28
- <% } -%>
29
- <%
30
- // Collection variable name depends on collectionNaming config
31
- const collectionVar = generate.collectionNaming === 'plural' ? collectionVarNamePlural : collectionVarName;
32
- // File name for imports depends on fileNaming config
33
- const fileName = generate.fileNaming === 'plural' ? plural : name;
34
- -%>
35
- <% if (hasSoftDelete) { -%>
36
-
37
- // TODO: Backend Electric shape endpoint should filter soft-deleted records
38
- // by including WHERE deleted_at IS NULL in the shape configuration.
39
- // Without this filter, soft-deleted records will reappear after Electric sync.
40
- <% } -%>
41
-
42
- export const <%= collectionVar %> = createCollection(
43
- electricCollectionOptions({
44
- id: '<%= plural %>',
45
- shapeOptions: {
46
- <% if (frontend.sync.useTableParam) { -%>
47
- <% if (frontend.sync.wrapInUrlConstructor !== false) { -%>
48
- url: new URL(
49
- '<%= frontend.sync.shapeUrl %>',
50
- typeof window !== 'undefined'
51
- ? window.location.origin
52
- : 'http://localhost:5173',
53
- ).toString(),
54
- <% } else { -%>
55
- url: '<%= frontend.sync.shapeUrl %>',
56
- <% } -%>
57
- params: {
58
- table: '<%= plural %>',
59
- },
60
- <% } else { -%>
61
- <% if (frontend.sync.wrapInUrlConstructor !== false) { -%>
62
- url: new URL(
63
- `<%= frontend.sync.shapeUrl %>/<%= plural %>`,
64
- typeof window !== 'undefined'
65
- ? window.location.origin
66
- : 'http://localhost:5173',
67
- ).toString(),
68
- <% } else { -%>
69
- url: `<%= frontend.sync.shapeUrl %>/<%= plural %>`,
70
- <% } -%>
71
- <% } -%>
72
- <% if (frontend.auth.function) { -%>
73
- headers: {
74
- Authorization: <%= frontend.auth.function %>(),
75
- },
76
- <% } -%>
77
- parser: {
78
- <% Object.entries(frontend.parsers).forEach(([type, fn]) => { -%>
79
- <%- type %>: <%- fn %>,
80
- <% }); -%>
81
- },
82
- <% if (frontend.sync.columnMapper) { -%>
83
- <% if (frontend.sync.columnMapperNeedsCall !== false) { -%>
84
- columnMapper: <%= frontend.sync.columnMapper %>(),
85
- <% } else { -%>
86
- columnMapper: <%= frontend.sync.columnMapper %>,
87
- <% } -%>
88
- <% } -%>
89
- },
90
- schema: <%= camelName %>Schema,
91
- getKey: (item) => item.id,
92
- <% if (generate.mutations && (exposeTrpc || exposeRepository)) { -%>
93
- <% if (exposeTrpc) { -%>
94
- onInsert: async ({ transaction }) => {
95
- const { modified } = transaction.mutations[0];
96
- const result = await trpc.<%= plural %>.create.mutate(modified);
97
- return { txid: result.txid };
98
- },
99
- onUpdate: async ({ transaction }) => {
100
- const { modified } = transaction.mutations[0];
101
- const result = await trpc.<%= plural %>.update.mutate({ id: modified.id, data: modified });
102
- return { txid: result.txid };
103
- },
104
- onDelete: async ({ transaction }) => {
105
- const { original } = transaction.mutations[0];
106
- const result = await trpc.<%= plural %>.delete.mutate({ id: original.id });
107
- return { txid: result.txid };
108
- },
109
- <% } -%>
110
- <% } -%>
111
- }),
112
- );
113
- <%
114
- // Collect unique belongs_to targets for imports (FK resolution)
115
- // Only import if fkResolution is enabled (default: true)
116
- const importedEntities = new Set();
117
- if (generate.fkResolution !== false) {
118
- existingBelongsTo.forEach((rel) => {
119
- if (rel.target !== name) {
120
- importedEntities.add(rel.target);
121
- }
122
- });
123
- }
124
- -%>
125
- <% if (importedEntities.size > 0) { -%>
126
-
127
- // Import related collections for FK resolution
128
- <% importedEntities.forEach((target) => {
129
- const targetCamel = target.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
130
- // Simple pluralization matching prompt.js pluralize function
131
- const targetPlural = target.endsWith('y') ? target.slice(0, -1) + 'ies' :
132
- (target.endsWith('s') || target.endsWith('x') || target.endsWith('ch') || target.endsWith('sh')) ? target + 'es' : target + 's';
133
- const targetFileName = generate.fileNaming === 'plural' ? targetPlural : target;
134
- const targetCamelPlural = targetCamel.endsWith('y') ? targetCamel.slice(0, -1) + 'ies' : targetCamel + 's';
135
- -%>
136
- import { <%= generate.collectionNaming === 'plural' ? targetCamelPlural : targetCamel %>Collection } from '<% if (generate.structure === 'entity-first') { %>./<%= targetFileName %>/collection<% } else { %>./<%= targetFileName %><% } %>';
137
- <% }); -%>
138
- <% } -%>
139
- <% if (generate.structure === 'entity-first') { -%>
140
-
141
- // Import types from sibling module
142
- import type { <%= className %>, <%= className %>Resolved } from './types';
143
- <% } else { -%>
144
-
145
- // Import types
146
- import type { <%= className %>, <%= className %>Resolved } from '<% if (generate.structure === 'concern-first') { %>../types/<%= fileName %><% } %>';
147
- <% } -%>
148
-
149
- // ============================================================================
150
- // Resolution (FK lookup - internal use)
151
- // ============================================================================
152
- <% if (existingBelongsTo.length > 0 && generate.fkResolution !== false) { -%>
153
-
154
- export function resolveRelations(entity: <%= className %>): <%= className %>Resolved {
155
- return {
156
- ...entity,
157
- <% existingBelongsTo.forEach((rel) => {
158
- const targetCamel = rel.target.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
159
- const targetCamelPlural = targetCamel.endsWith('y') ? targetCamel.slice(0, -1) + 'ies' : targetCamel + 's';
160
- const targetCollectionVar = generate.collectionNaming === 'plural' ? targetCamelPlural : targetCamel;
161
- -%>
162
- <%= rel.name %>: entity.<%= rel.foreignKeyCamel %>
163
- ? <%= targetCollectionVar %>Collection.state.get(entity.<%= rel.foreignKeyCamel %>)
164
- : undefined,
165
- <% }); -%>
166
- };
167
- }
168
- <% } else { -%>
169
-
170
- export function resolveRelations(entity: <%= className %>): <%= className %>Resolved {
171
- return entity;
172
- }
173
- <% } -%>