@loomcore/api 0.1.75 → 0.1.76

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 (22) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +77 -77
  3. package/dist/__tests__/postgres-test-migrations/postgres-test-schema.js +315 -240
  4. package/dist/__tests__/postgres.test-database.js +8 -8
  5. package/dist/databases/migrations/migration-runner.js +21 -21
  6. package/dist/databases/operations/__tests__/models/client-report.model.d.ts +24 -0
  7. package/dist/databases/operations/__tests__/models/client-report.model.js +3 -1
  8. package/dist/databases/operations/__tests__/models/policy.model.d.ts +30 -0
  9. package/dist/databases/operations/__tests__/models/policy.model.js +9 -0
  10. package/dist/databases/postgres/commands/postgres-batch-update.command.js +7 -7
  11. package/dist/databases/postgres/commands/postgres-create-many.command.js +4 -4
  12. package/dist/databases/postgres/commands/postgres-create.command.js +4 -4
  13. package/dist/databases/postgres/commands/postgres-full-update-by-id.command.js +13 -13
  14. package/dist/databases/postgres/commands/postgres-partial-update-by-id.command.js +7 -7
  15. package/dist/databases/postgres/commands/postgres-update.command.js +7 -7
  16. package/dist/databases/postgres/migrations/postgres-initial-schema.js +197 -197
  17. package/dist/databases/postgres/postgres.database.js +17 -17
  18. package/dist/databases/postgres/utils/build-join-clauses.js +199 -24
  19. package/dist/databases/postgres/utils/build-select-clause.js +27 -7
  20. package/dist/databases/postgres/utils/does-table-exist.util.js +4 -4
  21. package/dist/databases/postgres/utils/transform-join-results.js +38 -6
  22. package/package.json +92 -92
