@holo-js/config 0.2.6 → 0.3.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/chunk-SAQGYMAD.mjs +62 -0
- package/dist/index.d.ts +20 -918
- package/dist/index.mjs +33 -1768
- package/dist/registry.d.ts +18 -0
- package/dist/registry.mjs +12 -0
- package/package.json +6 -2
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
composeRegisteredConfig,
|
|
3
|
+
configRegistryInternals,
|
|
4
|
+
registerConfigNormalizer,
|
|
5
|
+
resetConfigNormalizers
|
|
6
|
+
} from "./chunk-SAQGYMAD.mjs";
|
|
7
|
+
|
|
1
8
|
// src/defaults.ts
|
|
2
9
|
import {
|
|
3
10
|
DEFAULT_HOLO_PROJECT_PATHS,
|
|
4
11
|
normalizeHoloProjectConfig
|
|
5
|
-
} from "@holo-js/
|
|
12
|
+
} from "@holo-js/kernel";
|
|
6
13
|
var DEFAULT_APP_NAME = "Holo";
|
|
7
14
|
var holoAppDefaults = Object.freeze({
|
|
8
15
|
name: DEFAULT_APP_NAME,
|
|
@@ -10,785 +17,12 @@ var holoAppDefaults = Object.freeze({
|
|
|
10
17
|
url: "http://localhost:3000",
|
|
11
18
|
debug: true,
|
|
12
19
|
env: "development",
|
|
20
|
+
plugins: Object.freeze([]),
|
|
13
21
|
paths: Object.freeze({ ...DEFAULT_HOLO_PROJECT_PATHS }),
|
|
14
22
|
models: Object.freeze([]),
|
|
15
23
|
migrations: Object.freeze([]),
|
|
16
24
|
seeders: Object.freeze([])
|
|
17
25
|
});
|
|
18
|
-
var holoDatabaseDefaults = Object.freeze({
|
|
19
|
-
defaultConnection: "default",
|
|
20
|
-
connections: Object.freeze({
|
|
21
|
-
default: Object.freeze({
|
|
22
|
-
driver: "sqlite",
|
|
23
|
-
url: "./data/database.sqlite",
|
|
24
|
-
schema: "public",
|
|
25
|
-
logging: false
|
|
26
|
-
})
|
|
27
|
-
})
|
|
28
|
-
});
|
|
29
|
-
var DEFAULT_REDIS_CONNECTION = "default";
|
|
30
|
-
var DEFAULT_REDIS_HOST = "127.0.0.1";
|
|
31
|
-
var DEFAULT_REDIS_PORT = 6379;
|
|
32
|
-
var DEFAULT_REDIS_DB = 0;
|
|
33
|
-
var holoRedisDefaults = Object.freeze({
|
|
34
|
-
default: DEFAULT_REDIS_CONNECTION,
|
|
35
|
-
connections: Object.freeze({
|
|
36
|
-
[DEFAULT_REDIS_CONNECTION]: Object.freeze({
|
|
37
|
-
name: DEFAULT_REDIS_CONNECTION,
|
|
38
|
-
host: DEFAULT_REDIS_HOST,
|
|
39
|
-
port: DEFAULT_REDIS_PORT,
|
|
40
|
-
username: void 0,
|
|
41
|
-
password: void 0,
|
|
42
|
-
db: DEFAULT_REDIS_DB
|
|
43
|
-
})
|
|
44
|
-
})
|
|
45
|
-
});
|
|
46
|
-
var holoStorageDefaults = Object.freeze({
|
|
47
|
-
defaultDisk: "local",
|
|
48
|
-
routePrefix: "/storage",
|
|
49
|
-
disks: Object.freeze({
|
|
50
|
-
local: Object.freeze({
|
|
51
|
-
driver: "local",
|
|
52
|
-
root: "./storage/app"
|
|
53
|
-
}),
|
|
54
|
-
public: Object.freeze({
|
|
55
|
-
driver: "public",
|
|
56
|
-
root: "./storage/app/public",
|
|
57
|
-
visibility: "public"
|
|
58
|
-
})
|
|
59
|
-
})
|
|
60
|
-
});
|
|
61
|
-
var DEFAULT_NOTIFICATIONS_TABLE = "notifications";
|
|
62
|
-
var DEFAULT_BROADCAST_CONNECTION = "null";
|
|
63
|
-
var DEFAULT_BROADCAST_HOST = "127.0.0.1";
|
|
64
|
-
var DEFAULT_BROADCAST_HTTP_PORT = 80;
|
|
65
|
-
var DEFAULT_BROADCAST_HTTPS_PORT = 443;
|
|
66
|
-
var DEFAULT_BROADCAST_WORKER_HOST = "0.0.0.0";
|
|
67
|
-
var DEFAULT_BROADCAST_WORKER_PORT = 8080;
|
|
68
|
-
var DEFAULT_BROADCAST_WORKER_PATH = "/app";
|
|
69
|
-
var DEFAULT_BROADCAST_HEALTH_PATH = "/health";
|
|
70
|
-
var DEFAULT_BROADCAST_STATS_PATH = "/stats";
|
|
71
|
-
var holoNotificationsDefaults = Object.freeze({
|
|
72
|
-
table: DEFAULT_NOTIFICATIONS_TABLE,
|
|
73
|
-
queue: Object.freeze({
|
|
74
|
-
connection: void 0,
|
|
75
|
-
queue: void 0,
|
|
76
|
-
afterCommit: false
|
|
77
|
-
})
|
|
78
|
-
});
|
|
79
|
-
var holoBroadcastDefaults = Object.freeze({
|
|
80
|
-
default: DEFAULT_BROADCAST_CONNECTION,
|
|
81
|
-
connections: Object.freeze({
|
|
82
|
-
log: Object.freeze({
|
|
83
|
-
name: "log",
|
|
84
|
-
driver: "log",
|
|
85
|
-
clientOptions: Object.freeze({})
|
|
86
|
-
}),
|
|
87
|
-
null: Object.freeze({
|
|
88
|
-
name: "null",
|
|
89
|
-
driver: "null",
|
|
90
|
-
clientOptions: Object.freeze({})
|
|
91
|
-
})
|
|
92
|
-
}),
|
|
93
|
-
worker: Object.freeze({
|
|
94
|
-
host: DEFAULT_BROADCAST_WORKER_HOST,
|
|
95
|
-
port: DEFAULT_BROADCAST_WORKER_PORT,
|
|
96
|
-
path: DEFAULT_BROADCAST_WORKER_PATH,
|
|
97
|
-
publicHost: void 0,
|
|
98
|
-
publicPort: void 0,
|
|
99
|
-
publicScheme: "https",
|
|
100
|
-
healthPath: DEFAULT_BROADCAST_HEALTH_PATH,
|
|
101
|
-
statsPath: DEFAULT_BROADCAST_STATS_PATH,
|
|
102
|
-
scaling: false
|
|
103
|
-
})
|
|
104
|
-
});
|
|
105
|
-
var DEFAULT_CACHE_DRIVER = "file";
|
|
106
|
-
var DEFAULT_CACHE_PREFIX = "";
|
|
107
|
-
var DEFAULT_CACHE_FILE_PATH = "./storage/framework/cache/data";
|
|
108
|
-
var DEFAULT_CACHE_REDIS_CONNECTION = "default";
|
|
109
|
-
var DEFAULT_CACHE_DATABASE_CONNECTION = "default";
|
|
110
|
-
var DEFAULT_CACHE_DATABASE_TABLE = "cache";
|
|
111
|
-
var DEFAULT_CACHE_DATABASE_LOCK_TABLE = "cache_locks";
|
|
112
|
-
var holoCacheDefaults = Object.freeze({
|
|
113
|
-
default: DEFAULT_CACHE_DRIVER,
|
|
114
|
-
prefix: DEFAULT_CACHE_PREFIX,
|
|
115
|
-
drivers: Object.freeze({
|
|
116
|
-
file: Object.freeze({
|
|
117
|
-
name: "file",
|
|
118
|
-
driver: "file",
|
|
119
|
-
path: DEFAULT_CACHE_FILE_PATH,
|
|
120
|
-
prefix: DEFAULT_CACHE_PREFIX
|
|
121
|
-
}),
|
|
122
|
-
memory: Object.freeze({
|
|
123
|
-
name: "memory",
|
|
124
|
-
driver: "memory",
|
|
125
|
-
maxEntries: void 0,
|
|
126
|
-
prefix: DEFAULT_CACHE_PREFIX
|
|
127
|
-
})
|
|
128
|
-
})
|
|
129
|
-
});
|
|
130
|
-
var DEFAULT_MAILER_NAME = "preview";
|
|
131
|
-
var DEFAULT_MAIL_PREVIEW_PATH = ".holo-js/runtime/mail-preview";
|
|
132
|
-
var DEFAULT_SMTP_HOST = "127.0.0.1";
|
|
133
|
-
var DEFAULT_SMTP_PORT = 1025;
|
|
134
|
-
var DEFAULT_MAIL_QUEUE_CONFIG = Object.freeze({
|
|
135
|
-
queued: false,
|
|
136
|
-
connection: void 0,
|
|
137
|
-
queue: void 0,
|
|
138
|
-
afterCommit: false
|
|
139
|
-
});
|
|
140
|
-
var holoMailDefaults = Object.freeze({
|
|
141
|
-
default: DEFAULT_MAILER_NAME,
|
|
142
|
-
from: void 0,
|
|
143
|
-
replyTo: void 0,
|
|
144
|
-
queue: DEFAULT_MAIL_QUEUE_CONFIG,
|
|
145
|
-
preview: Object.freeze({
|
|
146
|
-
allowedEnvironments: Object.freeze(["development"])
|
|
147
|
-
}),
|
|
148
|
-
markdown: Object.freeze({
|
|
149
|
-
wrapper: void 0
|
|
150
|
-
}),
|
|
151
|
-
mailers: Object.freeze({
|
|
152
|
-
preview: Object.freeze({
|
|
153
|
-
name: "preview",
|
|
154
|
-
driver: "preview",
|
|
155
|
-
from: void 0,
|
|
156
|
-
replyTo: void 0,
|
|
157
|
-
queue: DEFAULT_MAIL_QUEUE_CONFIG,
|
|
158
|
-
path: DEFAULT_MAIL_PREVIEW_PATH
|
|
159
|
-
}),
|
|
160
|
-
log: Object.freeze({
|
|
161
|
-
name: "log",
|
|
162
|
-
driver: "log",
|
|
163
|
-
from: void 0,
|
|
164
|
-
replyTo: void 0,
|
|
165
|
-
queue: DEFAULT_MAIL_QUEUE_CONFIG,
|
|
166
|
-
logBodies: false
|
|
167
|
-
}),
|
|
168
|
-
fake: Object.freeze({
|
|
169
|
-
name: "fake",
|
|
170
|
-
driver: "fake",
|
|
171
|
-
from: void 0,
|
|
172
|
-
replyTo: void 0,
|
|
173
|
-
queue: DEFAULT_MAIL_QUEUE_CONFIG
|
|
174
|
-
}),
|
|
175
|
-
smtp: Object.freeze({
|
|
176
|
-
name: "smtp",
|
|
177
|
-
driver: "smtp",
|
|
178
|
-
from: void 0,
|
|
179
|
-
replyTo: void 0,
|
|
180
|
-
queue: DEFAULT_MAIL_QUEUE_CONFIG,
|
|
181
|
-
host: DEFAULT_SMTP_HOST,
|
|
182
|
-
port: DEFAULT_SMTP_PORT,
|
|
183
|
-
secure: false
|
|
184
|
-
})
|
|
185
|
-
})
|
|
186
|
-
});
|
|
187
|
-
var DEFAULT_SESSION_DRIVER = "file";
|
|
188
|
-
var DEFAULT_SESSION_IDLE_TIMEOUT = 120;
|
|
189
|
-
var DEFAULT_SESSION_ABSOLUTE_LIFETIME = 120;
|
|
190
|
-
var DEFAULT_SESSION_REMEMBER_ME_LIFETIME = 43200;
|
|
191
|
-
var DEFAULT_SESSION_COOKIE_NAME = "holo_session";
|
|
192
|
-
var DEFAULT_SESSION_COOKIE_PATH = "/";
|
|
193
|
-
var DEFAULT_SESSION_COOKIE_SAME_SITE = "lax";
|
|
194
|
-
var DEFAULT_SESSION_DATABASE_CONNECTION = "default";
|
|
195
|
-
var DEFAULT_SESSION_DATABASE_TABLE = "sessions";
|
|
196
|
-
var DEFAULT_SESSION_FILE_PATH = "./storage/framework/sessions";
|
|
197
|
-
var holoSessionDefaults = Object.freeze({
|
|
198
|
-
driver: DEFAULT_SESSION_DRIVER,
|
|
199
|
-
stores: Object.freeze({
|
|
200
|
-
database: Object.freeze({
|
|
201
|
-
name: "database",
|
|
202
|
-
driver: "database",
|
|
203
|
-
connection: DEFAULT_SESSION_DATABASE_CONNECTION,
|
|
204
|
-
table: DEFAULT_SESSION_DATABASE_TABLE
|
|
205
|
-
}),
|
|
206
|
-
file: Object.freeze({
|
|
207
|
-
name: "file",
|
|
208
|
-
driver: "file",
|
|
209
|
-
path: DEFAULT_SESSION_FILE_PATH
|
|
210
|
-
})
|
|
211
|
-
}),
|
|
212
|
-
cookie: Object.freeze({
|
|
213
|
-
name: DEFAULT_SESSION_COOKIE_NAME,
|
|
214
|
-
path: DEFAULT_SESSION_COOKIE_PATH,
|
|
215
|
-
secure: false,
|
|
216
|
-
httpOnly: true,
|
|
217
|
-
sameSite: DEFAULT_SESSION_COOKIE_SAME_SITE,
|
|
218
|
-
partitioned: false,
|
|
219
|
-
maxAge: DEFAULT_SESSION_ABSOLUTE_LIFETIME
|
|
220
|
-
}),
|
|
221
|
-
idleTimeout: DEFAULT_SESSION_IDLE_TIMEOUT,
|
|
222
|
-
absoluteLifetime: DEFAULT_SESSION_ABSOLUTE_LIFETIME,
|
|
223
|
-
rememberMeLifetime: DEFAULT_SESSION_REMEMBER_ME_LIFETIME
|
|
224
|
-
});
|
|
225
|
-
var DEFAULT_CORS_PATHS = Object.freeze(["/api/*"]);
|
|
226
|
-
var DEFAULT_CORS_METHODS = Object.freeze(["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]);
|
|
227
|
-
var DEFAULT_CORS_HEADERS = Object.freeze(["Content-Type", "Authorization", "X-CSRF-TOKEN", "X-Requested-With"]);
|
|
228
|
-
var DEFAULT_CORS_MAX_AGE = 7200;
|
|
229
|
-
var holoCorsDefaults = Object.freeze({
|
|
230
|
-
paths: DEFAULT_CORS_PATHS,
|
|
231
|
-
origins: Object.freeze([]),
|
|
232
|
-
methods: DEFAULT_CORS_METHODS,
|
|
233
|
-
headers: DEFAULT_CORS_HEADERS,
|
|
234
|
-
credentials: false,
|
|
235
|
-
maxAge: DEFAULT_CORS_MAX_AGE,
|
|
236
|
-
statefulDomains: Object.freeze([])
|
|
237
|
-
});
|
|
238
|
-
var DEFAULT_SECURITY_CSRF_FIELD = "_token";
|
|
239
|
-
var DEFAULT_SECURITY_CSRF_HEADER = "X-CSRF-TOKEN";
|
|
240
|
-
var DEFAULT_SECURITY_CSRF_COOKIE = "XSRF-TOKEN";
|
|
241
|
-
var DEFAULT_SECURITY_RATE_LIMIT_DRIVER = "memory";
|
|
242
|
-
var DEFAULT_SECURITY_RATE_LIMIT_FILE_PATH = "./storage/framework/rate-limits";
|
|
243
|
-
var DEFAULT_SECURITY_RATE_LIMIT_REDIS_CONNECTION = "default";
|
|
244
|
-
var DEFAULT_SECURITY_RATE_LIMIT_REDIS_PREFIX = "holo:rate-limit:";
|
|
245
|
-
var DEFAULT_SECURITY_CSRF_CONFIG = Object.freeze({
|
|
246
|
-
enabled: false,
|
|
247
|
-
field: DEFAULT_SECURITY_CSRF_FIELD,
|
|
248
|
-
header: DEFAULT_SECURITY_CSRF_HEADER,
|
|
249
|
-
cookie: DEFAULT_SECURITY_CSRF_COOKIE,
|
|
250
|
-
except: Object.freeze([])
|
|
251
|
-
});
|
|
252
|
-
var DEFAULT_SECURITY_RATE_LIMIT_CONFIG = Object.freeze({
|
|
253
|
-
driver: DEFAULT_SECURITY_RATE_LIMIT_DRIVER,
|
|
254
|
-
memory: Object.freeze({
|
|
255
|
-
driver: "memory"
|
|
256
|
-
}),
|
|
257
|
-
file: Object.freeze({
|
|
258
|
-
path: DEFAULT_SECURITY_RATE_LIMIT_FILE_PATH
|
|
259
|
-
}),
|
|
260
|
-
redis: Object.freeze({
|
|
261
|
-
host: DEFAULT_REDIS_HOST,
|
|
262
|
-
port: DEFAULT_REDIS_PORT,
|
|
263
|
-
password: void 0,
|
|
264
|
-
username: void 0,
|
|
265
|
-
db: DEFAULT_REDIS_DB,
|
|
266
|
-
connection: DEFAULT_SECURITY_RATE_LIMIT_REDIS_CONNECTION,
|
|
267
|
-
prefix: DEFAULT_SECURITY_RATE_LIMIT_REDIS_PREFIX
|
|
268
|
-
}),
|
|
269
|
-
limiters: Object.freeze({})
|
|
270
|
-
});
|
|
271
|
-
var holoSecurityDefaults = Object.freeze({
|
|
272
|
-
csrf: DEFAULT_SECURITY_CSRF_CONFIG,
|
|
273
|
-
rateLimit: DEFAULT_SECURITY_RATE_LIMIT_CONFIG
|
|
274
|
-
});
|
|
275
|
-
var DEFAULT_AUTH_GUARD = "web";
|
|
276
|
-
var DEFAULT_AUTH_PROVIDER = "users";
|
|
277
|
-
var DEFAULT_AUTH_IDENTIFIERS = Object.freeze(["email"]);
|
|
278
|
-
var DEFAULT_AUTH_PASSWORD_BROKER = "users";
|
|
279
|
-
var DEFAULT_AUTH_PASSWORD_RESET_TABLE = "password_reset_tokens";
|
|
280
|
-
var DEFAULT_AUTH_PASSWORD_EXPIRE = 60;
|
|
281
|
-
var DEFAULT_AUTH_PASSWORD_THROTTLE = 60;
|
|
282
|
-
var DEFAULT_AUTH_PASSWORD_RESET_ROUTE = "/reset-password";
|
|
283
|
-
var DEFAULT_AUTH_EMAIL_VERIFICATION_ROUTE = "/verify-email";
|
|
284
|
-
var DEFAULT_WORKOS_SESSION_COOKIE = "wos-session";
|
|
285
|
-
var DEFAULT_CLERK_SESSION_COOKIE = "__session";
|
|
286
|
-
var holoAuthDefaults = Object.freeze({
|
|
287
|
-
defaults: Object.freeze({
|
|
288
|
-
guard: DEFAULT_AUTH_GUARD,
|
|
289
|
-
passwords: DEFAULT_AUTH_PASSWORD_BROKER
|
|
290
|
-
}),
|
|
291
|
-
guards: Object.freeze({
|
|
292
|
-
web: Object.freeze({
|
|
293
|
-
name: "web",
|
|
294
|
-
driver: "session",
|
|
295
|
-
provider: DEFAULT_AUTH_PROVIDER
|
|
296
|
-
})
|
|
297
|
-
}),
|
|
298
|
-
providers: Object.freeze({
|
|
299
|
-
users: Object.freeze({
|
|
300
|
-
name: "users",
|
|
301
|
-
model: "User",
|
|
302
|
-
identifiers: DEFAULT_AUTH_IDENTIFIERS
|
|
303
|
-
})
|
|
304
|
-
}),
|
|
305
|
-
passwords: Object.freeze({
|
|
306
|
-
users: Object.freeze({
|
|
307
|
-
name: "users",
|
|
308
|
-
provider: DEFAULT_AUTH_PROVIDER,
|
|
309
|
-
table: DEFAULT_AUTH_PASSWORD_RESET_TABLE,
|
|
310
|
-
expire: DEFAULT_AUTH_PASSWORD_EXPIRE,
|
|
311
|
-
throttle: DEFAULT_AUTH_PASSWORD_THROTTLE,
|
|
312
|
-
route: DEFAULT_AUTH_PASSWORD_RESET_ROUTE
|
|
313
|
-
})
|
|
314
|
-
}),
|
|
315
|
-
emailVerification: Object.freeze({
|
|
316
|
-
required: false,
|
|
317
|
-
route: DEFAULT_AUTH_EMAIL_VERIFICATION_ROUTE
|
|
318
|
-
}),
|
|
319
|
-
personalAccessTokens: Object.freeze({
|
|
320
|
-
defaultAbilities: Object.freeze(["*"])
|
|
321
|
-
}),
|
|
322
|
-
socialEncryptionKey: void 0,
|
|
323
|
-
social: Object.freeze({}),
|
|
324
|
-
workos: Object.freeze({}),
|
|
325
|
-
clerk: Object.freeze({})
|
|
326
|
-
});
|
|
327
|
-
var DEFAULT_QUEUE_CONNECTION = "sync";
|
|
328
|
-
var DEFAULT_QUEUE_NAME = "default";
|
|
329
|
-
var DEFAULT_QUEUE_RETRY_AFTER = 90;
|
|
330
|
-
var DEFAULT_QUEUE_BLOCK_FOR = 5;
|
|
331
|
-
var DEFAULT_QUEUE_SLEEP = 1;
|
|
332
|
-
var DEFAULT_FAILED_JOBS_CONNECTION = "default";
|
|
333
|
-
var DEFAULT_FAILED_JOBS_TABLE = "failed_jobs";
|
|
334
|
-
var DEFAULT_DATABASE_QUEUE_TABLE = "jobs";
|
|
335
|
-
var DEFAULT_QUEUE_CONFIG = Object.freeze({
|
|
336
|
-
default: DEFAULT_QUEUE_CONNECTION,
|
|
337
|
-
failed: Object.freeze({
|
|
338
|
-
driver: "database",
|
|
339
|
-
connection: DEFAULT_FAILED_JOBS_CONNECTION,
|
|
340
|
-
table: DEFAULT_FAILED_JOBS_TABLE
|
|
341
|
-
}),
|
|
342
|
-
connections: Object.freeze({
|
|
343
|
-
[DEFAULT_QUEUE_CONNECTION]: Object.freeze({
|
|
344
|
-
name: DEFAULT_QUEUE_CONNECTION,
|
|
345
|
-
driver: "sync",
|
|
346
|
-
queue: DEFAULT_QUEUE_NAME
|
|
347
|
-
})
|
|
348
|
-
})
|
|
349
|
-
});
|
|
350
|
-
function parseIntegerCandidate(value, parser) {
|
|
351
|
-
if (typeof value === "number") {
|
|
352
|
-
return value;
|
|
353
|
-
}
|
|
354
|
-
const trimmed = value.trim();
|
|
355
|
-
if (!trimmed) {
|
|
356
|
-
return Number.NaN;
|
|
357
|
-
}
|
|
358
|
-
if (parser === "parse-int") {
|
|
359
|
-
return Number.parseInt(value, 10);
|
|
360
|
-
}
|
|
361
|
-
if (parser === "digits") {
|
|
362
|
-
return /^\d+$/.test(trimmed) ? Number.parseInt(trimmed, 10) : Number.NaN;
|
|
363
|
-
}
|
|
364
|
-
return Number(trimmed);
|
|
365
|
-
}
|
|
366
|
-
function parseScopedInteger(value, fallback, namespace, label, options = {}) {
|
|
367
|
-
const normalized = typeof value === "undefined" ? fallback : parseIntegerCandidate(value, options.parser ?? "number");
|
|
368
|
-
if (!Number.isFinite(normalized) || !Number.isInteger(normalized)) {
|
|
369
|
-
throw new Error(`[${namespace}] ${label} must be an integer.`);
|
|
370
|
-
}
|
|
371
|
-
if (typeof options.minimum === "number" && normalized < options.minimum) {
|
|
372
|
-
throw new Error(`[${namespace}] ${label} must be greater than or equal to ${options.minimum}.`);
|
|
373
|
-
}
|
|
374
|
-
return normalized;
|
|
375
|
-
}
|
|
376
|
-
function parseScopedOptionalInteger(value, namespace, label, options = {}) {
|
|
377
|
-
if (typeof value === "undefined") {
|
|
378
|
-
return void 0;
|
|
379
|
-
}
|
|
380
|
-
return parseScopedInteger(value, Number.NaN, namespace, label, options);
|
|
381
|
-
}
|
|
382
|
-
function parseInteger(value, fallback, namespace, label, options = {}) {
|
|
383
|
-
return parseScopedInteger(value, fallback, namespace, label, {
|
|
384
|
-
...options,
|
|
385
|
-
parser: "parse-int"
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
function normalizeNonEmptyString(value, label) {
|
|
389
|
-
const normalized = value?.trim();
|
|
390
|
-
if (!normalized) {
|
|
391
|
-
throw new Error(label);
|
|
392
|
-
}
|
|
393
|
-
return normalized;
|
|
394
|
-
}
|
|
395
|
-
function normalizeScopedName(value, namespace, label) {
|
|
396
|
-
const normalized = value?.trim();
|
|
397
|
-
if (!normalized) {
|
|
398
|
-
throw new Error(`[${namespace}] ${label} must be a non-empty string.`);
|
|
399
|
-
}
|
|
400
|
-
return normalized;
|
|
401
|
-
}
|
|
402
|
-
function normalizeConnectionName(value, namespace, label) {
|
|
403
|
-
return normalizeScopedName(value, namespace, label);
|
|
404
|
-
}
|
|
405
|
-
function normalizeCacheName(value, label) {
|
|
406
|
-
return normalizeScopedName(value, "Holo Cache", label);
|
|
407
|
-
}
|
|
408
|
-
function normalizeCacheOptionalString(value) {
|
|
409
|
-
const normalized = value?.trim();
|
|
410
|
-
return normalized || void 0;
|
|
411
|
-
}
|
|
412
|
-
function parseCacheInteger(value, label, options = {}) {
|
|
413
|
-
return parseScopedOptionalInteger(value, "Holo Cache", label, options);
|
|
414
|
-
}
|
|
415
|
-
function resolveCachePrefix(globalPrefix, localPrefix) {
|
|
416
|
-
return normalizeCacheOptionalString(localPrefix) ?? globalPrefix;
|
|
417
|
-
}
|
|
418
|
-
function normalizeCacheDriverConfig(name, config2, globalPrefix) {
|
|
419
|
-
switch (config2.driver) {
|
|
420
|
-
case "memory": {
|
|
421
|
-
const memoryConfig = config2;
|
|
422
|
-
return Object.freeze({
|
|
423
|
-
name,
|
|
424
|
-
driver: "memory",
|
|
425
|
-
prefix: resolveCachePrefix(globalPrefix, memoryConfig.prefix),
|
|
426
|
-
maxEntries: parseCacheInteger(memoryConfig.maxEntries, `cache driver "${name}" maxEntries`, {
|
|
427
|
-
minimum: 1
|
|
428
|
-
})
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
case "file": {
|
|
432
|
-
const fileConfig = config2;
|
|
433
|
-
return Object.freeze({
|
|
434
|
-
name,
|
|
435
|
-
driver: "file",
|
|
436
|
-
path: normalizeCacheOptionalString(fileConfig.path) || DEFAULT_CACHE_FILE_PATH,
|
|
437
|
-
prefix: resolveCachePrefix(globalPrefix, fileConfig.prefix)
|
|
438
|
-
});
|
|
439
|
-
}
|
|
440
|
-
case "redis": {
|
|
441
|
-
const redisConfig = config2;
|
|
442
|
-
return Object.freeze({
|
|
443
|
-
name,
|
|
444
|
-
driver: "redis",
|
|
445
|
-
connection: redisConfig.connection,
|
|
446
|
-
prefix: resolveCachePrefix(globalPrefix, redisConfig.prefix)
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
case "database": {
|
|
450
|
-
const databaseConfig = config2;
|
|
451
|
-
return Object.freeze({
|
|
452
|
-
name,
|
|
453
|
-
driver: "database",
|
|
454
|
-
connection: databaseConfig.connection,
|
|
455
|
-
table: normalizeCacheOptionalString(databaseConfig.table) || DEFAULT_CACHE_DATABASE_TABLE,
|
|
456
|
-
lockTable: normalizeCacheOptionalString(databaseConfig.lockTable) || DEFAULT_CACHE_DATABASE_LOCK_TABLE,
|
|
457
|
-
prefix: resolveCachePrefix(globalPrefix, databaseConfig.prefix)
|
|
458
|
-
});
|
|
459
|
-
}
|
|
460
|
-
default:
|
|
461
|
-
throw new Error(`[Holo Cache] Unsupported cache driver "${String(config2.driver)}" on driver "${name}".`);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
function normalizeCacheConfig(config2 = {}, options = {}) {
|
|
465
|
-
const prefix = normalizeCacheOptionalString(config2.prefix) ?? DEFAULT_CACHE_PREFIX;
|
|
466
|
-
const defaultRedisConnection = options.redis?.default ?? DEFAULT_CACHE_REDIS_CONNECTION;
|
|
467
|
-
const defaultDatabaseConnection = options.database?.defaultConnection ?? DEFAULT_CACHE_DATABASE_CONNECTION;
|
|
468
|
-
const driverEntries = !config2.drivers || Object.keys(config2.drivers).length === 0 ? Object.entries(holoCacheDefaults.drivers) : Object.entries(config2.drivers);
|
|
469
|
-
const normalizedDriverEntries = driverEntries.map(([name, driver]) => {
|
|
470
|
-
const normalizedName = normalizeCacheName(name, "Cache driver name");
|
|
471
|
-
const driverConfig = (() => {
|
|
472
|
-
switch (driver.driver) {
|
|
473
|
-
case "redis":
|
|
474
|
-
return {
|
|
475
|
-
...driver,
|
|
476
|
-
connection: normalizeCacheOptionalString(driver.connection) ?? defaultRedisConnection
|
|
477
|
-
};
|
|
478
|
-
case "database":
|
|
479
|
-
return {
|
|
480
|
-
...driver,
|
|
481
|
-
connection: normalizeCacheOptionalString(driver.connection) ?? defaultDatabaseConnection
|
|
482
|
-
};
|
|
483
|
-
default:
|
|
484
|
-
return driver;
|
|
485
|
-
}
|
|
486
|
-
})();
|
|
487
|
-
return [normalizedName, normalizeCacheDriverConfig(normalizedName, driverConfig, prefix)];
|
|
488
|
-
});
|
|
489
|
-
const drivers = Object.freeze(Object.fromEntries(normalizedDriverEntries));
|
|
490
|
-
const configuredDefault = normalizeCacheOptionalString(config2.default);
|
|
491
|
-
if (configuredDefault && !Object.hasOwn(drivers, configuredDefault)) {
|
|
492
|
-
throw new Error(`[Holo Cache] default cache driver "${configuredDefault}" is not configured.`);
|
|
493
|
-
}
|
|
494
|
-
const fallbackDefaultDriver = normalizedDriverEntries.find(([name]) => name === DEFAULT_CACHE_DRIVER)?.[0] ?? normalizedDriverEntries[0][0];
|
|
495
|
-
const defaultDriver = configuredDefault ?? fallbackDefaultDriver;
|
|
496
|
-
return Object.freeze({
|
|
497
|
-
default: defaultDriver,
|
|
498
|
-
prefix,
|
|
499
|
-
drivers
|
|
500
|
-
});
|
|
501
|
-
}
|
|
502
|
-
function normalizeQueueName(value) {
|
|
503
|
-
return value?.trim() || DEFAULT_QUEUE_NAME;
|
|
504
|
-
}
|
|
505
|
-
function parseRedisInteger(value, fallback, label, options = {}) {
|
|
506
|
-
return parseScopedInteger(value, fallback, "Holo Redis", label, {
|
|
507
|
-
...options,
|
|
508
|
-
parser: "digits"
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
function normalizeRedisConnectionName(value, label) {
|
|
512
|
-
return normalizeScopedName(value, "Holo Redis", label);
|
|
513
|
-
}
|
|
514
|
-
function normalizeOptionalRedisString(value, label) {
|
|
515
|
-
if (typeof value === "undefined") {
|
|
516
|
-
return void 0;
|
|
517
|
-
}
|
|
518
|
-
const normalized = normalizeRedisConnectionName(value, label);
|
|
519
|
-
try {
|
|
520
|
-
const parsed = new URL(normalized);
|
|
521
|
-
if (parsed.protocol !== "redis:" && parsed.protocol !== "rediss:") {
|
|
522
|
-
throw new Error(`[Holo Redis] ${label} must use the redis:// or rediss:// scheme.`);
|
|
523
|
-
}
|
|
524
|
-
} catch (error) {
|
|
525
|
-
if (error instanceof Error && error.message.startsWith("[Holo Redis]")) {
|
|
526
|
-
throw error;
|
|
527
|
-
}
|
|
528
|
-
throw new Error(`[Holo Redis] ${label} must be a valid redis:// or rediss:// URL.`);
|
|
529
|
-
}
|
|
530
|
-
return normalized;
|
|
531
|
-
}
|
|
532
|
-
function normalizeOptionalRedisSocketPath(value, label) {
|
|
533
|
-
if (typeof value === "undefined") {
|
|
534
|
-
return void 0;
|
|
535
|
-
}
|
|
536
|
-
return normalizeRedisConnectionName(value, label);
|
|
537
|
-
}
|
|
538
|
-
function deriveNormalizedRedisSocketPath(socketPath, host) {
|
|
539
|
-
if (socketPath) {
|
|
540
|
-
return socketPath;
|
|
541
|
-
}
|
|
542
|
-
if (typeof host === "string" && (host.startsWith("unix://") || host.startsWith("/"))) {
|
|
543
|
-
return host.startsWith("unix://") ? host.slice("unix://".length) : host;
|
|
544
|
-
}
|
|
545
|
-
return void 0;
|
|
546
|
-
}
|
|
547
|
-
function normalizeRedisClusterNodeConfig(connectionName, index, config2) {
|
|
548
|
-
const label = `redis connection "${connectionName}" cluster node ${index + 1}`;
|
|
549
|
-
const url = normalizeOptionalRedisString(config2.url, `${label} url`);
|
|
550
|
-
const socketPath = normalizeOptionalRedisSocketPath(config2.socketPath, `${label} socketPath`);
|
|
551
|
-
const normalizedSocketPath = deriveNormalizedRedisSocketPath(socketPath, config2.host?.trim());
|
|
552
|
-
if (typeof normalizedSocketPath !== "undefined") {
|
|
553
|
-
throw new Error(`[Holo Redis] ${label} cannot use socketPath in cluster mode.`);
|
|
554
|
-
}
|
|
555
|
-
parseRedisDatabaseFromUrl(url, {
|
|
556
|
-
allowPath: false,
|
|
557
|
-
label: `${label} url`
|
|
558
|
-
});
|
|
559
|
-
const host = config2.host?.trim() || DEFAULT_REDIS_HOST;
|
|
560
|
-
return Object.freeze({
|
|
561
|
-
...typeof url === "undefined" ? {} : { url },
|
|
562
|
-
host,
|
|
563
|
-
port: parseRedisInteger(config2.port, DEFAULT_REDIS_PORT, `${label} port`, {
|
|
564
|
-
minimum: 1
|
|
565
|
-
})
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
function normalizeRedisClusterNodes(connectionName, nodes) {
|
|
569
|
-
if (!nodes || nodes.length === 0) {
|
|
570
|
-
return void 0;
|
|
571
|
-
}
|
|
572
|
-
return Object.freeze(nodes.map((node, index) => normalizeRedisClusterNodeConfig(connectionName, index, node)));
|
|
573
|
-
}
|
|
574
|
-
function parseRedisDatabaseFromUrl(url, options) {
|
|
575
|
-
if (typeof url === "undefined") {
|
|
576
|
-
return void 0;
|
|
577
|
-
}
|
|
578
|
-
try {
|
|
579
|
-
const parsed = new URL(url);
|
|
580
|
-
const pathname = parsed.pathname.replace(/^\/+/, "");
|
|
581
|
-
if (!pathname) {
|
|
582
|
-
return void 0;
|
|
583
|
-
}
|
|
584
|
-
const [databaseSegment] = pathname.split("/");
|
|
585
|
-
const { label } = options;
|
|
586
|
-
if (options.allowPath === false) {
|
|
587
|
-
throw new Error(`[Holo Redis] ${label} cannot include a database path in cluster mode.`);
|
|
588
|
-
}
|
|
589
|
-
if (!databaseSegment || !/^\d+$/.test(databaseSegment) || pathname !== databaseSegment) {
|
|
590
|
-
throw new Error(`[Holo Redis] ${label} database path must be a single integer segment.`);
|
|
591
|
-
}
|
|
592
|
-
return Number.parseInt(databaseSegment, 10);
|
|
593
|
-
} catch (error) {
|
|
594
|
-
if (error instanceof Error && error.message.startsWith("[Holo Redis]")) {
|
|
595
|
-
throw error;
|
|
596
|
-
}
|
|
597
|
-
return void 0;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
function normalizeRedisConnectionConfig(name, config2) {
|
|
601
|
-
const url = normalizeOptionalRedisString(config2.url, `redis connection "${name}" url`);
|
|
602
|
-
const clusters = normalizeRedisClusterNodes(name, config2.clusters);
|
|
603
|
-
const socketPath = normalizeOptionalRedisSocketPath(config2.socketPath, `redis connection "${name}" socketPath`);
|
|
604
|
-
const normalizedSocketPath = deriveNormalizedRedisSocketPath(socketPath, config2.host?.trim());
|
|
605
|
-
const targetModeCount = [url, clusters, normalizedSocketPath].filter((value) => typeof value !== "undefined").length;
|
|
606
|
-
if (targetModeCount > 1) {
|
|
607
|
-
throw new Error(`[Holo Redis] redis connection "${name}" must configure exactly one target mode: url, clusters, or socketPath.`);
|
|
608
|
-
}
|
|
609
|
-
const host = config2.host?.trim() || normalizedSocketPath || DEFAULT_REDIS_HOST;
|
|
610
|
-
const databaseFromUrl = parseRedisDatabaseFromUrl(url, {
|
|
611
|
-
label: `redis connection "${name}" url`
|
|
612
|
-
});
|
|
613
|
-
const database = parseRedisInteger(config2.db ?? databaseFromUrl, DEFAULT_REDIS_DB, `redis connection "${name}" db`, {
|
|
614
|
-
minimum: 0
|
|
615
|
-
});
|
|
616
|
-
if (typeof clusters !== "undefined" && database !== 0) {
|
|
617
|
-
throw new Error(`[Holo Redis] redis connection "${name}" cannot select redis.db=${database} in cluster mode; Redis Cluster only supports database 0.`);
|
|
618
|
-
}
|
|
619
|
-
return Object.freeze({
|
|
620
|
-
name,
|
|
621
|
-
...typeof url === "undefined" ? {} : { url },
|
|
622
|
-
...typeof clusters === "undefined" ? {} : { clusters },
|
|
623
|
-
...typeof normalizedSocketPath === "undefined" ? {} : { socketPath: normalizedSocketPath },
|
|
624
|
-
host,
|
|
625
|
-
port: parseRedisInteger(config2.port, DEFAULT_REDIS_PORT, `redis connection "${name}" port`, {
|
|
626
|
-
minimum: 1
|
|
627
|
-
}),
|
|
628
|
-
username: config2.username?.trim() || void 0,
|
|
629
|
-
password: config2.password?.trim() || void 0,
|
|
630
|
-
db: database
|
|
631
|
-
});
|
|
632
|
-
}
|
|
633
|
-
function normalizeRedisConnections(connections) {
|
|
634
|
-
if (!connections || Object.keys(connections).length === 0) {
|
|
635
|
-
return holoRedisDefaults.connections;
|
|
636
|
-
}
|
|
637
|
-
return Object.freeze(Object.fromEntries(
|
|
638
|
-
Object.entries(connections).map(([name, config2]) => {
|
|
639
|
-
const normalizedName = normalizeRedisConnectionName(name, "Redis connection name");
|
|
640
|
-
return [normalizedName, normalizeRedisConnectionConfig(normalizedName, config2)];
|
|
641
|
-
})
|
|
642
|
-
));
|
|
643
|
-
}
|
|
644
|
-
function resolveNormalizedRedisConnection(redisConfig, connectionName, label) {
|
|
645
|
-
const { connections } = redisConfig;
|
|
646
|
-
const resolved = connections[connectionName];
|
|
647
|
-
if (!resolved) {
|
|
648
|
-
throw new Error(`[Holo Redis] ${label} "${connectionName}" is not configured.`);
|
|
649
|
-
}
|
|
650
|
-
return resolved;
|
|
651
|
-
}
|
|
652
|
-
function parseSecurityInteger(value, fallback, label, options = {}) {
|
|
653
|
-
return parseScopedInteger(value, fallback, "Holo Security", label, options);
|
|
654
|
-
}
|
|
655
|
-
function normalizeSecurityName(value, label) {
|
|
656
|
-
return normalizeScopedName(value, "Holo Security", label);
|
|
657
|
-
}
|
|
658
|
-
function normalizeSecurityOptionalString(value) {
|
|
659
|
-
const normalized = value?.trim();
|
|
660
|
-
return normalized || void 0;
|
|
661
|
-
}
|
|
662
|
-
function normalizeCorsStringList(values, defaults, label) {
|
|
663
|
-
if (!values) {
|
|
664
|
-
return defaults;
|
|
665
|
-
}
|
|
666
|
-
return Object.freeze(values.map((value, index) => {
|
|
667
|
-
const normalized = value.trim();
|
|
668
|
-
if (!normalized) {
|
|
669
|
-
throw new Error(`[Holo CORS] ${label} entry at index ${index} must be a non-empty string.`);
|
|
670
|
-
}
|
|
671
|
-
return normalized;
|
|
672
|
-
}));
|
|
673
|
-
}
|
|
674
|
-
function normalizeCorsMethods(values) {
|
|
675
|
-
return Object.freeze(normalizeCorsStringList(values, DEFAULT_CORS_METHODS, "methods").map((value) => value.toUpperCase()));
|
|
676
|
-
}
|
|
677
|
-
function normalizeCorsMaxAge(value) {
|
|
678
|
-
return parseSecurityInteger(value ?? DEFAULT_CORS_MAX_AGE, DEFAULT_CORS_MAX_AGE, "cors maxAge", {
|
|
679
|
-
minimum: 0
|
|
680
|
-
});
|
|
681
|
-
}
|
|
682
|
-
function normalizeCorsConfig(config2 = {}) {
|
|
683
|
-
return Object.freeze({
|
|
684
|
-
paths: normalizeCorsStringList(config2.paths, DEFAULT_CORS_PATHS, "paths"),
|
|
685
|
-
origins: normalizeCorsStringList(config2.origins, holoCorsDefaults.origins, "origins"),
|
|
686
|
-
methods: normalizeCorsMethods(config2.methods),
|
|
687
|
-
headers: normalizeCorsStringList(config2.headers, DEFAULT_CORS_HEADERS, "headers"),
|
|
688
|
-
credentials: config2.credentials ?? holoCorsDefaults.credentials,
|
|
689
|
-
maxAge: normalizeCorsMaxAge(config2.maxAge),
|
|
690
|
-
statefulDomains: normalizeCorsStringList(config2.statefulDomains, holoCorsDefaults.statefulDomains, "statefulDomains")
|
|
691
|
-
});
|
|
692
|
-
}
|
|
693
|
-
function normalizeSyncConnection(name, config2) {
|
|
694
|
-
return Object.freeze({
|
|
695
|
-
name,
|
|
696
|
-
driver: "sync",
|
|
697
|
-
queue: normalizeQueueName(config2.queue)
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
function normalizeRedisConnection(name, config2, redisConfig) {
|
|
701
|
-
const explicitConnectionName = config2.connection?.trim();
|
|
702
|
-
const connectionName = explicitConnectionName || redisConfig?.default;
|
|
703
|
-
if (!connectionName) {
|
|
704
|
-
throw new Error(
|
|
705
|
-
`[@holo-js/config] Queue Redis connection "${name}" requires a top-level redis config with a default connection or an explicit connection name.`
|
|
706
|
-
);
|
|
707
|
-
}
|
|
708
|
-
if (!redisConfig) {
|
|
709
|
-
throw new Error(
|
|
710
|
-
`[@holo-js/config] Queue Redis connection "${name}" references shared Redis connection "${connectionName}" but no top-level redis config is loaded.`
|
|
711
|
-
);
|
|
712
|
-
}
|
|
713
|
-
const resolvedRedisConnection = resolveNormalizedRedisConnection(
|
|
714
|
-
redisConfig,
|
|
715
|
-
connectionName,
|
|
716
|
-
"Queue Redis connection"
|
|
717
|
-
);
|
|
718
|
-
return Object.freeze({
|
|
719
|
-
name,
|
|
720
|
-
driver: "redis",
|
|
721
|
-
connection: resolvedRedisConnection.name,
|
|
722
|
-
queue: normalizeQueueName(config2.queue),
|
|
723
|
-
retryAfter: parseInteger(config2.retryAfter, DEFAULT_QUEUE_RETRY_AFTER, "Holo Queue", `queue connection "${name}" retryAfter`, {
|
|
724
|
-
minimum: 0
|
|
725
|
-
}),
|
|
726
|
-
blockFor: parseInteger(config2.blockFor, DEFAULT_QUEUE_BLOCK_FOR, "Holo Queue", `queue connection "${name}" blockFor`, {
|
|
727
|
-
minimum: 0
|
|
728
|
-
}),
|
|
729
|
-
redis: Object.freeze({
|
|
730
|
-
...typeof resolvedRedisConnection.url === "undefined" ? {} : { url: resolvedRedisConnection.url },
|
|
731
|
-
...typeof resolvedRedisConnection.clusters === "undefined" ? {} : { clusters: resolvedRedisConnection.clusters },
|
|
732
|
-
host: resolvedRedisConnection.host,
|
|
733
|
-
port: resolvedRedisConnection.port,
|
|
734
|
-
password: resolvedRedisConnection.password,
|
|
735
|
-
username: resolvedRedisConnection.username,
|
|
736
|
-
db: resolvedRedisConnection.db
|
|
737
|
-
})
|
|
738
|
-
});
|
|
739
|
-
}
|
|
740
|
-
function normalizeDatabaseConnection(name, config2) {
|
|
741
|
-
return Object.freeze({
|
|
742
|
-
name,
|
|
743
|
-
driver: "database",
|
|
744
|
-
queue: normalizeQueueName(config2.queue),
|
|
745
|
-
retryAfter: parseInteger(config2.retryAfter, DEFAULT_QUEUE_RETRY_AFTER, "Holo Queue", `queue connection "${name}" retryAfter`, {
|
|
746
|
-
minimum: 0
|
|
747
|
-
}),
|
|
748
|
-
sleep: parseInteger(config2.sleep, DEFAULT_QUEUE_SLEEP, "Holo Queue", `queue connection "${name}" sleep`, {
|
|
749
|
-
minimum: 0
|
|
750
|
-
}),
|
|
751
|
-
connection: config2.connection?.trim() || DEFAULT_FAILED_JOBS_CONNECTION,
|
|
752
|
-
table: config2.table?.trim() || DEFAULT_DATABASE_QUEUE_TABLE
|
|
753
|
-
});
|
|
754
|
-
}
|
|
755
|
-
function normalizeConnectionConfig(name, config2, redisConfig) {
|
|
756
|
-
switch (config2.driver) {
|
|
757
|
-
case "sync":
|
|
758
|
-
return normalizeSyncConnection(name, config2);
|
|
759
|
-
case "redis":
|
|
760
|
-
return normalizeRedisConnection(name, config2, redisConfig);
|
|
761
|
-
case "database":
|
|
762
|
-
return normalizeDatabaseConnection(name, config2);
|
|
763
|
-
default:
|
|
764
|
-
throw new Error(`[Holo Queue] Unsupported queue driver "${String(config2.driver)}" on connection "${name}".`);
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
function normalizeConnections(connections, redisConfig) {
|
|
768
|
-
if (!connections || Object.keys(connections).length === 0) {
|
|
769
|
-
return DEFAULT_QUEUE_CONFIG.connections;
|
|
770
|
-
}
|
|
771
|
-
const normalizedEntries = Object.entries(connections).map(([name, config2]) => {
|
|
772
|
-
const normalizedName = normalizeConnectionName(name, "Holo Queue", "Queue connection name");
|
|
773
|
-
return [normalizedName, normalizeConnectionConfig(normalizedName, config2, redisConfig)];
|
|
774
|
-
});
|
|
775
|
-
return Object.freeze(Object.fromEntries(normalizedEntries));
|
|
776
|
-
}
|
|
777
|
-
function normalizeFailedStore(config2) {
|
|
778
|
-
if (config2 === false) {
|
|
779
|
-
return false;
|
|
780
|
-
}
|
|
781
|
-
const normalized = config2 ?? DEFAULT_QUEUE_CONFIG.failed;
|
|
782
|
-
if (normalized.driver && normalized.driver !== "database") {
|
|
783
|
-
throw new Error(`[Holo Queue] Unsupported failed job store driver "${normalized.driver}".`);
|
|
784
|
-
}
|
|
785
|
-
return Object.freeze({
|
|
786
|
-
driver: "database",
|
|
787
|
-
connection: normalized.connection?.trim() || DEFAULT_FAILED_JOBS_CONNECTION,
|
|
788
|
-
table: normalized.table?.trim() || DEFAULT_FAILED_JOBS_TABLE
|
|
789
|
-
});
|
|
790
|
-
}
|
|
791
|
-
var holoQueueDefaultsNormalized = DEFAULT_QUEUE_CONFIG;
|
|
792
26
|
function normalizeAppEnv(value, fallback = "development") {
|
|
793
27
|
if (!value) {
|
|
794
28
|
return fallback;
|
|
@@ -808,893 +42,13 @@ function normalizeAppConfig(config2 = {}) {
|
|
|
808
42
|
url: config2.url ?? holoAppDefaults.url,
|
|
809
43
|
debug: debug ?? holoAppDefaults.debug,
|
|
810
44
|
env: normalizeAppEnv(config2.env, holoAppDefaults.env),
|
|
45
|
+
plugins: Object.freeze([...new Set((config2.plugins ?? []).map((plugin) => plugin.trim()).filter((plugin) => plugin.length > 0))]),
|
|
811
46
|
paths: project.paths,
|
|
812
47
|
models: project.models,
|
|
813
48
|
migrations: project.migrations,
|
|
814
49
|
seeders: project.seeders
|
|
815
50
|
});
|
|
816
51
|
}
|
|
817
|
-
function normalizeSessionStoreConfig(name, config2, redisConfig) {
|
|
818
|
-
switch (config2.driver) {
|
|
819
|
-
case "database": {
|
|
820
|
-
const databaseConfig = config2;
|
|
821
|
-
return Object.freeze({
|
|
822
|
-
name,
|
|
823
|
-
driver: "database",
|
|
824
|
-
connection: databaseConfig.connection?.trim() || DEFAULT_SESSION_DATABASE_CONNECTION,
|
|
825
|
-
table: databaseConfig.table?.trim() || DEFAULT_SESSION_DATABASE_TABLE
|
|
826
|
-
});
|
|
827
|
-
}
|
|
828
|
-
case "file": {
|
|
829
|
-
const fileConfig = config2;
|
|
830
|
-
return Object.freeze({
|
|
831
|
-
name,
|
|
832
|
-
driver: "file",
|
|
833
|
-
path: fileConfig.path?.trim() || DEFAULT_SESSION_FILE_PATH
|
|
834
|
-
});
|
|
835
|
-
}
|
|
836
|
-
case "redis": {
|
|
837
|
-
const redisStoreConfig = config2;
|
|
838
|
-
const configuredConnection = redisStoreConfig.connection?.trim();
|
|
839
|
-
const connectionName = configuredConnection || redisConfig?.default;
|
|
840
|
-
if (!connectionName) {
|
|
841
|
-
throw new Error(
|
|
842
|
-
`[@holo-js/config] Session Redis store "${name}" requires a top-level redis config with a default connection or an explicit connection name.`
|
|
843
|
-
);
|
|
844
|
-
}
|
|
845
|
-
if (!redisConfig) {
|
|
846
|
-
throw new Error(
|
|
847
|
-
`[@holo-js/config] Session Redis store "${name}" references shared Redis connection "${connectionName}" but no top-level redis config is loaded.`
|
|
848
|
-
);
|
|
849
|
-
}
|
|
850
|
-
const resolvedConnection = resolveNormalizedRedisConnection(
|
|
851
|
-
redisConfig,
|
|
852
|
-
connectionName,
|
|
853
|
-
"Session Redis store"
|
|
854
|
-
);
|
|
855
|
-
return Object.freeze({
|
|
856
|
-
name,
|
|
857
|
-
driver: "redis",
|
|
858
|
-
connection: resolvedConnection.name,
|
|
859
|
-
...typeof resolvedConnection.url === "undefined" ? {} : { url: resolvedConnection.url },
|
|
860
|
-
...typeof resolvedConnection.clusters === "undefined" ? {} : { clusters: resolvedConnection.clusters },
|
|
861
|
-
host: resolvedConnection.host,
|
|
862
|
-
port: resolvedConnection.port,
|
|
863
|
-
username: resolvedConnection.username,
|
|
864
|
-
password: resolvedConnection.password,
|
|
865
|
-
db: resolvedConnection.db,
|
|
866
|
-
prefix: redisStoreConfig.prefix?.trim() || ""
|
|
867
|
-
});
|
|
868
|
-
}
|
|
869
|
-
default:
|
|
870
|
-
throw new Error(`[Holo Session] Unsupported session store driver "${String(config2.driver)}" on store "${name}".`);
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
function normalizeSessionConfig(config2 = {}, redisConfig) {
|
|
874
|
-
const stores = !config2.stores || Object.keys(config2.stores).length === 0 ? holoSessionDefaults.stores : Object.freeze(Object.fromEntries(Object.entries(config2.stores).map(([name, store]) => {
|
|
875
|
-
const normalizedName = normalizeConnectionName(name, "Holo Session", "Session store name");
|
|
876
|
-
return [normalizedName, normalizeSessionStoreConfig(normalizedName, store, redisConfig)];
|
|
877
|
-
})));
|
|
878
|
-
const configuredDriver = config2.driver?.trim();
|
|
879
|
-
const driver = configuredDriver || (DEFAULT_SESSION_DRIVER in stores ? DEFAULT_SESSION_DRIVER : void 0) || Object.keys(stores)[0] || DEFAULT_SESSION_DRIVER;
|
|
880
|
-
if (!(driver in stores)) {
|
|
881
|
-
throw new Error(`[Holo Session] default session driver "${driver}" is not configured.`);
|
|
882
|
-
}
|
|
883
|
-
const cookie = config2.cookie ?? {};
|
|
884
|
-
const sameSite = cookie.sameSite ?? DEFAULT_SESSION_COOKIE_SAME_SITE;
|
|
885
|
-
if (sameSite !== "lax" && sameSite !== "strict" && sameSite !== "none") {
|
|
886
|
-
throw new Error(`[Holo Session] cookie sameSite must be "lax", "strict", or "none".`);
|
|
887
|
-
}
|
|
888
|
-
const idleTimeout = parseInteger(config2.idleTimeout, DEFAULT_SESSION_IDLE_TIMEOUT, "Holo Session", "session idleTimeout", {
|
|
889
|
-
minimum: 0
|
|
890
|
-
});
|
|
891
|
-
const absoluteLifetime = parseInteger(
|
|
892
|
-
config2.absoluteLifetime,
|
|
893
|
-
DEFAULT_SESSION_ABSOLUTE_LIFETIME,
|
|
894
|
-
"Holo Session",
|
|
895
|
-
"session absoluteLifetime",
|
|
896
|
-
{
|
|
897
|
-
minimum: 0
|
|
898
|
-
}
|
|
899
|
-
);
|
|
900
|
-
const rememberMeLifetime = parseInteger(
|
|
901
|
-
config2.rememberMeLifetime,
|
|
902
|
-
DEFAULT_SESSION_REMEMBER_ME_LIFETIME,
|
|
903
|
-
"Holo Session",
|
|
904
|
-
"session rememberMeLifetime",
|
|
905
|
-
{
|
|
906
|
-
minimum: 0
|
|
907
|
-
}
|
|
908
|
-
);
|
|
909
|
-
return Object.freeze({
|
|
910
|
-
driver,
|
|
911
|
-
stores,
|
|
912
|
-
cookie: Object.freeze({
|
|
913
|
-
name: cookie.name?.trim() || DEFAULT_SESSION_COOKIE_NAME,
|
|
914
|
-
path: cookie.path?.trim() || DEFAULT_SESSION_COOKIE_PATH,
|
|
915
|
-
domain: cookie.domain?.trim() || void 0,
|
|
916
|
-
secure: cookie.secure ?? false,
|
|
917
|
-
httpOnly: cookie.httpOnly ?? true,
|
|
918
|
-
sameSite,
|
|
919
|
-
partitioned: cookie.partitioned ?? false,
|
|
920
|
-
maxAge: parseInteger(cookie.maxAge, absoluteLifetime, "Holo Session", "session cookie maxAge", {
|
|
921
|
-
minimum: 0
|
|
922
|
-
})
|
|
923
|
-
}),
|
|
924
|
-
idleTimeout,
|
|
925
|
-
absoluteLifetime,
|
|
926
|
-
rememberMeLifetime
|
|
927
|
-
});
|
|
928
|
-
}
|
|
929
|
-
function normalizeSecurityLimiter(name, config2) {
|
|
930
|
-
const key = typeof config2.key === "function" ? config2.key : void 0;
|
|
931
|
-
if (typeof config2.key !== "undefined" && typeof config2.key !== "function") {
|
|
932
|
-
throw new Error(`[Holo Security] rate limiter "${name}" key resolver must be a function when provided.`);
|
|
933
|
-
}
|
|
934
|
-
return Object.freeze({
|
|
935
|
-
name,
|
|
936
|
-
maxAttempts: parseSecurityInteger(config2.maxAttempts, 0, `rate limiter "${name}" maxAttempts`, {
|
|
937
|
-
minimum: 1
|
|
938
|
-
}),
|
|
939
|
-
decaySeconds: parseSecurityInteger(config2.decaySeconds, 0, `rate limiter "${name}" decaySeconds`, {
|
|
940
|
-
minimum: 1
|
|
941
|
-
}),
|
|
942
|
-
...key ? { key } : {}
|
|
943
|
-
});
|
|
944
|
-
}
|
|
945
|
-
function normalizeSecurityRateLimitConfig(config2, redisConfig) {
|
|
946
|
-
const driver = normalizeSecurityOptionalString(config2?.driver) || DEFAULT_SECURITY_RATE_LIMIT_DRIVER;
|
|
947
|
-
if (driver !== "memory" && driver !== "file" && driver !== "redis") {
|
|
948
|
-
throw new Error(`[Holo Security] Unsupported rate limit driver "${driver}".`);
|
|
949
|
-
}
|
|
950
|
-
const file = config2?.file ?? {};
|
|
951
|
-
const redis = config2?.redis ?? {};
|
|
952
|
-
const limiters = !config2?.limiters || Object.keys(config2.limiters).length === 0 ? holoSecurityDefaults.rateLimit.limiters : Object.freeze(Object.fromEntries(Object.entries(config2.limiters).map(([name, limiter]) => {
|
|
953
|
-
const normalizedName = normalizeSecurityName(name, "Rate limiter name");
|
|
954
|
-
return [normalizedName, normalizeSecurityLimiter(normalizedName, limiter)];
|
|
955
|
-
})));
|
|
956
|
-
return Object.freeze({
|
|
957
|
-
driver,
|
|
958
|
-
memory: Object.freeze({
|
|
959
|
-
driver: "memory"
|
|
960
|
-
}),
|
|
961
|
-
file: Object.freeze({
|
|
962
|
-
path: normalizeSecurityOptionalString(file.path) || DEFAULT_SECURITY_RATE_LIMIT_FILE_PATH
|
|
963
|
-
}),
|
|
964
|
-
redis: Object.freeze((() => {
|
|
965
|
-
const connectionName = normalizeSecurityOptionalString(redis.connection) || redisConfig?.default || DEFAULT_SECURITY_RATE_LIMIT_REDIS_CONNECTION;
|
|
966
|
-
const resolvedConnection = redisConfig ? resolveNormalizedRedisConnection(
|
|
967
|
-
redisConfig,
|
|
968
|
-
connectionName,
|
|
969
|
-
"Security rate-limit Redis connection"
|
|
970
|
-
) : driver === "redis" ? (() => {
|
|
971
|
-
throw new Error(
|
|
972
|
-
`[@holo-js/config] Security rate-limit Redis config references shared Redis connection "${connectionName}" but no top-level redis config is loaded.`
|
|
973
|
-
);
|
|
974
|
-
})() : {
|
|
975
|
-
name: connectionName,
|
|
976
|
-
host: DEFAULT_REDIS_HOST,
|
|
977
|
-
port: DEFAULT_REDIS_PORT,
|
|
978
|
-
password: void 0,
|
|
979
|
-
username: void 0,
|
|
980
|
-
db: DEFAULT_REDIS_DB
|
|
981
|
-
};
|
|
982
|
-
return {
|
|
983
|
-
...typeof resolvedConnection.url === "undefined" ? {} : { url: resolvedConnection.url },
|
|
984
|
-
...typeof resolvedConnection.clusters === "undefined" ? {} : { clusters: resolvedConnection.clusters },
|
|
985
|
-
host: resolvedConnection.host,
|
|
986
|
-
port: resolvedConnection.port,
|
|
987
|
-
password: resolvedConnection.password,
|
|
988
|
-
username: resolvedConnection.username,
|
|
989
|
-
db: resolvedConnection.db,
|
|
990
|
-
connection: resolvedConnection.name,
|
|
991
|
-
prefix: normalizeSecurityOptionalString(redis.prefix) || DEFAULT_SECURITY_RATE_LIMIT_REDIS_PREFIX
|
|
992
|
-
};
|
|
993
|
-
})()),
|
|
994
|
-
limiters
|
|
995
|
-
});
|
|
996
|
-
}
|
|
997
|
-
function normalizeSecurityConfig(config2 = {}, redisConfig) {
|
|
998
|
-
const csrf = typeof config2.csrf === "boolean" ? { enabled: config2.csrf } : config2.csrf ?? {};
|
|
999
|
-
const except = csrf.except ? Object.freeze(csrf.except.map((value, index) => {
|
|
1000
|
-
const normalized = value.trim();
|
|
1001
|
-
if (!normalized) {
|
|
1002
|
-
throw new Error(`[Holo Security] csrf except entry at index ${index} must be a non-empty string.`);
|
|
1003
|
-
}
|
|
1004
|
-
return normalized;
|
|
1005
|
-
})) : DEFAULT_SECURITY_CSRF_CONFIG.except;
|
|
1006
|
-
return Object.freeze({
|
|
1007
|
-
csrf: Object.freeze({
|
|
1008
|
-
enabled: csrf.enabled ?? DEFAULT_SECURITY_CSRF_CONFIG.enabled,
|
|
1009
|
-
field: normalizeSecurityOptionalString(csrf.field) || DEFAULT_SECURITY_CSRF_FIELD,
|
|
1010
|
-
header: normalizeSecurityOptionalString(csrf.header) || DEFAULT_SECURITY_CSRF_HEADER,
|
|
1011
|
-
cookie: normalizeSecurityOptionalString(csrf.cookie) || DEFAULT_SECURITY_CSRF_COOKIE,
|
|
1012
|
-
except
|
|
1013
|
-
}),
|
|
1014
|
-
rateLimit: normalizeSecurityRateLimitConfig(config2.rateLimit, redisConfig)
|
|
1015
|
-
});
|
|
1016
|
-
}
|
|
1017
|
-
function normalizeAuthProvider(name, config2) {
|
|
1018
|
-
const identifiers = Object.freeze(
|
|
1019
|
-
Array.from(new Set((config2.identifiers ?? DEFAULT_AUTH_IDENTIFIERS).map((value) => normalizeNonEmptyString(value, `[Holo Auth] provider "${name}" identifier entries must be non-empty strings.`))))
|
|
1020
|
-
);
|
|
1021
|
-
if (identifiers.length === 0) {
|
|
1022
|
-
throw new Error(`[Holo Auth] provider "${name}" must declare at least one identifier.`);
|
|
1023
|
-
}
|
|
1024
|
-
return Object.freeze({
|
|
1025
|
-
name,
|
|
1026
|
-
model: normalizeNonEmptyString(config2.model, `[Holo Auth] provider "${name}" model must be a non-empty string.`),
|
|
1027
|
-
identifiers
|
|
1028
|
-
});
|
|
1029
|
-
}
|
|
1030
|
-
function normalizeAuthGuard(name, config2, providers) {
|
|
1031
|
-
const provider = config2.provider?.trim() || DEFAULT_AUTH_PROVIDER;
|
|
1032
|
-
if (!(provider in providers)) {
|
|
1033
|
-
throw new Error(`[Holo Auth] guard "${name}" references unknown provider "${provider}".`);
|
|
1034
|
-
}
|
|
1035
|
-
if (config2.driver !== "session" && config2.driver !== "token") {
|
|
1036
|
-
throw new Error(`[Holo Auth] Unsupported auth guard driver "${String(config2.driver)}" on guard "${name}".`);
|
|
1037
|
-
}
|
|
1038
|
-
return Object.freeze({
|
|
1039
|
-
name,
|
|
1040
|
-
driver: config2.driver,
|
|
1041
|
-
provider
|
|
1042
|
-
});
|
|
1043
|
-
}
|
|
1044
|
-
function normalizePasswordBroker(name, config2, providers) {
|
|
1045
|
-
const provider = config2.provider?.trim() || DEFAULT_AUTH_PROVIDER;
|
|
1046
|
-
if (!(provider in providers)) {
|
|
1047
|
-
throw new Error(`[Holo Auth] password broker "${name}" references unknown provider "${provider}".`);
|
|
1048
|
-
}
|
|
1049
|
-
return Object.freeze({
|
|
1050
|
-
name,
|
|
1051
|
-
provider,
|
|
1052
|
-
table: config2.table?.trim() || DEFAULT_AUTH_PASSWORD_RESET_TABLE,
|
|
1053
|
-
expire: parseInteger(config2.expire, DEFAULT_AUTH_PASSWORD_EXPIRE, "Holo Auth", `auth password broker "${name}" expire`, {
|
|
1054
|
-
minimum: 0
|
|
1055
|
-
}),
|
|
1056
|
-
throttle: parseInteger(config2.throttle, DEFAULT_AUTH_PASSWORD_THROTTLE, "Holo Auth", `auth password broker "${name}" throttle`, {
|
|
1057
|
-
minimum: 0
|
|
1058
|
-
}),
|
|
1059
|
-
route: config2.route?.trim() || DEFAULT_AUTH_PASSWORD_RESET_ROUTE
|
|
1060
|
-
});
|
|
1061
|
-
}
|
|
1062
|
-
function normalizeSocialProvider(name, config2, guards, providers) {
|
|
1063
|
-
const guard = config2.guard?.trim();
|
|
1064
|
-
if (guard && !(guard in guards)) {
|
|
1065
|
-
throw new Error(`[Holo Auth] social provider "${name}" references unknown guard "${guard}".`);
|
|
1066
|
-
}
|
|
1067
|
-
const mapToProvider = config2.mapToProvider?.trim();
|
|
1068
|
-
if (mapToProvider && !(mapToProvider in providers)) {
|
|
1069
|
-
throw new Error(`[Holo Auth] social provider "${name}" references unknown provider "${mapToProvider}".`);
|
|
1070
|
-
}
|
|
1071
|
-
return Object.freeze({
|
|
1072
|
-
name,
|
|
1073
|
-
runtime: config2.runtime?.trim() || void 0,
|
|
1074
|
-
clientId: config2.clientId?.trim() || void 0,
|
|
1075
|
-
clientSecret: config2.clientSecret?.trim() || void 0,
|
|
1076
|
-
redirectUri: config2.redirectUri?.trim() || void 0,
|
|
1077
|
-
scopes: Object.freeze([...config2.scopes ?? []]),
|
|
1078
|
-
guard,
|
|
1079
|
-
mapToProvider,
|
|
1080
|
-
encryptTokens: config2.encryptTokens === true
|
|
1081
|
-
});
|
|
1082
|
-
}
|
|
1083
|
-
function normalizeWorkosProvider(name, config2, guards, providers) {
|
|
1084
|
-
const guard = config2.guard?.trim();
|
|
1085
|
-
if (guard && !(guard in guards)) {
|
|
1086
|
-
throw new Error(`[Holo Auth] WorkOS provider "${name}" references unknown guard "${guard}".`);
|
|
1087
|
-
}
|
|
1088
|
-
const mapToProvider = config2.mapToProvider?.trim();
|
|
1089
|
-
if (mapToProvider && !(mapToProvider in providers)) {
|
|
1090
|
-
throw new Error(`[Holo Auth] WorkOS provider "${name}" references unknown provider "${mapToProvider}".`);
|
|
1091
|
-
}
|
|
1092
|
-
return Object.freeze({
|
|
1093
|
-
name,
|
|
1094
|
-
clientId: config2.clientId?.trim() || void 0,
|
|
1095
|
-
apiKey: config2.apiKey?.trim() || void 0,
|
|
1096
|
-
redirectUri: config2.redirectUri?.trim() || void 0,
|
|
1097
|
-
sessionCookie: DEFAULT_WORKOS_SESSION_COOKIE,
|
|
1098
|
-
guard,
|
|
1099
|
-
mapToProvider
|
|
1100
|
-
});
|
|
1101
|
-
}
|
|
1102
|
-
function isHostedIdentityStore(value) {
|
|
1103
|
-
return Boolean(value) && typeof value === "object" && typeof value.findByProviderUserId === "function" && typeof value.findByUserId === "function" && typeof value.save === "function";
|
|
1104
|
-
}
|
|
1105
|
-
function isWorkosProviderConfig(value) {
|
|
1106
|
-
return typeof value === "object" && value !== null && !isHostedIdentityStore(value);
|
|
1107
|
-
}
|
|
1108
|
-
function getWorkosProviderEntries(config2) {
|
|
1109
|
-
if (!config2) {
|
|
1110
|
-
return Object.freeze([]);
|
|
1111
|
-
}
|
|
1112
|
-
const entries = [];
|
|
1113
|
-
for (const [name, value] of Object.entries(config2)) {
|
|
1114
|
-
if (name === "provider") {
|
|
1115
|
-
if (typeof value !== "undefined" && typeof value !== "string") {
|
|
1116
|
-
throw new Error('[Holo Auth] WorkOS provider key "provider" is reserved for the default provider name.');
|
|
1117
|
-
}
|
|
1118
|
-
continue;
|
|
1119
|
-
}
|
|
1120
|
-
if (name === "identityStore") {
|
|
1121
|
-
if (typeof value !== "undefined" && !isHostedIdentityStore(value)) {
|
|
1122
|
-
throw new Error("[Holo Auth] WorkOS identityStore must implement the hosted identity store contract.");
|
|
1123
|
-
}
|
|
1124
|
-
continue;
|
|
1125
|
-
}
|
|
1126
|
-
if (!isWorkosProviderConfig(value)) {
|
|
1127
|
-
throw new Error(`[Holo Auth] WorkOS provider "${name}" must be an object.`);
|
|
1128
|
-
}
|
|
1129
|
-
entries.push([name, value]);
|
|
1130
|
-
}
|
|
1131
|
-
return Object.freeze(entries);
|
|
1132
|
-
}
|
|
1133
|
-
function normalizeWorkosConfig(config2, guards, providers) {
|
|
1134
|
-
const providerEntries = getWorkosProviderEntries(config2);
|
|
1135
|
-
const provider = typeof config2?.provider === "string" ? config2.provider.trim() || void 0 : void 0;
|
|
1136
|
-
if (providerEntries.length === 0) {
|
|
1137
|
-
if (provider) {
|
|
1138
|
-
throw new Error(`[Holo Auth] WorkOS provider "${provider}" is not configured.`);
|
|
1139
|
-
}
|
|
1140
|
-
if (config2?.identityStore) {
|
|
1141
|
-
return Object.freeze({
|
|
1142
|
-
identityStore: config2.identityStore
|
|
1143
|
-
});
|
|
1144
|
-
}
|
|
1145
|
-
return holoAuthDefaults.workos;
|
|
1146
|
-
}
|
|
1147
|
-
const normalizedEntries = providerEntries.map(([name, providerConfig]) => {
|
|
1148
|
-
const normalizedName = normalizeConnectionName(name, "Holo Auth", "Auth WorkOS provider name");
|
|
1149
|
-
return [normalizedName, providerConfig];
|
|
1150
|
-
});
|
|
1151
|
-
if (provider && !normalizedEntries.some(([name]) => name === provider)) {
|
|
1152
|
-
throw new Error(`[Holo Auth] WorkOS provider "${provider}" is not configured.`);
|
|
1153
|
-
}
|
|
1154
|
-
return Object.freeze({
|
|
1155
|
-
...typeof provider === "undefined" ? {} : { provider },
|
|
1156
|
-
...config2?.identityStore ? { identityStore: config2.identityStore } : {},
|
|
1157
|
-
...Object.fromEntries(normalizedEntries.map(([name, providerConfig]) => [
|
|
1158
|
-
name,
|
|
1159
|
-
normalizeWorkosProvider(name, providerConfig, guards, providers)
|
|
1160
|
-
]))
|
|
1161
|
-
});
|
|
1162
|
-
}
|
|
1163
|
-
function normalizeClerkProvider(name, config2, guards, providers) {
|
|
1164
|
-
const guard = config2.guard?.trim();
|
|
1165
|
-
if (guard && !(guard in guards)) {
|
|
1166
|
-
throw new Error(`[Holo Auth] Clerk provider "${name}" references unknown guard "${guard}".`);
|
|
1167
|
-
}
|
|
1168
|
-
const mapToProvider = config2.mapToProvider?.trim();
|
|
1169
|
-
if (mapToProvider && !(mapToProvider in providers)) {
|
|
1170
|
-
throw new Error(`[Holo Auth] Clerk provider "${name}" references unknown provider "${mapToProvider}".`);
|
|
1171
|
-
}
|
|
1172
|
-
const redirectUri = config2.redirectUri?.trim();
|
|
1173
|
-
if (redirectUri) {
|
|
1174
|
-
try {
|
|
1175
|
-
new URL(redirectUri);
|
|
1176
|
-
} catch {
|
|
1177
|
-
throw new Error(`Invalid redirectUri in Clerk provider "${name}": ${redirectUri}`);
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
return Object.freeze({
|
|
1181
|
-
name,
|
|
1182
|
-
publishableKey: config2.publishableKey?.trim() || void 0,
|
|
1183
|
-
secretKey: config2.secretKey?.trim() || void 0,
|
|
1184
|
-
apiUrl: config2.apiUrl?.trim() || void 0,
|
|
1185
|
-
frontendApi: config2.frontendApi?.trim() || void 0,
|
|
1186
|
-
redirectUri: redirectUri || void 0,
|
|
1187
|
-
sessionCookie: config2.sessionCookie?.trim() || DEFAULT_CLERK_SESSION_COOKIE,
|
|
1188
|
-
authorizedParties: Object.freeze((config2.authorizedParties ?? []).map((value) => value.trim()).filter(Boolean)),
|
|
1189
|
-
guard,
|
|
1190
|
-
mapToProvider
|
|
1191
|
-
});
|
|
1192
|
-
}
|
|
1193
|
-
function isClerkProviderConfig(value) {
|
|
1194
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1195
|
-
return false;
|
|
1196
|
-
}
|
|
1197
|
-
const candidate = value;
|
|
1198
|
-
for (const key of ["publishableKey", "secretKey", "apiUrl", "frontendApi", "redirectUri", "sessionCookie", "guard", "mapToProvider"]) {
|
|
1199
|
-
const field = candidate[key];
|
|
1200
|
-
if (typeof field !== "undefined" && typeof field !== "string") {
|
|
1201
|
-
return false;
|
|
1202
|
-
}
|
|
1203
|
-
}
|
|
1204
|
-
return typeof candidate.authorizedParties === "undefined" || Array.isArray(candidate.authorizedParties) && candidate.authorizedParties.every((value2) => typeof value2 === "string");
|
|
1205
|
-
}
|
|
1206
|
-
function getClerkProviderEntries(config2) {
|
|
1207
|
-
if (!config2) {
|
|
1208
|
-
return Object.freeze([]);
|
|
1209
|
-
}
|
|
1210
|
-
const entries = [];
|
|
1211
|
-
for (const [name, value] of Object.entries(config2)) {
|
|
1212
|
-
if (name === "provider") {
|
|
1213
|
-
if (typeof value !== "undefined" && typeof value !== "string") {
|
|
1214
|
-
throw new Error('[Holo Auth] Clerk provider key "provider" is reserved for the default provider name.');
|
|
1215
|
-
}
|
|
1216
|
-
continue;
|
|
1217
|
-
}
|
|
1218
|
-
if (name === "identityStore") {
|
|
1219
|
-
if (typeof value !== "undefined" && !isHostedIdentityStore(value)) {
|
|
1220
|
-
throw new Error("[Holo Auth] Clerk identityStore must implement the hosted identity store contract.");
|
|
1221
|
-
}
|
|
1222
|
-
continue;
|
|
1223
|
-
}
|
|
1224
|
-
if (!isClerkProviderConfig(value)) {
|
|
1225
|
-
throw new Error(`[Holo Auth] Clerk provider "${name}" must be a Clerk provider config object.`);
|
|
1226
|
-
}
|
|
1227
|
-
entries.push([name, value]);
|
|
1228
|
-
}
|
|
1229
|
-
return Object.freeze(entries);
|
|
1230
|
-
}
|
|
1231
|
-
function normalizeClerkConfig(config2, guards, providers) {
|
|
1232
|
-
const providerEntries = getClerkProviderEntries(config2);
|
|
1233
|
-
const provider = typeof config2?.provider === "string" ? config2.provider.trim() || void 0 : void 0;
|
|
1234
|
-
if (providerEntries.length === 0) {
|
|
1235
|
-
if (provider) {
|
|
1236
|
-
throw new Error(`[Holo Auth] Clerk provider "${provider}" is not configured.`);
|
|
1237
|
-
}
|
|
1238
|
-
if (config2?.identityStore) {
|
|
1239
|
-
return Object.freeze({
|
|
1240
|
-
identityStore: config2.identityStore
|
|
1241
|
-
});
|
|
1242
|
-
}
|
|
1243
|
-
return holoAuthDefaults.clerk;
|
|
1244
|
-
}
|
|
1245
|
-
const normalizedEntries = providerEntries.map(([name, providerConfig]) => {
|
|
1246
|
-
const normalizedName = normalizeConnectionName(name, "Holo Auth", "Auth Clerk provider name");
|
|
1247
|
-
return [normalizedName, providerConfig];
|
|
1248
|
-
});
|
|
1249
|
-
if (provider && !normalizedEntries.some(([name]) => name === provider)) {
|
|
1250
|
-
throw new Error(`[Holo Auth] Clerk provider "${provider}" is not configured.`);
|
|
1251
|
-
}
|
|
1252
|
-
return Object.freeze({
|
|
1253
|
-
...typeof provider === "undefined" ? {} : { provider },
|
|
1254
|
-
...config2?.identityStore ? { identityStore: config2.identityStore } : {},
|
|
1255
|
-
...Object.fromEntries(normalizedEntries.map(([name, providerConfig]) => [
|
|
1256
|
-
name,
|
|
1257
|
-
normalizeClerkProvider(name, providerConfig, guards, providers)
|
|
1258
|
-
]))
|
|
1259
|
-
});
|
|
1260
|
-
}
|
|
1261
|
-
function normalizeAuthConfig(config2 = {}, _options = {}) {
|
|
1262
|
-
const providers = !config2.providers || Object.keys(config2.providers).length === 0 ? holoAuthDefaults.providers : Object.freeze(Object.fromEntries(Object.entries(config2.providers).map(([name, provider]) => {
|
|
1263
|
-
const normalizedName = normalizeConnectionName(name, "Holo Auth", "Auth provider name");
|
|
1264
|
-
return [normalizedName, normalizeAuthProvider(normalizedName, provider)];
|
|
1265
|
-
})));
|
|
1266
|
-
const guards = !config2.guards || Object.keys(config2.guards).length === 0 ? Object.freeze({
|
|
1267
|
-
[DEFAULT_AUTH_GUARD]: normalizeAuthGuard(
|
|
1268
|
-
DEFAULT_AUTH_GUARD,
|
|
1269
|
-
holoAuthDefaults.guards[DEFAULT_AUTH_GUARD],
|
|
1270
|
-
providers
|
|
1271
|
-
)
|
|
1272
|
-
}) : Object.freeze(Object.fromEntries(Object.entries(config2.guards).map(([name, guard]) => {
|
|
1273
|
-
const normalizedName = normalizeConnectionName(name, "Holo Auth", "Auth guard name");
|
|
1274
|
-
return [normalizedName, normalizeAuthGuard(normalizedName, guard, providers)];
|
|
1275
|
-
})));
|
|
1276
|
-
const passwords = !config2.passwords || Object.keys(config2.passwords).length === 0 ? Object.freeze({
|
|
1277
|
-
[DEFAULT_AUTH_PASSWORD_BROKER]: normalizePasswordBroker(
|
|
1278
|
-
DEFAULT_AUTH_PASSWORD_BROKER,
|
|
1279
|
-
holoAuthDefaults.passwords[DEFAULT_AUTH_PASSWORD_BROKER],
|
|
1280
|
-
providers
|
|
1281
|
-
)
|
|
1282
|
-
}) : Object.freeze(Object.fromEntries(Object.entries(config2.passwords).map(([name, broker]) => {
|
|
1283
|
-
const normalizedName = normalizeConnectionName(name, "Holo Auth", "Auth password broker name");
|
|
1284
|
-
return [normalizedName, normalizePasswordBroker(normalizedName, broker, providers)];
|
|
1285
|
-
})));
|
|
1286
|
-
const defaultGuard = config2.defaults?.guard?.trim() || DEFAULT_AUTH_GUARD;
|
|
1287
|
-
if (!(defaultGuard in guards)) {
|
|
1288
|
-
throw new Error(`[Holo Auth] default auth guard "${defaultGuard}" is not configured.`);
|
|
1289
|
-
}
|
|
1290
|
-
const defaultPasswords = config2.defaults?.passwords?.trim() || DEFAULT_AUTH_PASSWORD_BROKER;
|
|
1291
|
-
if (!(defaultPasswords in passwords)) {
|
|
1292
|
-
throw new Error(`[Holo Auth] default password broker "${defaultPasswords}" is not configured.`);
|
|
1293
|
-
}
|
|
1294
|
-
const social = !config2.social || Object.keys(config2.social).length === 0 ? holoAuthDefaults.social : Object.freeze(Object.fromEntries(Object.entries(config2.social).map(([name, provider]) => {
|
|
1295
|
-
const normalizedName = normalizeConnectionName(name, "Holo Auth", "Auth social provider name");
|
|
1296
|
-
return [normalizedName, normalizeSocialProvider(normalizedName, provider, guards, providers)];
|
|
1297
|
-
})));
|
|
1298
|
-
const workos = normalizeWorkosConfig(config2.workos, guards, providers);
|
|
1299
|
-
const clerk = normalizeClerkConfig(config2.clerk, guards, providers);
|
|
1300
|
-
return Object.freeze({
|
|
1301
|
-
defaults: Object.freeze({
|
|
1302
|
-
guard: defaultGuard,
|
|
1303
|
-
passwords: defaultPasswords
|
|
1304
|
-
}),
|
|
1305
|
-
guards,
|
|
1306
|
-
providers,
|
|
1307
|
-
passwords,
|
|
1308
|
-
emailVerification: Object.freeze({
|
|
1309
|
-
required: typeof config2.emailVerification === "boolean" ? config2.emailVerification : config2.emailVerification?.required ?? false,
|
|
1310
|
-
route: typeof config2.emailVerification === "boolean" ? DEFAULT_AUTH_EMAIL_VERIFICATION_ROUTE : config2.emailVerification?.route?.trim() || DEFAULT_AUTH_EMAIL_VERIFICATION_ROUTE
|
|
1311
|
-
}),
|
|
1312
|
-
personalAccessTokens: Object.freeze({
|
|
1313
|
-
defaultAbilities: Object.freeze([...config2.personalAccessTokens?.defaultAbilities ?? holoAuthDefaults.personalAccessTokens.defaultAbilities])
|
|
1314
|
-
}),
|
|
1315
|
-
socialEncryptionKey: config2.socialEncryptionKey?.trim() || _options.appKey?.trim() || void 0,
|
|
1316
|
-
social,
|
|
1317
|
-
workos,
|
|
1318
|
-
clerk
|
|
1319
|
-
});
|
|
1320
|
-
}
|
|
1321
|
-
function normalizeDatabaseConfig(config2 = {}) {
|
|
1322
|
-
const configuredConnections = config2.connections;
|
|
1323
|
-
const connections = configuredConnections && Object.keys(configuredConnections).length > 0 ? Object.freeze({ ...configuredConnections }) : holoDatabaseDefaults.connections;
|
|
1324
|
-
const defaultConnection = config2.defaultConnection ?? Object.keys(connections)[0];
|
|
1325
|
-
return Object.freeze({
|
|
1326
|
-
/* v8 ignore next */
|
|
1327
|
-
defaultConnection: defaultConnection ?? "default",
|
|
1328
|
-
connections
|
|
1329
|
-
});
|
|
1330
|
-
}
|
|
1331
|
-
function normalizeStorageConfig(config2 = {}) {
|
|
1332
|
-
return Object.freeze({
|
|
1333
|
-
defaultDisk: config2.defaultDisk ?? holoStorageDefaults.defaultDisk,
|
|
1334
|
-
routePrefix: config2.routePrefix ?? holoStorageDefaults.routePrefix,
|
|
1335
|
-
disks: Object.freeze({
|
|
1336
|
-
...holoStorageDefaults.disks,
|
|
1337
|
-
...config2.disks ?? {}
|
|
1338
|
-
})
|
|
1339
|
-
});
|
|
1340
|
-
}
|
|
1341
|
-
function normalizeOptionalBroadcastString(value, label) {
|
|
1342
|
-
if (typeof value === "undefined") {
|
|
1343
|
-
return void 0;
|
|
1344
|
-
}
|
|
1345
|
-
const normalized = String(value).trim();
|
|
1346
|
-
if (!normalized) {
|
|
1347
|
-
throw new Error(`[Holo Broadcast] ${label} must be a non-empty string when provided.`);
|
|
1348
|
-
}
|
|
1349
|
-
return normalized;
|
|
1350
|
-
}
|
|
1351
|
-
function normalizeBroadcastPort(value, fallback, label) {
|
|
1352
|
-
const normalized = typeof value === "number" ? value : typeof value === "string" && value.trim() ? Number(value.trim()) : fallback;
|
|
1353
|
-
if (!Number.isInteger(normalized) || normalized <= 0) {
|
|
1354
|
-
throw new Error(`[Holo Broadcast] ${label} must be a positive integer.`);
|
|
1355
|
-
}
|
|
1356
|
-
return normalized;
|
|
1357
|
-
}
|
|
1358
|
-
function normalizeBroadcastScheme(value, fallback, label) {
|
|
1359
|
-
const normalized = normalizeOptionalBroadcastString(value, label)?.toLowerCase();
|
|
1360
|
-
if (typeof normalized === "undefined") {
|
|
1361
|
-
return fallback;
|
|
1362
|
-
}
|
|
1363
|
-
if (normalized !== "http" && normalized !== "https") {
|
|
1364
|
-
throw new Error(`[Holo Broadcast] ${label} must be "http" or "https".`);
|
|
1365
|
-
}
|
|
1366
|
-
return normalized;
|
|
1367
|
-
}
|
|
1368
|
-
function normalizeBroadcastConnectionOptions(options, fallbackHost, label) {
|
|
1369
|
-
const scheme = normalizeBroadcastScheme(
|
|
1370
|
-
options?.scheme,
|
|
1371
|
-
options?.useTLS === false ? "http" : "https",
|
|
1372
|
-
`${label} scheme`
|
|
1373
|
-
);
|
|
1374
|
-
const resolvedFallbackPort = scheme === "http" ? DEFAULT_BROADCAST_HTTP_PORT : DEFAULT_BROADCAST_HTTPS_PORT;
|
|
1375
|
-
return Object.freeze({
|
|
1376
|
-
host: normalizeOptionalBroadcastString(options?.host, `${label} host`) ?? fallbackHost,
|
|
1377
|
-
port: normalizeBroadcastPort(options?.port, resolvedFallbackPort, `${label} port`),
|
|
1378
|
-
scheme,
|
|
1379
|
-
useTLS: options?.useTLS ?? scheme === "https",
|
|
1380
|
-
cluster: normalizeOptionalBroadcastString(options?.cluster, `${label} cluster`) ?? void 0
|
|
1381
|
-
});
|
|
1382
|
-
}
|
|
1383
|
-
function normalizeBroadcastWorkerConfig(worker, connectionOptions, configuredConnectionPort) {
|
|
1384
|
-
const scaling = worker?.scaling;
|
|
1385
|
-
const publicScheme = normalizeBroadcastScheme(worker?.publicScheme, connectionOptions?.scheme ?? "https", "Broadcast worker public scheme");
|
|
1386
|
-
const fallbackPort = typeof configuredConnectionPort === "undefined" ? DEFAULT_BROADCAST_WORKER_PORT : normalizeBroadcastPort(configuredConnectionPort, DEFAULT_BROADCAST_WORKER_PORT, "Broadcast worker port");
|
|
1387
|
-
if (scaling && scaling.driver !== "redis") {
|
|
1388
|
-
throw new Error('[Holo Broadcast] Broadcast worker scaling driver must be "redis".');
|
|
1389
|
-
}
|
|
1390
|
-
return Object.freeze({
|
|
1391
|
-
host: normalizeOptionalBroadcastString(worker?.host, "Broadcast worker host") ?? DEFAULT_BROADCAST_WORKER_HOST,
|
|
1392
|
-
port: normalizeBroadcastPort(worker?.port, fallbackPort, "Broadcast worker port"),
|
|
1393
|
-
path: normalizeOptionalBroadcastString(worker?.path, "Broadcast worker path") ?? DEFAULT_BROADCAST_WORKER_PATH,
|
|
1394
|
-
publicHost: normalizeOptionalBroadcastString(worker?.publicHost, "Broadcast worker public host") ?? void 0,
|
|
1395
|
-
publicPort: typeof worker?.publicPort === "undefined" ? publicScheme === "http" ? DEFAULT_BROADCAST_HTTP_PORT : void 0 : normalizeBroadcastPort(
|
|
1396
|
-
worker.publicPort,
|
|
1397
|
-
/* v8 ignore next -- defensive HTTPS port default; tests only exercise HTTP scheme */
|
|
1398
|
-
publicScheme === "http" ? DEFAULT_BROADCAST_HTTP_PORT : DEFAULT_BROADCAST_HTTPS_PORT,
|
|
1399
|
-
"Broadcast worker public port"
|
|
1400
|
-
),
|
|
1401
|
-
publicScheme,
|
|
1402
|
-
healthPath: normalizeOptionalBroadcastString(worker?.healthPath, "Broadcast worker health path") ?? DEFAULT_BROADCAST_HEALTH_PATH,
|
|
1403
|
-
statsPath: normalizeOptionalBroadcastString(worker?.statsPath, "Broadcast worker stats path") ?? DEFAULT_BROADCAST_STATS_PATH,
|
|
1404
|
-
scaling: scaling && typeof scaling === "object" ? Object.freeze({
|
|
1405
|
-
driver: "redis",
|
|
1406
|
-
connection: normalizeOptionalBroadcastString(scaling.connection, "Broadcast worker scaling connection") ?? "default"
|
|
1407
|
-
}) : holoBroadcastDefaults.worker.scaling
|
|
1408
|
-
});
|
|
1409
|
-
}
|
|
1410
|
-
function normalizeBroadcastConnection(name, connection) {
|
|
1411
|
-
const normalizedName = normalizeOptionalBroadcastString(name, "Broadcast connection name");
|
|
1412
|
-
const driver = normalizeOptionalBroadcastString(connection.driver, `Broadcast connection "${name}" driver`);
|
|
1413
|
-
if (!normalizedName || !driver) {
|
|
1414
|
-
throw new Error("[Holo Broadcast] Broadcast connections must define a name and driver.");
|
|
1415
|
-
}
|
|
1416
|
-
const clientOptions = Object.freeze({
|
|
1417
|
-
...connection.clientOptions ?? {}
|
|
1418
|
-
});
|
|
1419
|
-
if (driver === "holo") {
|
|
1420
|
-
return Object.freeze({
|
|
1421
|
-
name: normalizedName,
|
|
1422
|
-
driver: "holo",
|
|
1423
|
-
key: normalizeOptionalBroadcastString(connection.key, `Broadcast connection "${name}" key`) ?? (() => {
|
|
1424
|
-
throw new Error(`[Holo Broadcast] Broadcast connection "${name}" must define a key.`);
|
|
1425
|
-
})(),
|
|
1426
|
-
secret: normalizeOptionalBroadcastString(connection.secret, `Broadcast connection "${name}" secret`) ?? (() => {
|
|
1427
|
-
throw new Error(`[Holo Broadcast] Broadcast connection "${name}" must define a secret.`);
|
|
1428
|
-
})(),
|
|
1429
|
-
appId: normalizeOptionalBroadcastString(connection.appId, `Broadcast connection "${name}" appId`) ?? (() => {
|
|
1430
|
-
throw new Error(`[Holo Broadcast] Broadcast connection "${name}" must define an appId.`);
|
|
1431
|
-
})(),
|
|
1432
|
-
options: normalizeBroadcastConnectionOptions(connection.options, DEFAULT_BROADCAST_HOST, `Broadcast connection "${name}" options`),
|
|
1433
|
-
clientOptions
|
|
1434
|
-
});
|
|
1435
|
-
}
|
|
1436
|
-
if (driver === "pusher") {
|
|
1437
|
-
const cluster = normalizeOptionalBroadcastString(connection.options?.cluster, `Broadcast connection "${name}" cluster`) ?? void 0;
|
|
1438
|
-
return Object.freeze({
|
|
1439
|
-
name: normalizedName,
|
|
1440
|
-
driver: "pusher",
|
|
1441
|
-
key: normalizeOptionalBroadcastString(connection.key, `Broadcast connection "${name}" key`) ?? (() => {
|
|
1442
|
-
throw new Error(`[Holo Broadcast] Broadcast connection "${name}" must define a key.`);
|
|
1443
|
-
})(),
|
|
1444
|
-
secret: normalizeOptionalBroadcastString(connection.secret, `Broadcast connection "${name}" secret`) ?? (() => {
|
|
1445
|
-
throw new Error(`[Holo Broadcast] Broadcast connection "${name}" must define a secret.`);
|
|
1446
|
-
})(),
|
|
1447
|
-
appId: normalizeOptionalBroadcastString(connection.appId, `Broadcast connection "${name}" appId`) ?? (() => {
|
|
1448
|
-
throw new Error(`[Holo Broadcast] Broadcast connection "${name}" must define an appId.`);
|
|
1449
|
-
})(),
|
|
1450
|
-
options: normalizeBroadcastConnectionOptions(
|
|
1451
|
-
{
|
|
1452
|
-
...connection.options,
|
|
1453
|
-
cluster
|
|
1454
|
-
},
|
|
1455
|
-
normalizeOptionalBroadcastString(connection.options?.host, `Broadcast connection "${name}" host`) ?? (cluster ? `api-${cluster}.pusher.com` : "api-mt1.pusher.com"),
|
|
1456
|
-
`Broadcast connection "${name}" options`
|
|
1457
|
-
),
|
|
1458
|
-
clientOptions
|
|
1459
|
-
});
|
|
1460
|
-
}
|
|
1461
|
-
if (driver === "log") {
|
|
1462
|
-
return Object.freeze({
|
|
1463
|
-
name: normalizedName,
|
|
1464
|
-
driver: "log",
|
|
1465
|
-
clientOptions
|
|
1466
|
-
});
|
|
1467
|
-
}
|
|
1468
|
-
if (driver === "null") {
|
|
1469
|
-
return Object.freeze({
|
|
1470
|
-
name: normalizedName,
|
|
1471
|
-
driver: "null",
|
|
1472
|
-
clientOptions
|
|
1473
|
-
});
|
|
1474
|
-
}
|
|
1475
|
-
if (driver === "ably") {
|
|
1476
|
-
throw new Error('[Holo Broadcast] Broadcast driver "ably" is not supported yet.');
|
|
1477
|
-
}
|
|
1478
|
-
const {
|
|
1479
|
-
driver: _ignoredDriver,
|
|
1480
|
-
clientOptions: _ignoredClientOptions,
|
|
1481
|
-
...customConfig
|
|
1482
|
-
} = connection;
|
|
1483
|
-
return Object.freeze({
|
|
1484
|
-
driver,
|
|
1485
|
-
clientOptions,
|
|
1486
|
-
...customConfig,
|
|
1487
|
-
name: normalizedName
|
|
1488
|
-
});
|
|
1489
|
-
}
|
|
1490
|
-
function normalizeBroadcastConfig(config2 = {}) {
|
|
1491
|
-
const normalizedConnections = Object.fromEntries(
|
|
1492
|
-
Object.entries(config2.connections ?? holoBroadcastDefaults.connections).map(([name, connection]) => [name, normalizeBroadcastConnection(name, connection)])
|
|
1493
|
-
);
|
|
1494
|
-
const defaultConnection = normalizeOptionalBroadcastString(config2.default, "Default broadcast connection") ?? holoBroadcastDefaults.default;
|
|
1495
|
-
if (!normalizedConnections[defaultConnection]) {
|
|
1496
|
-
throw new Error(
|
|
1497
|
-
`[Holo Broadcast] default broadcast connection "${defaultConnection}" is not configured. Available connections: ${Object.keys(normalizedConnections).join(", ")}`
|
|
1498
|
-
);
|
|
1499
|
-
}
|
|
1500
|
-
const defaultBroadcastConnection = normalizedConnections[defaultConnection];
|
|
1501
|
-
const defaultHoloConnectionOptions = defaultBroadcastConnection && defaultBroadcastConnection.driver === "holo" && "options" in defaultBroadcastConnection ? defaultBroadcastConnection.options : void 0;
|
|
1502
|
-
const configuredDefaultConnection = config2.connections?.[defaultConnection];
|
|
1503
|
-
const configuredDefaultHoloConnectionPort = configuredDefaultConnection?.driver === "holo" ? configuredDefaultConnection.options?.port : void 0;
|
|
1504
|
-
return Object.freeze({
|
|
1505
|
-
default: defaultConnection,
|
|
1506
|
-
connections: Object.freeze(normalizedConnections),
|
|
1507
|
-
worker: normalizeBroadcastWorkerConfig(config2.worker, defaultHoloConnectionOptions, configuredDefaultHoloConnectionPort)
|
|
1508
|
-
});
|
|
1509
|
-
}
|
|
1510
|
-
function normalizeOptionalMailString(value, label) {
|
|
1511
|
-
if (typeof value === "undefined") {
|
|
1512
|
-
return void 0;
|
|
1513
|
-
}
|
|
1514
|
-
const normalized = value.trim();
|
|
1515
|
-
if (!normalized) {
|
|
1516
|
-
throw new Error(`[Holo Mail] ${label} must be a non-empty string when provided.`);
|
|
1517
|
-
}
|
|
1518
|
-
return normalized;
|
|
1519
|
-
}
|
|
1520
|
-
function isValidMailAddress(email) {
|
|
1521
|
-
if (email.includes(" ")) {
|
|
1522
|
-
return false;
|
|
1523
|
-
}
|
|
1524
|
-
const parts = email.split("@");
|
|
1525
|
-
return parts.length === 2 && parts[0].length > 0 && parts[1].length > 0;
|
|
1526
|
-
}
|
|
1527
|
-
function normalizeMailAddress(address, label) {
|
|
1528
|
-
if (!address) {
|
|
1529
|
-
return void 0;
|
|
1530
|
-
}
|
|
1531
|
-
const email = normalizeOptionalMailString(address.email, `${label} email`)?.toLowerCase();
|
|
1532
|
-
if (!email || !isValidMailAddress(email)) {
|
|
1533
|
-
throw new Error(`[Holo Mail] ${label} email must be a valid email address.`);
|
|
1534
|
-
}
|
|
1535
|
-
const name = normalizeOptionalMailString(address.name, `${label} name`);
|
|
1536
|
-
return Object.freeze({
|
|
1537
|
-
email,
|
|
1538
|
-
...name ? { name } : {}
|
|
1539
|
-
});
|
|
1540
|
-
}
|
|
1541
|
-
function normalizeMailQueueConfig(queue, fallback = holoMailDefaults.queue) {
|
|
1542
|
-
return Object.freeze({
|
|
1543
|
-
queued: queue?.queued ?? fallback.queued,
|
|
1544
|
-
connection: normalizeOptionalMailString(queue?.connection, "Mail queue connection") ?? fallback.connection,
|
|
1545
|
-
queue: normalizeOptionalMailString(queue?.queue, "Mail queue name") ?? fallback.queue,
|
|
1546
|
-
afterCommit: queue?.afterCommit ?? fallback.afterCommit
|
|
1547
|
-
});
|
|
1548
|
-
}
|
|
1549
|
-
function normalizeMailPreviewEnvironments(environments) {
|
|
1550
|
-
if (typeof environments === "undefined") {
|
|
1551
|
-
return holoMailDefaults.preview.allowedEnvironments;
|
|
1552
|
-
}
|
|
1553
|
-
const normalized = /* @__PURE__ */ new Set();
|
|
1554
|
-
for (const environment of environments) {
|
|
1555
|
-
if (environment !== "development" && environment !== "production" && environment !== "test") {
|
|
1556
|
-
throw new Error("[Holo Mail] Mail preview environments must be development, production, or test.");
|
|
1557
|
-
}
|
|
1558
|
-
normalized.add(environment);
|
|
1559
|
-
}
|
|
1560
|
-
return Object.freeze([...normalized]);
|
|
1561
|
-
}
|
|
1562
|
-
function normalizeMailMailerConfig(name, config2, fallback) {
|
|
1563
|
-
const normalizedName = normalizeOptionalMailString(name, "Mail mailer name");
|
|
1564
|
-
const driver = normalizeOptionalMailString(config2.driver, `Mail mailer "${name}" driver`);
|
|
1565
|
-
if (!normalizedName || !driver) {
|
|
1566
|
-
throw new Error("[Holo Mail] Mailers must define a name and driver.");
|
|
1567
|
-
}
|
|
1568
|
-
const base = {
|
|
1569
|
-
name: normalizedName,
|
|
1570
|
-
driver,
|
|
1571
|
-
from: normalizeMailAddress(config2.from, `Mail mailer "${name}" from`) ?? fallback?.from,
|
|
1572
|
-
replyTo: normalizeMailAddress(config2.replyTo, `Mail mailer "${name}" replyTo`) ?? fallback?.replyTo,
|
|
1573
|
-
queue: normalizeMailQueueConfig(config2.queue, fallback?.queue ?? holoMailDefaults.queue)
|
|
1574
|
-
};
|
|
1575
|
-
if (driver === "preview") {
|
|
1576
|
-
const previewFallback = fallback?.driver === "preview" ? fallback : void 0;
|
|
1577
|
-
return Object.freeze({
|
|
1578
|
-
...base,
|
|
1579
|
-
driver: "preview",
|
|
1580
|
-
path: normalizeOptionalMailString(config2.path, `Mail mailer "${name}" preview path`) ?? previewFallback?.path ?? DEFAULT_MAIL_PREVIEW_PATH
|
|
1581
|
-
});
|
|
1582
|
-
}
|
|
1583
|
-
if (driver === "log") {
|
|
1584
|
-
const logFallback = fallback?.driver === "log" ? fallback : void 0;
|
|
1585
|
-
return Object.freeze({
|
|
1586
|
-
...base,
|
|
1587
|
-
driver: "log",
|
|
1588
|
-
logBodies: config2.logBodies ?? logFallback?.logBodies ?? false
|
|
1589
|
-
});
|
|
1590
|
-
}
|
|
1591
|
-
if (driver === "fake") {
|
|
1592
|
-
return Object.freeze({
|
|
1593
|
-
...base,
|
|
1594
|
-
driver: "fake"
|
|
1595
|
-
});
|
|
1596
|
-
}
|
|
1597
|
-
if (driver === "smtp") {
|
|
1598
|
-
const smtpFallback = fallback?.driver === "smtp" ? fallback : void 0;
|
|
1599
|
-
const rawPort = config2.port;
|
|
1600
|
-
const normalizedPort = typeof rawPort === "number" ? rawPort : typeof rawPort === "string" && rawPort.trim() ? Number(rawPort.trim()) : smtpFallback?.port ?? DEFAULT_SMTP_PORT;
|
|
1601
|
-
if (!Number.isFinite(normalizedPort) || normalizedPort <= 0) {
|
|
1602
|
-
throw new Error(`[Holo Mail] Mail mailer "${name}" SMTP port must be a positive number.`);
|
|
1603
|
-
}
|
|
1604
|
-
return Object.freeze({
|
|
1605
|
-
...base,
|
|
1606
|
-
driver: "smtp",
|
|
1607
|
-
host: normalizeOptionalMailString(config2.host, `Mail mailer "${name}" SMTP host`) ?? smtpFallback?.host ?? DEFAULT_SMTP_HOST,
|
|
1608
|
-
port: normalizedPort,
|
|
1609
|
-
secure: config2.secure ?? smtpFallback?.secure ?? false,
|
|
1610
|
-
user: normalizeOptionalMailString(config2.user, `Mail mailer "${name}" SMTP user`) ?? smtpFallback?.user ?? void 0,
|
|
1611
|
-
password: normalizeOptionalMailString(config2.password, `Mail mailer "${name}" SMTP password`) ?? smtpFallback?.password ?? void 0
|
|
1612
|
-
});
|
|
1613
|
-
}
|
|
1614
|
-
const customFields = Object.fromEntries(
|
|
1615
|
-
Object.entries(config2).filter(([key]) => key !== "driver" && key !== "from" && key !== "replyTo" && key !== "queue")
|
|
1616
|
-
);
|
|
1617
|
-
return Object.freeze({
|
|
1618
|
-
...base,
|
|
1619
|
-
...customFields
|
|
1620
|
-
});
|
|
1621
|
-
}
|
|
1622
|
-
function normalizeMailConfig(config2 = {}) {
|
|
1623
|
-
const mergedMailers = {
|
|
1624
|
-
...holoMailDefaults.mailers
|
|
1625
|
-
};
|
|
1626
|
-
for (const [name, mailer] of Object.entries(config2.mailers ?? {})) {
|
|
1627
|
-
mergedMailers[name] = normalizeMailMailerConfig(name, mailer, mergedMailers[name]);
|
|
1628
|
-
}
|
|
1629
|
-
const defaultMailer = normalizeOptionalMailString(config2.default, "Default mailer") ?? holoMailDefaults.default;
|
|
1630
|
-
if (!mergedMailers[defaultMailer]) {
|
|
1631
|
-
throw new Error(
|
|
1632
|
-
`[Holo Mail] default mailer "${defaultMailer}" is not configured. Available mailers: ${Object.keys(mergedMailers).join(", ")}`
|
|
1633
|
-
);
|
|
1634
|
-
}
|
|
1635
|
-
return Object.freeze({
|
|
1636
|
-
default: defaultMailer,
|
|
1637
|
-
from: normalizeMailAddress(config2.from, "Mail from") ?? holoMailDefaults.from,
|
|
1638
|
-
replyTo: normalizeMailAddress(config2.replyTo, "Mail replyTo") ?? holoMailDefaults.replyTo,
|
|
1639
|
-
queue: normalizeMailQueueConfig(config2.queue),
|
|
1640
|
-
preview: Object.freeze({
|
|
1641
|
-
allowedEnvironments: normalizeMailPreviewEnvironments(config2.preview?.allowedEnvironments)
|
|
1642
|
-
}),
|
|
1643
|
-
markdown: Object.freeze({
|
|
1644
|
-
wrapper: normalizeOptionalMailString(config2.markdown?.wrapper, "Mail markdown wrapper") ?? holoMailDefaults.markdown.wrapper
|
|
1645
|
-
}),
|
|
1646
|
-
mailers: Object.freeze(mergedMailers)
|
|
1647
|
-
});
|
|
1648
|
-
}
|
|
1649
|
-
function normalizeOptionalNotificationsString(value, label) {
|
|
1650
|
-
if (typeof value === "undefined") {
|
|
1651
|
-
return void 0;
|
|
1652
|
-
}
|
|
1653
|
-
const normalized = value.trim();
|
|
1654
|
-
if (!normalized) {
|
|
1655
|
-
throw new Error(`[Holo Notifications] ${label} must be a non-empty string when provided.`);
|
|
1656
|
-
}
|
|
1657
|
-
return normalized;
|
|
1658
|
-
}
|
|
1659
|
-
function normalizeNotificationsConfig(config2 = {}) {
|
|
1660
|
-
return Object.freeze({
|
|
1661
|
-
table: normalizeOptionalNotificationsString(config2.table, "Notifications table") ?? DEFAULT_NOTIFICATIONS_TABLE,
|
|
1662
|
-
queue: Object.freeze({
|
|
1663
|
-
connection: normalizeOptionalNotificationsString(config2.queue?.connection, "Notifications queue connection"),
|
|
1664
|
-
queue: normalizeOptionalNotificationsString(config2.queue?.queue, "Notifications queue name"),
|
|
1665
|
-
afterCommit: config2.queue?.afterCommit === true
|
|
1666
|
-
})
|
|
1667
|
-
});
|
|
1668
|
-
}
|
|
1669
|
-
function normalizeRedisConfig(config2 = {}) {
|
|
1670
|
-
const connections = normalizeRedisConnections(config2.connections);
|
|
1671
|
-
const connectionNames = Object.keys(connections);
|
|
1672
|
-
const defaultConnection = config2.default?.trim() || connectionNames[0];
|
|
1673
|
-
if (!connections[defaultConnection]) {
|
|
1674
|
-
throw new Error(
|
|
1675
|
-
`[Holo Redis] default redis connection "${defaultConnection}" is not configured. Available connections: ${connectionNames.join(", ")}`
|
|
1676
|
-
);
|
|
1677
|
-
}
|
|
1678
|
-
return Object.freeze({
|
|
1679
|
-
default: defaultConnection,
|
|
1680
|
-
connections
|
|
1681
|
-
});
|
|
1682
|
-
}
|
|
1683
|
-
function normalizeQueueConfigForHolo(config2 = {}, redisConfig) {
|
|
1684
|
-
const connections = normalizeConnections(config2.connections, redisConfig);
|
|
1685
|
-
const connectionNames = Object.keys(connections);
|
|
1686
|
-
const defaultConnection = config2.default?.trim() || connectionNames[0];
|
|
1687
|
-
if (!connections[defaultConnection]) {
|
|
1688
|
-
throw new Error(
|
|
1689
|
-
`[Holo Queue] default queue connection "${defaultConnection}" is not configured. Available connections: ${connectionNames.join(", ")}`
|
|
1690
|
-
);
|
|
1691
|
-
}
|
|
1692
|
-
return Object.freeze({
|
|
1693
|
-
default: defaultConnection,
|
|
1694
|
-
failed: normalizeFailedStore(config2.failed),
|
|
1695
|
-
connections
|
|
1696
|
-
});
|
|
1697
|
-
}
|
|
1698
52
|
|
|
1699
53
|
// src/access.ts
|
|
1700
54
|
function isObject(value) {
|
|
@@ -1918,6 +272,9 @@ function resolveEnvPlaceholders(value, envValues) {
|
|
|
1918
272
|
import { mkdir, readFile as readFile2, readdir, rm, writeFile } from "fs/promises";
|
|
1919
273
|
import { basename as basename2, dirname, extname, join as join2, resolve as resolve2 } from "path";
|
|
1920
274
|
import { pathToFileURL } from "url";
|
|
275
|
+
import {
|
|
276
|
+
normalizeRedisConfig
|
|
277
|
+
} from "@holo-js/kernel";
|
|
1921
278
|
var CONFIG_EXTENSION_PRIORITY = [".ts", ".mts", ".js", ".mjs", ".cts", ".cjs"];
|
|
1922
279
|
var SUPPORTED_CONFIG_EXTENSIONS = new Set(CONFIG_EXTENSION_PRIORITY);
|
|
1923
280
|
var HOLO_CONFIG_CACHE_VERSION = 3;
|
|
@@ -2066,41 +423,11 @@ function mergeLoadedFiles(cachedFiles, liveFiles, deferredConfigNames) {
|
|
|
2066
423
|
function normalizeLoadedConfig(rawConfig, options) {
|
|
2067
424
|
const resolvedRawConfig = resolveEnvPlaceholders(rawConfig, options.environment.values);
|
|
2068
425
|
const app = normalizeAppConfig(resolvedRawConfig.app);
|
|
2069
|
-
const database = normalizeDatabaseConfig(resolvedRawConfig.database);
|
|
2070
426
|
const redis = normalizeRedisConfig(resolvedRawConfig.redis);
|
|
2071
|
-
const
|
|
2072
|
-
const cache = normalizeCacheConfig(resolvedRawConfig.cache, {
|
|
2073
|
-
database,
|
|
2074
|
-
redis: resolvedRedisConfig
|
|
2075
|
-
});
|
|
2076
|
-
const cors = normalizeCorsConfig(resolvedRawConfig.cors);
|
|
2077
|
-
const storage = normalizeStorageConfig(resolvedRawConfig.storage);
|
|
2078
|
-
const queue = normalizeQueueConfigForHolo(resolvedRawConfig.queue, resolvedRedisConfig);
|
|
2079
|
-
const broadcast = normalizeBroadcastConfig(resolvedRawConfig.broadcast);
|
|
2080
|
-
const mail = normalizeMailConfig(resolvedRawConfig.mail);
|
|
2081
|
-
const notifications = normalizeNotificationsConfig(resolvedRawConfig.notifications);
|
|
2082
|
-
const media = Object.freeze({ ...resolvedRawConfig.media ?? {} });
|
|
2083
|
-
const session = normalizeSessionConfig(resolvedRawConfig.session, resolvedRedisConfig);
|
|
2084
|
-
const security = normalizeSecurityConfig(resolvedRawConfig.security, resolvedRedisConfig);
|
|
2085
|
-
const auth = normalizeAuthConfig(resolvedRawConfig.auth, {
|
|
2086
|
-
appKey: app.key
|
|
2087
|
-
});
|
|
2088
|
-
const firstPartyConfig = {
|
|
427
|
+
const firstPartyConfig = composeRegisteredConfig(resolvedRawConfig, {
|
|
2089
428
|
app,
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
cache,
|
|
2093
|
-
cors,
|
|
2094
|
-
storage,
|
|
2095
|
-
queue,
|
|
2096
|
-
broadcast,
|
|
2097
|
-
mail,
|
|
2098
|
-
notifications,
|
|
2099
|
-
media,
|
|
2100
|
-
session,
|
|
2101
|
-
security,
|
|
2102
|
-
auth
|
|
2103
|
-
};
|
|
429
|
+
redis
|
|
430
|
+
});
|
|
2104
431
|
const firstPartyConfigKeys = new Set(Object.keys(firstPartyConfig));
|
|
2105
432
|
const customEntries = Object.entries(resolvedRawConfig).filter(([key]) => {
|
|
2106
433
|
return !firstPartyConfigKeys.has(key);
|
|
@@ -2153,8 +480,11 @@ function splitCacheableConfig(rawConfig) {
|
|
|
2153
480
|
function getDeferredConfigNames(payload) {
|
|
2154
481
|
return Array.isArray(payload.deferredConfigNames) ? payload.deferredConfigNames : Object.freeze([]);
|
|
2155
482
|
}
|
|
483
|
+
function getNormalizerConfigNames(payload) {
|
|
484
|
+
return payload.normalizerConfigNames ?? Object.freeze([]);
|
|
485
|
+
}
|
|
2156
486
|
function isCachePayload(value) {
|
|
2157
|
-
return isObject2(value) && (value.version === 1 || value.version === HOLO_CONFIG_CACHE_VERSION) && isObject2(value.environment) && typeof value.environment.name === "string" && Array.isArray(value.environment.loadedFiles) && Array.isArray(value.environment.warnings) && Array.isArray(value.configFiles) && isObject2(value.config) && (typeof value.deferredConfigNames === "undefined" || Array.isArray(value.deferredConfigNames));
|
|
487
|
+
return isObject2(value) && (value.version === 1 || value.version === HOLO_CONFIG_CACHE_VERSION) && isObject2(value.environment) && typeof value.environment.name === "string" && Array.isArray(value.environment.loadedFiles) && Array.isArray(value.environment.warnings) && Array.isArray(value.configFiles) && isObject2(value.config) && (typeof value.deferredConfigNames === "undefined" || Array.isArray(value.deferredConfigNames)) && (typeof value.normalizerConfigNames === "undefined" || Array.isArray(value.normalizerConfigNames));
|
|
2158
488
|
}
|
|
2159
489
|
function resolveConfigCachePath(projectRoot) {
|
|
2160
490
|
return join2(resolve2(projectRoot), HOLO_CONFIG_CACHE_PATH);
|
|
@@ -2197,7 +527,8 @@ async function writeConfigCache(projectRoot, options = {}) {
|
|
|
2197
527
|
},
|
|
2198
528
|
configFiles: loadedFiles,
|
|
2199
529
|
config: cacheableConfig,
|
|
2200
|
-
deferredConfigNames
|
|
530
|
+
deferredConfigNames,
|
|
531
|
+
normalizerConfigNames: configRegistryInternals.getRegisteredNames().filter((name) => Object.hasOwn(rawConfig, name))
|
|
2201
532
|
}, null, 2)}
|
|
2202
533
|
`;
|
|
2203
534
|
await writeFileIfChanged(cachePath, contents);
|
|
@@ -2228,6 +559,12 @@ async function loadConfigDirectory(projectRoot, options = {}) {
|
|
|
2228
559
|
const deferredConfigNames = getDeferredConfigNames(cached);
|
|
2229
560
|
let rawConfig2 = cached.config;
|
|
2230
561
|
let loadedFiles2 = cached.configFiles;
|
|
562
|
+
const cachedConfigNames = getNormalizerConfigNames(cached).filter((name) => !deferredConfigNames.includes(name));
|
|
563
|
+
if (cachedConfigNames.length > 0) {
|
|
564
|
+
await collectRawConfig(configDir, environment2.values, {
|
|
565
|
+
onlyConfigNames: cachedConfigNames
|
|
566
|
+
});
|
|
567
|
+
}
|
|
2231
568
|
if (deferredConfigNames.length > 0) {
|
|
2232
569
|
const live = await collectRawConfig(configDir, environment2.values, {
|
|
2233
570
|
onlyConfigNames: deferredConfigNames
|
|
@@ -2261,106 +598,34 @@ function defineConfig(config2) {
|
|
|
2261
598
|
function defineAppConfig(config2) {
|
|
2262
599
|
return defineConfig(config2);
|
|
2263
600
|
}
|
|
2264
|
-
function defineDatabaseConfig(config2) {
|
|
2265
|
-
return defineConfig(config2);
|
|
2266
|
-
}
|
|
2267
|
-
function defineRedisConfig(config2) {
|
|
2268
|
-
return defineConfig(config2);
|
|
2269
|
-
}
|
|
2270
|
-
function defineCacheConfig(config2) {
|
|
2271
|
-
return defineConfig(config2);
|
|
2272
|
-
}
|
|
2273
|
-
function defineStorageConfig(config2) {
|
|
2274
|
-
return defineConfig(config2);
|
|
2275
|
-
}
|
|
2276
|
-
function defineQueueConfig(config2) {
|
|
2277
|
-
return defineConfig(config2);
|
|
2278
|
-
}
|
|
2279
|
-
function defineBroadcastConfig(config2) {
|
|
2280
|
-
return defineConfig(config2);
|
|
2281
|
-
}
|
|
2282
|
-
function defineMailConfig(config2) {
|
|
2283
|
-
return defineConfig(config2);
|
|
2284
|
-
}
|
|
2285
|
-
function defineNotificationsConfig(config2) {
|
|
2286
|
-
return defineConfig(config2);
|
|
2287
|
-
}
|
|
2288
|
-
function defineMediaConfig(config2) {
|
|
2289
|
-
return defineConfig(config2);
|
|
2290
|
-
}
|
|
2291
|
-
function defineSessionConfig(config2) {
|
|
2292
|
-
return defineConfig(config2);
|
|
2293
|
-
}
|
|
2294
|
-
function defineSecurityConfig(config2) {
|
|
2295
|
-
return defineConfig(config2);
|
|
2296
|
-
}
|
|
2297
|
-
function defineCorsConfig(config2) {
|
|
2298
|
-
return defineConfig(config2);
|
|
2299
|
-
}
|
|
2300
|
-
function defineAuthConfig(config2) {
|
|
2301
|
-
return defineConfig(config2);
|
|
2302
|
-
}
|
|
2303
601
|
var loaderInternals = {
|
|
2304
602
|
getDeferredConfigNames,
|
|
603
|
+
getNormalizerConfigNames,
|
|
2305
604
|
getConfigExtensionPriority,
|
|
2306
605
|
resolveConfigExport,
|
|
2307
606
|
splitCacheableConfig
|
|
2308
607
|
};
|
|
2309
608
|
export {
|
|
2310
609
|
DEFAULT_APP_NAME,
|
|
2311
|
-
DEFAULT_SESSION_COOKIE_NAME,
|
|
2312
610
|
clearConfigCache,
|
|
611
|
+
composeRegisteredConfig,
|
|
2313
612
|
config,
|
|
613
|
+
configRegistryInternals,
|
|
2314
614
|
configureConfigRuntime,
|
|
2315
615
|
configureEnvRuntime,
|
|
2316
616
|
createConfigAccessors,
|
|
2317
617
|
defineAppConfig,
|
|
2318
|
-
defineAuthConfig,
|
|
2319
|
-
defineBroadcastConfig,
|
|
2320
|
-
defineCacheConfig,
|
|
2321
618
|
defineConfig,
|
|
2322
|
-
defineCorsConfig,
|
|
2323
|
-
defineDatabaseConfig,
|
|
2324
|
-
defineMailConfig,
|
|
2325
|
-
defineMediaConfig,
|
|
2326
|
-
defineNotificationsConfig,
|
|
2327
|
-
defineQueueConfig,
|
|
2328
|
-
defineRedisConfig,
|
|
2329
|
-
defineSecurityConfig,
|
|
2330
|
-
defineSessionConfig,
|
|
2331
|
-
defineStorageConfig,
|
|
2332
619
|
env,
|
|
2333
620
|
holoAppDefaults,
|
|
2334
|
-
holoAuthDefaults,
|
|
2335
|
-
holoBroadcastDefaults,
|
|
2336
|
-
holoCacheDefaults,
|
|
2337
|
-
holoCorsDefaults,
|
|
2338
|
-
holoDatabaseDefaults,
|
|
2339
|
-
holoMailDefaults,
|
|
2340
|
-
holoNotificationsDefaults,
|
|
2341
|
-
holoQueueDefaultsNormalized,
|
|
2342
|
-
holoRedisDefaults,
|
|
2343
|
-
holoSecurityDefaults,
|
|
2344
|
-
holoSessionDefaults,
|
|
2345
|
-
holoStorageDefaults,
|
|
2346
621
|
isEnvPlaceholder,
|
|
2347
622
|
loadConfigDirectory,
|
|
2348
623
|
loadEnvironment,
|
|
2349
624
|
loaderInternals,
|
|
2350
625
|
normalizeAppConfig,
|
|
2351
626
|
normalizeAppEnv,
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
normalizeCacheConfig,
|
|
2355
|
-
normalizeCorsConfig,
|
|
2356
|
-
normalizeDatabaseConfig,
|
|
2357
|
-
normalizeMailConfig,
|
|
2358
|
-
normalizeNotificationsConfig,
|
|
2359
|
-
normalizeQueueConfigForHolo,
|
|
2360
|
-
normalizeRedisConfig,
|
|
2361
|
-
normalizeSecurityConfig,
|
|
2362
|
-
normalizeSessionConfig,
|
|
2363
|
-
normalizeStorageConfig,
|
|
627
|
+
registerConfigNormalizer,
|
|
628
|
+
resetConfigNormalizers,
|
|
2364
629
|
resetConfigRuntime,
|
|
2365
630
|
resolveAppEnvironment,
|
|
2366
631
|
resolveConfigCachePath,
|