@carlonicora/nestjs-neo4jsonapi 1.31.2 → 1.32.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 (238) hide show
  1. package/dist/common/helpers/define-entity.d.ts +29 -0
  2. package/dist/common/helpers/define-entity.d.ts.map +1 -1
  3. package/dist/common/helpers/define-entity.js +42 -1
  4. package/dist/common/helpers/define-entity.js.map +1 -1
  5. package/dist/common/interfaces/entity.descriptor.interface.d.ts +2 -2
  6. package/dist/common/interfaces/entity.descriptor.interface.d.ts.map +1 -1
  7. package/dist/common/interfaces/entity.descriptor.interface.js +2 -1
  8. package/dist/common/interfaces/entity.descriptor.interface.js.map +1 -1
  9. package/dist/common/interfaces/entity.schema.interface.d.ts +19 -1
  10. package/dist/common/interfaces/entity.schema.interface.d.ts.map +1 -1
  11. package/dist/core/email/templates/en/paymentFailure.hbs +56 -0
  12. package/dist/core/email/templates/en/paymentSuccessAdmin.hbs +31 -0
  13. package/dist/core/email/templates/en/paymentSuccessCustomer.hbs +51 -0
  14. package/dist/core/email/templates/en/subscriptionStatusChange.hbs +48 -0
  15. package/dist/core/jsonapi/serialisers/descriptor.based.serialiser.d.ts.map +1 -1
  16. package/dist/core/jsonapi/serialisers/descriptor.based.serialiser.js +13 -0
  17. package/dist/core/jsonapi/serialisers/descriptor.based.serialiser.js.map +1 -1
  18. package/dist/core/jsonapi/serialisers/jsonapi.paginator.d.ts +3 -0
  19. package/dist/core/jsonapi/serialisers/jsonapi.paginator.d.ts.map +1 -1
  20. package/dist/core/jsonapi/serialisers/jsonapi.paginator.js +6 -0
  21. package/dist/core/jsonapi/serialisers/jsonapi.paginator.js.map +1 -1
  22. package/dist/core/jsonapi/services/jsonapi.service.d.ts.map +1 -1
  23. package/dist/core/jsonapi/services/jsonapi.service.js +6 -0
  24. package/dist/core/jsonapi/services/jsonapi.service.js.map +1 -1
  25. package/dist/core/neo4j/abstracts/abstract.service.d.ts +2 -0
  26. package/dist/core/neo4j/abstracts/abstract.service.d.ts.map +1 -1
  27. package/dist/core/neo4j/abstracts/abstract.service.js +8 -4
  28. package/dist/core/neo4j/abstracts/abstract.service.js.map +1 -1
  29. package/dist/core/neo4j/services/neo4j.service.d.ts +9 -0
  30. package/dist/core/neo4j/services/neo4j.service.d.ts.map +1 -1
  31. package/dist/core/neo4j/services/neo4j.service.js +95 -1
  32. package/dist/core/neo4j/services/neo4j.service.js.map +1 -1
  33. package/dist/foundations/audit/entities/audit.entity.d.ts +1 -1
  34. package/dist/foundations/audit/entities/audit.entity.d.ts.map +1 -1
  35. package/dist/foundations/audit/serialisers/audit.serialiser.js +2 -2
  36. package/dist/foundations/audit/serialisers/audit.serialiser.js.map +1 -1
  37. package/dist/foundations/auth/entities/auth.entity.d.ts +1 -1
  38. package/dist/foundations/auth/entities/auth.entity.d.ts.map +1 -1
  39. package/dist/foundations/auth/repositories/auth.repository.d.ts +1 -1
  40. package/dist/foundations/auth/repositories/auth.repository.d.ts.map +1 -1
  41. package/dist/foundations/auth/repositories/auth.repository.js +31 -13
  42. package/dist/foundations/auth/repositories/auth.repository.js.map +1 -1
  43. package/dist/foundations/auth/serialisers/auth.serialiser.js +2 -2
  44. package/dist/foundations/auth/serialisers/auth.serialiser.js.map +1 -1
  45. package/dist/foundations/auth/services/auth.service.d.ts +1 -1
  46. package/dist/foundations/auth/services/auth.service.d.ts.map +1 -1
  47. package/dist/foundations/company/company.module.d.ts.map +1 -1
  48. package/dist/foundations/company/company.module.js +9 -5
  49. package/dist/foundations/company/company.module.js.map +1 -1
  50. package/dist/foundations/company/entities/company.d.ts +44 -0
  51. package/dist/foundations/company/entities/company.d.ts.map +1 -0
  52. package/dist/foundations/company/entities/company.js +47 -0
  53. package/dist/foundations/company/entities/company.js.map +1 -0
  54. package/dist/foundations/company/entities/company.meta.d.ts +1 -1
  55. package/dist/foundations/company/entities/company.meta.d.ts.map +1 -1
  56. package/dist/foundations/company/index.d.ts +1 -2
  57. package/dist/foundations/company/index.d.ts.map +1 -1
  58. package/dist/foundations/company/index.js +3 -3
  59. package/dist/foundations/company/index.js.map +1 -1
  60. package/dist/foundations/company/repositories/company.repository.d.ts +26 -1
  61. package/dist/foundations/company/repositories/company.repository.d.ts.map +1 -1
  62. package/dist/foundations/company/repositories/company.repository.js +67 -11
  63. package/dist/foundations/company/repositories/company.repository.js.map +1 -1
  64. package/dist/foundations/company/services/company.service.d.ts +4 -1
  65. package/dist/foundations/company/services/company.service.d.ts.map +1 -1
  66. package/dist/foundations/company/services/company.service.js +11 -6
  67. package/dist/foundations/company/services/company.service.js.map +1 -1
  68. package/dist/foundations/content/entities/content.entity.d.ts +1 -1
  69. package/dist/foundations/content/entities/content.entity.d.ts.map +1 -1
  70. package/dist/foundations/content/serialisers/content.serialiser.js +3 -3
  71. package/dist/foundations/content/serialisers/content.serialiser.js.map +1 -1
  72. package/dist/foundations/module/queries/feature.module.query.d.ts +3 -1
  73. package/dist/foundations/module/queries/feature.module.query.d.ts.map +1 -1
  74. package/dist/foundations/module/queries/feature.module.query.js +27 -15
  75. package/dist/foundations/module/queries/feature.module.query.js.map +1 -1
  76. package/dist/foundations/notification/entities/notification.entity.d.ts +1 -1
  77. package/dist/foundations/notification/entities/notification.entity.d.ts.map +1 -1
  78. package/dist/foundations/notification/serialisers/notifications.serialiser.js +2 -2
  79. package/dist/foundations/notification/serialisers/notifications.serialiser.js.map +1 -1
  80. package/dist/foundations/oauth/entities/oauth.client.entity.d.ts +2 -2
  81. package/dist/foundations/oauth/entities/oauth.client.entity.d.ts.map +1 -1
  82. package/dist/foundations/relevancy/repositories/relevancy.repository.d.ts.map +1 -1
  83. package/dist/foundations/relevancy/repositories/relevancy.repository.js +1 -1
  84. package/dist/foundations/relevancy/repositories/relevancy.repository.js.map +1 -1
  85. package/dist/foundations/relevancy/services/relevancy.service.js +1 -1
  86. package/dist/foundations/relevancy/services/relevancy.service.js.map +1 -1
  87. package/dist/foundations/role/entities/role.d.ts +28 -0
  88. package/dist/foundations/role/entities/role.d.ts.map +1 -0
  89. package/dist/foundations/role/entities/role.js +33 -0
  90. package/dist/foundations/role/entities/role.js.map +1 -0
  91. package/dist/foundations/role/entities/role.meta.d.ts +1 -1
  92. package/dist/foundations/role/entities/role.meta.d.ts.map +1 -1
  93. package/dist/foundations/role/repositories/role.repository.d.ts +1 -1
  94. package/dist/foundations/role/repositories/role.repository.d.ts.map +1 -1
  95. package/dist/foundations/role/repositories/role.repository.js +7 -7
  96. package/dist/foundations/role/repositories/role.repository.js.map +1 -1
  97. package/dist/foundations/role/role.module.d.ts.map +1 -1
  98. package/dist/foundations/role/role.module.js +3 -4
  99. package/dist/foundations/role/role.module.js.map +1 -1
  100. package/dist/foundations/role/services/role.service.js +5 -5
  101. package/dist/foundations/role/services/role.service.js.map +1 -1
  102. package/dist/foundations/stripe-customer/entities/stripe-customer.entity.d.ts +1 -1
  103. package/dist/foundations/stripe-customer/entities/stripe-customer.entity.d.ts.map +1 -1
  104. package/dist/foundations/stripe-price/dtos/stripe-price.dto.d.ts +12 -0
  105. package/dist/foundations/stripe-price/dtos/stripe-price.dto.d.ts.map +1 -1
  106. package/dist/foundations/stripe-price/dtos/stripe-price.dto.js +47 -1
  107. package/dist/foundations/stripe-price/dtos/stripe-price.dto.js.map +1 -1
  108. package/dist/foundations/stripe-price/entities/stripe-price.entity.d.ts +2 -0
  109. package/dist/foundations/stripe-price/entities/stripe-price.entity.d.ts.map +1 -1
  110. package/dist/foundations/stripe-price/entities/stripe-price.map.d.ts.map +1 -1
  111. package/dist/foundations/stripe-price/entities/stripe-price.map.js +1 -0
  112. package/dist/foundations/stripe-price/entities/stripe-price.map.js.map +1 -1
  113. package/dist/foundations/stripe-price/entities/stripe-price.model.d.ts.map +1 -1
  114. package/dist/foundations/stripe-price/entities/stripe-price.model.js +2 -1
  115. package/dist/foundations/stripe-price/entities/stripe-price.model.js.map +1 -1
  116. package/dist/foundations/stripe-price/repositories/stripe-price.repository.d.ts +3 -0
  117. package/dist/foundations/stripe-price/repositories/stripe-price.repository.d.ts.map +1 -1
  118. package/dist/foundations/stripe-price/repositories/stripe-price.repository.js +64 -4
  119. package/dist/foundations/stripe-price/repositories/stripe-price.repository.js.map +1 -1
  120. package/dist/foundations/stripe-price/serialisers/stripe-price.serialiser.d.ts.map +1 -1
  121. package/dist/foundations/stripe-price/serialisers/stripe-price.serialiser.js +5 -0
  122. package/dist/foundations/stripe-price/serialisers/stripe-price.serialiser.js.map +1 -1
  123. package/dist/foundations/stripe-price/services/stripe-price-admin.service.d.ts.map +1 -1
  124. package/dist/foundations/stripe-price/services/stripe-price-admin.service.js +10 -0
  125. package/dist/foundations/stripe-price/services/stripe-price-admin.service.js.map +1 -1
  126. package/dist/foundations/stripe-subscription/repositories/stripe-subscription.repository.d.ts +11 -0
  127. package/dist/foundations/stripe-subscription/repositories/stripe-subscription.repository.d.ts.map +1 -1
  128. package/dist/foundations/stripe-subscription/repositories/stripe-subscription.repository.js +22 -0
  129. package/dist/foundations/stripe-subscription/repositories/stripe-subscription.repository.js.map +1 -1
  130. package/dist/foundations/stripe-subscription/services/feature-sync.service.d.ts +33 -0
  131. package/dist/foundations/stripe-subscription/services/feature-sync.service.d.ts.map +1 -0
  132. package/dist/foundations/stripe-subscription/services/feature-sync.service.js +155 -0
  133. package/dist/foundations/stripe-subscription/services/feature-sync.service.js.map +1 -0
  134. package/dist/foundations/stripe-subscription/services/stripe-subscription-admin.service.d.ts.map +1 -1
  135. package/dist/foundations/stripe-subscription/services/stripe-subscription-admin.service.js +11 -0
  136. package/dist/foundations/stripe-subscription/services/stripe-subscription-admin.service.js.map +1 -1
  137. package/dist/foundations/stripe-subscription/stripe-subscription.module.d.ts.map +1 -1
  138. package/dist/foundations/stripe-subscription/stripe-subscription.module.js +3 -0
  139. package/dist/foundations/stripe-subscription/stripe-subscription.module.js.map +1 -1
  140. package/dist/foundations/stripe-webhook/processors/stripe-webhook.processor.d.ts +3 -1
  141. package/dist/foundations/stripe-webhook/processors/stripe-webhook.processor.d.ts.map +1 -1
  142. package/dist/foundations/stripe-webhook/processors/stripe-webhook.processor.js +79 -9
  143. package/dist/foundations/stripe-webhook/processors/stripe-webhook.processor.js.map +1 -1
  144. package/dist/foundations/stripe-webhook/services/stripe-webhook-notification.service.d.ts +26 -1
  145. package/dist/foundations/stripe-webhook/services/stripe-webhook-notification.service.d.ts.map +1 -1
  146. package/dist/foundations/stripe-webhook/services/stripe-webhook-notification.service.js +124 -2
  147. package/dist/foundations/stripe-webhook/services/stripe-webhook-notification.service.js.map +1 -1
  148. package/dist/foundations/stripe-webhook/stripe-webhook.module.d.ts.map +1 -1
  149. package/dist/foundations/stripe-webhook/stripe-webhook.module.js +2 -0
  150. package/dist/foundations/stripe-webhook/stripe-webhook.module.js.map +1 -1
  151. package/dist/foundations/tokenusage/entities/tokenusage.entity.d.ts +1 -1
  152. package/dist/foundations/tokenusage/entities/tokenusage.entity.d.ts.map +1 -1
  153. package/dist/foundations/user/controllers/user.controller.d.ts +1 -1
  154. package/dist/foundations/user/controllers/user.controller.d.ts.map +1 -1
  155. package/dist/foundations/user/entities/user.d.ts +124 -0
  156. package/dist/foundations/user/entities/user.d.ts.map +1 -0
  157. package/dist/foundations/user/entities/user.js +81 -0
  158. package/dist/foundations/user/entities/user.js.map +1 -0
  159. package/dist/foundations/user/entities/user.meta.d.ts +1 -1
  160. package/dist/foundations/user/entities/user.meta.d.ts.map +1 -1
  161. package/dist/foundations/user/index.d.ts +1 -4
  162. package/dist/foundations/user/index.d.ts.map +1 -1
  163. package/dist/foundations/user/index.js +6 -23
  164. package/dist/foundations/user/index.js.map +1 -1
  165. package/dist/foundations/user/repositories/user.repository.d.ts +13 -1
  166. package/dist/foundations/user/repositories/user.repository.d.ts.map +1 -1
  167. package/dist/foundations/user/repositories/user.repository.js +85 -21
  168. package/dist/foundations/user/repositories/user.repository.js.map +1 -1
  169. package/dist/foundations/user/services/user.service.d.ts.map +1 -1
  170. package/dist/foundations/user/services/user.service.js +12 -12
  171. package/dist/foundations/user/services/user.service.js.map +1 -1
  172. package/dist/foundations/user/user.module.d.ts.map +1 -1
  173. package/dist/foundations/user/user.module.js +7 -8
  174. package/dist/foundations/user/user.module.js.map +1 -1
  175. package/dist/openapi/factories/entity-schema.factory.js +12 -0
  176. package/dist/openapi/factories/entity-schema.factory.js.map +1 -1
  177. package/dist/openapi/schemas/jsonapi-base.schemas.d.ts +1 -0
  178. package/dist/openapi/schemas/jsonapi-base.schemas.d.ts.map +1 -1
  179. package/dist/openapi/schemas/jsonapi-base.schemas.js.map +1 -1
  180. package/dist/tools/migrate-entity/__tests__/ast-parser.spec.js +331 -0
  181. package/dist/tools/migrate-entity/__tests__/descriptor-generator.spec.js +482 -0
  182. package/dist/tools/migrate-entity/__tests__/file-discovery.spec.js +190 -0
  183. package/dist/tools/migrate-entity/__tests__/integration.spec.js +261 -0
  184. package/dist/tools/migrate-entity/index.js +2 -2
  185. package/dist/tools/migrate-entity/lib/ast-parser.js +255 -10
  186. package/dist/tools/migrate-entity/lib/descriptor-generator.js +384 -55
  187. package/dist/tools/migrate-entity/lib/entity-migrator.js +112 -9
  188. package/dist/tools/migrate-entity/lib/module-updater.js +25 -9
  189. package/dist/tools/migrate-entity/lib/reference-updater.js +110 -24
  190. package/package.json +2 -2
  191. package/dist/foundations/company/entities/company.entity.d.ts +0 -18
  192. package/dist/foundations/company/entities/company.entity.d.ts.map +0 -1
  193. package/dist/foundations/company/entities/company.entity.js +0 -3
  194. package/dist/foundations/company/entities/company.entity.js.map +0 -1
  195. package/dist/foundations/company/entities/company.map.d.ts +0 -8
  196. package/dist/foundations/company/entities/company.map.d.ts.map +0 -1
  197. package/dist/foundations/company/entities/company.map.js +0 -23
  198. package/dist/foundations/company/entities/company.map.js.map +0 -1
  199. package/dist/foundations/company/entities/company.model.d.ts +0 -4
  200. package/dist/foundations/company/entities/company.model.d.ts.map +0 -1
  201. package/dist/foundations/company/entities/company.model.js +0 -17
  202. package/dist/foundations/company/entities/company.model.js.map +0 -1
  203. package/dist/foundations/company/serialisers/company.serialiser.d.ts +0 -14
  204. package/dist/foundations/company/serialisers/company.serialiser.d.ts.map +0 -1
  205. package/dist/foundations/company/serialisers/company.serialiser.js +0 -76
  206. package/dist/foundations/company/serialisers/company.serialiser.js.map +0 -1
  207. package/dist/foundations/role/entities/role.entity.d.ts +0 -9
  208. package/dist/foundations/role/entities/role.entity.d.ts.map +0 -1
  209. package/dist/foundations/role/entities/role.entity.js +0 -3
  210. package/dist/foundations/role/entities/role.entity.js.map +0 -1
  211. package/dist/foundations/role/entities/role.map.d.ts +0 -8
  212. package/dist/foundations/role/entities/role.map.d.ts.map +0 -1
  213. package/dist/foundations/role/entities/role.map.js +0 -15
  214. package/dist/foundations/role/entities/role.map.js.map +0 -1
  215. package/dist/foundations/role/entities/role.model.d.ts +0 -4
  216. package/dist/foundations/role/entities/role.model.d.ts.map +0 -1
  217. package/dist/foundations/role/entities/role.model.js +0 -15
  218. package/dist/foundations/role/entities/role.model.js.map +0 -1
  219. package/dist/foundations/role/serialisers/role.serialiser.d.ts +0 -12
  220. package/dist/foundations/role/serialisers/role.serialiser.d.ts.map +0 -1
  221. package/dist/foundations/role/serialisers/role.serialiser.js +0 -46
  222. package/dist/foundations/role/serialisers/role.serialiser.js.map +0 -1
  223. package/dist/foundations/user/entities/user.entity.d.ts +0 -26
  224. package/dist/foundations/user/entities/user.entity.d.ts.map +0 -1
  225. package/dist/foundations/user/entities/user.entity.js +0 -3
  226. package/dist/foundations/user/entities/user.entity.js.map +0 -1
  227. package/dist/foundations/user/entities/user.map.d.ts +0 -8
  228. package/dist/foundations/user/entities/user.map.d.ts.map +0 -1
  229. package/dist/foundations/user/entities/user.map.js +0 -27
  230. package/dist/foundations/user/entities/user.map.js.map +0 -1
  231. package/dist/foundations/user/entities/user.model.d.ts +0 -7
  232. package/dist/foundations/user/entities/user.model.d.ts.map +0 -1
  233. package/dist/foundations/user/entities/user.model.js +0 -30
  234. package/dist/foundations/user/entities/user.model.js.map +0 -1
  235. package/dist/foundations/user/serialisers/user.serialiser.d.ts +0 -14
  236. package/dist/foundations/user/serialisers/user.serialiser.d.ts.map +0 -1
  237. package/dist/foundations/user/serialisers/user.serialiser.js +0 -80
  238. package/dist/foundations/user/serialisers/user.serialiser.js.map +0 -1