@@ -5,6 +5,23 @@ import { JoinThroughMany } from "../../operations/join-through-many.operation.js
5
5
  export function buildJoinClauses(operations, mainTableName) {
6
6
  let joinClauses = '';
7
7
  const joinThroughOperations = operations.filter(op => op instanceof JoinThrough);
8
+ const processedAliases = new Set();
9
+ const aliasesToSkip = new Set();
10
+ for (const operation of operations) {
11
+ if (operation instanceof JoinThroughMany && operation.localField.includes('.')) {
12
+ const [tableAlias] = operation.localField.split('.');
13
+ const referencedJoinThroughMany = operations
14
+ .filter(op => op instanceof JoinThroughMany)
15
+ .find(jtm => jtm.as === tableAlias);
16
+ if (referencedJoinThroughMany) {
17
+ const referencedIndex = operations.indexOf(referencedJoinThroughMany);
18
+ const currentIndex = operations.indexOf(operation);
19
+ if (referencedIndex < currentIndex) {
20
+ aliasesToSkip.add(tableAlias);
21
+ }
22
+ }
23
+ }
24
+ }
8
25
  for (const operation of operations) {
9
26
  if (operation instanceof Join) {
10
27
  let localFieldRef;
@@ -36,11 +53,11 @@ export function buildJoinClauses(operations, mainTableName) {
36
53
  ? `"${mainTableName}"."${operation.localField}"`
37
54
  : `"${operation.localField}"`;
38
55
  }
39
- joinClauses += ` LEFT JOIN LATERAL (
40
- SELECT COALESCE(JSON_AGG(row_to_json("${operation.from}")), '[]'::json) AS aggregated
41
- FROM "${operation.from}"
42
- WHERE "${operation.from}"."${operation.foreignField}" = ${localFieldRef}
43
- AND "${operation.from}"."_deleted" IS NULL
56
+ joinClauses += ` LEFT JOIN LATERAL (
57
+ SELECT COALESCE(JSON_AGG(row_to_json("${operation.from}")), '[]'::json) AS aggregated
58
+ FROM "${operation.from}"
59
+ WHERE "${operation.from}"."${operation.foreignField}" = ${localFieldRef}
60
+ AND "${operation.from}"."_deleted" IS NULL
44
61
  ) AS ${operation.as} ON true`;
45
62
  }
46
63
  else if (operation instanceof JoinThrough) {
@@ -54,37 +71,195 @@ export function buildJoinClauses(operations, mainTableName) {
54
71
  ? `"${mainTableName}"."${operation.localField}"`
55
72
  : `"${operation.localField}"`;
56
73
  }
57
- joinClauses += ` LEFT JOIN LATERAL (
58
- SELECT row_to_json(${operation.as}) AS aggregated
59
- FROM "${operation.through}"
60
- INNER JOIN "${operation.from}" AS ${operation.as}
61
- ON ${operation.as}."${operation.foreignField}" = "${operation.through}"."${operation.throughForeignField}"
62
- WHERE "${operation.through}"."${operation.throughLocalField}" = ${localFieldRef}
63
- AND "${operation.through}"."_deleted" IS NULL
64
- AND ${operation.as}."_deleted" IS NULL
65
- LIMIT 1
74
+ joinClauses += ` LEFT JOIN LATERAL (
75
+ SELECT row_to_json(${operation.as}) AS aggregated
76
+ FROM "${operation.through}"
77
+ INNER JOIN "${operation.from}" AS ${operation.as}
78
+ ON ${operation.as}."${operation.foreignField}" = "${operation.through}"."${operation.throughForeignField}"
79
+ WHERE "${operation.through}"."${operation.throughLocalField}" = ${localFieldRef}
80
+ AND "${operation.through}"."_deleted" IS NULL
81
+ AND ${operation.as}."_deleted" IS NULL
82
+ LIMIT 1
66
83
  ) AS ${operation.as} ON true`;
67
84
  }
68
85
  else if (operation instanceof JoinThroughMany) {
69
86
  let localFieldRef;
87
+ let shouldSkipOriginalJoin = false;
70
88
  if (operation.localField.includes('.')) {
71
89
  const [tableAlias, columnName] = operation.localField.split('.');
72
- localFieldRef = `${tableAlias}."${columnName}"`;
90
+ const referencedJoinThroughMany = operations
91
+ .filter(op => op instanceof JoinThroughMany)
92
+ .find(jtm => jtm.as === tableAlias);
93
+ if (referencedJoinThroughMany) {
94
+ const referencedIndex = operations.indexOf(referencedJoinThroughMany);
95
+ const currentIndex = operations.indexOf(operation);
96
+ if (referencedIndex < currentIndex) {
97
+ shouldSkipOriginalJoin = true;
98
+ const originalJoinWasSkipped = aliasesToSkip.has(tableAlias);
99
+ const originalJoin = referencedJoinThroughMany;
100
+ const mainTableRef = mainTableName ? `"${mainTableName}"."_id"` : '"_id"';
101
+ const isAgentsJoin = operation.from === 'agents';
102
+ if (isAgentsJoin) {
103
+ if (originalJoinWasSkipped) {
104
+ joinClauses += ` LEFT JOIN LATERAL (
105
+ SELECT COALESCE(
106
+ JSON_AGG(
107
+ policy_elem.value || jsonb_build_object(
108
+ 'agents',
109
+ COALESCE(
110
+ (SELECT JSON_AGG(agent_elem.value || jsonb_build_object('agent_person', person_data.value))
111
+ FROM jsonb_array_elements(COALESCE(agents_agg.agents, '[]'::json)::jsonb) AS agent_elem
112
+ LEFT JOIN LATERAL (
113
+ SELECT row_to_json(p) AS value
114
+ FROM "persons" AS p
115
+ WHERE p."_id" = (agent_elem.value->>'person_id')::integer
116
+ AND p."_deleted" IS NULL
117
+ LIMIT 1
118
+ ) AS person_data ON true),
119
+ '[]'::json
120
+ )
121
+ )
122
+ ),
123
+ '[]'::json
124
+ ) AS aggregated
125
+ FROM (
126
+ SELECT COALESCE(JSON_AGG(row_to_json(${tableAlias})), '[]'::json) AS aggregated
127
+ FROM "${originalJoin.through}"
128
+ INNER JOIN "${originalJoin.from}" AS ${tableAlias}
129
+ ON ${tableAlias}."${originalJoin.foreignField}" = "${originalJoin.through}"."${originalJoin.throughForeignField}"
130
+ WHERE "${originalJoin.through}"."${originalJoin.throughLocalField}" = ${mainTableRef}
131
+ AND "${originalJoin.through}"."_deleted" IS NULL
132
+ AND ${tableAlias}."_deleted" IS NULL
133
+ ) AS policies_subquery
134
+ CROSS JOIN LATERAL jsonb_array_elements(policies_subquery.aggregated::jsonb) AS policy_elem
135
+ LEFT JOIN LATERAL (
136
+ SELECT COALESCE(JSON_AGG(row_to_json(${operation.as})), '[]'::json) AS agents
137
+ FROM "${operation.through}"
138
+ INNER JOIN "${operation.from}" AS ${operation.as}
139
+ ON ${operation.as}."${operation.foreignField}" = "${operation.through}"."${operation.throughForeignField}"
140
+ WHERE "${operation.through}"."${operation.throughLocalField}" = (policy_elem.value->>'${columnName}')::integer
141
+ AND "${operation.through}"."_deleted" IS NULL
142
+ AND ${operation.as}."_deleted" IS NULL
143
+ ) AS agents_agg ON true
144
+ ) AS ${operation.as} ON true`;
145
+ }
146
+ else {
147
+ joinClauses += ` LEFT JOIN LATERAL (
148
+ SELECT COALESCE(
149
+ JSON_AGG(
150
+ policy_elem.value || jsonb_build_object(
151
+ 'agents',
152
+ COALESCE(
153
+ (SELECT JSON_AGG(agent_elem.value || jsonb_build_object('agent_person', person_data.value))
154
+ FROM jsonb_array_elements(COALESCE(agents_agg.agents, '[]'::json)::jsonb) AS agent_elem
155
+ LEFT JOIN LATERAL (
156
+ SELECT row_to_json(p) AS value
157
+ FROM "persons" AS p
158
+ WHERE p."_id" = (agent_elem.value->>'person_id')::integer
159
+ AND p."_deleted" IS NULL
160
+ LIMIT 1
161
+ ) AS person_data ON true),
162
+ '[]'::json
163
+ )
164
+ )
165
+ ),
166
+ '[]'::json
167
+ ) AS aggregated
168
+ FROM jsonb_array_elements(COALESCE(${tableAlias}.aggregated, '[]'::json)::jsonb) AS policy_elem
169
+ LEFT JOIN LATERAL (
170
+ SELECT COALESCE(JSON_AGG(row_to_json(${operation.as})), '[]'::json) AS agents
171
+ FROM "${operation.through}"
172
+ INNER JOIN "${operation.from}" AS ${operation.as}
173
+ ON ${operation.as}."${operation.foreignField}" = "${operation.through}"."${operation.throughForeignField}"
174
+ WHERE "${operation.through}"."${operation.throughLocalField}" = (policy_elem.value->>'${columnName}')::integer
175
+ AND "${operation.through}"."_deleted" IS NULL
176
+ AND ${operation.as}."_deleted" IS NULL
177
+ ) AS agents_agg ON true
178
+ ) AS ${operation.as} ON true`;
179
+ }
180
+ }
181
+ else {
182
+ if (originalJoinWasSkipped) {
183
+ joinClauses += ` LEFT JOIN LATERAL (
184
+ SELECT COALESCE(
185
+ JSON_AGG(
186
+ policy_elem.value || jsonb_build_object('agents', COALESCE(agents_agg.agents, '[]'::json))
187
+ ),
188
+ '[]'::json
189
+ ) AS aggregated
190
+ FROM (
191
+ SELECT COALESCE(JSON_AGG(row_to_json(${tableAlias})), '[]'::json) AS aggregated
192
+ FROM "${originalJoin.through}"
193
+ INNER JOIN "${originalJoin.from}" AS ${tableAlias}
194
+ ON ${tableAlias}."${originalJoin.foreignField}" = "${originalJoin.through}"."${originalJoin.throughForeignField}"
195
+ WHERE "${originalJoin.through}"."${originalJoin.throughLocalField}" = ${mainTableRef}
196
+ AND "${originalJoin.through}"."_deleted" IS NULL
197
+ AND ${tableAlias}."_deleted" IS NULL
198
+ ) AS policies_subquery
199
+ CROSS JOIN LATERAL jsonb_array_elements(policies_subquery.aggregated::jsonb) AS policy_elem
200
+ LEFT JOIN LATERAL (
201
+ SELECT COALESCE(JSON_AGG(row_to_json(${operation.as})), '[]'::json) AS agents
202
+ FROM "${operation.through}"
203
+ INNER JOIN "${operation.from}" AS ${operation.as}
204
+ ON ${operation.as}."${operation.foreignField}" = "${operation.through}"."${operation.throughForeignField}"
205
+ WHERE "${operation.through}"."${operation.throughLocalField}" = (policy_elem.value->>'${columnName}')::integer
206
+ AND "${operation.through}"."_deleted" IS NULL
207
+ AND ${operation.as}."_deleted" IS NULL
208
+ ) AS agents_agg ON true
209
+ ) AS ${operation.as} ON true`;
210
+ }
211
+ else {
212
+ joinClauses += ` LEFT JOIN LATERAL (
213
+ SELECT COALESCE(
214
+ JSON_AGG(
215
+ policy_elem.value || jsonb_build_object('agents', COALESCE(agents_agg.agents, '[]'::json))
216
+ ),
217
+ '[]'::json
218
+ ) AS aggregated
219
+ FROM jsonb_array_elements(COALESCE(${tableAlias}.aggregated, '[]'::json)::jsonb) AS policy_elem
220
+ LEFT JOIN LATERAL (
221
+ SELECT COALESCE(JSON_AGG(row_to_json(${operation.as})), '[]'::json) AS agents
222
+ FROM "${operation.through}"
223
+ INNER JOIN "${operation.from}" AS ${operation.as}
224
+ ON ${operation.as}."${operation.foreignField}" = "${operation.through}"."${operation.throughForeignField}"
225
+ WHERE "${operation.through}"."${operation.throughLocalField}" = (policy_elem.value->>'${columnName}')::integer
226
+ AND "${operation.through}"."_deleted" IS NULL
227
+ AND ${operation.as}."_deleted" IS NULL
228
+ ) AS agents_agg ON true
229
+ ) AS ${operation.as} ON true`;
230
+ }
231
+ }
232
+ processedAliases.add(operation.as);
233
+ continue;
234
+ }
235
+ else {
236
+ localFieldRef = `${tableAlias}."${columnName}"`;
237
+ }
238
+ }
239
+ else {
240
+ localFieldRef = `${tableAlias}."${columnName}"`;
241
+ }
73
242
  }
74
243
  else {
75
244
  localFieldRef = mainTableName
76
245
  ? `"${mainTableName}"."${operation.localField}"`
77
246
  : `"${operation.localField}"`;
78
247
  }
79
- joinClauses += ` LEFT JOIN LATERAL (
80
- SELECT COALESCE(JSON_AGG(row_to_json(${operation.as})), '[]'::json) AS aggregated
81
- FROM "${operation.through}"
82
- INNER JOIN "${operation.from}" AS ${operation.as}
83
- ON ${operation.as}."${operation.foreignField}" = "${operation.through}"."${operation.throughForeignField}"
84
- WHERE "${operation.through}"."${operation.throughLocalField}" = ${localFieldRef}
85
- AND "${operation.through}"."_deleted" IS NULL
86
- AND ${operation.as}."_deleted" IS NULL
87
- ) AS ${operation.as} ON true`;
248
+ if (!shouldSkipOriginalJoin && !aliasesToSkip.has(operation.as)) {
249
+ joinClauses += ` LEFT JOIN LATERAL (
250
+ SELECT COALESCE(JSON_AGG(row_to_json(${operation.as})), '[]'::json) AS aggregated
251
+ FROM "${operation.through}"
252
+ INNER JOIN "${operation.from}" AS ${operation.as}
253
+ ON ${operation.as}."${operation.foreignField}" = "${operation.through}"."${operation.throughForeignField}"
254
+ WHERE "${operation.through}"."${operation.throughLocalField}" = ${localFieldRef}
255
+ AND "${operation.through}"."_deleted" IS NULL
256
+ AND ${operation.as}."_deleted" IS NULL
257
+ ) AS ${operation.as} ON true`;
258
+ processedAliases.add(operation.as);
259
+ }
260
+ else if (aliasesToSkip.has(operation.as)) {
261
+ processedAliases.add(operation.as);
262
+ }
88
263
  }
89
264
  }
90
265
  return joinClauses;
@@ -3,12 +3,12 @@ import { JoinMany } from '../../operations/join-many.operation.js';
3
3
  import { JoinThrough } from '../../operations/join-through.operation.js';
4
4
  import { JoinThroughMany } from '../../operations/join-through-many.operation.js';
5
5
  async function getTableColumns(client, tableName) {
6
- const result = await client.query(`
7
- SELECT column_name
8
- FROM information_schema.columns
9
- WHERE table_schema = current_schema()
10
- AND table_name = $1
11
- ORDER BY ordinal_position
6
+ const result = await client.query(`
7
+ SELECT column_name
8
+ FROM information_schema.columns
9
+ WHERE table_schema = current_schema()
10
+ AND table_name = $1
11
+ ORDER BY ordinal_position
12
12
  `, [tableName]);
13
13
  return result.rows.map(row => row.column_name);
14
14
  }
@@ -35,8 +35,28 @@ export async function buildSelectClause(client, mainTableName, mainTableAlias, o
35
35
  for (const joinThrough of joinThroughOperations) {
36
36
  joinSelects.push(`${joinThrough.as}.aggregated AS "${joinThrough.as}"`);
37
37
  }
38
+ const replacedJoins = new Map();
38
39
  for (const joinThroughMany of joinThroughManyOperations) {
39
- joinSelects.push(`${joinThroughMany.as}.aggregated AS "${joinThroughMany.as}"`);
40
+ if (joinThroughMany.localField.includes('.')) {
41
+ const [tableAlias] = joinThroughMany.localField.split('.');
42
+ const referencedJoin = joinThroughManyOperations.find(j => j.as === tableAlias);
43
+ if (referencedJoin) {
44
+ const referencedIndex = operations.indexOf(referencedJoin);
45
+ const currentIndex = operations.indexOf(joinThroughMany);
46
+ if (referencedIndex < currentIndex) {
47
+ replacedJoins.set(tableAlias, joinThroughMany.as);
48
+ }
49
+ }
50
+ }
51
+ }
52
+ for (const joinThroughMany of joinThroughManyOperations) {
53
+ if (replacedJoins.has(joinThroughMany.as)) {
54
+ const replacingAlias = replacedJoins.get(joinThroughMany.as);
55
+ joinSelects.push(`${replacingAlias}.aggregated AS "${joinThroughMany.as}"`);
56
+ }
57
+ else {
58
+ joinSelects.push(`${joinThroughMany.as}.aggregated AS "${joinThroughMany.as}"`);
59
+ }
40
60
  }
41
61
  const allSelects = [...mainSelects, ...joinSelects];
42
62
  return allSelects.join(', ');
@@ -1,8 +1,8 @@
1
1
  export async function doesTableExist(client, tableName) {
2
- const result = await client.query(`
3
- SELECT EXISTS (
4
- SELECT 1 FROM information_schema.tables WHERE table_schema = current_schema() AND table_name = $1
5
- )
2
+ const result = await client.query(`
3
+ SELECT EXISTS (
4
+ SELECT 1 FROM information_schema.tables WHERE table_schema = current_schema() AND table_name = $1
5
+ )
6
6
  `, [tableName]);
7
7
  return result.rows[0].exists;
8
8
  }
@@ -145,8 +145,27 @@ export function transformJoinResults(rows, operations) {
145
145
  transformed[joinMany.as] = parsedValue;
146
146
  }
147
147
  }
148
+ const replacedJoins = new Map();
148
149
  for (const joinThroughMany of joinThroughManyOperations) {
149
- const jsonValue = row[joinThroughMany.as];
150
+ if (joinThroughMany.localField.includes('.')) {
151
+ const [tableAlias] = joinThroughMany.localField.split('.');
152
+ const referencedJoin = joinThroughManyOperations.find(j => j.as === tableAlias);
153
+ if (referencedJoin) {
154
+ const referencedIndex = operations.indexOf(referencedJoin);
155
+ const currentIndex = operations.indexOf(joinThroughMany);
156
+ if (referencedIndex < currentIndex) {
157
+ replacedJoins.set(tableAlias, joinThroughMany.as);
158
+ }
159
+ }
160
+ }
161
+ }
162
+ for (const joinThroughMany of joinThroughManyOperations) {
163
+ if (replacedJoins.has(joinThroughMany.as)) {
164
+ continue;
165
+ }
166
+ const originalAlias = Array.from(replacedJoins.entries()).find(([_, replacing]) => replacing === joinThroughMany.as)?.[0];
167
+ const aliasToUse = originalAlias || joinThroughMany.as;
168
+ const jsonValue = row[aliasToUse];
150
169
  let parsedValue;
151
170
  if (jsonValue !== null && jsonValue !== undefined) {
152
171
  parsedValue = typeof jsonValue === 'string'
@@ -160,16 +179,29 @@ export function transformJoinResults(rows, operations) {
160
179
  const [tableAlias] = joinThroughMany.localField.split('.');
161
180
  const relatedJoin = joinOperations.find(j => j.as === tableAlias);
162
181
  const relatedJoinThrough = joinThroughOperations.find(j => j.as === tableAlias);
163
- if ((relatedJoin && transformed[relatedJoin.as]) || (relatedJoinThrough && transformed[relatedJoinThrough.as])) {
164
- const targetAlias = relatedJoin ? relatedJoin.as : relatedJoinThrough.as;
165
- transformed[targetAlias][joinThroughMany.as] = parsedValue;
182
+ const relatedJoinThroughMany = joinThroughManyOperations.find(j => j.as === tableAlias);
183
+ if ((relatedJoin && transformed[relatedJoin.as]) ||
184
+ (relatedJoinThrough && transformed[relatedJoinThrough.as]) ||
185
+ (relatedJoinThroughMany && transformed[relatedJoinThroughMany.as])) {
186
+ const targetAlias = relatedJoin ? relatedJoin.as :
187
+ (relatedJoinThrough ? relatedJoinThrough.as : relatedJoinThroughMany.as);
188
+ if (replacedJoins.get(targetAlias) === joinThroughMany.as) {
189
+ transformed[targetAlias] = parsedValue;
190
+ }
191
+ else {
192
+ let fieldName = joinThroughMany.as;
193
+ if (fieldName === 'policy_agents' && targetAlias === 'policies') {
194
+ fieldName = 'agents';
195
+ }
196
+ transformed[targetAlias][fieldName] = parsedValue;
197
+ }
166
198
  }
167
199
  else {
168
- transformed[joinThroughMany.as] = parsedValue;
200
+ transformed[aliasToUse] = parsedValue;
169
201
  }
170
202
  }
171
203
  else {
172
- transformed[joinThroughMany.as] = parsedValue;
204
+ transformed[aliasToUse] = parsedValue;
173
205
  }
174
206
  }
175
207
  return transformed;
package/package.json CHANGED
@@ -1,92 +1,92 @@
1
- {
2
- "name": "@loomcore/api",
3
- "version": "0.1.75",
4
- "private": false,
5
- "description": "Loom Core Api - An opinionated Node.js api using Typescript, Express, and MongoDb or PostgreSQL",
6
- "scripts": {
7
- "clean": "rm -rf dist",
8
- "tsc": "tsc --project tsconfig.prod.json",
9
- "build": "npm-run-all -s clean tsc",
10
- "add": "git add .",
11
- "commit": "git commit -m \"Updates\"",
12
- "patch": "npm version patch",
13
- "push": "git push",
14
- "publishMe": "npm publish --access public",
15
- "pub": "npm-run-all -s add commit patch build push publishMe",
16
- "update-lib-versions": "npx --yes npm-check-updates -u -f @loomcore/common",
17
- "install-updated-libs": "npm i @loomcore/common",
18
- "update-libs": "npm-run-all -s update-lib-versions install-updated-libs",
19
- "typecheck": "tsc",
20
- "test": "npm-run-all -s test:postgres test:mongodb",
21
- "test:postgres": "cross-env NODE_ENV=test TEST_DATABASE=postgres vitest run",
22
- "test:postgres:real": "cross-env NODE_ENV=test TEST_DATABASE=postgres USE_REAL_POSTGRES=true vitest run",
23
- "test:mongodb": "cross-env NODE_ENV=test TEST_DATABASE=mongodb vitest run",
24
- "test:ci": "npm-run-all -s test:ci:postgres test:ci:mongodb",
25
- "test:ci:postgres": "cross-env NODE_ENV=test TEST_DATABASE=postgres vitest run --reporter=json --outputFile=test-results-postgres.json",
26
- "test:ci:mongodb": "cross-env NODE_ENV=test TEST_DATABASE=mongodb vitest run --reporter=json --outputFile=test-results-mongodb.json",
27
- "test:watch": "cross-env NODE_ENV=test vitest",
28
- "coverage": "npm-run-all -s coverage:postgres coverage:mongodb",
29
- "coverage:postgres": "cross-env NODE_ENV=test TEST_DATABASE=postgres vitest run --coverage",
30
- "coverage:mongodb": "cross-env NODE_ENV=test TEST_DATABASE=mongodb vitest run --coverage",
31
- "test:db:start": "docker-compose -f docker-compose.test.yml up -d",
32
- "test:db:stop": "docker-compose -f docker-compose.test.yml down",
33
- "test:db:logs": "docker-compose -f docker-compose.test.yml logs -f"
34
- },
35
- "author": "Tim Hardy",
36
- "license": "Apache 2.0",
37
- "main": "dist/index.js",
38
- "type": "module",
39
- "types": "dist/index.d.ts",
40
- "files": [
41
- "dist/**/*"
42
- ],
43
- "exports": {
44
- "./__tests__": "./dist/__tests__/index.js",
45
- "./config": "./dist/config/index.js",
46
- "./controllers": "./dist/controllers/index.js",
47
- "./databases": "./dist/databases/index.js",
48
- "./errors": "./dist/errors/index.js",
49
- "./middleware": "./dist/middleware/index.js",
50
- "./models": "./dist/models/index.js",
51
- "./services": "./dist/services/index.js",
52
- "./utils": "./dist/utils/index.js"
53
- },
54
- "dependencies": {
55
- "jsonwebtoken": "^9.0.2",
56
- "node-mailjet": "^6.0.8",
57
- "qs": "^6.14.1"
58
- },
59
- "peerDependencies": {
60
- "@loomcore/common": "^0.0.43",
61
- "@sinclair/typebox": "0.34.33",
62
- "cookie-parser": "^1.4.6",
63
- "cors": "^2.8.5",
64
- "express": "^5.1.0",
65
- "lodash": "^4.17.21",
66
- "moment": "^2.30.1",
67
- "mongodb": "^6.16.0",
68
- "pg": "^8.15.6",
69
- "rxjs": "^7.8.0",
70
- "umzug": "^3.8.2"
71
- },
72
- "devDependencies": {
73
- "@types/cookie-parser": "^1.4.7",
74
- "@types/cors": "^2.8.18",
75
- "@types/express": "^5.0.1",
76
- "@types/jsonwebtoken": "^9.0.9",
77
- "@types/lodash": "^4.17.13",
78
- "@types/pg": "^8.15.6",
79
- "@types/qs": "^6.14.0",
80
- "@types/supertest": "^6.0.3",
81
- "@vitest/coverage-v8": "^3.0.9",
82
- "cross-env": "^7.0.3",
83
- "mongodb-memory-server": "^9.3.0",
84
- "npm-run-all": "^4.1.5",
85
- "pg-mem": "^3.0.8",
86
- "rxjs": "^7.8.0",
87
- "supertest": "^7.1.0",
88
- "typescript": "^5.8.3",
89
- "vite": "^6.2.5",
90
- "vitest": "^3.0.9"
91
- }
92
- }
1
+ {
2
+ "name": "@loomcore/api",
3
+ "version": "0.1.76",
4
+ "private": false,
5
+ "description": "Loom Core Api - An opinionated Node.js api using Typescript, Express, and MongoDb or PostgreSQL",
6
+ "scripts": {
7
+ "clean": "rm -rf dist",
8
+ "tsc": "tsc --project tsconfig.prod.json",
9
+ "build": "npm-run-all -s clean tsc",
10
+ "add": "git add .",
11
+ "commit": "git commit -m \"Updates\"",
12
+ "patch": "npm version patch",
13
+ "push": "git push",
14
+ "publishMe": "npm publish --access public",
15
+ "pub": "npm-run-all -s add commit patch build push publishMe",
16
+ "update-lib-versions": "npx --yes npm-check-updates -u -f @loomcore/common",
17
+ "install-updated-libs": "npm i @loomcore/common",
18
+ "update-libs": "npm-run-all -s update-lib-versions install-updated-libs",
19
+ "typecheck": "tsc",
20
+ "test": "npm-run-all -s test:postgres test:mongodb",
21
+ "test:postgres": "cross-env NODE_ENV=test TEST_DATABASE=postgres vitest run",
22
+ "test:postgres:real": "cross-env NODE_ENV=test TEST_DATABASE=postgres USE_REAL_POSTGRES=true vitest run",
23
+ "test:mongodb": "cross-env NODE_ENV=test TEST_DATABASE=mongodb vitest run",
24
+ "test:ci": "npm-run-all -s test:ci:postgres test:ci:mongodb",
25
+ "test:ci:postgres": "cross-env NODE_ENV=test TEST_DATABASE=postgres vitest run --reporter=json --outputFile=test-results-postgres.json",
26
+ "test:ci:mongodb": "cross-env NODE_ENV=test TEST_DATABASE=mongodb vitest run --reporter=json --outputFile=test-results-mongodb.json",
27
+ "test:watch": "cross-env NODE_ENV=test vitest",
28
+ "coverage": "npm-run-all -s coverage:postgres coverage:mongodb",
29
+ "coverage:postgres": "cross-env NODE_ENV=test TEST_DATABASE=postgres vitest run --coverage",
30
+ "coverage:mongodb": "cross-env NODE_ENV=test TEST_DATABASE=mongodb vitest run --coverage",
31
+ "test:db:start": "docker-compose -f docker-compose.test.yml up -d",
32
+ "test:db:stop": "docker-compose -f docker-compose.test.yml down",
33
+ "test:db:logs": "docker-compose -f docker-compose.test.yml logs -f"
34
+ },
35
+ "author": "Tim Hardy",
36
+ "license": "Apache 2.0",
37
+ "main": "dist/index.js",
38
+ "type": "module",
39
+ "types": "dist/index.d.ts",
40
+ "files": [
41
+ "dist/**/*"
42
+ ],
43
+ "exports": {
44
+ "./__tests__": "./dist/__tests__/index.js",
45
+ "./config": "./dist/config/index.js",
46
+ "./controllers": "./dist/controllers/index.js",
47
+ "./databases": "./dist/databases/index.js",
48
+ "./errors": "./dist/errors/index.js",
49
+ "./middleware": "./dist/middleware/index.js",
50
+ "./models": "./dist/models/index.js",
51
+ "./services": "./dist/services/index.js",
52
+ "./utils": "./dist/utils/index.js"
53
+ },
54
+ "dependencies": {
55
+ "jsonwebtoken": "^9.0.2",
56
+ "node-mailjet": "^6.0.8",
57
+ "qs": "^6.14.1"
58
+ },
59
+ "peerDependencies": {
60
+ "@loomcore/common": "^0.0.43",
61
+ "@sinclair/typebox": "0.34.33",
62
+ "cookie-parser": "^1.4.6",
63
+ "cors": "^2.8.5",
64
+ "express": "^5.1.0",
65
+ "lodash": "^4.17.21",
66
+ "moment": "^2.30.1",
67
+ "mongodb": "^6.16.0",
68
+ "pg": "^8.15.6",
69
+ "rxjs": "^7.8.0",
70
+ "umzug": "^3.8.2"
71
+ },
72
+ "devDependencies": {
73
+ "@types/cookie-parser": "^1.4.7",
74
+ "@types/cors": "^2.8.18",
75
+ "@types/express": "^5.0.1",
76
+ "@types/jsonwebtoken": "^9.0.9",
77
+ "@types/lodash": "^4.17.13",
78
+ "@types/pg": "^8.15.6",
79
+ "@types/qs": "^6.14.0",
80
+ "@types/supertest": "^6.0.3",
81
+ "@vitest/coverage-v8": "^3.0.9",
82
+ "cross-env": "^7.0.3",
83
+ "mongodb-memory-server": "^9.3.0",
84
+ "npm-run-all": "^4.1.5",
85
+ "pg-mem": "^3.0.8",
86
+ "rxjs": "^7.8.0",
87
+ "supertest": "^7.1.0",
88
+ "typescript": "^5.8.3",
89
+ "vite": "^6.2.5",
90
+ "vitest": "^3.0.9"
91
+ }
92
+ }