@memberjunction/server 5.31.0 → 5.33.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.
- package/dist/auth/newUsers.d.ts.map +1 -1
- package/dist/auth/newUsers.js +11 -3
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +23 -3
- package/dist/context.js.map +1 -1
- package/dist/generated/generated.d.ts +13 -10
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +89 -77
- package/dist/generated/generated.js.map +1 -1
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -7
- package/dist/index.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +5 -1
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +9 -4
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/package.json +68 -68
- package/src/__tests__/databaseAbstraction.test.ts +123 -61
- package/src/auth/newUsers.ts +12 -3
- package/src/context.ts +21 -3
- package/src/generated/generated.ts +68 -59
- package/src/index.ts +12 -7
- package/src/resolvers/GetDataResolver.ts +6 -2
- package/src/resolvers/IntegrationDiscoveryResolver.ts +10 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/server",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.33.0",
|
|
4
4
|
"description": "MemberJunction: This project provides API access via GraphQL to the common data store.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -27,73 +27,73 @@
|
|
|
27
27
|
"@as-integrations/express5": "^1.0.0",
|
|
28
28
|
"@graphql-tools/schema": "latest",
|
|
29
29
|
"@graphql-tools/utils": "^11.0.0",
|
|
30
|
-
"@memberjunction/actions": "5.
|
|
31
|
-
"@memberjunction/actions-apollo": "5.
|
|
32
|
-
"@memberjunction/actions-base": "5.
|
|
33
|
-
"@memberjunction/actions-bizapps-accounting": "5.
|
|
34
|
-
"@memberjunction/actions-bizapps-crm": "5.
|
|
35
|
-
"@memberjunction/actions-bizapps-formbuilders": "5.
|
|
36
|
-
"@memberjunction/actions-bizapps-lms": "5.
|
|
37
|
-
"@memberjunction/actions-bizapps-social": "5.
|
|
38
|
-
"@memberjunction/ai": "5.
|
|
39
|
-
"@memberjunction/ai-agent-manager": "5.
|
|
40
|
-
"@memberjunction/ai-agent-manager-actions": "5.
|
|
41
|
-
"@memberjunction/ai-agents": "5.
|
|
42
|
-
"@memberjunction/ai-core-plus": "5.
|
|
43
|
-
"@memberjunction/ai-mcp-client": "5.
|
|
44
|
-
"@memberjunction/ai-prompts": "5.
|
|
45
|
-
"@memberjunction/ai-provider-bundle": "5.
|
|
46
|
-
"@memberjunction/ai-vector-sync": "5.
|
|
47
|
-
"@memberjunction/ai-vectordb": "5.
|
|
48
|
-
"@memberjunction/ai-vectors-pinecone": "5.
|
|
49
|
-
"@memberjunction/aiengine": "5.
|
|
50
|
-
"@memberjunction/api-keys": "5.
|
|
51
|
-
"@memberjunction/auth-providers": "5.
|
|
52
|
-
"@memberjunction/codegen-lib": "5.
|
|
53
|
-
"@memberjunction/communication-ms-graph": "5.
|
|
54
|
-
"@memberjunction/communication-sendgrid": "5.
|
|
55
|
-
"@memberjunction/communication-types": "5.
|
|
56
|
-
"@memberjunction/component-registry-client-sdk": "5.
|
|
57
|
-
"@memberjunction/computer-use-engine": "5.
|
|
58
|
-
"@memberjunction/config": "5.
|
|
59
|
-
"@memberjunction/core": "5.
|
|
60
|
-
"@memberjunction/core-actions": "5.
|
|
61
|
-
"@memberjunction/core-entities": "5.
|
|
62
|
-
"@memberjunction/core-entities-server": "5.
|
|
63
|
-
"@memberjunction/data-context": "5.
|
|
64
|
-
"@memberjunction/data-context-server": "5.
|
|
65
|
-
"@memberjunction/doc-utils": "5.
|
|
66
|
-
"@memberjunction/encryption": "5.
|
|
67
|
-
"@memberjunction/entity-communications-base": "5.
|
|
68
|
-
"@memberjunction/entity-communications-server": "5.
|
|
69
|
-
"@memberjunction/external-change-detection": "5.
|
|
70
|
-
"@memberjunction/generic-database-provider": "5.
|
|
71
|
-
"@memberjunction/global": "5.
|
|
72
|
-
"@memberjunction/graphql-dataprovider": "5.
|
|
73
|
-
"@memberjunction/integration-engine": "5.
|
|
74
|
-
"@memberjunction/integration-schema-builder": "5.
|
|
75
|
-
"@memberjunction/interactive-component-types": "5.
|
|
76
|
-
"@memberjunction/notifications": "5.
|
|
77
|
-
"@memberjunction/postgresql-dataprovider": "5.
|
|
78
|
-
"@memberjunction/queue": "5.
|
|
79
|
-
"@memberjunction/redis-provider": "5.
|
|
80
|
-
"@memberjunction/scheduling-actions": "5.
|
|
81
|
-
"@memberjunction/scheduling-base-types": "5.
|
|
82
|
-
"@memberjunction/scheduling-engine": "5.
|
|
83
|
-
"@memberjunction/scheduling-engine-base": "5.
|
|
84
|
-
"@memberjunction/schema-engine": "5.
|
|
85
|
-
"@memberjunction/search-engine": "5.
|
|
86
|
-
"@memberjunction/server-extensions-core": "5.
|
|
87
|
-
"@memberjunction/skip-types": "5.
|
|
88
|
-
"@memberjunction/sql-dialect": "5.
|
|
89
|
-
"@memberjunction/sqlserver-dataprovider": "5.
|
|
90
|
-
"@memberjunction/storage": "5.
|
|
91
|
-
"@memberjunction/tag-engine": "5.
|
|
92
|
-
"@memberjunction/tag-engine-base": "5.
|
|
93
|
-
"@memberjunction/templates": "5.
|
|
94
|
-
"@memberjunction/testing-engine": "5.
|
|
95
|
-
"@memberjunction/testing-engine-base": "5.
|
|
96
|
-
"@memberjunction/version-history": "5.
|
|
30
|
+
"@memberjunction/actions": "5.33.0",
|
|
31
|
+
"@memberjunction/actions-apollo": "5.33.0",
|
|
32
|
+
"@memberjunction/actions-base": "5.33.0",
|
|
33
|
+
"@memberjunction/actions-bizapps-accounting": "5.33.0",
|
|
34
|
+
"@memberjunction/actions-bizapps-crm": "5.33.0",
|
|
35
|
+
"@memberjunction/actions-bizapps-formbuilders": "5.33.0",
|
|
36
|
+
"@memberjunction/actions-bizapps-lms": "5.33.0",
|
|
37
|
+
"@memberjunction/actions-bizapps-social": "5.33.0",
|
|
38
|
+
"@memberjunction/ai": "5.33.0",
|
|
39
|
+
"@memberjunction/ai-agent-manager": "5.33.0",
|
|
40
|
+
"@memberjunction/ai-agent-manager-actions": "5.33.0",
|
|
41
|
+
"@memberjunction/ai-agents": "5.33.0",
|
|
42
|
+
"@memberjunction/ai-core-plus": "5.33.0",
|
|
43
|
+
"@memberjunction/ai-mcp-client": "5.33.0",
|
|
44
|
+
"@memberjunction/ai-prompts": "5.33.0",
|
|
45
|
+
"@memberjunction/ai-provider-bundle": "5.33.0",
|
|
46
|
+
"@memberjunction/ai-vector-sync": "5.33.0",
|
|
47
|
+
"@memberjunction/ai-vectordb": "5.33.0",
|
|
48
|
+
"@memberjunction/ai-vectors-pinecone": "5.33.0",
|
|
49
|
+
"@memberjunction/aiengine": "5.33.0",
|
|
50
|
+
"@memberjunction/api-keys": "5.33.0",
|
|
51
|
+
"@memberjunction/auth-providers": "5.33.0",
|
|
52
|
+
"@memberjunction/codegen-lib": "5.33.0",
|
|
53
|
+
"@memberjunction/communication-ms-graph": "5.33.0",
|
|
54
|
+
"@memberjunction/communication-sendgrid": "5.33.0",
|
|
55
|
+
"@memberjunction/communication-types": "5.33.0",
|
|
56
|
+
"@memberjunction/component-registry-client-sdk": "5.33.0",
|
|
57
|
+
"@memberjunction/computer-use-engine": "5.33.0",
|
|
58
|
+
"@memberjunction/config": "5.33.0",
|
|
59
|
+
"@memberjunction/core": "5.33.0",
|
|
60
|
+
"@memberjunction/core-actions": "5.33.0",
|
|
61
|
+
"@memberjunction/core-entities": "5.33.0",
|
|
62
|
+
"@memberjunction/core-entities-server": "5.33.0",
|
|
63
|
+
"@memberjunction/data-context": "5.33.0",
|
|
64
|
+
"@memberjunction/data-context-server": "5.33.0",
|
|
65
|
+
"@memberjunction/doc-utils": "5.33.0",
|
|
66
|
+
"@memberjunction/encryption": "5.33.0",
|
|
67
|
+
"@memberjunction/entity-communications-base": "5.33.0",
|
|
68
|
+
"@memberjunction/entity-communications-server": "5.33.0",
|
|
69
|
+
"@memberjunction/external-change-detection": "5.33.0",
|
|
70
|
+
"@memberjunction/generic-database-provider": "5.33.0",
|
|
71
|
+
"@memberjunction/global": "5.33.0",
|
|
72
|
+
"@memberjunction/graphql-dataprovider": "5.33.0",
|
|
73
|
+
"@memberjunction/integration-engine": "5.33.0",
|
|
74
|
+
"@memberjunction/integration-schema-builder": "5.33.0",
|
|
75
|
+
"@memberjunction/interactive-component-types": "5.33.0",
|
|
76
|
+
"@memberjunction/notifications": "5.33.0",
|
|
77
|
+
"@memberjunction/postgresql-dataprovider": "5.33.0",
|
|
78
|
+
"@memberjunction/queue": "5.33.0",
|
|
79
|
+
"@memberjunction/redis-provider": "5.33.0",
|
|
80
|
+
"@memberjunction/scheduling-actions": "5.33.0",
|
|
81
|
+
"@memberjunction/scheduling-base-types": "5.33.0",
|
|
82
|
+
"@memberjunction/scheduling-engine": "5.33.0",
|
|
83
|
+
"@memberjunction/scheduling-engine-base": "5.33.0",
|
|
84
|
+
"@memberjunction/schema-engine": "5.33.0",
|
|
85
|
+
"@memberjunction/search-engine": "5.33.0",
|
|
86
|
+
"@memberjunction/server-extensions-core": "5.33.0",
|
|
87
|
+
"@memberjunction/skip-types": "5.33.0",
|
|
88
|
+
"@memberjunction/sql-dialect": "5.33.0",
|
|
89
|
+
"@memberjunction/sqlserver-dataprovider": "5.33.0",
|
|
90
|
+
"@memberjunction/storage": "5.33.0",
|
|
91
|
+
"@memberjunction/tag-engine": "5.33.0",
|
|
92
|
+
"@memberjunction/tag-engine-base": "5.33.0",
|
|
93
|
+
"@memberjunction/templates": "5.33.0",
|
|
94
|
+
"@memberjunction/testing-engine": "5.33.0",
|
|
95
|
+
"@memberjunction/testing-engine-base": "5.33.0",
|
|
96
|
+
"@memberjunction/version-history": "5.33.0",
|
|
97
97
|
"@types/compression": "^1.8.1",
|
|
98
98
|
"@types/cors": "^2.8.19",
|
|
99
99
|
"@types/jsonwebtoken": "9.0.10",
|
|
@@ -94,6 +94,25 @@ vi.mock('@memberjunction/core', () => ({
|
|
|
94
94
|
SetProvider: vi.fn(),
|
|
95
95
|
}));
|
|
96
96
|
|
|
97
|
+
// `resolveDbPlatformFromEnv` lives in `@memberjunction/generic-database-provider`
|
|
98
|
+
// (server-only — it touches `process.env`). The real package would pull in
|
|
99
|
+
// AI / actions / queue transitively, which is too heavy for a unit-test mock.
|
|
100
|
+
// Inline the actual implementation here so the env-var-handling tests below
|
|
101
|
+
// exercise the genuine behavior (they're testing this function).
|
|
102
|
+
vi.mock('@memberjunction/generic-database-provider', () => ({
|
|
103
|
+
resolveDbPlatformFromEnv: (envVarName: string = 'DB_PLATFORM'): 'sqlserver' | 'postgresql' | undefined => {
|
|
104
|
+
const raw = process.env[envVarName];
|
|
105
|
+
if (raw === undefined) return undefined;
|
|
106
|
+
const normalized = raw.trim().toLowerCase();
|
|
107
|
+
if (normalized === '') return undefined;
|
|
108
|
+
if (normalized === 'sqlserver' || normalized === 'postgresql') return normalized;
|
|
109
|
+
throw new Error(
|
|
110
|
+
`Invalid ${envVarName} value '${raw}'. Must be 'sqlserver' or 'postgresql' (case-insensitive). ` +
|
|
111
|
+
`Legacy aliases ('mssql', 'postgres', 'pg') and the legacy env var DB_TYPE are no longer supported.`,
|
|
112
|
+
);
|
|
113
|
+
},
|
|
114
|
+
}));
|
|
115
|
+
|
|
97
116
|
vi.mock('@memberjunction/sqlserver-dataprovider', () => ({
|
|
98
117
|
SQLServerDataProvider: vi.fn(),
|
|
99
118
|
SQLServerProviderConfigData: vi.fn(),
|
|
@@ -116,14 +135,14 @@ import {
|
|
|
116
135
|
GetReadWriteProvider,
|
|
117
136
|
} from '../util.js';
|
|
118
137
|
|
|
119
|
-
//
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return 'sqlserver';
|
|
138
|
+
// `index.ts` exports `getDbType` but importing it triggers type-graphql at
|
|
139
|
+
// module load time, which is too heavy for a unit test. Re-derive the same
|
|
140
|
+
// logic here using the canonical helper from @memberjunction/global so the
|
|
141
|
+
// behavior under test stays in lockstep with production.
|
|
142
|
+
import { resolveDbPlatformFromEnv } from '@memberjunction/generic-database-provider';
|
|
143
|
+
import type { DatabasePlatform } from '@memberjunction/core';
|
|
144
|
+
function getDbType(): DatabasePlatform {
|
|
145
|
+
return resolveDbPlatformFromEnv() ?? 'sqlserver';
|
|
127
146
|
}
|
|
128
147
|
|
|
129
148
|
// --------------------------------------------------------------------------
|
|
@@ -196,52 +215,80 @@ describe('Database Abstraction Layer', () => {
|
|
|
196
215
|
});
|
|
197
216
|
|
|
198
217
|
// ======================================================================
|
|
199
|
-
// 1. DB_TYPE
|
|
218
|
+
// 1. DB_PLATFORM detection (strict: throws on typo, DB_TYPE no longer read)
|
|
200
219
|
// ======================================================================
|
|
201
|
-
describe('getDbType –
|
|
202
|
-
|
|
220
|
+
describe('getDbType – DB_PLATFORM env detection', () => {
|
|
221
|
+
beforeEach(() => {
|
|
222
|
+
// Clear both vars before each case. DB_PLATFORM is what the resolver
|
|
223
|
+
// reads now; DB_TYPE is cleared too so we can prove it's ignored
|
|
224
|
+
// (no silent fallback to the removed legacy var).
|
|
225
|
+
delete process.env.DB_PLATFORM;
|
|
203
226
|
delete process.env.DB_TYPE;
|
|
204
|
-
expect(getDbType()).toBe('sqlserver');
|
|
205
227
|
});
|
|
206
228
|
|
|
207
|
-
it('
|
|
208
|
-
|
|
209
|
-
expect(getDbType()).toBe('postgresql');
|
|
229
|
+
it('returns "sqlserver" by default when DB_PLATFORM is not set', () => {
|
|
230
|
+
expect(getDbType()).toBe('sqlserver');
|
|
210
231
|
});
|
|
211
232
|
|
|
212
|
-
it('
|
|
213
|
-
process.env.
|
|
233
|
+
it('returns "postgresql" when DB_PLATFORM is the canonical "postgresql"', () => {
|
|
234
|
+
process.env.DB_PLATFORM = 'postgresql';
|
|
214
235
|
expect(getDbType()).toBe('postgresql');
|
|
215
236
|
});
|
|
216
237
|
|
|
217
|
-
it('
|
|
218
|
-
process.env.
|
|
219
|
-
expect(getDbType()).toBe('
|
|
238
|
+
it('returns "sqlserver" when DB_PLATFORM is the canonical "sqlserver"', () => {
|
|
239
|
+
process.env.DB_PLATFORM = 'sqlserver';
|
|
240
|
+
expect(getDbType()).toBe('sqlserver');
|
|
220
241
|
});
|
|
221
242
|
|
|
222
|
-
it('
|
|
223
|
-
process.env.
|
|
243
|
+
it('is case-insensitive for canonical values', () => {
|
|
244
|
+
process.env.DB_PLATFORM = 'PostgreSQL';
|
|
224
245
|
expect(getDbType()).toBe('postgresql');
|
|
225
246
|
|
|
226
|
-
process.env.
|
|
227
|
-
expect(getDbType()).toBe('
|
|
228
|
-
|
|
229
|
-
process.env.DB_TYPE = 'PG';
|
|
230
|
-
expect(getDbType()).toBe('postgresql');
|
|
247
|
+
process.env.DB_PLATFORM = 'SQLSERVER';
|
|
248
|
+
expect(getDbType()).toBe('sqlserver');
|
|
231
249
|
});
|
|
232
250
|
|
|
233
|
-
it('
|
|
234
|
-
process.env.
|
|
251
|
+
it('treats empty-string DB_PLATFORM as unset (returns "sqlserver" default)', () => {
|
|
252
|
+
process.env.DB_PLATFORM = '';
|
|
235
253
|
expect(getDbType()).toBe('sqlserver');
|
|
236
254
|
});
|
|
237
255
|
|
|
238
|
-
it('
|
|
239
|
-
process.env.
|
|
256
|
+
it('treats whitespace-only DB_PLATFORM as unset', () => {
|
|
257
|
+
process.env.DB_PLATFORM = ' ';
|
|
240
258
|
expect(getDbType()).toBe('sqlserver');
|
|
241
259
|
});
|
|
242
260
|
|
|
243
|
-
it('
|
|
244
|
-
process.env.
|
|
261
|
+
it('throws on legacy alias "mssql"', () => {
|
|
262
|
+
process.env.DB_PLATFORM = 'mssql';
|
|
263
|
+
expect(() => getDbType()).toThrow(/Invalid DB_PLATFORM value 'mssql'/);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('throws on legacy alias "postgres"', () => {
|
|
267
|
+
process.env.DB_PLATFORM = 'postgres';
|
|
268
|
+
expect(() => getDbType()).toThrow(/Invalid DB_PLATFORM value 'postgres'/);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it('throws on legacy alias "pg"', () => {
|
|
272
|
+
process.env.DB_PLATFORM = 'pg';
|
|
273
|
+
expect(() => getDbType()).toThrow(/Invalid DB_PLATFORM value 'pg'/);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it('throws on unrecognized value "mysql"', () => {
|
|
277
|
+
process.env.DB_PLATFORM = 'mysql';
|
|
278
|
+
expect(() => getDbType()).toThrow(/Invalid DB_PLATFORM value 'mysql'/);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('error message names the offending env var (so callers know which one)', () => {
|
|
282
|
+
process.env.DB_PLATFORM = 'oracle';
|
|
283
|
+
expect(() => getDbType()).toThrow(
|
|
284
|
+
/Must be 'sqlserver' or 'postgresql'/,
|
|
285
|
+
);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('ignores DB_TYPE entirely (legacy env var no longer consulted)', () => {
|
|
289
|
+
// Before strict mode, DB_TYPE was the primary, then a fallback. Now
|
|
290
|
+
// it's neither — anyone with DB_TYPE in their .env must rename it.
|
|
291
|
+
process.env.DB_TYPE = 'postgresql';
|
|
245
292
|
expect(getDbType()).toBe('sqlserver');
|
|
246
293
|
});
|
|
247
294
|
});
|
|
@@ -487,32 +534,32 @@ describe('Database Abstraction Layer', () => {
|
|
|
487
534
|
// 7. Context creation – database type branching in contextFunction
|
|
488
535
|
// ======================================================================
|
|
489
536
|
describe('Database type branching for context creation', () => {
|
|
490
|
-
|
|
491
|
-
process.env.
|
|
492
|
-
|
|
493
|
-
const isPostgres = dbType === 'postgresql' || dbType === 'postgres' || dbType === 'pg';
|
|
494
|
-
expect(isPostgres).toBe(true);
|
|
537
|
+
beforeEach(() => {
|
|
538
|
+
delete process.env.DB_PLATFORM;
|
|
539
|
+
delete process.env.DB_TYPE;
|
|
495
540
|
});
|
|
496
541
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
542
|
+
// The branching logic in context creation goes through the same
|
|
543
|
+
// canonical helper that getDbType() uses, so all callers see one
|
|
544
|
+
// consistent platform value.
|
|
545
|
+
it('identifies postgres when DB_PLATFORM is "postgresql"', () => {
|
|
546
|
+
process.env.DB_PLATFORM = 'postgresql';
|
|
547
|
+
expect(getDbType() === 'postgresql').toBe(true);
|
|
502
548
|
});
|
|
503
549
|
|
|
504
|
-
it('
|
|
505
|
-
process.env.
|
|
506
|
-
|
|
507
|
-
const isPostgres = dbType === 'postgresql' || dbType === 'postgres' || dbType === 'pg';
|
|
508
|
-
expect(isPostgres).toBe(false);
|
|
550
|
+
it('throws (does not silently downgrade) on legacy alias "pg"', () => {
|
|
551
|
+
process.env.DB_PLATFORM = 'pg';
|
|
552
|
+
expect(() => getDbType()).toThrow(/Invalid DB_PLATFORM/);
|
|
509
553
|
});
|
|
510
554
|
|
|
511
|
-
it('
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
555
|
+
it('does not identify postgres when DB_PLATFORM is "sqlserver"', () => {
|
|
556
|
+
process.env.DB_PLATFORM = 'sqlserver';
|
|
557
|
+
expect(getDbType() === 'postgresql').toBe(false);
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
it('does not identify postgres when DB_PLATFORM is undefined', () => {
|
|
561
|
+
delete process.env.DB_PLATFORM;
|
|
562
|
+
expect(getDbType() === 'postgresql').toBe(false);
|
|
516
563
|
});
|
|
517
564
|
});
|
|
518
565
|
|
|
@@ -793,23 +840,38 @@ describe('Database Abstraction Layer', () => {
|
|
|
793
840
|
// 14. getDbType return type
|
|
794
841
|
// ======================================================================
|
|
795
842
|
describe('getDbType return type compliance', () => {
|
|
796
|
-
|
|
843
|
+
beforeEach(() => {
|
|
844
|
+
delete process.env.DB_PLATFORM;
|
|
797
845
|
delete process.env.DB_TYPE;
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
it('returns a value matching the DatabasePlatform union type when unset', () => {
|
|
798
849
|
const result = getDbType();
|
|
799
850
|
const validValues: string[] = ['sqlserver', 'postgresql'];
|
|
800
851
|
expect(validValues).toContain(result);
|
|
801
852
|
});
|
|
802
853
|
|
|
803
|
-
it('
|
|
804
|
-
|
|
805
|
-
|
|
854
|
+
it('returns a canonical value or throws — never returns a non-canonical string', () => {
|
|
855
|
+
// Strict contract: getDbType() either returns one of the two canonical
|
|
856
|
+
// platform names, or throws. There's no third "fallback to default"
|
|
857
|
+
// outcome for non-empty unrecognized values — silent fallback was the
|
|
858
|
+
// bug we're eliminating.
|
|
859
|
+
const validReturns = ['sqlserver', 'postgresql'];
|
|
860
|
+
|
|
861
|
+
// Unset / empty / whitespace return the default
|
|
862
|
+
for (const val of [undefined, '', ' ']) {
|
|
806
863
|
if (val === undefined) {
|
|
807
|
-
delete process.env.
|
|
864
|
+
delete process.env.DB_PLATFORM;
|
|
808
865
|
} else {
|
|
809
|
-
process.env.
|
|
866
|
+
process.env.DB_PLATFORM = val;
|
|
810
867
|
}
|
|
811
|
-
|
|
812
|
-
|
|
868
|
+
expect(validReturns).toContain(getDbType());
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
// Unrecognized non-empty values throw
|
|
872
|
+
for (const val of ['oracle', 'mysql', 'sqlite', 'mongodb']) {
|
|
873
|
+
process.env.DB_PLATFORM = val;
|
|
874
|
+
expect(() => getDbType()).toThrow(/Invalid DB_PLATFORM/);
|
|
813
875
|
}
|
|
814
876
|
});
|
|
815
877
|
});
|
package/src/auth/newUsers.ts
CHANGED
|
@@ -110,9 +110,16 @@ export class NewUserBase {
|
|
|
110
110
|
LogStatus(`Created User Application ${application.Name} for new user ${user.Name}`);
|
|
111
111
|
|
|
112
112
|
const rv: RunView = new RunView();
|
|
113
|
+
// Boolean literal goes through the active provider's dialect:
|
|
114
|
+
// SQL Server emits `= 1`, PostgreSQL emits `= TRUE`.
|
|
115
|
+
// This keeps the filter server-side (no client-side `.filter()`
|
|
116
|
+
// pass) and uses the single source-of-truth helper instead of
|
|
117
|
+
// hardcoded SQL that is correct on one dialect but breaks on
|
|
118
|
+
// the other.
|
|
119
|
+
const trueLit = provider.Dialect.BooleanLiteral(true);
|
|
113
120
|
const rvResult: RunViewResult<MJApplicationEntityEntityType> = await rv.RunView({
|
|
114
121
|
EntityName: 'MJ: Application Entities',
|
|
115
|
-
ExtraFilter: `ApplicationID = '${application.ID}'
|
|
122
|
+
ExtraFilter: `ApplicationID = '${application.ID}' AND DefaultForNewUser = ${trueLit}`,
|
|
116
123
|
}, contextUser);
|
|
117
124
|
|
|
118
125
|
if(!rvResult.Success){
|
|
@@ -120,9 +127,11 @@ export class NewUserBase {
|
|
|
120
127
|
continue;
|
|
121
128
|
}
|
|
122
129
|
|
|
123
|
-
|
|
130
|
+
const defaultForNewUserEntities = rvResult.Results;
|
|
124
131
|
|
|
125
|
-
|
|
132
|
+
LogStatus(`Creating ${defaultForNewUserEntities.length} User Application Entities for User Application ${application.Name} for new user ${user.Name}`);
|
|
133
|
+
|
|
134
|
+
for(const [index, appEntity] of defaultForNewUserEntities.entries()){
|
|
126
135
|
const userAppEntity: MJUserApplicationEntityEntity = await md.GetEntityObject<MJUserApplicationEntityEntity>('MJ: User Application Entities', contextUser);
|
|
127
136
|
userAppEntity.NewRecord();
|
|
128
137
|
userAppEntity.UserApplicationID = userApplication.ID;
|
package/src/context.ts
CHANGED
|
@@ -18,8 +18,27 @@ import { DatabaseProviderBase } from '@memberjunction/core';
|
|
|
18
18
|
import { SQLServerDataProvider, SQLServerProviderConfigData, UserCache } from '@memberjunction/sqlserver-dataprovider';
|
|
19
19
|
import { Metadata } from '@memberjunction/core';
|
|
20
20
|
import { UUIDsEqual } from '@memberjunction/global';
|
|
21
|
+
import { resolveDbPlatformFromEnv } from '@memberjunction/generic-database-provider';
|
|
21
22
|
import { GetAPIKeyEngine } from '@memberjunction/api-keys';
|
|
22
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Renders a value for one-line console logging without Node's `[Object]` truncation.
|
|
26
|
+
* Arrays keep their structure; non-array objects collapse to JSON, truncated at `maxLen`.
|
|
27
|
+
* Objects whose JSON exceeds `maxLen` and contain nested structure are recursed into so
|
|
28
|
+
* outer keys remain visible.
|
|
29
|
+
*/
|
|
30
|
+
function shortenForLog(value: unknown, maxLen = 300): unknown {
|
|
31
|
+
if (value === null || typeof value !== 'object') return value;
|
|
32
|
+
if (Array.isArray(value)) return value.map((v) => shortenForLog(v, maxLen));
|
|
33
|
+
const json = JSON.stringify(value);
|
|
34
|
+
if (json.length <= maxLen) return json;
|
|
35
|
+
const result: Record<string, unknown> = {};
|
|
36
|
+
for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
|
|
37
|
+
result[k] = shortenForLog(v, maxLen);
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
|
|
23
42
|
const verifyAsync = async (issuer: string, token: string): Promise<jwt.JwtPayload> =>
|
|
24
43
|
new Promise((resolve, reject) => {
|
|
25
44
|
const options = getValidationOptions(issuer);
|
|
@@ -323,7 +342,7 @@ export const contextFunction =
|
|
|
323
342
|
const reqAny = req as any;
|
|
324
343
|
const operationName: string | undefined = reqAny.body?.operationName;
|
|
325
344
|
if (operationName !== 'IntrospectionQuery') {
|
|
326
|
-
console.
|
|
345
|
+
console.dir({ operationName, variables: shortenForLog(reqAny.body?.variables) }, { depth: null, breakLength: 200 });
|
|
327
346
|
}
|
|
328
347
|
|
|
329
348
|
// Auth already happened in the unified auth middleware — just read the result
|
|
@@ -356,8 +375,7 @@ async function createPerRequestProviders(
|
|
|
356
375
|
dataSource: sql.ConnectionPool,
|
|
357
376
|
dataSources: DataSourceInfo[]
|
|
358
377
|
): Promise<Array<{ provider: DatabaseProviderBase; type: 'Read-Write' | 'Read-Only' }>> {
|
|
359
|
-
const
|
|
360
|
-
const isPostgres = dbType === 'postgresql' || dbType === 'postgres' || dbType === 'pg';
|
|
378
|
+
const isPostgres = resolveDbPlatformFromEnv() === 'postgresql';
|
|
361
379
|
|
|
362
380
|
let p: DatabaseProviderBase;
|
|
363
381
|
if (isPostgres) {
|