@@ -44,6 +44,7 @@ exports.parseMetaFile = parseMetaFile;
44
44
  exports.parseEntityFile = parseEntityFile;
45
45
  exports.parseMapFile = parseMapFile;
46
46
  exports.parseSerialiserFile = parseSerialiserFile;
47
+ exports.parseAliasModels = parseAliasModels;
47
48
  exports.parseCypherRelationships = parseCypherRelationships;
48
49
  exports.findAndParseCypherRelationships = findAndParseCypherRelationships;
49
50
  exports.detectCypherServiceWarnings = detectCypherServiceWarnings;
@@ -56,7 +57,8 @@ function parseOldFiles(files) {
56
57
  const entityType = files.entity ? parseEntityFile(files.entity) : createEmptyEntityType(meta.labelName);
57
58
  const mapper = files.map ? parseMapFile(files.map) : null;
58
59
  const serialiser = files.serialiser ? parseSerialiserFile(files.serialiser) : null;
59
- return { meta, entityType, mapper, serialiser };
60
+ const aliasModels = files.model ? parseAliasModels(files.model, meta.labelName) : [];
61
+ return { meta, entityType, mapper, serialiser, aliasModels };
60
62
  }
61
63
  /**
62
64
  * Parses the meta.ts file to extract type, endpoint, nodeName, labelName.
@@ -112,7 +114,7 @@ function parseMapFile(filePath) {
112
114
  return { fields, imports };
113
115
  }
114
116
  /**
115
- * Parses the serialiser.ts file to extract attributes, meta, and relationships.
117
+ * Parses the serialiser.ts file to extract attributes, meta, relationships, services, and custom methods.
116
118
  */
