@apso/cli 0.0.45 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -74,42 +74,57 @@ export class <%= it.name %> {
74
74
 
75
75
  // Associations
76
76
  <% it.associations.forEach((assoc) => { %>
77
+
78
+ <%// Generate property ONLY based on referenceName (to_name) %>
79
+ <%// relationshipName is the camelCased version of referenceName %>
80
+ <%// pluralizedRelationshipName is the pluralized version (for arrays) %>
81
+
77
82
  <% if (assoc.type === 'OneToMany') { %>
78
83
 
79
84
  @OneToMany(
80
85
  () => <%= assoc.name %>,
81
- <%= assoc.camelCasedName %> => <%= assoc.camelCasedName %>.<%= assoc.entityName %>
86
+ <%= assoc.camelCasedName %> => <%= assoc.camelCasedName %>.<%= assoc.inverseSidePropertyName %>
82
87
  )
83
- <%= assoc.pluralizedName %>: <%= assoc.name %>[]
84
-
88
+ <%= assoc.pluralizedRelationshipName %>: <%= assoc.name %>[];
89
+
85
90
  <% } else if (assoc.type === 'ManyToOne') { %>
86
91
  <% if (assoc.index) { %>
87
92
  @Index()
88
93
  <% } %>
89
- @ManyToOne(() => <%= assoc.name %><% if (assoc.biDirectional) { %>, <%= assoc.camelCasedName %> => <%= assoc.camelCasedName %>.<%= it.pluralizedName %><% } %><% if (assoc.cascadeDelete) { %>, { onDelete: "CASCADE" }<% } %>)
94
+ @ManyToOne(() => <%= assoc.name %><% if (assoc.biDirectional) { %>, <%= assoc.camelCasedName %> => <%= assoc.camelCasedName %>.<%= assoc.inverseSidePropertyName %><% } %><% if (assoc.cascadeDelete) { %>, { onDelete: "CASCADE" }<% } %>)
90
95
  @JoinColumn({ name: '<%= assoc.camelCasedId %>' })
91
- <%= assoc.relationshipName %>: <%= assoc.name %>
96
+ <%= assoc.relationshipName %>: <%= assoc.name %>;
92
97
 
93
98
  @Column({ type: "integer", <% if (assoc.nullable) { %> nullable: true <% } %>})
94
99
  <%= assoc.camelCasedId %>: number;
95
-
100
+
96
101
  <% } else if (assoc.type === 'ManyToMany') { %>
97
-
98
- @ManyToMany(() => <%= assoc.name %><% if (assoc.biDirectional) { %>, <%= assoc.camelCasedName %> => <%= assoc.camelCasedName %>.<%= it.pluralizedName %><% } %>)
99
- <% if (assoc.joinTable) { %>@JoinTable()<% } %>
100
- <%= assoc.pluralizedRelationshipName %>: <%= assoc.name %>[]
101
-
102
+
103
+ @ManyToMany(() => <%= assoc.name %><% if (assoc.biDirectional) { %>, <%= assoc.camelCasedName %> => <%= assoc.camelCasedName %>.<%= assoc.inverseSidePropertyName %><% } %>)
104
+ <% if (assoc.joinTable) { %>
105
+ @JoinTable(<%
106
+ let joinTableArgs = [];
107
+ if (assoc.joinTableName) { joinTableArgs.push(`name: '${assoc.joinTableName}'`); }
108
+ if (assoc.joinColumnName) { joinTableArgs.push(`joinColumn: { name: '${assoc.joinColumnName}', referencedColumnName: 'id' }`); }
109
+ if (assoc.inverseJoinColumnName) { joinTableArgs.push(`inverseJoinColumn: { name: '${assoc.inverseJoinColumnName}', referencedColumnName: 'id' }`); }
110
+ if (joinTableArgs.length > 0) {
111
+ %>{
112
+ <%~ joinTableArgs.join(',\n ') %>
113
+ }<% } %>)
114
+ <% } %>
115
+ <%= assoc.pluralizedRelationshipName %>: <%= assoc.name %>[];
116
+
102
117
  <% } else if (assoc.type === 'OneToOne') { %>
103
-
118
+
104
119
  @OneToOne(
105
120
  (type: any) => <%= assoc.name%>,
106
- <% if (assoc.biDirectional) { %>(p) => p.<%= assoc.entityName %>,<% } %>
121
+ <% if (assoc.biDirectional) { %>(<%= assoc.camelCasedName %>) => <%= assoc.camelCasedName %>.<%= assoc.inverseSidePropertyName %>,<% } %>
107
122
  {
108
123
  onDelete: "CASCADE",
109
124
  cascade: ["insert", "update"],
110
125
  })
111
- @JoinColumn()
112
- <%= assoc.relationshipName %>: <%= assoc.name %>
126
+ <% if (assoc.joinTable) { %>@JoinColumn()<% } %>
127
+ <%= assoc.relationshipName %>: <%= assoc.name %>;
113
128
 
114
129
  <% } %>
115
130
  <% }) %>
@@ -25,6 +25,7 @@ import {<%= it.svcName %>} from './<%= it.entityName %>.service';
25
25
  <% if (it.associations.length) { %>
26
26
  join: {
27
27
  <% it.associations.forEach((assoc) => { %>
28
+ <% /* Removed check: relying on distinct pluralizedRelationshipName */ %>
28
29
  <% if (assoc.type === 'OneToMany') { %>
29
30
  <%= assoc.pluralizedRelationshipName %>: { eager: false },
30
31
  <% } else if (assoc.type === 'ManyToOne') { %>
@@ -0,0 +1,38 @@
1
+ import { Test, TestingModule } from '@nestjs/testing';
2
+ import { <%= it.svcName %> } from './<%= it.entityName %>.service';
3
+ import { getRepositoryToken } from '@nestjs/typeorm';
4
+ import { <%= it.entityName %> } from './<%= it.entityName %>.entity';
5
+
6
+ describe('<%= it.svcName %>', () => {
7
+ let service: <%= it.svcName %>;
8
+ let mockRepository: any;
9
+
10
+ beforeEach(async () => {
11
+ mockRepository = {
12
+ find: jest.fn().mockResolvedValue([]),
13
+ findOne: jest.fn().mockResolvedValue({}),
14
+ save: jest.fn().mockResolvedValue({}),
15
+ create: jest.fn().mockReturnValue({}),
16
+ update: jest.fn().mockResolvedValue({}),
17
+ delete: jest.fn().mockResolvedValue({}),
18
+ };
19
+
20
+ const module: TestingModule = await Test.createTestingModule({
21
+ providers: [
22
+ <%= it.svcName %>,
23
+ {
24
+ provide: getRepositoryToken(<%= it.entityName %>),
25
+ useValue: mockRepository,
26
+ },
27
+ ],
28
+ }).compile();
29
+
30
+ service = module.get<<%= it.svcName %>>(<%= it.svcName %>);
31
+ });
32
+
33
+ it('should be defined', () => {
34
+ expect(service).toBeDefined();
35
+ });
36
+
37
+ // Add more tests as needed
38
+ });
@@ -8,6 +8,9 @@ export interface ApsorcRelationship {
8
8
  bi_directional?: boolean;
9
9
  cascadeDelete?: boolean;
10
10
  index?: boolean;
11
+ joinTableName?: string;
12
+ joinColumnName?: string;
13
+ inverseJoinColumnName?: string;
11
14
  }
12
15
  export interface Relationship {
13
16
  name: string;
@@ -18,6 +21,10 @@ export interface Relationship {
18
21
  biDirectional?: boolean;
19
22
  cascadeDelete?: boolean;
20
23
  index?: boolean;
24
+ joinTableName?: string;
25
+ joinColumnName?: string;
26
+ inverseJoinColumnName?: string;
27
+ inverseReferenceName?: string;
21
28
  }
22
29
  export interface RelationshipForTemplate extends Relationship {
23
30
  relationshipName: string;
@@ -28,6 +35,7 @@ export interface RelationshipForTemplate extends Relationship {
28
35
  entityName: string;
29
36
  joinTable: boolean;
30
37
  biDirectional: boolean;
38
+ inversePropertyName?: string;
31
39
  }
32
40
  export type RelationshipMap = {
33
41
  [key: string]: Relationship[];
@@ -63,17 +63,23 @@ const convertAssociationToRelationship = (entityName, association, entities) =>
63
63
  };
64
64
  const parseV1Relationships = (entities) => {
65
65
  const relationshipMap = {};
66
+ // First, convert all v1 associations to the v2 ApsorcRelationship format
67
+ const apsorcRelationships = [];
66
68
  for (const entity of entities) {
67
- if (!entity.associations) {
68
- continue;
69
- }
70
- for (const association of entity.associations) {
71
- const apsorcRelationship = convertAssociationToRelationship(entity.name, association, entities);
72
- if (apsorcRelationship === null) {
73
- continue;
69
+ if (entity.associations) {
70
+ for (const association of entity.associations) {
71
+ const convertedRel = convertAssociationToRelationship(entity.name, association, entities);
72
+ if (convertedRel) {
73
+ apsorcRelationships.push(convertedRel);
74
+ }
74
75
  }
75
- const parsedResult = (0, parse_1.parseRelationship)(apsorcRelationship);
76
- for (const key of Object.keys(parsedResult)) {
76
+ }
77
+ }
78
+ // Now, process each converted relationship, passing the full list
79
+ for (const apsorcRelationship of apsorcRelationships) {
80
+ const parsedResult = (0, parse_1.parseRelationship)(apsorcRelationship, apsorcRelationships);
81
+ for (const key of Object.keys(parsedResult)) {
82
+ if (parsedResult[key] && parsedResult[key].length > 0) { // Ensure non-empty result
77
83
  relationshipMap[key] = [
78
84
  ...(relationshipMap[key] || []),
79
85
  ...parsedResult[key],
@@ -1,11 +1,55 @@
1
1
  import { ApsorcRelationship, Relationship, RelationshipMap, RelationshipForTemplate } from "../../types";
2
+ /**
3
+ * Parses a OneToMany relationship definition.
4
+ * These are treated as bidirectional from the .apsorc definition.
5
+ * Only generates the configuration for the 'from' side.
6
+ * @param relationship The .apsorc relationship definition.
7
+ * @returns A RelationshipMap containing only the entry for the 'from' side.
8
+ */
2
9
  export declare const parseOneToMany: (relationship: ApsorcRelationship) => RelationshipMap;
10
+ /**
11
+ * Parses a ManyToOne relationship definition.
12
+ * These are treated as unidirectional from the .apsorc definition.
13
+ * Only generates the configuration for the 'from' side.
14
+ * @param relationship The .apsorc relationship definition.
15
+ * @returns A RelationshipMap containing only the entry for the 'from' side.
16
+ */
3
17
  export declare const parseManytoOne: (relationship: ApsorcRelationship) => RelationshipMap;
4
- export declare const parseManyToMany: (relationship: ApsorcRelationship) => RelationshipMap;
5
- export declare const parseOneToOne: (relationship: ApsorcRelationship) => RelationshipMap;
6
- export declare const parseRelationship: (relationship: ApsorcRelationship) => RelationshipMap;
18
+ /**
19
+ * Parses a ManyToMany relationship definition.
20
+ * Determines bidirectionality based on flags and inverse definitions.
21
+ * Determines the owning side (which gets the @JoinTable decorator).
22
+ * Calculates reference names (property names), defaulting if 'to_name' is missing.
23
+ * If bidirectional, generates configuration for both 'from' and 'to' sides.
24
+ * @param relationship The .apsorc relationship definition.
25
+ * @param allRelationships The full list of relationship definitions for finding inverses.
26
+ * @returns A RelationshipMap containing entries for one or both sides.
27
+ */
28
+ export declare const parseManyToMany: (relationship: ApsorcRelationship, allRelationships: ApsorcRelationship[]) => RelationshipMap;
29
+ /**
30
+ * Parses a single relationship definition from .apsorc.
31
+ * Dispatches to the appropriate type-specific parser (parseManyToMany, parseOneToMany, etc.).
32
+ * For bidirectional relationships, the type-specific parsers handle generating data for both sides.
33
+ * @param relationship The single .apsorc relationship definition to parse.
34
+ * @param allRelationships The full list of relationship definitions (needed for context, e.g., finding inverses).
35
+ * @returns A RelationshipMap, potentially containing entries for both entities involved in the relationship.
36
+ */
37
+ export declare const parseRelationship: (relationship: ApsorcRelationship, allRelationships: ApsorcRelationship[]) => RelationshipMap;
38
+ /**
39
+ * Parses the entire array of relationship definitions from the .apsorc file.
40
+ * Iterates through each definition, calls parseRelationship, and merges the results.
41
+ * @param relationships The array of relationship definitions from .apsorc.
42
+ * @returns A comprehensive RelationshipMap mapping entity names to their Relationship objects.
43
+ */
7
44
  export declare const parseRelationships: (relationships: ApsorcRelationship[]) => RelationshipMap;
8
45
  export declare const getRelationshipIdField: (relationship: Relationship) => string;
46
+ /**
47
+ * Transforms the parsed Relationship data into the final format needed by the entity/controller templates.
48
+ * Calculates additional helper properties like pluralized names and inverse property names.
49
+ * @param entityName The name of the entity for which to generate template data.
50
+ * @param relationships An array of Relationship objects for the given entity.
51
+ * @returns An array of RelationshipForTemplate objects with extra properties for the template.
52
+ */
9
53
  export declare const getRelationshipForTemplate: (entityName: string, relationships: Relationship[]) => RelationshipForTemplate[];
10
54
  export declare const getNestedRelationships: (entityName: string, relationshipMap: RelationshipMap, prefix?: string, visited?: Set<string>) => string[];
11
55
  export declare const getRelationshipsForImport: (entityName: string, relationships?: Relationship[]) => string[];