@nymbalhq/config 0.2.0 → 1.1.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/index.d.ts +542 -157
- package/dist/index.js +157 -52
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -37,6 +37,27 @@ function envBool(key, defaultValue = false) {
|
|
|
37
37
|
return raw === "true" || raw === "1" || raw === "yes" || raw === "on";
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
// src/known-providers.ts
|
|
41
|
+
var KNOWN_PROVIDERS = {
|
|
42
|
+
payments: ["native", "stripe", "custom"],
|
|
43
|
+
email: ["native", "smtp", "custom"],
|
|
44
|
+
reviews: ["native", "custom"],
|
|
45
|
+
search: ["native", "custom"],
|
|
46
|
+
analytics: ["native", "custom"],
|
|
47
|
+
shipping: ["native", "custom"],
|
|
48
|
+
tax: ["native", "custom"],
|
|
49
|
+
ai: ["none", "anthropic", "custom"]
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// src/known-infrastructure.ts
|
|
53
|
+
var KNOWN_INFRASTRUCTURE = {
|
|
54
|
+
commandStore: ["sqlite", "postgres"],
|
|
55
|
+
documentStore: ["in-memory", "redis", "postgres-jsonb"],
|
|
56
|
+
eventBus: ["in-process", "redis-streams"],
|
|
57
|
+
media: ["local-fs", "s3"]
|
|
58
|
+
};
|
|
59
|
+
var REMOVED_INFRASTRUCTURE_KEYS = ["cloud", "compute"];
|
|
60
|
+
|
|
40
61
|
// src/load.ts
|
|
41
62
|
import { existsSync } from "fs";
|
|
42
63
|
import { dirname, isAbsolute, resolve } from "path";
|
|
@@ -60,12 +81,88 @@ var storeSchema = z.object({
|
|
|
60
81
|
locale: z.string().min(2),
|
|
61
82
|
timezone: z.string().min(1)
|
|
62
83
|
});
|
|
63
|
-
var
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
84
|
+
var quotedList = (values) => values.map((v) => `'${v}'`).join(", ");
|
|
85
|
+
function infrastructureValue(slot, values) {
|
|
86
|
+
return z.enum(values, {
|
|
87
|
+
errorMap: (issue, ctx) => issue.code === z.ZodIssueCode.invalid_enum_value ? {
|
|
88
|
+
message: `unknown ${slot} '${String(issue.received)}'; the ${slot} values are ${quotedList(values)}`
|
|
89
|
+
} : { message: ctx.defaultError }
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
var INFRASTRUCTURE_KEYS = [...Object.keys(KNOWN_INFRASTRUCTURE), "redis", "s3"];
|
|
93
|
+
function unrecognizedInfrastructureKeys(keys) {
|
|
94
|
+
return keys.map(
|
|
95
|
+
(key) => REMOVED_INFRASTRUCTURE_KEYS.includes(key) ? `infrastructure.${key} was removed: it drives nothing, so delete it from the config` : `unknown infrastructure key '${key}'; the infrastructure keys are ${quotedList(INFRASTRUCTURE_KEYS)}`
|
|
96
|
+
).join("; ");
|
|
97
|
+
}
|
|
98
|
+
var redisSchema = z.object({
|
|
99
|
+
/** Defaults to `REDIS_URL`. */
|
|
100
|
+
url: z.string().min(1).optional(),
|
|
101
|
+
/** Namespaces every key and stream; defaults to `NYMBAL_REDIS_PREFIX`, then `'nymbal'`. */
|
|
102
|
+
prefix: z.string().min(1).optional(),
|
|
103
|
+
/** How long a publish waits for the groups it delivers to (default 15 000). */
|
|
104
|
+
ackTimeoutMs: z.number().int().positive().optional(),
|
|
105
|
+
/** How long an entry may stay pending on a consumer before a live one takes it over (default 5 000). */
|
|
106
|
+
claimIdleMs: z.number().int().positive().optional(),
|
|
107
|
+
/** The approximate length each stream is trimmed to (default 10 000). */
|
|
108
|
+
streamMaxLen: z.number().int().positive().optional()
|
|
109
|
+
}).strict();
|
|
110
|
+
var S3_KEYS = ["bucket", "region", "endpoint", "prefix", "publicUrl", "forcePathStyle"];
|
|
111
|
+
var s3Schema = z.object(
|
|
112
|
+
{
|
|
113
|
+
/** Defaults to `S3_BUCKET`; one of the two is required. */
|
|
114
|
+
bucket: z.string().min(1).optional(),
|
|
115
|
+
/** Defaults to `AWS_REGION`, then `'us-east-1'`. */
|
|
116
|
+
region: z.string().min(1).optional(),
|
|
117
|
+
/** An S3-compatible API (MinIO, R2); defaults to `S3_ENDPOINT`, then AWS. */
|
|
118
|
+
endpoint: z.string().min(1).optional(),
|
|
119
|
+
/** Where every object key starts; defaults to `NYMBAL_S3_PREFIX`, then none. */
|
|
120
|
+
prefix: z.string().optional(),
|
|
121
|
+
/** Where the bucket's objects are served from (a CDN); defaults to `S3_PUBLIC_URL`, then the bucket's own URL. */
|
|
122
|
+
publicUrl: z.string().min(1).optional(),
|
|
123
|
+
/** Path-style requests; true by default when an endpoint is set. */
|
|
124
|
+
forcePathStyle: z.boolean().optional()
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
errorMap: (issue, ctx) => issue.code === z.ZodIssueCode.unrecognized_keys ? {
|
|
128
|
+
message: `unknown infrastructure.s3 key${issue.keys.length > 1 ? "s" : ""} ${quotedList(issue.keys)}; the s3 keys are ${quotedList(S3_KEYS)}, and credentials come from the AWS SDK (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, a profile or a role), never the config`
|
|
129
|
+
} : { message: ctx.defaultError }
|
|
130
|
+
}
|
|
131
|
+
).strict();
|
|
132
|
+
var infrastructureSchema = z.object(
|
|
133
|
+
{
|
|
134
|
+
commandStore: infrastructureValue("commandStore", KNOWN_INFRASTRUCTURE.commandStore),
|
|
135
|
+
documentStore: infrastructureValue("documentStore", KNOWN_INFRASTRUCTURE.documentStore),
|
|
136
|
+
eventBus: infrastructureValue("eventBus", KNOWN_INFRASTRUCTURE.eventBus),
|
|
137
|
+
media: infrastructureValue("media", KNOWN_INFRASTRUCTURE.media).default("local-fs"),
|
|
138
|
+
redis: redisSchema.optional(),
|
|
139
|
+
s3: s3Schema.optional()
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
errorMap: (issue, ctx) => issue.code === z.ZodIssueCode.unrecognized_keys ? { message: unrecognizedInfrastructureKeys(issue.keys) } : { message: ctx.defaultError }
|
|
143
|
+
}
|
|
144
|
+
).strict().superRefine((infra, ctx) => {
|
|
145
|
+
if (infra.documentStore === "postgres-jsonb" && infra.commandStore !== "postgres") {
|
|
146
|
+
ctx.addIssue({
|
|
147
|
+
code: z.ZodIssueCode.custom,
|
|
148
|
+
path: ["documentStore"],
|
|
149
|
+
message: `documentStore 'postgres-jsonb' shares the command store's Postgres connection, so it needs commandStore 'postgres' (not '${infra.commandStore}')`
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
if (infra.eventBus === "redis-streams" && infra.documentStore === "in-memory") {
|
|
153
|
+
ctx.addIssue({
|
|
154
|
+
code: z.ZodIssueCode.custom,
|
|
155
|
+
path: ["eventBus"],
|
|
156
|
+
message: `eventBus 'redis-streams' needs a shared documentStore ('redis' or 'postgres-jsonb'), not 'in-memory': a named group hands each event to one instance, so a per-process read model would miss the rest`
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
if (infra.s3 !== void 0 && infra.media !== "s3") {
|
|
160
|
+
ctx.addIssue({
|
|
161
|
+
code: z.ZodIssueCode.custom,
|
|
162
|
+
path: ["s3"],
|
|
163
|
+
message: `infrastructure.s3 configures media 's3', but media is '${infra.media}': set media to 's3' or delete the s3 block`
|
|
164
|
+
});
|
|
165
|
+
}
|
|
69
166
|
});
|
|
70
167
|
var securitySchema = z.object({
|
|
71
168
|
adapter: z.enum(["middleware", "cloudflare", "aws-waf", "akamai"]),
|
|
@@ -92,19 +189,26 @@ var securitySchema = z.object({
|
|
|
92
189
|
refreshTtl: z.string().regex(/^\d+(ms|s|m|h|d)$/, 'TTL must look like "7d"').default("7d")
|
|
93
190
|
}).default({})
|
|
94
191
|
});
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
192
|
+
function adapterBlock(slot, providers) {
|
|
193
|
+
const known = providers.map((p) => `'${p}'`).join(", ");
|
|
194
|
+
return z.object({
|
|
195
|
+
provider: z.enum(providers, {
|
|
196
|
+
errorMap: (issue, ctx) => issue.code === z.ZodIssueCode.invalid_enum_value ? {
|
|
197
|
+
message: `unknown ${slot} provider '${String(issue.received)}'; the ${slot} providers are ${known}`
|
|
198
|
+
} : { message: ctx.defaultError }
|
|
199
|
+
}),
|
|
200
|
+
config: z.record(z.string(), z.unknown()).optional()
|
|
201
|
+
});
|
|
202
|
+
}
|
|
99
203
|
var commerceSchema = z.object({
|
|
100
|
-
payments: adapterBlock,
|
|
101
|
-
email: adapterBlock,
|
|
102
|
-
reviews: adapterBlock,
|
|
103
|
-
search: adapterBlock,
|
|
104
|
-
analytics: adapterBlock,
|
|
105
|
-
shipping: adapterBlock,
|
|
106
|
-
tax: adapterBlock,
|
|
107
|
-
ai: adapterBlock,
|
|
204
|
+
payments: adapterBlock("payments", KNOWN_PROVIDERS.payments),
|
|
205
|
+
email: adapterBlock("email", KNOWN_PROVIDERS.email),
|
|
206
|
+
reviews: adapterBlock("reviews", KNOWN_PROVIDERS.reviews),
|
|
207
|
+
search: adapterBlock("search", KNOWN_PROVIDERS.search),
|
|
208
|
+
analytics: adapterBlock("analytics", KNOWN_PROVIDERS.analytics),
|
|
209
|
+
shipping: adapterBlock("shipping", KNOWN_PROVIDERS.shipping),
|
|
210
|
+
tax: adapterBlock("tax", KNOWN_PROVIDERS.tax),
|
|
211
|
+
ai: adapterBlock("ai", KNOWN_PROVIDERS.ai),
|
|
108
212
|
orders: z.object({
|
|
109
213
|
numberPrefix: z.string().min(1).default("NYM"),
|
|
110
214
|
numberStart: z.number().int().nonnegative().default(1e3)
|
|
@@ -143,37 +247,13 @@ var nymbalConfigSchema = z.object({
|
|
|
143
247
|
autoUpdates: false
|
|
144
248
|
})
|
|
145
249
|
}).superRefine((cfg, ctx) => {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
154
|
-
if (!["in-process", "redis-streams"].includes(cfg.infrastructure.eventBus)) {
|
|
155
|
-
ctx.addIssue({
|
|
156
|
-
code: z.ZodIssueCode.custom,
|
|
157
|
-
path: ["infrastructure", "eventBus"],
|
|
158
|
-
message: `cloud=local only supports 'in-process' or 'redis-streams' for eventBus`
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
if (!["in-process", "worker-threads"].includes(cfg.infrastructure.compute)) {
|
|
162
|
-
ctx.addIssue({
|
|
163
|
-
code: z.ZodIssueCode.custom,
|
|
164
|
-
path: ["infrastructure", "compute"],
|
|
165
|
-
message: `cloud=local only supports 'in-process' or 'worker-threads' for compute`
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
if (cfg.security.adapter === "middleware") {
|
|
170
|
-
if (["aws", "gcp", "azure"].includes(cfg.infrastructure.cloud)) {
|
|
171
|
-
ctx.addIssue({
|
|
172
|
-
code: z.ZodIssueCode.custom,
|
|
173
|
-
path: ["security", "adapter"],
|
|
174
|
-
message: `security.adapter='middleware' is intended for local/docker development. Use a WAF adapter ('cloudflare', 'aws-waf', 'akamai') for cloud=${cfg.infrastructure.cloud}.`
|
|
175
|
-
});
|
|
176
|
-
}
|
|
250
|
+
const email = cfg.commerce.email;
|
|
251
|
+
if (email.provider === "native" && email.config?.["transport"] === "smtp") {
|
|
252
|
+
ctx.addIssue({
|
|
253
|
+
code: z.ZodIssueCode.custom,
|
|
254
|
+
path: ["commerce", "email", "config", "transport"],
|
|
255
|
+
message: `the native email provider only prints to the console; for SMTP mail set email.provider to 'smtp' (@nymbalhq/adapter-smtp)`
|
|
256
|
+
});
|
|
177
257
|
}
|
|
178
258
|
});
|
|
179
259
|
|
|
@@ -198,18 +278,20 @@ async function loadConfig(startDir = process.cwd()) {
|
|
|
198
278
|
);
|
|
199
279
|
}
|
|
200
280
|
const jiti = createJiti(pathToFileURL(path).href, { interopDefault: true });
|
|
201
|
-
let
|
|
281
|
+
let mod;
|
|
202
282
|
try {
|
|
203
|
-
|
|
283
|
+
mod = await jiti.import(path);
|
|
204
284
|
} catch (err) {
|
|
205
285
|
throw new ConfigError2(`Failed to load ${path}: ${err.message}`, {
|
|
206
286
|
cause: err,
|
|
207
287
|
context: { path }
|
|
208
288
|
});
|
|
209
289
|
}
|
|
290
|
+
const raw = mod["default"] ?? mod;
|
|
291
|
+
const adapters = adaptersExport(mod["adapters"], path);
|
|
210
292
|
try {
|
|
211
293
|
const config = nymbalConfigSchema.parse(raw);
|
|
212
|
-
return { config, path, projectRoot: dirname(path) };
|
|
294
|
+
return { config, path, projectRoot: dirname(path), ...adapters !== void 0 && { adapters } };
|
|
213
295
|
} catch (err) {
|
|
214
296
|
if (err instanceof z2.ZodError) {
|
|
215
297
|
throw new ConfigError2(formatZodError(err, path), {
|
|
@@ -220,6 +302,24 @@ async function loadConfig(startDir = process.cwd()) {
|
|
|
220
302
|
throw err;
|
|
221
303
|
}
|
|
222
304
|
}
|
|
305
|
+
function adaptersExport(value, path) {
|
|
306
|
+
if (value === void 0) return void 0;
|
|
307
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
308
|
+
throw new ConfigError2(`${path}: the adapters export must be an object keyed by commerce slot`, {
|
|
309
|
+
code: "config.adapters_invalid",
|
|
310
|
+
context: { path }
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
const slots = Object.keys(KNOWN_PROVIDERS);
|
|
314
|
+
const unknown = Object.keys(value).filter((key) => !slots.includes(key));
|
|
315
|
+
if (unknown.length > 0) {
|
|
316
|
+
throw new ConfigError2(
|
|
317
|
+
`${path}: the adapters export names ${unknown.join(", ")}, which is no commerce slot (${slots.join(", ")})`,
|
|
318
|
+
{ code: "config.adapters_invalid", context: { path, unknown } }
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
return value;
|
|
322
|
+
}
|
|
223
323
|
function formatZodError(err, path) {
|
|
224
324
|
const lines = err.issues.map((issue) => {
|
|
225
325
|
const at = issue.path.length > 0 ? issue.path.join(".") : "<root>";
|
|
@@ -230,6 +330,9 @@ ${lines.join("\n")}`;
|
|
|
230
330
|
}
|
|
231
331
|
export {
|
|
232
332
|
DEFAULT_JWT_SECRET,
|
|
333
|
+
KNOWN_INFRASTRUCTURE,
|
|
334
|
+
KNOWN_PROVIDERS,
|
|
335
|
+
REMOVED_INFRASTRUCTURE_KEYS,
|
|
233
336
|
commerceSchema,
|
|
234
337
|
defineConfig,
|
|
235
338
|
deploymentSchema,
|
|
@@ -243,6 +346,8 @@ export {
|
|
|
243
346
|
infrastructureSchema,
|
|
244
347
|
loadConfig,
|
|
245
348
|
nymbalConfigSchema,
|
|
349
|
+
redisSchema,
|
|
350
|
+
s3Schema,
|
|
246
351
|
securitySchema,
|
|
247
352
|
storeSchema
|
|
248
353
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/define-config.ts","../src/env.ts","../src/load.ts","../src/schema.ts"],"sourcesContent":["import type { NymbalConfigInput } from './schema.js'\n\nexport function defineConfig<T extends NymbalConfigInput>(config: T): T {\n return config\n}\n","import { ConfigError } from '@nymbalhq/types'\n\nexport function env(key: string, defaultValue?: string): string {\n const value = process.env[key]\n if (value !== undefined && value !== '') return value\n if (defaultValue !== undefined) return defaultValue\n throw new ConfigError(`Missing required environment variable: ${key}`, {\n context: { key },\n })\n}\n\nexport function envOptional(key: string): string | undefined {\n const value = process.env[key]\n return value !== undefined && value !== '' ? value : undefined\n}\n\nexport function envNumber(key: string, defaultValue?: number): number {\n const raw = envOptional(key)\n if (raw === undefined) {\n if (defaultValue !== undefined) return defaultValue\n throw new ConfigError(`Missing required environment variable: ${key}`, { context: { key } })\n }\n const parsed = Number(raw)\n if (!Number.isFinite(parsed)) {\n throw new ConfigError(`Environment variable ${key} is not a valid number: ${raw}`, {\n context: { key, raw },\n })\n }\n return parsed\n}\n\nexport function envBool(key: string, defaultValue = false): boolean {\n const raw = envOptional(key)?.toLowerCase()\n if (raw === undefined) return defaultValue\n return raw === 'true' || raw === '1' || raw === 'yes' || raw === 'on'\n}\n","import { existsSync } from 'node:fs'\nimport { dirname, isAbsolute, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { createJiti } from 'jiti'\nimport { z } from 'zod'\nimport { ConfigError } from '@nymbalhq/types'\nimport { nymbalConfigSchema, type NymbalConfig } from './schema.js'\n\nconst CONFIG_FILE = 'nymbal.config.ts'\n\nexport interface LoadedConfig {\n config: NymbalConfig\n path: string\n projectRoot: string\n}\n\nexport function findConfigFile(startDir: string): string | null {\n let current = isAbsolute(startDir) ? startDir : resolve(startDir)\n while (true) {\n const candidate = resolve(current, CONFIG_FILE)\n if (existsSync(candidate)) return candidate\n const parent = dirname(current)\n if (parent === current) return null\n current = parent\n }\n}\n\nexport async function loadConfig(startDir: string = process.cwd()): Promise<LoadedConfig> {\n const path = findConfigFile(startDir)\n if (!path) {\n throw new ConfigError(\n `Could not find ${CONFIG_FILE} in ${startDir} or any parent directory.`,\n { context: { startDir } },\n )\n }\n\n const jiti = createJiti(pathToFileURL(path).href, { interopDefault: true })\n let raw: unknown\n try {\n raw = await jiti.import(path, { default: true })\n } catch (err) {\n throw new ConfigError(`Failed to load ${path}: ${(err as Error).message}`, {\n cause: err,\n context: { path },\n })\n }\n\n try {\n const config = nymbalConfigSchema.parse(raw)\n return { config, path, projectRoot: dirname(path) }\n } catch (err) {\n if (err instanceof z.ZodError) {\n throw new ConfigError(formatZodError(err, path), {\n cause: err,\n context: { path, issues: err.issues },\n })\n }\n throw err\n }\n}\n\nfunction formatZodError(err: z.ZodError, path: string): string {\n const lines = err.issues.map((issue) => {\n const at = issue.path.length > 0 ? issue.path.join('.') : '<root>'\n return ` • ${at}: ${issue.message}`\n })\n return `Invalid configuration in ${path}:\\n${lines.join('\\n')}`\n}\n","import { z } from 'zod'\n\nconst rateLimitRuleSchema = z.object({\n requests: z.number().int().positive(),\n window: z.string().regex(/^\\d+(ms|s|m|h)$/, 'window must look like \"60s\", \"5m\", \"1h\"'),\n action: z.enum(['block', 'challenge', 'throttle']),\n})\n\nconst rateLimitPathPattern = /^\\/[\\w\\-/*:]*$/\n\n/** The schema's JWT secret when none is configured: fine for development, refused in production. */\nexport const DEFAULT_JWT_SECRET = 'dev-secret-please-override-me-1234567890'\n\nexport const storeSchema = z.object({\n name: z.string().min(1),\n currency: z.string().length(3),\n locale: z.string().min(2),\n timezone: z.string().min(1),\n})\n\nexport const infrastructureSchema = z.object({\n cloud: z.enum(['local', 'aws', 'gcp', 'azure', 'docker']),\n commandStore: z.enum(['sqlite', 'postgres']),\n documentStore: z.enum(['in-memory', 'dynamodb', 'firestore', 'cosmosdb', 'postgres-jsonb']),\n eventBus: z.enum(['in-process', 'eventbridge', 'pubsub', 'service-bus', 'redis-streams']),\n compute: z.enum(['in-process', 'lambda', 'cloud-functions', 'azure-functions', 'worker-threads']),\n})\n\nexport const securitySchema = z.object({\n adapter: z.enum(['middleware', 'cloudflare', 'aws-waf', 'akamai']),\n rateLimit: z\n .record(\n z.string().regex(rateLimitPathPattern, {\n message: 'rate limit keys must start with \"/\" and use only letters, numbers, -, _, /, *, :',\n }),\n rateLimitRuleSchema,\n )\n .default({}),\n botProtection: z\n .object({\n mode: z.enum(['off', 'managed', 'strict']).default('off'),\n allowList: z.array(z.string()).default([]),\n })\n .default({ mode: 'off', allowList: [] }),\n headers: z\n .object({\n hsts: z.boolean().default(true),\n contentSecurityPolicy: z\n .union([z.enum(['strict', 'relaxed', 'off']), z.string()])\n .default('strict'),\n referrerPolicy: z.string().default('strict-origin-when-cross-origin'),\n xFrameOptions: z.enum(['deny', 'sameorigin']).default('deny'),\n })\n .default({}),\n csrf: z.boolean().default(true),\n auth: z\n .object({\n jwtSecret: z.string().min(16).default(DEFAULT_JWT_SECRET),\n accessTtl: z\n .string()\n .regex(/^\\d+(ms|s|m|h|d)$/, 'TTL must look like \"15m\"')\n .default('15m'),\n refreshTtl: z\n .string()\n .regex(/^\\d+(ms|s|m|h|d)$/, 'TTL must look like \"7d\"')\n .default('7d'),\n })\n .default({}),\n})\n\nconst adapterBlock = z.object({\n provider: z.string().min(1),\n config: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const commerceSchema = z.object({\n payments: adapterBlock,\n email: adapterBlock,\n reviews: adapterBlock,\n search: adapterBlock,\n analytics: adapterBlock,\n shipping: adapterBlock,\n tax: adapterBlock,\n ai: adapterBlock,\n orders: z\n .object({\n numberPrefix: z.string().min(1).default('NYM'),\n numberStart: z.number().int().nonnegative().default(1000),\n })\n .default({}),\n})\n\nexport const httpSchema = z.object({\n adapter: z.enum(['fastify', 'hono']).default('fastify'),\n port: z.number().int().positive().default(3001),\n host: z.string().default('0.0.0.0'),\n /** Whether `X-Forwarded-For` sets the client IP the rate limiter keys on; only behind a proxy you run. */\n trustProxy: z.boolean().default(false),\n cors: z\n .object({\n allowedOrigins: z\n .array(z.string())\n .default(['http://localhost:3000', 'http://localhost:4321']),\n credentials: z.boolean().default(true),\n })\n .default({}),\n})\n\nexport const deploymentSchema = z.object({\n strategy: z.enum(['standard', 'blue-green']).default('standard'),\n})\n\nexport const featuresSchema = z.object({\n staging: z.boolean().default(false),\n heartbeat: z.boolean().default(false),\n autoUpdates: z.boolean().default(false),\n})\n\nexport const nymbalConfigSchema = z\n .object({\n store: storeSchema,\n template: z.enum(['astro', 'nextjs']),\n infrastructure: infrastructureSchema,\n security: securitySchema,\n commerce: commerceSchema,\n http: httpSchema,\n deployment: deploymentSchema,\n features: featuresSchema.default({\n staging: false,\n heartbeat: false,\n autoUpdates: false,\n }),\n })\n .superRefine((cfg, ctx) => {\n // Local infrastructure restricts which document-store / event-bus options make sense.\n if (cfg.infrastructure.cloud === 'local') {\n if (!['in-memory', 'postgres-jsonb'].includes(cfg.infrastructure.documentStore)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['infrastructure', 'documentStore'],\n message: `cloud=local only supports 'in-memory' or 'postgres-jsonb' for documentStore`,\n })\n }\n if (!['in-process', 'redis-streams'].includes(cfg.infrastructure.eventBus)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['infrastructure', 'eventBus'],\n message: `cloud=local only supports 'in-process' or 'redis-streams' for eventBus`,\n })\n }\n if (!['in-process', 'worker-threads'].includes(cfg.infrastructure.compute)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['infrastructure', 'compute'],\n message: `cloud=local only supports 'in-process' or 'worker-threads' for compute`,\n })\n }\n }\n\n // middleware security adapter is v0.1 and not intended for managed-cloud production deployments.\n if (cfg.security.adapter === 'middleware') {\n if (['aws', 'gcp', 'azure'].includes(cfg.infrastructure.cloud)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['security', 'adapter'],\n message: `security.adapter='middleware' is intended for local/docker development. Use a WAF adapter ('cloudflare', 'aws-waf', 'akamai') for cloud=${cfg.infrastructure.cloud}.`,\n })\n }\n }\n })\n\nexport type NymbalConfigInput = z.input<typeof nymbalConfigSchema>\nexport type NymbalConfig = z.output<typeof nymbalConfigSchema>\n"],"mappings":"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","names":["z","ConfigError","ConfigError","z"]}
|
|
1
|
+
{"version":3,"sources":["../src/define-config.ts","../src/env.ts","../src/known-providers.ts","../src/known-infrastructure.ts","../src/load.ts","../src/schema.ts"],"sourcesContent":["import type { NymbalConfigInput } from './schema.js'\n\nexport function defineConfig<T extends NymbalConfigInput>(config: T): T {\n return config\n}\n","import { ConfigError } from '@nymbalhq/types'\n\nexport function env(key: string, defaultValue?: string): string {\n const value = process.env[key]\n if (value !== undefined && value !== '') return value\n if (defaultValue !== undefined) return defaultValue\n throw new ConfigError(`Missing required environment variable: ${key}`, {\n context: { key },\n })\n}\n\nexport function envOptional(key: string): string | undefined {\n const value = process.env[key]\n return value !== undefined && value !== '' ? value : undefined\n}\n\nexport function envNumber(key: string, defaultValue?: number): number {\n const raw = envOptional(key)\n if (raw === undefined) {\n if (defaultValue !== undefined) return defaultValue\n throw new ConfigError(`Missing required environment variable: ${key}`, { context: { key } })\n }\n const parsed = Number(raw)\n if (!Number.isFinite(parsed)) {\n throw new ConfigError(`Environment variable ${key} is not a valid number: ${raw}`, {\n context: { key, raw },\n })\n }\n return parsed\n}\n\nexport function envBool(key: string, defaultValue = false): boolean {\n const raw = envOptional(key)?.toLowerCase()\n if (raw === undefined) return defaultValue\n return raw === 'true' || raw === '1' || raw === 'yes' || raw === 'on'\n}\n","import type { CommerceSlot } from '@nymbalhq/types'\n\nexport type { CommerceSlot }\n\n/**\n * The providers each commerce slot accepts. A provider that needs an SDK lives in an `@nymbalhq/adapter-*` package the\n * kernel loads only when the config names it; `custom` takes the adapter a project passes to `createApp`.\n */\nexport const KNOWN_PROVIDERS = {\n payments: ['native', 'stripe', 'custom'],\n email: ['native', 'smtp', 'custom'],\n reviews: ['native', 'custom'],\n search: ['native', 'custom'],\n analytics: ['native', 'custom'],\n shipping: ['native', 'custom'],\n tax: ['native', 'custom'],\n ai: ['none', 'anthropic', 'custom'],\n} as const satisfies Readonly<Record<CommerceSlot, readonly [string, ...string[]]>>\n","/**\n * The values each infrastructure slot accepts: only what is built. `in-memory`, `in-process` and `local-fs` are the\n * kernel's own; `redis`, `postgres-jsonb`, `redis-streams` and `s3` live in `@nymbalhq/*` packages the kernel loads\n * only when the config names them.\n */\nexport const KNOWN_INFRASTRUCTURE = {\n commandStore: ['sqlite', 'postgres'],\n documentStore: ['in-memory', 'redis', 'postgres-jsonb'],\n eventBus: ['in-process', 'redis-streams'],\n media: ['local-fs', 's3'],\n} as const satisfies Readonly<Record<string, readonly [string, ...string[]]>>\n\nexport type InfrastructureSlot = keyof typeof KNOWN_INFRASTRUCTURE\n\n/** Keys that drove nothing and were removed; a config that still sets one is told to delete it. */\nexport const REMOVED_INFRASTRUCTURE_KEYS = ['cloud', 'compute'] as const\n","import { existsSync } from 'node:fs'\nimport { dirname, isAbsolute, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { createJiti } from 'jiti'\nimport { z } from 'zod'\nimport { ConfigError, type CommerceSlotAdapters } from '@nymbalhq/types'\nimport { KNOWN_PROVIDERS } from './known-providers.js'\nimport { nymbalConfigSchema, type NymbalConfig } from './schema.js'\n\nconst CONFIG_FILE = 'nymbal.config.ts'\n\nexport interface LoadedConfig {\n config: NymbalConfig\n path: string\n projectRoot: string\n /** The module's named `adapters` export: one adapter per slot whose provider is `custom`, for createApp. */\n adapters?: Partial<CommerceSlotAdapters>\n}\n\nexport function findConfigFile(startDir: string): string | null {\n let current = isAbsolute(startDir) ? startDir : resolve(startDir)\n while (true) {\n const candidate = resolve(current, CONFIG_FILE)\n if (existsSync(candidate)) return candidate\n const parent = dirname(current)\n if (parent === current) return null\n current = parent\n }\n}\n\nexport async function loadConfig(startDir: string = process.cwd()): Promise<LoadedConfig> {\n const path = findConfigFile(startDir)\n if (!path) {\n throw new ConfigError(\n `Could not find ${CONFIG_FILE} in ${startDir} or any parent directory.`,\n { context: { startDir } },\n )\n }\n\n const jiti = createJiti(pathToFileURL(path).href, { interopDefault: true })\n let mod: Record<string, unknown>\n try {\n mod = await jiti.import<Record<string, unknown>>(path)\n } catch (err) {\n throw new ConfigError(`Failed to load ${path}: ${(err as Error).message}`, {\n cause: err,\n context: { path },\n })\n }\n\n const raw = mod['default'] ?? mod\n const adapters = adaptersExport(mod['adapters'], path)\n try {\n const config = nymbalConfigSchema.parse(raw)\n return { config, path, projectRoot: dirname(path), ...(adapters !== undefined && { adapters }) }\n } catch (err) {\n if (err instanceof z.ZodError) {\n throw new ConfigError(formatZodError(err, path), {\n cause: err,\n context: { path, issues: err.issues },\n })\n }\n throw err\n }\n}\n\n/** The `adapters` export, keyed by commerce slot; anything else is a mistake worth naming before createApp runs. */\nfunction adaptersExport(value: unknown, path: string): Partial<CommerceSlotAdapters> | undefined {\n if (value === undefined) return undefined\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new ConfigError(`${path}: the adapters export must be an object keyed by commerce slot`, {\n code: 'config.adapters_invalid',\n context: { path },\n })\n }\n const slots = Object.keys(KNOWN_PROVIDERS)\n const unknown = Object.keys(value).filter((key) => !slots.includes(key))\n if (unknown.length > 0) {\n throw new ConfigError(\n `${path}: the adapters export names ${unknown.join(', ')}, which is no commerce slot (${slots.join(', ')})`,\n { code: 'config.adapters_invalid', context: { path, unknown } },\n )\n }\n return value as Partial<CommerceSlotAdapters>\n}\n\nfunction formatZodError(err: z.ZodError, path: string): string {\n const lines = err.issues.map((issue) => {\n const at = issue.path.length > 0 ? issue.path.join('.') : '<root>'\n return ` • ${at}: ${issue.message}`\n })\n return `Invalid configuration in ${path}:\\n${lines.join('\\n')}`\n}\n","import { z } from 'zod'\nimport {\n KNOWN_INFRASTRUCTURE,\n REMOVED_INFRASTRUCTURE_KEYS,\n type InfrastructureSlot,\n} from './known-infrastructure.js'\nimport { KNOWN_PROVIDERS, type CommerceSlot } from './known-providers.js'\n\nconst rateLimitRuleSchema = z.object({\n requests: z.number().int().positive(),\n window: z.string().regex(/^\\d+(ms|s|m|h)$/, 'window must look like \"60s\", \"5m\", \"1h\"'),\n action: z.enum(['block', 'challenge', 'throttle']),\n})\n\nconst rateLimitPathPattern = /^\\/[\\w\\-/*:]*$/\n\n/** The schema's JWT secret when none is configured: fine for development, refused in production. */\nexport const DEFAULT_JWT_SECRET = 'dev-secret-please-override-me-1234567890'\n\nexport const storeSchema = z.object({\n name: z.string().min(1),\n currency: z.string().length(3),\n locale: z.string().min(2),\n timezone: z.string().min(1),\n})\n\nconst quotedList = (values: readonly string[]): string => values.map((v) => `'${v}'`).join(', ')\n\n/** A slot's value must be one the slot lists; an unknown one is named with the list. */\nfunction infrastructureValue<const V extends readonly [string, ...string[]]>(\n slot: InfrastructureSlot,\n values: V,\n) {\n return z.enum(values, {\n errorMap: (issue, ctx) =>\n issue.code === z.ZodIssueCode.invalid_enum_value\n ? {\n message: `unknown ${slot} '${String(issue.received)}'; the ${slot} values are ${quotedList(values)}`,\n }\n : { message: ctx.defaultError },\n })\n}\n\nconst INFRASTRUCTURE_KEYS = [...Object.keys(KNOWN_INFRASTRUCTURE), 'redis', 's3']\n\nfunction unrecognizedInfrastructureKeys(keys: string[]): string {\n return keys\n .map((key) =>\n (REMOVED_INFRASTRUCTURE_KEYS as readonly string[]).includes(key)\n ? `infrastructure.${key} was removed: it drives nothing, so delete it from the config`\n : `unknown infrastructure key '${key}'; the infrastructure keys are ${quotedList(INFRASTRUCTURE_KEYS)}`,\n )\n .join('; ')\n}\n\n/** The shared Redis connection of the `redis` document store and the `redis-streams` bus. */\nexport const redisSchema = z\n .object({\n /** Defaults to `REDIS_URL`. */\n url: z.string().min(1).optional(),\n /** Namespaces every key and stream; defaults to `NYMBAL_REDIS_PREFIX`, then `'nymbal'`. */\n prefix: z.string().min(1).optional(),\n /** How long a publish waits for the groups it delivers to (default 15 000). */\n ackTimeoutMs: z.number().int().positive().optional(),\n /** How long an entry may stay pending on a consumer before a live one takes it over (default 5 000). */\n claimIdleMs: z.number().int().positive().optional(),\n /** The approximate length each stream is trimmed to (default 10 000). */\n streamMaxLen: z.number().int().positive().optional(),\n })\n .strict()\n\nconst S3_KEYS = ['bucket', 'region', 'endpoint', 'prefix', 'publicUrl', 'forcePathStyle']\n\n/**\n * The bucket `media: 's3'` stores in. Each field falls back to the environment in the platform; credentials are never\n * config keys: the AWS SDK's default chain provides them.\n */\nexport const s3Schema = z\n .object(\n {\n /** Defaults to `S3_BUCKET`; one of the two is required. */\n bucket: z.string().min(1).optional(),\n /** Defaults to `AWS_REGION`, then `'us-east-1'`. */\n region: z.string().min(1).optional(),\n /** An S3-compatible API (MinIO, R2); defaults to `S3_ENDPOINT`, then AWS. */\n endpoint: z.string().min(1).optional(),\n /** Where every object key starts; defaults to `NYMBAL_S3_PREFIX`, then none. */\n prefix: z.string().optional(),\n /** Where the bucket's objects are served from (a CDN); defaults to `S3_PUBLIC_URL`, then the bucket's own URL. */\n publicUrl: z.string().min(1).optional(),\n /** Path-style requests; true by default when an endpoint is set. */\n forcePathStyle: z.boolean().optional(),\n },\n {\n errorMap: (issue, ctx) =>\n issue.code === z.ZodIssueCode.unrecognized_keys\n ? {\n message: `unknown infrastructure.s3 key${issue.keys.length > 1 ? 's' : ''} ${quotedList(issue.keys)}; the s3 keys are ${quotedList(S3_KEYS)}, and credentials come from the AWS SDK (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, a profile or a role), never the config`,\n }\n : { message: ctx.defaultError },\n },\n )\n .strict()\n\nexport const infrastructureSchema = z\n .object(\n {\n commandStore: infrastructureValue('commandStore', KNOWN_INFRASTRUCTURE.commandStore),\n documentStore: infrastructureValue('documentStore', KNOWN_INFRASTRUCTURE.documentStore),\n eventBus: infrastructureValue('eventBus', KNOWN_INFRASTRUCTURE.eventBus),\n media: infrastructureValue('media', KNOWN_INFRASTRUCTURE.media).default('local-fs'),\n redis: redisSchema.optional(),\n s3: s3Schema.optional(),\n },\n {\n errorMap: (issue, ctx) =>\n issue.code === z.ZodIssueCode.unrecognized_keys\n ? { message: unrecognizedInfrastructureKeys(issue.keys) }\n : { message: ctx.defaultError },\n },\n )\n .strict()\n .superRefine((infra, ctx) => {\n if (infra.documentStore === 'postgres-jsonb' && infra.commandStore !== 'postgres') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['documentStore'],\n message: `documentStore 'postgres-jsonb' shares the command store's Postgres connection, so it needs commandStore 'postgres' (not '${infra.commandStore}')`,\n })\n }\n if (infra.eventBus === 'redis-streams' && infra.documentStore === 'in-memory') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['eventBus'],\n message: `eventBus 'redis-streams' needs a shared documentStore ('redis' or 'postgres-jsonb'), not 'in-memory': a named group hands each event to one instance, so a per-process read model would miss the rest`,\n })\n }\n if (infra.s3 !== undefined && infra.media !== 's3') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['s3'],\n message: `infrastructure.s3 configures media 's3', but media is '${infra.media}': set media to 's3' or delete the s3 block`,\n })\n }\n })\n\nexport const securitySchema = z.object({\n adapter: z.enum(['middleware', 'cloudflare', 'aws-waf', 'akamai']),\n rateLimit: z\n .record(\n z.string().regex(rateLimitPathPattern, {\n message: 'rate limit keys must start with \"/\" and use only letters, numbers, -, _, /, *, :',\n }),\n rateLimitRuleSchema,\n )\n .default({}),\n botProtection: z\n .object({\n mode: z.enum(['off', 'managed', 'strict']).default('off'),\n allowList: z.array(z.string()).default([]),\n })\n .default({ mode: 'off', allowList: [] }),\n headers: z\n .object({\n hsts: z.boolean().default(true),\n contentSecurityPolicy: z\n .union([z.enum(['strict', 'relaxed', 'off']), z.string()])\n .default('strict'),\n referrerPolicy: z.string().default('strict-origin-when-cross-origin'),\n xFrameOptions: z.enum(['deny', 'sameorigin']).default('deny'),\n })\n .default({}),\n csrf: z.boolean().default(true),\n auth: z\n .object({\n jwtSecret: z.string().min(16).default(DEFAULT_JWT_SECRET),\n accessTtl: z\n .string()\n .regex(/^\\d+(ms|s|m|h|d)$/, 'TTL must look like \"15m\"')\n .default('15m'),\n refreshTtl: z\n .string()\n .regex(/^\\d+(ms|s|m|h|d)$/, 'TTL must look like \"7d\"')\n .default('7d'),\n })\n .default({}),\n})\n\n/** A slot's block: its provider must be one the slot knows, and an unknown one is named with the slot's list. */\nfunction adapterBlock<const P extends readonly [string, ...string[]]>(\n slot: CommerceSlot,\n providers: P,\n) {\n const known = providers.map((p) => `'${p}'`).join(', ')\n return z.object({\n provider: z.enum(providers, {\n errorMap: (issue, ctx) =>\n issue.code === z.ZodIssueCode.invalid_enum_value\n ? {\n message: `unknown ${slot} provider '${String(issue.received)}'; the ${slot} providers are ${known}`,\n }\n : { message: ctx.defaultError },\n }),\n config: z.record(z.string(), z.unknown()).optional(),\n })\n}\n\nexport const commerceSchema = z.object({\n payments: adapterBlock('payments', KNOWN_PROVIDERS.payments),\n email: adapterBlock('email', KNOWN_PROVIDERS.email),\n reviews: adapterBlock('reviews', KNOWN_PROVIDERS.reviews),\n search: adapterBlock('search', KNOWN_PROVIDERS.search),\n analytics: adapterBlock('analytics', KNOWN_PROVIDERS.analytics),\n shipping: adapterBlock('shipping', KNOWN_PROVIDERS.shipping),\n tax: adapterBlock('tax', KNOWN_PROVIDERS.tax),\n ai: adapterBlock('ai', KNOWN_PROVIDERS.ai),\n orders: z\n .object({\n numberPrefix: z.string().min(1).default('NYM'),\n numberStart: z.number().int().nonnegative().default(1000),\n })\n .default({}),\n})\n\nexport const httpSchema = z.object({\n adapter: z.enum(['fastify', 'hono']).default('fastify'),\n port: z.number().int().positive().default(3001),\n host: z.string().default('0.0.0.0'),\n /** Whether `X-Forwarded-For` sets the client IP the rate limiter keys on; only behind a proxy you run. */\n trustProxy: z.boolean().default(false),\n cors: z\n .object({\n allowedOrigins: z\n .array(z.string())\n .default(['http://localhost:3000', 'http://localhost:4321']),\n credentials: z.boolean().default(true),\n })\n .default({}),\n})\n\nexport const deploymentSchema = z.object({\n strategy: z.enum(['standard', 'blue-green']).default('standard'),\n})\n\nexport const featuresSchema = z.object({\n staging: z.boolean().default(false),\n heartbeat: z.boolean().default(false),\n autoUpdates: z.boolean().default(false),\n})\n\nexport const nymbalConfigSchema = z\n .object({\n store: storeSchema,\n template: z.enum(['astro', 'nextjs']),\n infrastructure: infrastructureSchema,\n security: securitySchema,\n commerce: commerceSchema,\n http: httpSchema,\n deployment: deploymentSchema,\n features: featuresSchema.default({\n staging: false,\n heartbeat: false,\n autoUpdates: false,\n }),\n })\n .superRefine((cfg, ctx) => {\n // SMTP left the kernel for @nymbalhq/adapter-smtp; a native block still asking for it would print to the console.\n const email = cfg.commerce.email\n if (email.provider === 'native' && email.config?.['transport'] === 'smtp') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['commerce', 'email', 'config', 'transport'],\n message: `the native email provider only prints to the console; for SMTP mail set email.provider to 'smtp' (@nymbalhq/adapter-smtp)`,\n })\n }\n })\n\nexport type NymbalConfigInput = z.input<typeof nymbalConfigSchema>\nexport type NymbalConfig = z.output<typeof nymbalConfigSchema>\n"],"mappings":"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","names":["z","ConfigError","ConfigError","z"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nymbalhq/config",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Typed configuration surface for Nymbal",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"jiti": "^2.4.0",
|
|
31
31
|
"zod": "^3.23.8",
|
|
32
|
-
"@nymbalhq/types": "
|
|
32
|
+
"@nymbalhq/types": "1.1.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"tsup": "^8.3.5",
|