117
119
  function parseSerialiserFile(filePath) {
118
120
  const content = fs.readFileSync(filePath, "utf-8");
@@ -120,7 +122,11 @@ function parseSerialiserFile(filePath) {
120
122
  const meta = extractSerialiserMeta(content);
121
123
  const relationships = extractSerialiserRelationships(content);
122
124
  const imports = extractImports(content);
123
- return { attributes, meta, relationships, imports };
125
+ const services = extractSerialiserServices(content);
126
+ const customMethods = extractSerialiserCustomMethods(content);
127
+ // Detect S3 transforms by parsing function-based attributes that use S3Service
128
+ const s3Transforms = detectS3Transforms(content);
129
+ return { attributes, meta, relationships, imports, services, customMethods, s3Transforms };
124
130
  }
125
131
  /**
126
132
  * Extracts type fields from entity type definition.
@@ -189,23 +195,56 @@ function extractImports(content) {
189
195
  }
190
196
  /**
191
197
  * Extracts serialiser attributes from this.attributes = {...}.
198
+ * Handles both simple string mappings and function-based computed attributes.
192
199
  */
193
200
  function extractSerialiserAttributes(content) {
194
201
  const attributes = [];
195
- // Match: this.attributes = { name: "name", content: "content", ... }
196
- const attrMatch = content.match(/this\.attributes\s*=\s*\{([^}]+)\}/s);
197
- if (!attrMatch)
202
+ // Find the start of this.attributes = {
203
+ const attrStart = content.indexOf("this.attributes");
204
+ if (attrStart === -1)
198
205
  return attributes;
199
- const attrBlock = attrMatch[1];
200
- const fieldPattern = /(\w+):\s*["'](\w+)["']/g;
206
+ // Find the opening brace
207
+ const braceStart = content.indexOf("{", attrStart);
208
+ if (braceStart === -1)
209
+ return attributes;
210
+ // Find matching closing brace (handle nested braces)
211
+ let depth = 1;
212
+ let i = braceStart + 1;
213
+ while (i < content.length && depth > 0) {
214
+ if (content[i] === "{")
215
+ depth++;
216
+ else if (content[i] === "}")
217
+ depth--;
218
+ i++;
219
+ }
220
+ const attrBlock = content.substring(braceStart + 1, i - 1);
221
+ // Match simple string mappings: name: "name", or name: 'name',
222
+ const simplePattern = /(\w+):\s*["'](\w+)["']/g;
201
223
  let match;
202
- while ((match = fieldPattern.exec(attrBlock)) !== null) {
224
+ while ((match = simplePattern.exec(attrBlock)) !== null) {
203
225
  attributes.push({
204
226
  name: match[1],
205
227
  mapping: match[2],
206
228
  isMeta: false,
207
229
  });
208
230
  }
231
+ // Match function-based computed attributes (arrow functions that return data properties)
232
+ // Pattern: fieldName: (data: Type) => { ... return data.property; }
233
+ // Or: fieldName: (data: Type) => data.property
234
+ const funcPattern = /(\w+):\s*(?:async\s+)?\([^)]*\)\s*=>\s*(?:\{[^}]*return\s+(?:data\.)?(\w+)[^}]*\}|(?:data\.)?(\w+))/g;
235
+ while ((match = funcPattern.exec(attrBlock)) !== null) {
236
+ const fieldName = match[1];
237
+ // Skip if already added as simple mapping
238
+ if (attributes.some((a) => a.name === fieldName))
239
+ continue;
240
+ // The mapping is either from the function body return or simple arrow return
241
+ const mapping = match[2] || match[3] || fieldName;
242
+ attributes.push({
243
+ name: fieldName,
244
+ mapping: mapping,
245
+ isMeta: false,
246
+ });
247
+ }
209
248
  return attributes;
210
249
  }
