@nymbalhq/config 1.1.0 → 1.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/index.js CHANGED
@@ -164,7 +164,18 @@ var infrastructureSchema = z.object(
164
164
  });
165
165
  }
166
166
  });
167
- var securitySchema = z.object({
167
+ var cloudflareSchema = z.object({
168
+ zoneId: z.string().optional(),
169
+ apiToken: z.string().optional(),
170
+ /** The Cloudflare v4 API; the adapter defaults it to https://api.cloudflare.com/client/v4. */
171
+ apiBase: z.string().url().optional()
172
+ });
173
+ var customRuleSchema = z.object({
174
+ name: z.string().min(1),
175
+ expression: z.string().min(1),
176
+ action: z.enum(["block", "managed_challenge", "js_challenge", "log"])
177
+ });
178
+ var securityFields = z.object({
168
179
  adapter: z.enum(["middleware", "cloudflare", "aws-waf", "akamai"]),
169
180
  rateLimit: z.record(
170
181
  z.string().regex(rateLimitPathPattern, {
@@ -187,8 +198,39 @@ var securitySchema = z.object({
187
198
  jwtSecret: z.string().min(16).default(DEFAULT_JWT_SECRET),
188
199
  accessTtl: z.string().regex(/^\d+(ms|s|m|h|d)$/, 'TTL must look like "15m"').default("15m"),
189
200
  refreshTtl: z.string().regex(/^\d+(ms|s|m|h|d)$/, 'TTL must look like "7d"').default("7d")
190
- }).default({})
201
+ }).default({}),
202
+ cloudflare: cloudflareSchema.optional(),
203
+ geo: z.object({
204
+ block: z.array(z.string().regex(/^[A-Z]{2}$/, 'geo.block codes are ISO 3166 alpha-2, like "RU"')).default([])
205
+ }).default({ block: [] }),
206
+ customRules: z.array(customRuleSchema).default([]),
207
+ managedRulesets: z.array(z.enum(["cloudflare", "owasp"])).default([])
191
208
  });
209
+ var securitySchema = securityFields.superRefine((security, ctx) => {
210
+ if (security.adapter === "cloudflare") {
211
+ for (const field of ["zoneId", "apiToken"]) {
212
+ if (!security.cloudflare?.[field]) {
213
+ ctx.addIssue({
214
+ code: z.ZodIssueCode.custom,
215
+ path: ["cloudflare", field],
216
+ message: `security.adapter 'cloudflare' needs security.cloudflare.${field}`
217
+ });
218
+ }
219
+ }
220
+ }
221
+ const seen = /* @__PURE__ */ new Set();
222
+ security.customRules.forEach((rule, i) => {
223
+ if (seen.has(rule.name)) {
224
+ ctx.addIssue({
225
+ code: z.ZodIssueCode.custom,
226
+ path: ["customRules", i, "name"],
227
+ message: `customRules has two rules named '${rule.name}'; names must be unique`
228
+ });
229
+ }
230
+ seen.add(rule.name);
231
+ });
232
+ });
233
+ var NPM_PACKAGE_NAME = /^(?:@[a-z0-9~-][a-z0-9._~-]*\/)?[a-z0-9~-][a-z0-9._~-]*$/;
192
234
  function adapterBlock(slot, providers) {
193
235
  const known = providers.map((p) => `'${p}'`).join(", ");
194
236
  return z.object({
@@ -197,7 +239,9 @@ function adapterBlock(slot, providers) {
197
239
  message: `unknown ${slot} provider '${String(issue.received)}'; the ${slot} providers are ${known}`
198
240
  } : { message: ctx.defaultError }
199
241
  }),
200
- config: z.record(z.string(), z.unknown()).optional()
242
+ config: z.record(z.string(), z.unknown()).optional(),
243
+ /** The npm package a `custom` slot's adapter comes from, for tooling (`nymbal test:contracts`); the kernel never reads it. */
244
+ package: z.string().max(214, "an npm package name is at most 214 characters").regex(NPM_PACKAGE_NAME, "must be an npm package name, such as `@acme/nymbal-search`").optional()
201
245
  });
202
246
  }
203
247
  var commerceSchema = z.object({
@@ -233,6 +277,23 @@ var featuresSchema = z.object({
233
277
  heartbeat: z.boolean().default(false),
234
278
  autoUpdates: z.boolean().default(false)
235
279
  });
280
+ var eventArchiveSchema = z.object({
281
+ adapter: z.literal("s3"),
282
+ bucket: z.string().min(1),
283
+ /** Where every archive key starts; none when not given. */
284
+ prefix: z.string().optional(),
285
+ /** `'us-east-1'` when not given. */
286
+ region: z.string().min(1).optional(),
287
+ /** An S3-compatible API (MinIO, R2). */
288
+ endpoint: z.string().min(1).optional(),
289
+ /** Path-style requests; true by default when an endpoint is set. */
290
+ forcePathStyle: z.boolean().optional()
291
+ }).strict();
292
+ var eventsSchema = z.object({
293
+ /** Days a delivered event stays in the log. */
294
+ retentionDays: z.number().int().min(1).default(30),
295
+ archive: eventArchiveSchema.optional()
296
+ }).strict();
236
297
  var nymbalConfigSchema = z.object({
237
298
  store: storeSchema,
238
299
  template: z.enum(["astro", "nextjs"]),
@@ -245,8 +306,17 @@ var nymbalConfigSchema = z.object({
245
306
  staging: false,
246
307
  heartbeat: false,
247
308
  autoUpdates: false
248
- })
309
+ }),
310
+ events: eventsSchema.default({})
249
311
  }).superRefine((cfg, ctx) => {
312
+ const archiveBucket = cfg.events.archive?.bucket;
313
+ if (archiveBucket !== void 0 && cfg.infrastructure.media === "s3" && archiveBucket === cfg.infrastructure.s3?.bucket) {
314
+ ctx.addIssue({
315
+ code: z.ZodIssueCode.custom,
316
+ path: ["events", "archive", "bucket"],
317
+ message: `events.archive.bucket is infrastructure.s3.bucket ('${archiveBucket}'), the media bucket, which serves its objects publicly; archive events to a private bucket of their own`
318
+ });
319
+ }
250
320
  const email = cfg.commerce.email;
251
321
  if (email.provider === "native" && email.config?.["transport"] === "smtp") {
252
322
  ctx.addIssue({
@@ -340,6 +410,8 @@ export {
340
410
  envBool,
341
411
  envNumber,
342
412
  envOptional,
413
+ eventArchiveSchema,
414
+ eventsSchema,
343
415
  featuresSchema,
344
416
  findConfigFile,
345
417
  httpSchema,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
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"]}
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\n/** Where a `cloudflare` store's rules go: required when `security.adapter` is `cloudflare`, read with `env()`. */\nconst cloudflareSchema = z.object({\n zoneId: z.string().optional(),\n apiToken: z.string().optional(),\n /** The Cloudflare v4 API; the adapter defaults it to https://api.cloudflare.com/client/v4. */\n apiBase: z.string().url().optional(),\n})\n\nconst customRuleSchema = z.object({\n name: z.string().min(1),\n expression: z.string().min(1),\n action: z.enum(['block', 'managed_challenge', 'js_challenge', 'log']),\n})\n\nconst securityFields = 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 cloudflare: cloudflareSchema.optional(),\n geo: z\n .object({\n block: z\n .array(z.string().regex(/^[A-Z]{2}$/, 'geo.block codes are ISO 3166 alpha-2, like \"RU\"'))\n .default([]),\n })\n .default({ block: [] }),\n customRules: z.array(customRuleSchema).default([]),\n managedRulesets: z.array(z.enum(['cloudflare', 'owasp'])).default([]),\n})\n\nexport const securitySchema = securityFields.superRefine((security, ctx) => {\n if (security.adapter === 'cloudflare') {\n for (const field of ['zoneId', 'apiToken'] as const) {\n if (!security.cloudflare?.[field]) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['cloudflare', field],\n message: `security.adapter 'cloudflare' needs security.cloudflare.${field}`,\n })\n }\n }\n }\n const seen = new Set<string>()\n security.customRules.forEach((rule, i) => {\n if (seen.has(rule.name)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['customRules', i, 'name'],\n message: `customRules has two rules named '${rule.name}'; names must be unique`,\n })\n }\n seen.add(rule.name)\n })\n})\n\n/**\n * npm's rules for a new package name: lower case and URL-safe, optionally `@scope/`, never starting with `.` or `_`.\n * The 214-character limit is checked beside it.\n */\nconst NPM_PACKAGE_NAME = /^(?:@[a-z0-9~-][a-z0-9._~-]*\\/)?[a-z0-9~-][a-z0-9._~-]*$/\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 /** The npm package a `custom` slot's adapter comes from, for tooling (`nymbal test:contracts`); the kernel never reads it. */\n package: z\n .string()\n .max(214, 'an npm package name is at most 214 characters')\n .regex(NPM_PACKAGE_NAME, 'must be an npm package name, such as `@acme/nymbal-search`')\n .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\n/**\n * The bucket delivered events past retention are archived to before they are deleted. Its objects hold customer\n * data, so it must be private: never the media bucket, which serves its objects publicly. Credentials come from the\n * AWS SDK's default chain, as `infrastructure.s3`'s do.\n */\nexport const eventArchiveSchema = z\n .object({\n adapter: z.literal('s3'),\n bucket: z.string().min(1),\n /** Where every archive key starts; none when not given. */\n prefix: z.string().optional(),\n /** `'us-east-1'` when not given. */\n region: z.string().min(1).optional(),\n /** An S3-compatible API (MinIO, R2). */\n endpoint: z.string().min(1).optional(),\n /** Path-style requests; true by default when an endpoint is set. */\n forcePathStyle: z.boolean().optional(),\n })\n .strict()\n\nexport const eventsSchema = z\n .object({\n /** Days a delivered event stays in the log. */\n retentionDays: z.number().int().min(1).default(30),\n archive: eventArchiveSchema.optional(),\n })\n .strict()\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 events: eventsSchema.default({}),\n })\n .superRefine((cfg, ctx) => {\n const archiveBucket = cfg.events.archive?.bucket\n if (\n archiveBucket !== undefined &&\n cfg.infrastructure.media === 's3' &&\n archiveBucket === cfg.infrastructure.s3?.bucket\n ) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['events', 'archive', 'bucket'],\n message: `events.archive.bucket is infrastructure.s3.bucket ('${archiveBucket}'), the media bucket, which serves its objects publicly; archive events to a private bucket of their own`,\n })\n }\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": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Typed configuration surface for Nymbal",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -27,17 +27,18 @@
27
27
  "dist"
28
28
  ],
29
29
  "dependencies": {
30
+ "@nymbalhq/types": "1.3.0",
30
31
  "jiti": "^2.4.0",
31
- "zod": "^3.23.8",
32
- "@nymbalhq/types": "1.1.0"
32
+ "zod": "^3.23.8"
33
33
  },
34
34
  "devDependencies": {
35
- "tsup": "^8.3.5",
36
- "typescript": "^5.6.3"
35
+ "@typescript/native": "npm:typescript@^7.0.2",
36
+ "tsup": "^9.0.0",
37
+ "typescript": "npm:@typescript/typescript6@^6.0.2"
37
38
  },
38
39
  "scripts": {
39
40
  "build": "tsup",
40
41
  "dev": "tsup --watch",
41
- "typecheck": "tsc -p tsconfig.json --noEmit"
42
+ "typecheck": "tsc -p tsconfig.json --noEmit --rootDir ../.."
42
43
  }
43
44
  }