@pattern-stack/codegen 0.7.5 → 0.7.6

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 (119) hide show
  1. package/dist/runtime/base-classes/index.d.ts +2 -0
  2. package/dist/runtime/base-classes/index.js +345 -18
  3. package/dist/runtime/base-classes/index.js.map +1 -1
  4. package/dist/runtime/base-classes/junction-sync-repository.d.ts +87 -0
  5. package/dist/runtime/base-classes/junction-sync-repository.js +362 -0
  6. package/dist/runtime/base-classes/junction-sync-repository.js.map +1 -0
  7. package/dist/runtime/base-classes/sync-upsert-config.d.ts +58 -0
  8. package/dist/runtime/base-classes/sync-upsert-config.js +1 -0
  9. package/dist/runtime/base-classes/sync-upsert-config.js.map +1 -0
  10. package/dist/runtime/base-classes/synced-entity-repository.d.ts +68 -6
  11. package/dist/runtime/base-classes/synced-entity-repository.js +173 -7
  12. package/dist/runtime/base-classes/synced-entity-repository.js.map +1 -1
  13. package/dist/runtime/subsystems/sync/execute-sync.use-case.js +19 -1
  14. package/dist/runtime/subsystems/sync/execute-sync.use-case.js.map +1 -1
  15. package/dist/runtime/subsystems/sync/index.js +19 -1
  16. package/dist/runtime/subsystems/sync/index.js.map +1 -1
  17. package/dist/runtime/subsystems/sync/sync-sink.protocol.d.ts +6 -0
  18. package/dist/src/cli/index.js +24 -2
  19. package/dist/src/cli/index.js.map +1 -1
  20. package/dist/src/index.js +21 -2
  21. package/dist/src/index.js.map +1 -1
  22. package/package.json +1 -1
  23. package/runtime/base-classes/index.ts +9 -0
  24. package/runtime/base-classes/junction-sync-repository.ts +284 -0
  25. package/runtime/base-classes/sync-upsert-config.ts +58 -0
  26. package/runtime/base-classes/synced-entity-repository.ts +263 -9
  27. package/runtime/subsystems/sync/execute-sync.use-case.ts +25 -1
  28. package/runtime/subsystems/sync/sync-sink.protocol.ts +7 -0
  29. package/src/patterns/library/synced.pattern.ts +2 -1
  30. package/templates/_shared/generated-banner.mjs +74 -0
  31. package/templates/broadcast/new/backend-interface.ejs.t +1 -0
  32. package/templates/broadcast/new/bridge-listener.ejs.t +1 -0
  33. package/templates/broadcast/new/channel.ejs.t +1 -0
  34. package/templates/broadcast/new/index.ejs.t +1 -0
  35. package/templates/broadcast/new/memory-backend.ejs.t +1 -0
  36. package/templates/broadcast/new/module.ejs.t +1 -0
  37. package/templates/broadcast/new/prompt.js +13 -0
  38. package/templates/broadcast/new/websocket-backend.ejs.t +1 -0
  39. package/templates/entity/new/backend/application/commands/create.ejs.t +1 -0
  40. package/templates/entity/new/backend/application/commands/delete.ejs.t +1 -0
  41. package/templates/entity/new/backend/application/commands/grouped-index.ejs.t +1 -0
  42. package/templates/entity/new/backend/application/commands/index.ejs.t +1 -0
  43. package/templates/entity/new/backend/application/commands/update.ejs.t +1 -0
  44. package/templates/entity/new/backend/application/queries/declarative-queries.ejs.t +1 -0
  45. package/templates/entity/new/backend/application/queries/get-by-id.ejs.t +1 -0
  46. package/templates/entity/new/backend/application/queries/grouped-index.ejs.t +1 -0
  47. package/templates/entity/new/backend/application/queries/index.ejs.t +1 -0
  48. package/templates/entity/new/backend/application/queries/list.ejs.t +1 -0
  49. package/templates/entity/new/backend/application/queries/relationships.queries.ejs.t +1 -0
  50. package/templates/entity/new/backend/application/schemas/dto.ejs.t +1 -0
  51. package/templates/entity/new/backend/database/repository.ejs.t +1 -0
  52. package/templates/entity/new/backend/database/schema.ejs.t +1 -0
  53. package/templates/entity/new/backend/domain/entity.ejs.t +1 -0
  54. package/templates/entity/new/backend/domain/grouped-index.ejs.t +1 -0
  55. package/templates/entity/new/backend/domain/index.ejs.t +1 -0
  56. package/templates/entity/new/backend/domain/repository-interface.ejs.t +1 -0
  57. package/templates/entity/new/backend/modules/core/module.ejs.t +1 -0
  58. package/templates/entity/new/backend/modules/core/sync-source.ejs.t +1 -0
  59. package/templates/entity/new/backend/modules/core/sync-source.providers.ejs.t +1 -0
  60. package/templates/entity/new/backend/modules/trpc/module.ejs.t +1 -0
  61. package/templates/entity/new/backend/presentation/controller.ejs.t +1 -0
  62. package/templates/entity/new/clean-lite-ps/controller.ejs.t +1 -0
  63. package/templates/entity/new/clean-lite-ps/dto/create.ejs.t +1 -0
  64. package/templates/entity/new/clean-lite-ps/dto/output.ejs.t +1 -0
  65. package/templates/entity/new/clean-lite-ps/dto/update.ejs.t +1 -0
  66. package/templates/entity/new/clean-lite-ps/entity.ejs.t +1 -0
  67. package/templates/entity/new/clean-lite-ps/index.ejs.t +1 -0
  68. package/templates/entity/new/clean-lite-ps/module.ejs.t +1 -0
  69. package/templates/entity/new/clean-lite-ps/prompt-extension.js +148 -0
  70. package/templates/entity/new/clean-lite-ps/repository.ejs.t +92 -1
  71. package/templates/entity/new/clean-lite-ps/search-controller.ejs.t +1 -0
  72. package/templates/entity/new/clean-lite-ps/service.ejs.t +1 -0
  73. package/templates/entity/new/clean-lite-ps/use-cases/create.ejs.t +1 -0
  74. package/templates/entity/new/clean-lite-ps/use-cases/declarative-queries.ejs.t +1 -0
  75. package/templates/entity/new/clean-lite-ps/use-cases/delete.ejs.t +1 -0
  76. package/templates/entity/new/clean-lite-ps/use-cases/find-by-id-with-fields.ejs.t +1 -0
  77. package/templates/entity/new/clean-lite-ps/use-cases/find-by-id.ejs.t +1 -0
  78. package/templates/entity/new/clean-lite-ps/use-cases/list-with-fields.ejs.t +1 -0
  79. package/templates/entity/new/clean-lite-ps/use-cases/list.ejs.t +1 -0
  80. package/templates/entity/new/clean-lite-ps/use-cases/search.ejs.t +1 -0
  81. package/templates/entity/new/clean-lite-ps/use-cases/update.ejs.t +1 -0
  82. package/templates/entity/new/frontend/entity/collection.ejs.t +1 -0
  83. package/templates/entity/new/frontend/entity/combined.ejs.t +1 -0
  84. package/templates/entity/new/frontend/entity/fields.ejs.t +1 -0
  85. package/templates/entity/new/frontend/entity/hooks.ejs.t +1 -0
  86. package/templates/entity/new/frontend/entity/index.ejs.t +1 -0
  87. package/templates/entity/new/frontend/entity/mutation-hooks.ejs.t +1 -0
  88. package/templates/entity/new/frontend/entity/mutations.ejs.t +1 -0
  89. package/templates/entity/new/frontend/entity/types.ejs.t +1 -0
  90. package/templates/entity/new/frontend/store/hooks.ejs.t +1 -0
  91. package/templates/entity/new/frontend/unified-entity.ejs.t +1 -0
  92. package/templates/entity/new/prompt.js +19 -0
  93. package/templates/junction/new/entity.ejs.t +1 -0
  94. package/templates/junction/new/index.ejs.t +1 -0
  95. package/templates/junction/new/module.ejs.t +1 -0
  96. package/templates/junction/new/prompt.js +83 -0
  97. package/templates/junction/new/repository.ejs.t +44 -3
  98. package/templates/junction/new/service.ejs.t +1 -0
  99. package/templates/relationship/new/controller.ejs.t +1 -0
  100. package/templates/relationship/new/dto/create.ejs.t +1 -0
  101. package/templates/relationship/new/dto/output.ejs.t +1 -0
  102. package/templates/relationship/new/dto/update.ejs.t +1 -0
  103. package/templates/relationship/new/entity.ejs.t +1 -0
  104. package/templates/relationship/new/index.ejs.t +1 -0
  105. package/templates/relationship/new/module.ejs.t +1 -0
  106. package/templates/relationship/new/prompt.js +14 -0
  107. package/templates/relationship/new/repository.ejs.t +1 -0
  108. package/templates/relationship/new/service.ejs.t +1 -0
  109. package/templates/relationship/new/use-cases/declarative-queries.ejs.t +1 -0
  110. package/templates/relationship/new/use-cases/find-by-id.ejs.t +1 -0
  111. package/templates/relationship/new/use-cases/list.ejs.t +1 -0
  112. package/templates/subsystem/auth/auth-oauth-state.schema.ejs.t +1 -0
  113. package/templates/subsystem/auth/prompt.js +8 -0
  114. package/templates/subsystem/events/domain-events.schema.ejs.t +1 -0
  115. package/templates/subsystem/events/prompt.js +8 -0
  116. package/templates/subsystem/jobs/job-orchestration.schema.ejs.t +1 -0
  117. package/templates/subsystem/jobs/prompt.js +8 -0
  118. package/templates/subsystem/sync/prompt.js +8 -0
  119. package/templates/subsystem/sync/sync-audit.schema.ejs.t +1 -0