211
250
  /**
@@ -251,12 +290,164 @@ function extractSerialiserRelationships(content) {
251
290
  const dtoKeyMatch = block.match(/name:\s*[`"'](\w+)[`"']/);
252
291
  const dtoKey = dtoKeyMatch ? dtoKeyMatch[1] : undefined;
253
292
  // Extract model from this.serialiserFactory.create(UserModel)
254
- const modelMatch = block.match(/this\.serialiserFactory\.create\((\w+)\)/);
293
+ // Also handles already-migrated entities: this.serialiserFactory.create(CompanyDescriptor.model)
294
+ const modelMatch = block.match(/this\.serialiserFactory\.create\((\w+)(?:\.model)?\)/);
255
295
  const modelImport = modelMatch ? modelMatch[1] : "";
256
296
  relationships.push({ name, dtoKey, modelImport });
257
297
  }
258
298
  return relationships;
259
299
  }
300
+ /**
301
+ * Extracts injected services from the serialiser constructor.
302
+ * Matches patterns like: private readonly s3Service: S3Service
303
+ */
304
+ function extractSerialiserServices(content) {
305
+ const services = [];
306
+ // Match: private readonly xxxService: XxxService (but not SerialiserFactory)
307
+ const pattern = /private\s+readonly\s+\w+:\s+(\w+Service)/g;
308
+ let match;
309
+ while ((match = pattern.exec(content)) !== null) {
310
+ const serviceName = match[1];
311
+ // Skip SerialiserFactory - it's framework infrastructure, not app service
312
+ if (serviceName !== "SerialiserFactory") {
313
+ services.push(serviceName);
314
+ }
315
+ }
316
+ return services;
317
+ }
318
+ /**
319
+ * Extracts custom method names from the serialiser class.
320
+ * These methods may contain transform logic that needs manual migration.
321
+ */
322
+ function extractSerialiserCustomMethods(content) {
323
+ const customMethods = [];
324
+ // Match method definitions: async methodName(...) or methodName(...)
325
+ // Skip constructor, standard lifecycle methods, and standard serialiser methods
326
+ const methodPattern = /(?:async\s+)?(\w+)\s*\([^)]*\)\s*(?::\s*[^{]+)?\s*\{/g;
327
+ const standardMethods = new Set([
328
+ "constructor",
329
+ "onModuleInit",
330
+ "onModuleDestroy",
331
+ // Standard serialiser methods from AbstractJsonApiSerialiser
332
+ "type",
333
+ "create",
334
+ "endpoint",
335
+ "endpointParameters",
336
+ "id",
337
+ "attributes",
338
+ "meta",
339
+ "links",
340
+ "relationships",
341
+ ]);
342
+ let match;
343
+ while ((match = methodPattern.exec(content)) !== null) {
344
+ const methodName = match[1];
345
+ if (!standardMethods.has(methodName)) {
346
+ customMethods.push(methodName);
347
+ }
348
+ }
349
+ return customMethods;
350
+ }
351
+ /**
352
+ * Detects S3 transforms by parsing function-based attributes that use S3Service.
353
+ *
354
+ * Looks for patterns like:
355
+ * ```typescript
356
+ * avatar: async (data: User) => {
357
+ * return await this.s3Service.generateSignedUrl({ key: data.avatar });
358
+ * }
359
+ * ```
360
+ *
361
+ * Also detects array transforms using Promise.all with map.
362
+ */
363
+ function detectS3Transforms(content) {
364
+ const transforms = [];
365
+ // Find the this.attributes = { ... } block
366
+ const attrStart = content.indexOf("this.attributes");
367
+ if (attrStart === -1)
368
+ return transforms;
369
+ const braceStart = content.indexOf("{", attrStart);
370
+ if (braceStart === -1)
371
+ return transforms;
372
+ // Find matching closing brace (handle nested braces)
373
+ let depth = 1;
374
+ let i = braceStart + 1;
375
+ while (i < content.length && depth > 0) {
376
+ if (content[i] === "{")
377
+ depth++;
378
+ else if (content[i] === "}")
379
+ depth--;
380
+ i++;
381
+ }
382
+ const attrBlock = content.substring(braceStart + 1, i - 1);
383
+ // Find function-based attributes that use s3Service.generateSignedUrl
384
+ // Pattern: fieldName: async (data) => { ... s3Service.generateSignedUrl ... }
385
+ // We need to match the field name and check if the function body uses S3
386
+ // Split by top-level commas to get individual attribute definitions
387
+ const attrDefs = splitAttributeDefinitions(attrBlock);
388
+ for (const def of attrDefs) {
389
+ // Check if this definition uses s3Service.generateSignedUrl
390
+ if (!def.includes("s3Service") && !def.includes("generateSignedUrl")) {
391
+ continue;
392
+ }
393
+ // Extract field name (first identifier before the colon)
394
+ const fieldNameMatch = def.match(/^\s*(\w+)\s*:/);
395
+ if (!fieldNameMatch)
396
+ continue;
397
+ const fieldName = fieldNameMatch[1];
398
+ // Check if it's an array transform (uses Promise.all or .map)
399
+ const isArray = def.includes("Promise.all") || def.includes(".map(");
400
+ transforms.push({ fieldName, isArray });
401
+ }
402
+ return transforms;
403
+ }
404
+ /**
405
+ * Splits the attributes block into individual attribute definitions,
406
+ * respecting nested braces and arrow functions.
407
+ */
408
+ function splitAttributeDefinitions(attrBlock) {
409
+ const definitions = [];
410
+ let current = "";
411
+ let depth = 0;
412
+ let inString = false;
413
+ let stringChar = "";
414
+ for (let i = 0; i < attrBlock.length; i++) {
415
+ const char = attrBlock[i];
416
+ const prevChar = i > 0 ? attrBlock[i - 1] : "";
417
+ // Track string state
418
+ if ((char === '"' || char === "'" || char === "`") && prevChar !== "\\") {
419
+ if (!inString) {
420
+ inString = true;
421
+ stringChar = char;
422
+ }
423
+ else if (char === stringChar) {
424
+ inString = false;
425
+ }
426
+ }
427
+ if (!inString) {
428
+ if (char === "{" || char === "(" || char === "[") {
429
+ depth++;
430
+ }
431
+ else if (char === "}" || char === ")" || char === "]") {
432
+ depth--;
433
+ }
434
+ else if (char === "," && depth === 0) {
435
+ // Top-level comma - end of attribute definition
436
+ if (current.trim()) {
437
+ definitions.push(current.trim());
438
+ }
439
+ current = "";
440
+ continue;
441
+ }
442
+ }
443
+ current += char;
444
+ }
445
+ // Add the last definition
446
+ if (current.trim()) {
447
+ definitions.push(current.trim());
448
+ }
449
+ return definitions;
450
+ }
260
451
  /**
261
452
  * Creates an empty entity type when entity file doesn't exist.
262
453
  */
@@ -268,6 +459,60 @@ function createEmptyEntityType(labelName) {
268
459
  imports: [],
269
460
  };
270
461
  }
