@noverax/courier-build 0.0.0-stage → 0.4.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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +289 -2
  3. package/lib/config/index.d.ts +420 -0
  4. package/lib/config/index.js +66 -0
  5. package/lib/config-file-of-Zkwyi9zf.js +28 -0
  6. package/lib/config-in-page-message-DLd3f0Jd.js +20 -0
  7. package/lib/courier-routes-options-BYF7Sfdf.d.cts +13 -0
  8. package/lib/courier-routes-options-BYF7Sfdf.d.ts +13 -0
  9. package/lib/engine/worker.d.ts +1 -0
  10. package/lib/engine/worker.js +551 -0
  11. package/lib/errno-code-CNx_E80R.js +32 -0
  12. package/lib/esbuild/index.d.ts +58 -0
  13. package/lib/esbuild/index.js +191 -0
  14. package/lib/index-_VUU5N5v.d.ts +134 -0
  15. package/lib/index.d.ts +101 -0
  16. package/lib/index.js +4 -0
  17. package/lib/jest/routes-thread.d.ts +1 -0
  18. package/lib/jest/routes-thread.js +46 -0
  19. package/lib/jest/transformer.cjs +121 -0
  20. package/lib/jest/transformer.d.cts +39 -0
  21. package/lib/load-config-BeedbpkN.js +1419 -0
  22. package/lib/metro/index.cjs +25 -0
  23. package/lib/metro/index.d.cts +55 -0
  24. package/lib/metro/index.d.ts +67 -0
  25. package/lib/metro/index.js +105 -0
  26. package/lib/package-file-CVAKY_Nu.js +39 -0
  27. package/lib/rollup/index.d.ts +51 -0
  28. package/lib/rollup/index.js +95 -0
  29. package/lib/routes-engine-BfwrCuNL.d.ts +117 -0
  30. package/lib/routes-file-DcpgxYb1.js +206 -0
  31. package/lib/routes-loader-context-40OKDrQp.d.ts +26 -0
  32. package/lib/routes-module-code-DO3aII6v.js +402 -0
  33. package/lib/routes-module-id-CnUjQjYF.js +12 -0
  34. package/lib/routes-read-error-DQhKIE2F.js +30 -0
  35. package/lib/routes-rule-CjzX6NS5.js +108 -0
  36. package/lib/rsbuild/index.d.ts +41 -0
  37. package/lib/rsbuild/index.js +37 -0
  38. package/lib/rspack/index.d.ts +3 -0
  39. package/lib/rspack/index.js +1 -0
  40. package/lib/shared-engine-CCu7vP_0.js +28 -0
  41. package/lib/vite/index.d.ts +33 -0
  42. package/lib/vite/index.js +346 -0
  43. package/lib/webpack/index.d.ts +4 -0
  44. package/lib/webpack/index.js +3 -0
  45. package/lib/webpack/loader.cjs +31 -0
  46. package/lib/webpack/loader.d.cts +40 -0
  47. package/lib/webpack/run-routes-loader.d.ts +22 -0
  48. package/lib/webpack/run-routes-loader.js +103 -0
  49. package/lib/webpack-B0v9i8lk.js +42 -0
  50. package/lib/worker-messages-BT2vvNQJ.js +35 -0
  51. package/package.json +209 -4