@@ -278,11 +278,35 @@ export class ExecuteSyncUseCase<T extends Record<string, unknown>> {
278
278
  );
279
279
 
280
280
  if (diff === 'noop') {
281
+ // Sinks that declare `reprojectsOnNoop` reproject side data the differ
282
+ // can't see (e.g. EAV field_values) — so fall through to the idempotent
283
+ // upsert instead of short-circuiting. The canonical state is unchanged,
284
+ // so the audit `operation` stays `'noop'`, but we capture the local id
285
+ // returned by the upsert. Sinks without the flag keep today's behavior.
286
+ if (!this.sink.reprojectsOnNoop) {
287
+ await this.recorder.recordItem({
288
+ syncRunId: runId,
289
+ entityType: input.subscription.domain,
290
+ externalId: change.externalId,
291
+ localId: null,
292
+ operation: 'noop',
293
+ status: 'success',
294
+ changedFields: {},
295
+ tenantId: input.tenantId,
296
+ });
297
+ return;
298
+ }
299
+
300
+ const { id: noopLocalId } = await this.sink.upsertByExternalId(
301
+ input.userId,
302
+ change.record,
303
+ input.provider,
304
+ );
281
305
  await this.recorder.recordItem({
282
306
  syncRunId: runId,
283
307
  entityType: input.subscription.domain,
284
308
  externalId: change.externalId,
285
- localId: null,
309
+ localId: noopLocalId,
286
310
  operation: 'noop',
287
311
  status: 'success',
288
312
  changedFields: {},
@@ -52,4 +52,11 @@ export interface ISyncSink<TCanonical> {
52
52
  userId: string,
53
53
  externalId: string,
54
54
  ): Promise<{ id: string } | null>;
55
+
56
+ /**
57
+ * When true, the orchestrator does NOT short-circuit on a `noop` diff — it
58
+ * still calls upsertByExternalId so the sink can reproject side data (e.g.
59
+ * EAV field_values) the differ doesn't see. Default false.
60
+ */
61
+ readonly reprojectsOnNoop?: boolean;
55
62
  }
@@ -23,7 +23,8 @@ export const SyncedPattern = definePattern({
23
23
  serviceImport: '@shared/base-classes/synced-entity-service',
24
24
  repositoryInheritedMethods: [
25
25
  'findById, findByIds, list, count, exists, create, update, delete, upsertMany',
26
- 'findByExternalId, findAllByUserId, findVisibleByUserId, syncUpsert',
26
+ 'findByExternalId, findManyByExternalIds, findAllByUserId, findVisibleByUserId',
27
+ 'syncUpsertOne, findByExternalIdProjected, softDeleteByExternalId, syncUpsert',
27
28
  ],
28
29
  serviceInheritedMethods: [
29
30
  'findById, findByIds, list, count, exists, create, update, delete',
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Shared `@generated` banner helper.
3
+ *
4
+ * Single source of truth for the DO-NOT-EDIT banner that every
5
+ * force-overwritten codegen output carries. The banner exists because
6
+ * force-emitted files are silently re-written on every `bun run codegen`
7
+ * (and wholesale on `codegen entity new --all`). Without a visible warning,
8
+ * a hand edit made directly into a generated file looks permanent — until
9
+ * the next re-emit wipes it. The banner is the warning.
10
+ *
11
+ * Why a helper (not copy-pasted text): the banner wording is a contract.
12
+ * Centralising it means a future change (e.g. a new extension seam, a
13
+ * reworded regenerate command) touches one file, and the emission tests
14
+ * assert against this exact function.
15
+ *
16
+ * Consumed by each generator's `prompt.js`, which calls
17
+ * `renderGeneratedBanner({ source, generator, seam })` once and forwards the
18
+ * result as the `generatedBanner` template local. Templates emit it as their
19
+ * first body line via:
20
+ *
21
+ * <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
22
+ *
23
+ * The `typeof` guard keeps direct-EJS rendering (unit tests that build their
24
+ * own locals) from throwing a ReferenceError when a test does not opt into
25
+ * the banner local.
26
+ */
27
+
28
+ /**
29
+ * Marker substring that identifies a generated-banner line. Tests and
30
+ * tooling can grep for this to assert (or strip) the banner. Kept as a
31
+ * single token so it survives reflow / line-wrapping changes to the prose.
32
+ */
33
+ export const GENERATED_BANNER_MARKER = '@generated by @pattern-stack/codegen';
34
+
35
+ /**
36
+ * Render the DO-NOT-EDIT banner.
37
+ *
38
+ * @param {object} opts
39
+ * @param {string} [opts.source] Source definition path (e.g. the entity
40
+ * YAML), relative to the consumer repo root
41
+ * when known. Interpolated into the banner so
42
+ * a reader knows which file to edit instead.
43
+ * @param {string} [opts.generator] The codegen generator that emitted the file
44
+ * (e.g. 'entity', 'junction'). Purely
45
+ * informational; helps when `source` is
46
+ * unavailable.
47
+ * @param {string} [opts.seam] The supported extension seam — how to
48
+ * customise behaviour without editing the
49
+ * generated file (e.g. 'a pattern in
50
+ * src/patterns/*.pattern.ts', 'a subclass /
51
+ * base-class behavior config').
52
+ * @param {string} [opts.comment] Comment leader for the host language.
53
+ * Defaults to '//' (TS/JS). Pass '--' for SQL.
54
+ * @returns {string} A single comment line, no trailing newline.
55
+ */
56
+ export function renderGeneratedBanner(opts = {}) {
57
+ const { source, generator, seam, comment = '//' } = opts;
58
+
59
+ const from = source
60
+ ? ` from ${source}`
61
+ : generator
62
+ ? ` (${generator} generator)`
63
+ : '';
64
+ const extend = seam
65
+ ? ` To extend, use ${seam}.`
66
+ : '';
67
+
68
+ return (
69
+ `${comment} ${GENERATED_BANNER_MARKER}${from} — DO NOT EDIT. ` +
70
+ `Hand edits are overwritten on re-emit. Regenerate with \`bun run codegen\`.${extend}`
71
+ );
72
+ }
73
+
74
+ export default renderGeneratedBanner;
@@ -2,6 +2,7 @@
2
2
  to: src/infrastructure/broadcast/broadcast-backend.interface.ts
3
3
  force: true
4
4
  ---
5
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
5
6
  export type BroadcastHandler = (
6
7
  eventType: string,
7
8
  payload: Record<string, unknown>,
@@ -2,6 +2,7 @@
2
2
  to: src/infrastructure/broadcast/broadcast-bridge.listener.ts
3
3
  force: true
4
4
  ---
5
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
5
6
  import { Injectable, Logger } from '@nestjs/common'
6
7
  import { OnEvent } from '@nestjs/event-emitter'
7
8
  import { WebSocketBroadcastBackend } from './websocket-broadcast.backend'
@@ -2,6 +2,7 @@
2
2
  to: src/infrastructure/broadcast/channel.ts
3
3
  force: true
4
4
  ---
5
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
5
6
  import type { BroadcastBackend, BroadcastHandler } from './broadcast-backend.interface'
6
7
 
7
8
  /**
@@ -2,6 +2,7 @@
2
2
  to: src/infrastructure/broadcast/index.ts
3
3
  force: true
4
4
  ---
5
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
5
6
  // Interfaces
6
7
  export type { BroadcastBackend, BroadcastHandler } from './broadcast-backend.interface'
7
8
  export { BROADCAST_BACKEND } from './broadcast-backend.interface'
@@ -2,6 +2,7 @@
2
2
  to: src/infrastructure/broadcast/memory-broadcast.backend.ts
3
3
  force: true
4
4
  ---
5
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
5
6
  import { Injectable } from '@nestjs/common'
6
7
  import type {
7
8
  BroadcastBackend,
@@ -2,6 +2,7 @@
2
2
  to: src/infrastructure/broadcast/broadcast.module.ts
3
3
  force: true
4
4
  ---
5
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
5
6
  import { Module } from '@nestjs/common'
6
7
  import { WebSocketBroadcastBackend } from './websocket-broadcast.backend'
7
8
  import { MemoryBroadcastBackend } from './memory-broadcast.backend'
@@ -9,6 +9,7 @@
9
9
  import fs from 'node:fs'
10
10
  import path from 'node:path'
11
11
  import yaml from 'yaml'
12
+ import { renderGeneratedBanner } from '../../_shared/generated-banner.mjs'
12
13
 
13
14
  // ============================================================================
14
15
  // Default Configuration
@@ -243,7 +244,19 @@ export default {
243
244
  events: events.sort(),
244
245
  }))
245
246
 
247
+ // @generated DO-NOT-EDIT banner — stamped at the top of every
248
+ // force-overwritten broadcast output. `args.yaml` (when provided) is the
249
+ // consumer-relative source config; otherwise defaults are used.
250
+ const generatedBanner = renderGeneratedBanner({
251
+ source: args.yaml,
252
+ generator: 'broadcast',
253
+ seam: 'the broadcast config YAML',
254
+ })
255
+
246
256
  return {
257
+ // @generated DO-NOT-EDIT banner (see renderGeneratedBanner)
258
+ generatedBanner,
259
+
247
260
  // Basic config
248
261
  name: broadcast.name,
249
262
  websocketPath: broadcast.websocket?.path ?? '/ws/broadcast',
@@ -2,6 +2,7 @@
2
2
  to: src/infrastructure/broadcast/websocket-broadcast.backend.ts
3
3
  force: true
4
4
  ---
5
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
5
6
  import { Injectable, Logger } from '@nestjs/common'
6
7
  import {
7
8
  WebSocketGateway,
@@ -3,6 +3,7 @@ to: "<%= generate.commands ? outputPaths.createCommand : '' %>"
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (outputPaths.createCommand) { -%>
7
8
  /**
8
9
  * Create <%= className %> Command
@@ -3,6 +3,7 @@ to: "<%= generate.commands ? outputPaths.deleteCommand : '' %>"
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (outputPaths.deleteCommand) { -%>
7
8
  /**
8
9
  * Delete <%= className %> Command
@@ -3,6 +3,7 @@ to: "<%= generate.commands ? outputPaths.commandsGroupedIndex : '' %>"
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (outputPaths.commandsGroupedIndex) { -%>
7
8
  /**
8
9
  * <%= className %> Commands Module
@@ -3,6 +3,7 @@ to: "<%= generate.commands ? outputPaths.commandsIndex : '' %>"
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (outputPaths.commandsIndex) { -%>
7
8
  /**
8
9
  * <%= className %> Commands Barrel Export
@@ -3,6 +3,7 @@ to: "<%= generate.commands ? outputPaths.updateCommand : '' %>"
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (outputPaths.updateCommand) { -%>
7
8
  /**
8
9
  * Update <%= className %> Command
@@ -3,6 +3,7 @@ to: "<%= hasDeclarativeQueries ? `${basePaths.backendSrc}/${paths.queries}/decla
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (hasDeclarativeQueries) { -%>
7
8
  /**
8
9
  * Declarative Query Classes for <%= className %>
@@ -3,6 +3,7 @@ to: "<%= generate.queries ? outputPaths.getByIdQuery : '' %>"
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (outputPaths.getByIdQuery) { -%>
7
8
  /**
8
9
  * Get <%= className %> By ID Query
@@ -3,6 +3,7 @@ to: "<%= generate.queries ? outputPaths.queriesGroupedIndex : '' %>"
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (outputPaths.queriesGroupedIndex) { -%>
7
8
  /**
8
9
  * <%= className %> Queries Module
@@ -3,6 +3,7 @@ to: "<%= generate.queries ? outputPaths.queriesIndex : '' %>"
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (outputPaths.queriesIndex) { -%>
7
8
  /**
8
9
  * <%= className %> Queries Barrel Export
@@ -3,6 +3,7 @@ to: "<%= generate.queries ? outputPaths.listQuery : '' %>"
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (outputPaths.listQuery) { -%>
7
8
  /**
8
9
  * List <%= classNamePlural %> Query
@@ -3,6 +3,7 @@ to: "<%= (isCleanArchitecture && hasRelationships && !isGrouped) ? `${basePaths.
3
3
  skip_if: <%= !(isCleanArchitecture && hasRelationships && !isGrouped) %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (isCleanArchitecture && hasRelationships && !isGrouped) { -%>
7
8
  /**
8
9
  * Relationship Composition Queries for <%= className %>
@@ -3,6 +3,7 @@ to: "<%= generate.dtos ? outputPaths.dto : '' %>"
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  /**
7
8
  * <%= className %> DTOs
8
9
  * Generated by entity codegen - do not edit directly
@@ -3,6 +3,7 @@ to: <%= basePaths.backendSrc %>/<%= paths.repositories %>/<%= name %>.repository
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  /**
7
8
  * <%= className %> Repository Implementation
8
9
  * Generated by entity codegen - do not edit directly
@@ -3,6 +3,7 @@ to: "<%= generate.drizzleSchema ? outputPaths.drizzleSchema : '' %>"
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  /**
7
8
  * <%= className %> Drizzle Schema
8
9
  * Generated by entity codegen - do not edit directly
@@ -3,6 +3,7 @@ to: <%= outputPaths.entity %>
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (outputPaths.entity) { -%>
7
8
  /**
8
9
  * <%= className %> Domain Entity
@@ -3,6 +3,7 @@ to: <%= outputPaths.domainGroupedIndex %>
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (outputPaths.domainGroupedIndex) { -%>
7
8
  /**
8
9
  * <%= className %> Domain Module
@@ -3,6 +3,7 @@ to: <%= basePaths.backendSrc %>/<%= paths.domain %>/index.ts
3
3
  skip_if: <%= !isCleanArchitecture || (!isNested || isGrouped) %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  /**
7
8
  * <%= className %> Domain Barrel Export
8
9
  * Generated by entity codegen - do not edit directly
@@ -3,6 +3,7 @@ to: <%= outputPaths.repositoryInterface %>
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (outputPaths.repositoryInterface) { -%>
7
8
  /**
8
9
  * <%= className %> Repository Interface
@@ -3,6 +3,7 @@ to: <%= outputPaths.module %>
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  /**
7
8
  * <%= classNamePlural %> Module
8
9
  * Generated by entity codegen - do not edit directly
@@ -3,6 +3,7 @@ to: "<%= hasDetection ? (isCleanLitePs ? clpOutputPaths.syncSourceModule : `${ba
3
3
  skip_if: <%= !hasDetection %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  import { Module } from '@nestjs/common';
7
8
  import { buildChangeSource } from '@shared/subsystems/sync';
8
9
  import type {
@@ -3,6 +3,7 @@ to: "<%= hasDetection ? (isCleanLitePs ? clpOutputPaths.syncSourceProviders : `$
3
3
  skip_if: <%= !hasDetection %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  /**
7
8
  * <%= className %> sync-source providers
8
9
  * Generated by entity codegen — do not edit directly.
@@ -3,6 +3,7 @@ to: "<%= exposeTrpc ? `${basePaths.backendSrc}/presentation/trpc/${plural}.route
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (exposeTrpc) { -%>
7
8
  /**
8
9
  * <%= classNamePlural %> tRPC Router
@@ -3,6 +3,7 @@ to: "<%= (exposeRest || exposeElectric) ? `${basePaths.backendSrc}/${paths.contr
3
3
  skip_if: <%= !isCleanArchitecture %>
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (exposeRest) { -%>
7
8
  /**
8
9
  * <%= classNamePlural %> Controller
@@ -3,6 +3,7 @@ to: "<%= typeof clpOutputPaths !== 'undefined' ? clpOutputPaths.controller : nul
3
3
  skip_if: "<%= typeof clpOutputPaths === 'undefined' %>"
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  import { Controller, Get<% if (generateWrites) { %>, Post, Patch, Delete, Body, Headers<% } %>, NotFoundException, Param, ParseUUIDPipe } from '@nestjs/common';
7
8
  import { ApiBearerAuth, <% if (generateWrites) { %>ApiBody, <% } %>ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger';
8
9
  import { <%= classNames.findByIdUseCase %> } from './use-cases/find-<%= entityName %>-by-id.use-case';
@@ -3,6 +3,7 @@ to: "<%= typeof clpOutputPaths !== 'undefined' ? clpOutputPaths.createDto : null
3
3
  skip_if: "<%= typeof clpOutputPaths === 'undefined' %>"
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  import { z } from 'zod';
7
8
 
8
9
  export const <%= classNames.createSchema %> = z.object({
@@ -3,6 +3,7 @@ to: "<%= typeof clpOutputPaths !== 'undefined' ? clpOutputPaths.outputDto : null
3
3
  skip_if: "<%= typeof clpOutputPaths === 'undefined' %>"
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  import { z } from 'zod';
7
8
 
8
9
  export const <%= classNames.outputSchema %> = z.object({
@@ -3,6 +3,7 @@ to: "<%= typeof clpOutputPaths !== 'undefined' ? clpOutputPaths.updateDto : null
3
3
  skip_if: "<%= typeof clpOutputPaths === 'undefined' %>"
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  import { z } from 'zod';
7
8
  import { <%= classNames.createSchema %> } from './create-<%= entityName %>.dto';
8
9
 
@@ -3,6 +3,7 @@ to: "<%= typeof clpOutputPaths !== 'undefined' ? clpOutputPaths.entity : null %>
3
3
  skip_if: "<%= typeof clpOutputPaths === 'undefined' %>"
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  import {
7
8
  <%_ clpDrizzleImports.filter(i => i !== 'relations').forEach(i => { _%>
8
9
  <%= i %>,
@@ -3,6 +3,7 @@ to: "<%= typeof clpOutputPaths !== 'undefined' ? clpOutputPaths.index : null %>"
3
3
  skip_if: "<%= typeof clpOutputPaths === 'undefined' %>"
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  /**
7
8
  * <%= classNames.entity %> module barrel export
8
9
  * Generated by entity codegen - do not edit directly
@@ -3,6 +3,7 @@ to: "<%= typeof clpOutputPaths !== 'undefined' ? clpOutputPaths.module : null %>
3
3
  skip_if: "<%= typeof clpOutputPaths === 'undefined' %>"
4
4
  force: true
5
5
  ---
6
+ <%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
6
7
  <% if (hasEmits) { -%>
7
8
  /**
8
9
  * EVT-7: This entity emits typed domain events. Use-cases depend on