462
+ /**
463
+ * Parses alias models from the model file.
464
+ *
465
+ * Alias models are additional model exports that spread from the base model
466
+ * but use a different meta. Example:
467
+ *
468
+ * ```typescript
469
+ * export const UserModel: DataModelInterface<User> = {
470
+ * ...userMeta,
471
+ * // ...
472
+ * };
473
+ *
474
+ * export const OwnerModel: DataModelInterface<User> = {
475
+ * ...UserModel,
476
+ * ...ownerMeta,
477
+ * };
478
+ * ```
479
+ *
480
+ * @param filePath Path to the model file
481
+ * @param baseLabelName The label name of the base model (e.g., "User")
482
+ * @returns Array of alias model info
483
+ */
484
+ function parseAliasModels(filePath, baseLabelName) {
485
+ if (!fs.existsSync(filePath)) {
486
+ return [];
487
+ }
488
+ const content = fs.readFileSync(filePath, "utf-8");
489
+ const aliasModels = [];
490
+ // Pattern to match alias model definitions:
491
+ // export const XxxModel: DataModelInterface<Entity> = {
492
+ // ...BaseModel,
493
+ // ...xxxMeta,
494
+ // };
495
+ // Note: Alias models spread from the base model AND override with their own meta
496
+ const aliasPattern = /export\s+const\s+(\w+Model)\s*:\s*DataModelInterface<\w+>\s*=\s*\{[^}]*\.\.\.(\w+Model)[^}]*\.\.\.(\w+Meta)[^}]*\}/gs;
497
+ let match;
498
+ while ((match = aliasPattern.exec(content)) !== null) {
499
+ const modelName = match[1];
500
+ const baseModel = match[2];
501
+ const metaName = match[3];
502
+ // Skip the base model itself (it doesn't spread from another model)
503
+ // Only include models that spread from the base model
504
+ if (baseModel === `${baseLabelName}Model`) {
505
+ // Derive descriptor name from model name: OwnerModel -> OwnerDescriptor
506
+ const descriptorName = modelName.replace(/Model$/, "Descriptor");
507
+ aliasModels.push({
508
+ modelName,
509
+ metaName,
510
+ descriptorName,
511
+ });
512
+ }
513
+ }
514
+ return aliasModels;
515
+ }
271
516
  /**
272
517
  * Parses Cypher MATCH patterns from a repository or cypher.service file
273
518
  * to extract actual relationship types and directions.