@@ -0,0 +1,420 @@
1
+ import { CourierError } from "@noverax/courier";
2
+ import { Jiti, TransformOptions, TransformResult } from "jiti";
3
+ import { CourierConfig } from "@noverax/courier/config";
4
+ /** The file names a Courier config may have, in the order they are looked for */
5
+ export declare const CONFIG_BASENAMES: ReadonlyArray<string>;
6
+ /**
7
+ * Every path a config is looked for at from a folder, in the order it is
8
+ * looked for: each of {@link CONFIG_BASENAMES} in the folder, then in each
9
+ * folder above it, up to the top of the project — the first folder that
10
+ * holds its repository (`.git`, `.hg`, `.jj`) or is the root of its
11
+ * workspace (`pnpm-workspace.yaml`, or a `package.json` that declares
12
+ * `workspaces`) — or, with no such folder, the root of the file system.
13
+ *
14
+ * @param startDir - The folder to look in first
15
+ * @returns The paths, absolute, whether there or not
16
+ * @example
17
+ * ```ts
18
+ * configCandidates("/repo/apps/web"); // → ["/repo/apps/web/courier.config.ts", …, "/repo/courier.config.cjs"]
19
+ * ```
20
+ */
21
+ export declare function configCandidates(startDir: string): string[];
22
+ /**
23
+ * A store of jiti transforms: TypeScript and ESM sources compiled to the
24
+ * CommonJS jiti evaluates, reused while the bytes and options that produced
25
+ * them are unchanged.
26
+ */
27
+ interface TransformCache {
28
+ /**
29
+ * What jiti's transform yields for `options`: the kept code when the store
30
+ * holds a successful transform of the same file from the same bytes and
31
+ * options, and otherwise whatever `compute` returns.
32
+ *
33
+ * @param options - What jiti hands its transform
34
+ * @param compute - jiti's own transform, run on a miss
35
+ * @returns The result of `compute`, or its kept code, byte for byte
36
+ */
37
+ transform(options: TransformOptions, compute: (options: TransformOptions) => TransformResult): TransformResult;
38
+ }
39
+ /** Where a {@link TransformCache} keeps transforms, and how much in memory. */
40
+ interface TransformCacheOptions {
41
+ /**
42
+ * A directory to keep transforms in across processes, as
43
+ * `findTransformCacheDirectory` finds it. Without one, or with `null`,
44
+ * transforms are kept in memory only.
45
+ */
46
+ directory?: string | null | undefined;
47
+ /**
48
+ * Characters of transformed code kept in memory across all files; the file
49
+ * used least recently is dropped first once they are exceeded. `0` keeps
50
+ * none, for a process that loads each module once. Defaults to 128 Mi
51
+ * characters.
52
+ */
53
+ maxMemoryChars?: number | undefined;
54
+ /**
55
+ * Whether the `directory` is only read: nothing in it is created, written,
56
+ * pruned or marked as used, so a transform computed on a miss stays in
57
+ * this process. For a process that loads, once, what another process has
58
+ * just kept there, as a mock worker loads the modules Studio loaded: its
59
+ * own entries would only duplicate that process's. Defaults to `false`.
60
+ */
61
+ readOnly?: boolean | undefined;
62
+ }
63
+ /**
64
+ * Create a {@link TransformCache} that keeps transforms in memory for the
65
+ * life of the process and, given a `directory`, on disk for the next one.
66
+ *
67
+ * Each file holds one entry per module system — required and imported are
68
+ * transformed differently, and a module reached both ways keeps both. An
69
+ * entry is reused only when the digest of jiti's version, the options and
70
+ * the source matches, so an edited file is transformed again the first time
71
+ * it is loaded.
72
+ *
73
+ * A transform is looked for in memory, then in the directory, where a hit
74
+ * is also kept in memory; only when both miss is it computed, and a success
75
+ * is then kept in both. The directory is shared with every process that
76
+ * names it, and a directory that cannot be read or written only costs
77
+ * transforms; see `createTransformCacheDisk` for what an entry must be to be
78
+ * used. A mock worker, which loads once the modules Studio has just loaded,
79
+ * opens Studio's directory `readOnly` with `maxMemoryChars: 0`: it reads
80
+ * what Studio kept, adds nothing to the directory, and holds nothing in
81
+ * memory past its one load.
82
+ *
83
+ * A failed transform, one whose result carries an `error`, is never kept:
84
+ * babel can fail on bytes it transforms without complaint a moment later,
85
+ * such as a deeply nested module that overflows the stack while babel is
86
+ * still cold. Such a file is transformed again on every load, and every
87
+ * failure reaches jiti with its error, as it does without a cache. A file
88
+ * named by a relative path, or not named, is transformed every time.
89
+ *
90
+ * @param options - The directory (default: none, memory only), the memory
91
+ * bound (default: 128 Mi characters), and whether the directory is only
92
+ * read (default: no)
93
+ * @returns A cache to pass to `createConfigJiti` or `loadCourierConfig`
94
+ * @example
95
+ * ```ts
96
+ * const transformCache = createTransformCache({
97
+ * directory: findTransformCacheDirectory(projectRoot),
98
+ * });
99
+ * const first = await loadCourierConfig({ cwd: projectRoot, transformCache });
100
+ * // Unchanged modules are not transformed again, here or in the next process:
101
+ * const second = await loadCourierConfig({ cwd: projectRoot, transformCache });
102
+ *
103
+ * // A process that loads once what another has just kept:
104
+ * const reader = createTransformCache({ directory, readOnly: true, maxMemoryChars: 0 });
105
+ * ```
106
+ */
107
+ export declare function createTransformCache({ directory, maxMemoryChars, readOnly }?: TransformCacheOptions): TransformCache;
108
+ /** How a project-file loader resolves imports and transforms modules. */
109
+ interface ConfigJitiOptions {
110
+ /**
111
+ * Whether imports resolve through the project's tsconfig path aliases, as
112
+ * the project's own files expect. Off to load an installed package as it is:
113
+ * an alias of its scope would send its imports to project sources.
114
+ */
115
+ aliases?: boolean | undefined;
116
+ /**
117
+ * Where to reuse each module's transform while its bytes are unchanged.
118
+ * Without one, every module is transformed on every load. Aliases take no
119
+ * part in it: they change where an import resolves, never the code a
120
+ * module's own bytes transform to.
121
+ */
122
+ transformCache?: TransformCache | undefined;
123
+ /**
124
+ * Told the file of each module the load transforms — the config and every
125
+ * TypeScript or ES module of the project it reaches — so whoever follows
126
+ * the project knows which files its config depends on.
127
+ */
128
+ onModule?: ((filename: string) => void) | undefined;
129
+ /**
130
+ * Runs each transform the load makes, the first of which loads the
131
+ * transformer itself. A caller noting what the config's code reads runs it
132
+ * unnoted: what the transformer reads is its own, not the config's.
133
+ */
134
+ runTransform?: (<TResult>(transform: () => TResult) => TResult) | undefined;
135
+ }
136
+ /**
137
+ * The module loader for Courier's project files — `courier.config.*` and
138
+ * `courier.mocks.*` — with the options both need: the project's tsconfig path
139
+ * aliases, default-export interop, no module cache, and no native import
140
+ * tried before the loader's own.
141
+ *
142
+ * The module cache is off because this is also the reload path: the dev
143
+ * server loads the files again on every edit, and a cached module would hand
144
+ * back the file as it was before the user changed it. Every load therefore
145
+ * reads and evaluates every file again; a `transformCache` only spares the
146
+ * transform of a file whose bytes are unchanged.
147
+ *
148
+ * jiti's native attempt, which imports every module natively before falling
149
+ * back to its own loader, stays off too, whatever `JITI_TRY_NATIVE` says and
150
+ * under Bun, where it defaults to on: a module imported natively is the
151
+ * runtime's first evaluation of it for the life of the process, so an edit to
152
+ * it would never be seen, and the attempt comes before the module cache
153
+ * `evalModule` is handed, so two files evaluated over one cache would each
154
+ * evaluate a module they both import.
155
+ *
156
+ * jiti's own file cache stays off, with or without a `transformCache`:
157
+ * - it writes each entry in place, so concurrent writers can leave an entry
158
+ * torn between two transforms that its check still accepts;
159
+ * - an entry it cannot write makes the whole load throw `EACCES`;
160
+ * - unless the file's own directory has a `node_modules`, it falls back to
161
+ * `os.tmpdir()/jiti`, where another user of the machine can place an entry
162
+ * that is then run;
163
+ * - its key ignores `interopDefault` and the babel options, so a transform
164
+ * made under other options can be handed back;
165
+ * - nothing ever prunes it.
166
+ *
167
+ * jiti is loaded here rather than at the top of a module so a bundler that
168
+ * merely reaches this code does not pull a TypeScript transpiler into its
169
+ * graph; only a process that actually reads such a file pays for it.
170
+ *
171
+ * @param file - Absolute, symlink-resolved path of the file to load; modules
172
+ * and aliases resolve from its directory
173
+ * @param options - Whether to resolve through the project's path aliases
174
+ * (default: yes), and where to reuse transforms (default: nowhere)
175
+ * @returns A jiti instance for that file
176
+ * @example
177
+ * ```ts
178
+ * const transformCache = createTransformCache();
179
+ * const jiti = await createConfigJiti(configFile, { transformCache });
180
+ * const config = await jiti.import(configFile, { default: true });
181
+ * ```
182
+ */
183
+ export declare function createConfigJiti(file: string, { aliases, transformCache, onModule, runTransform }?: ConfigJitiOptions): Promise<Jiti>;
184
+ /**
185
+ * Result of a successful `loadCourierConfig` call.
186
+ *
187
+ * `configFile` is the absolute, symlink-resolved path of the file that
188
+ * was loaded — the dev-server side uses it for the `fs.watch` dep tracker;
189
+ * the runtime side uses it only for log/debug output.
190
+ */
191
+ interface LoadedCourierConfig {
192
+ config: CourierConfig;
193
+ configFile: string;
194
+ }
195
+ /**
196
+ * Options for `loadCourierConfig`.
197
+ */
198
+ interface LoadCourierConfigOptions {
199
+ /**
200
+ * Starting directory for the config search. Defaults to `process.cwd()`.
201
+ * The dev-server passes the explicit project root; the runtime path
202
+ * passes `process.cwd()` so the walk-up finds configs located at the
203
+ * workspace root from a nested package cwd (common in monorepos).
204
+ */
205
+ cwd?: string | undefined;
206
+ /**
207
+ * When true, skip the walk-up and require the config file to exist at
208
+ * exactly `cwd`. The dev-server uses this because it was told the
209
+ * project root explicitly and wants to distinguish "no config in root"
210
+ * from "config found higher up" (which would usually mean the user
211
+ * pointed at the wrong directory). The runtime path leaves this false
212
+ * so a nested `cwd` still discovers a root-level config.
213
+ *
214
+ * Defaults to false (walk up).
215
+ */
216
+ requireAtCwd?: boolean | undefined;
217
+ /**
218
+ * Where to reuse each module's transform while its bytes are unchanged. A
219
+ * caller that keeps one across loads transforms only the modules whose
220
+ * bytes changed; without one, every module is transformed on every load.
221
+ */
222
+ transformCache?: TransformCache | undefined;
223
+ /** Told the file of each module the load transforms; see `createConfigJiti`. */
224
+ onModule?: ((filename: string) => void) | undefined;
225
+ /**
226
+ * Reuse the transforms kept in the project's `node_modules/.cache`, the
227
+ * ones Studio keeps, and keep there the ones this load makes: a process
228
+ * that loads the config beside Studio — an app that attaches, the MCP
229
+ * server, `courier-server` — transforms only the modules no process has
230
+ * transformed yet. On a project of a thousand endpoints that is hundreds
231
+ * of modules, most of a second. Passed over when `transformCache` is given.
232
+ */
233
+ projectTransforms?: boolean | undefined;
234
+ }
235
+ /**
236
+ * Walk up from `startDir` looking for a `courier.config.*` file, up to the
237
+ * top of the project: the folder that holds its repository or is the root
238
+ * of its workspace (see {@link configCandidates}). A config found in a folder
239
+ * above `startDir` is taken only when it belongs to this user or to the
240
+ * owner of `startDir`, and no user outside its group may write it: a folder
241
+ * many users share, such as `/tmp`, would otherwise run anyone's config.
242
+ *
243
+ * @param startDir - The directory to look in first
244
+ * @returns The absolute path of the first match, or `null` when no directory
245
+ * up to the top of the project holds one
246
+ * @throws UntrustedConfigError when the nearest config lies above `startDir`
247
+ * and someone else could have put it there
248
+ * @example
249
+ * ```ts
250
+ * findConfigFile("/app/src"); // → "/app/courier.config.ts", or null
251
+ * ```
252
+ */
253
+ export declare function findConfigFile(startDir: string): string | null;
254
+ /**
255
+ * Find a config file in `cwd` itself, without walking up.
256
+ *
257
+ * @param cwd - The directory to look in
258
+ * @returns The first of {@link CONFIG_BASENAMES} present there, or `null`
259
+ * @example
260
+ * ```ts
261
+ * findConfigFileAt(process.cwd()); // → "/app/courier.config.ts", or null
262
+ * ```
263
+ */
264
+ export declare function findConfigFileAt(cwd: string): string | null;
265
+ /**
266
+ * Find and load a `courier.config.*` file.
267
+ *
268
+ * Returns `null` when no config file exists, so a caller can fall back.
269
+ * Throws when a file was found and loading it failed, reporting what the
270
+ * loader reported — for a TypeScript config, usually an unresolvable import.
271
+ *
272
+ * @param options - Where to look, and where to reuse transforms
273
+ * @returns The config and its canonical path, or `null` when there is no config
274
+ * @example
275
+ * ```ts
276
+ * const loaded = await loadCourierConfig({ cwd: projectRoot, requireAtCwd: true });
277
+ * ```
278
+ */
279
+ export declare function loadCourierConfig(options?: LoadCourierConfigOptions): Promise<LoadedCourierConfig | null>;
280
+ /**
281
+ * The transforms kept in a project's `node_modules/.cache` — the ones Studio
282
+ * keeps — for a process that loads the project's modules once: it reuses
283
+ * them, keeps there the ones it makes, and holds none in memory.
284
+ *
285
+ * @param projectRoot - The project's root
286
+ * @returns The cache, or `undefined` when the project has no directory to keep them in
287
+ * @example
288
+ * ```ts
289
+ * await loadCourierConfigFile(file, { transformCache: projectTransformCache(dirname(file)) });
290
+ * ```
291
+ */
292
+ export declare function projectTransformCache(projectRoot: string): TransformCache | undefined;
293
+ /** How one config file is loaded: the loader's options, and when its code is about to run. */
294
+ interface LoadConfigFileOptions extends ConfigJitiOptions {
295
+ /**
296
+ * Called once the loader is made, just before the config's code runs. A
297
+ * caller noting what that code reads starts here, so the loader's own
298
+ * start-up is not taken for the config's.
299
+ */
300
+ beforeRun?: (() => void) | undefined;
301
+ }
302
+ /**
303
+ * Load one config file, found by whatever means the caller chose — the
304
+ * standalone server takes it from `--config`.
305
+ *
306
+ * @param file - Absolute path of an existing config file
307
+ * @param options - How the loader resolves imports and where it reuses
308
+ * transforms, see {@link ConfigJitiOptions}, and what runs before the config
309
+ * @returns The config and the canonical path it was loaded from
310
+ * @throws What the loader reported when the file will not load — for a
311
+ * TypeScript config, usually an unresolvable import
312
+ * @example
313
+ * ```ts
314
+ * const { config } = await loadCourierConfigFile("/app/courier.config.ts", {
315
+ * transformCache: createTransformCache(),
316
+ * });
317
+ * ```
318
+ */
319
+ export declare function loadCourierConfigFile(file: string, { beforeRun, ...options }?: LoadConfigFileOptions): Promise<LoadedCourierConfig>;
320
+ /** Path aliases a project declares, ready for both consumers. */
321
+ interface PathAliases {
322
+ /**
323
+ * Prefix → absolute target, in the shape jiti's `alias` option takes.
324
+ * Only the first target of a mapping appears: jiti resolves one path per
325
+ * alias, while `candidatesFor` offers every declared target.
326
+ */
327
+ readonly loader: Readonly<Record<string, string>>;
328
+ /** Absolute paths `specifier` may denote, in declaration order. */
329
+ candidatesFor(specifier: string): string[];
330
+ }
331
+ /**
332
+ * Read the path aliases that apply to `projectRoot`.
333
+ *
334
+ * @param projectRoot - Directory holding the project's `tsconfig.json`
335
+ * @returns The aliases, empty when the project declares none
336
+ *
337
+ * @example
338
+ * ```ts
339
+ * const aliases = readPathAliases("/app");
340
+ * aliases.candidatesFor("@/lib/sources"); // → ["/app/src/lib/sources"]
341
+ * ```
342
+ */
343
+ export declare function readPathAliases(projectRoot: string): PathAliases;
344
+ /**
345
+ * Where a project's transforms are kept across processes:
346
+ * `.cache/courier/transform` in the nearest `node_modules` directory at or
347
+ * above the project root.
348
+ *
349
+ * The nearest one is taken, not the one module resolution would reach: under
350
+ * pnpm that lies inside `.pnpm`, and what keeps the directory safe is the
351
+ * rule below, not where it is. Every file in it holds code that Studio, mock
352
+ * workers and build plugins run, so on POSIX the directory is refused when
353
+ * `node_modules`, `.cache`, `courier` or `transform` — those that exist — is
354
+ * a symbolic link or belongs to another user, and when `courier` or
355
+ * `transform`, which only Studio creates, is writable by its group or
356
+ * others; any of these lets someone else replace or remove entries, or put
357
+ * the directory somewhere they control. `node_modules` and `.cache` may be
358
+ * group-writable, as package managers leave them under a umask of 002:
359
+ * whoever can write `node_modules` can replace any package in it already. On
360
+ * Windows only links and other kinds of file are refused.
361
+ *
362
+ * There is none when no `node_modules` exists, as with Yarn Plug'n'Play, or
363
+ * when `COURIER_TRANSFORM_CACHE` is `0`, `false` or `off` in any case. The
364
+ * system temporary directory, which every user of the machine may write, is
365
+ * never used instead. Why there is none is logged at debug level, once for
366
+ * each root until the reason changes, however often the root is looked up.
367
+ *
368
+ * @param projectRoot - The directory holding `courier.config.*`
369
+ * @param env - The environment to read `COURIER_TRANSFORM_CACHE` from
370
+ * (default: `process.env`)
371
+ * @returns The directory, which may not exist yet, or `null` for none
372
+ * @example
373
+ * ```ts
374
+ * const transformCache = createTransformCache({
375
+ * directory: findTransformCacheDirectory(projectRoot),
376
+ * });
377
+ * ```
378
+ */
379
+ export declare function findTransformCacheDirectory(projectRoot: string, env?: Readonly<Record<string, string | undefined>>): string | null;
380
+ /**
381
+ * The keys of a courier.config that Courier does not read, at the top and
382
+ * in its `studio`, `server`, `runtime` and `agents` blocks — a misspelt `studo:` say
383
+ * — so a load can name them rather than ignore them in silence.
384
+ *
385
+ * @param config - The config, as its module exported it
386
+ * @returns Each such key, dotted under its block
387
+ * @example
388
+ * ```ts
389
+ * unknownConfigKeys({ sources: {}, studo: {}, server: { prot: 3001 } }); // → ["studo", "server.prot"]
390
+ * ```
391
+ */
392
+ export declare function unknownConfigKeys(config: unknown): string[];
393
+ /** Where a config that was not run lies, and the folder it was looked for from. */
394
+ interface UntrustedConfigContext extends Record<string, unknown> {
395
+ /** The config, absolute. */
396
+ configFile: string;
397
+ /** The folder the config was looked for from, below it. */
398
+ folder: string;
399
+ }
400
+ /**
401
+ * The config nearest a folder lies in a folder above it, and someone else
402
+ * could have put it there: it belongs to another user, or any user may
403
+ * write it. It was not run, as it would run with the rights of whoever
404
+ * builds or serves the project.
405
+ *
406
+ * @example
407
+ * ```ts
408
+ * throw new UntrustedConfigError("/tmp/courier.config.ts", "/tmp/app", "it belongs to uid 1001");
409
+ * ```
410
+ */
411
+ export declare class UntrustedConfigError extends CourierError<"CONFIG_NOT_TRUSTED"> {
412
+ readonly context: UntrustedConfigContext;
413
+ /**
414
+ * @param configFile - The config that was not run, absolute
415
+ * @param folder - The folder it was looked for from
416
+ * @param reason - Why it is not trusted, worded to follow "and"
417
+ */
418
+ constructor(configFile: string, folder: string, reason: string);
419
+ }
420
+ export type { ConfigJitiOptions, LoadConfigFileOptions, LoadCourierConfigOptions, LoadedCourierConfig, PathAliases, TransformCache, TransformCacheOptions, UntrustedConfigContext };
@@ -0,0 +1,66 @@
1
+ import { n as isRecord } from "../errno-code-CNx_E80R.js";
2
+ import { a as projectTransformCache, c as UntrustedConfigError, d as CONFIG_BASENAMES, f as configCandidates, i as loadCourierConfigFile, l as createConfigJiti, n as findConfigFileAt, o as findTransformCacheDirectory, r as loadCourierConfig, s as createTransformCache, t as findConfigFile, u as readPathAliases } from "../load-config-BeedbpkN.js";
3
+ // src/config/unknown-config-keys.ts
4
+ const TOP_LEVEL = {
5
+ sources: true,
6
+ imports: true,
7
+ studio: true,
8
+ server: true,
9
+ runtime: true,
10
+ agents: true
11
+ };
12
+ const BLOCKS = /* @__PURE__ */ new Map([
13
+ ["studio", {
14
+ port: true,
15
+ host: true,
16
+ mockBasePort: true,
17
+ open: true,
18
+ allowedSpecHosts: true,
19
+ routes: true
20
+ }],
21
+ ["server", {
22
+ port: true,
23
+ host: true,
24
+ allowedOrigins: true,
25
+ allowedHosts: true,
26
+ maxBodyBytes: true,
27
+ maxUploadBytes: true,
28
+ rateLimit: true,
29
+ browsersOnly: true
30
+ }],
31
+ ["runtime", { appOrigin: true }],
32
+ ["agents", {
33
+ offer: true,
34
+ allow: true,
35
+ deny: true,
36
+ access: true,
37
+ confirm: true
38
+ }]
39
+ ]);
40
+ /**
41
+ * The keys of a courier.config that Courier does not read, at the top and
42
+ * in its `studio`, `server`, `runtime` and `agents` blocks — a misspelt `studo:` say
43
+ * — so a load can name them rather than ignore them in silence.
44
+ *
45
+ * @param config - The config, as its module exported it
46
+ * @returns Each such key, dotted under its block
47
+ * @example
48
+ * ```ts
49
+ * unknownConfigKeys({ sources: {}, studo: {}, server: { prot: 3001 } }); // → ["studo", "server.prot"]
50
+ * ```
51
+ */
52
+ function unknownConfigKeys(config) {
53
+ if (!isRecord(config)) return [];
54
+ const unknown = [];
55
+ for (const [key, value] of Object.entries(config)) {
56
+ if (!Object.hasOwn(TOP_LEVEL, key)) {
57
+ unknown.push(key);
58
+ continue;
59
+ }
60
+ const known = BLOCKS.get(key);
61
+ if (!known || !isRecord(value)) continue;
62
+ for (const inner of Object.keys(value)) if (!Object.hasOwn(known, inner)) unknown.push(`${key}.${inner}`);
63
+ }
64
+ return unknown;
65
+ }
66
+ export { CONFIG_BASENAMES, UntrustedConfigError, configCandidates, createConfigJiti, createTransformCache, findConfigFile, findConfigFileAt, findTransformCacheDirectory, loadCourierConfig, loadCourierConfigFile, projectTransformCache, readPathAliases, unknownConfigKeys };
@@ -0,0 +1,28 @@
1
+ import { t as errnoCode } from "./errno-code-CNx_E80R.js";
2
+ import { c as UntrustedConfigError, t as findConfigFile } from "./load-config-BeedbpkN.js";
3
+ import { resolve } from "node:path";
4
+ import { realpathSync } from "node:fs";
5
+ // src/util/config-file-of.ts
6
+ /**
7
+ * The config file the routes are read from, as a bundler names a module:
8
+ * its real path. One that is not there yet, or that is not run, gives none
9
+ * here; the engine reports why when the routes are read.
10
+ *
11
+ * @param root - The project's root, where the config is looked for and above
12
+ * @param named - The config, from the root or absolute, when it is not the one found
13
+ * @returns The config file, absolute and real; none when there is no config to read
14
+ * @example
15
+ * ```ts
16
+ * configFileOf("/app"); // "/app/courier.config.ts"
17
+ * ```
18
+ */
19
+ function configFileOf(root, named) {
20
+ try {
21
+ const file = named === void 0 ? findConfigFile(root) : resolve(root, named);
22
+ return file === null ? void 0 : realpathSync(file);
23
+ } catch (error) {
24
+ if (error instanceof UntrustedConfigError || errnoCode(error) === "ENOENT") return void 0;
25
+ throw error;
26
+ }
27
+ }
28
+ export { configFileOf as t };
@@ -0,0 +1,20 @@
1
+ import { basename } from "node:path";
2
+ // src/util/config-in-page-message.ts
3
+ /**
4
+ * Why the project's config cannot be a module of a page, and what to write
5
+ * instead. It holds the server's settings and the definition of every API —
6
+ * their addresses, their middleware, what reads their secrets — and imported
7
+ * as a value it ships all of them to the browser. A page needs its type
8
+ * alone, which an `import type` gives without a byte of it.
9
+ *
10
+ * @param configFile - The project's config
11
+ * @returns The message a build fails with
12
+ * @example
13
+ * ```ts
14
+ * configInPageMessage("/app/courier.config.ts"); // "[courier] courier.config.ts is imported into a page as a value, …"
15
+ * ```
16
+ */
17
+ function configInPageMessage(configFile) {
18
+ return `[courier] ${basename(configFile)} is imported into a page as a value, which would ship the server's settings and every API's definition to the browser. Import its type alone: write \`import type config from\` where the page writes \`import config from\`.`;
19
+ }
20
+ export { configInPageMessage as t };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Options of the routes plugins that need to know only where the config is:
3
+ * those of webpack, Rspack, Rsbuild, esbuild, Rollup and Jest, and of the
4
+ * frameworks built on them.
5
+ */
6
+ interface CourierRoutesOptions {
7
+ /**
8
+ * The config file, from the project's root or absolute, when it is not
9
+ * the `courier.config.*` in the root or the nearest folder above it.
10
+ */
11
+ config?: string | undefined;
12
+ }
13
+ export { CourierRoutesOptions as t };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Options of the routes plugins that need to know only where the config is:
3
+ * those of webpack, Rspack, Rsbuild, esbuild, Rollup and Jest, and of the
4
+ * frameworks built on them.
5
+ */
6
+ interface CourierRoutesOptions {
7
+ /**
8
+ * The config file, from the project's root or absolute, when it is not
9
+ * the `courier.config.*` in the root or the nearest folder above it.
10
+ */
11
+ config?: string | undefined;
12
+ }
13
+ export { CourierRoutesOptions as t };
@@ -0,0 +1 @@
1
+ export {}