@gobing-ai/ts-runtime 0.3.0 → 0.3.2
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/README.md +234 -176
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +14 -0
- package/dist/context.d.ts +28 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +45 -2
- package/dist/file-system-cf.d.ts +25 -0
- package/dist/file-system-cf.d.ts.map +1 -0
- package/dist/file-system-cf.js +59 -0
- package/dist/file-system-node.d.ts +29 -0
- package/dist/file-system-node.d.ts.map +1 -0
- package/dist/file-system-node.js +94 -0
- package/dist/file-system.d.ts +47 -0
- package/dist/file-system.d.ts.map +1 -0
- package/dist/file-system.js +0 -0
- package/dist/fs.d.ts +31 -1
- package/dist/fs.d.ts.map +1 -1
- package/dist/fs.js +32 -19
- package/dist/index.d.ts +21 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -2
- package/dist/path.d.ts +12 -0
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +65 -4
- package/dist/platform.d.ts +12 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +41 -0
- package/dist/plugin/capability-registry.d.ts +35 -0
- package/dist/plugin/capability-registry.d.ts.map +1 -0
- package/dist/plugin/capability-registry.js +43 -0
- package/dist/plugin/extension-loader.d.ts +66 -0
- package/dist/plugin/extension-loader.d.ts.map +1 -0
- package/dist/plugin/extension-loader.js +47 -0
- package/dist/plugin/extension-path.d.ts +15 -0
- package/dist/plugin/extension-path.d.ts.map +1 -0
- package/dist/plugin/extension-path.js +20 -0
- package/dist/plugin/index.d.ts +4 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/index.js +3 -0
- package/dist/plugin.d.ts +2 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +1 -0
- package/dist/process-executor.d.ts +77 -19
- package/dist/process-executor.d.ts.map +1 -1
- package/dist/process-executor.js +209 -37
- package/dist/runtime-cf.d.ts +6 -0
- package/dist/runtime-cf.d.ts.map +1 -0
- package/dist/runtime-cf.js +33 -0
- package/dist/runtime-factory.d.ts +24 -0
- package/dist/runtime-factory.d.ts.map +1 -0
- package/dist/runtime-factory.js +0 -0
- package/dist/runtime-node-bun.d.ts +8 -0
- package/dist/runtime-node-bun.d.ts.map +1 -0
- package/dist/runtime-node-bun.js +67 -0
- package/dist/schema-validation.d.ts +16 -0
- package/dist/schema-validation.d.ts.map +1 -1
- package/dist/schema-validation.js +9 -4
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -2
- package/src/config.ts +16 -4
- package/src/context.ts +58 -4
- package/src/file-system-cf.ts +74 -0
- package/src/file-system-node.ts +122 -0
- package/src/file-system.ts +55 -0
- package/src/fs.ts +35 -18
- package/src/index.ts +57 -2
- package/src/path.ts +68 -4
- package/src/platform.ts +47 -0
- package/src/plugin/capability-registry.ts +58 -0
- package/src/plugin/extension-loader.ts +105 -0
- package/src/plugin/extension-path.ts +20 -0
- package/src/plugin/index.ts +3 -0
- package/src/plugin.ts +1 -0
- package/src/process-executor.ts +296 -58
- package/src/runtime-cf.ts +44 -0
- package/src/runtime-factory.ts +28 -0
- package/src/runtime-node-bun.ts +83 -0
- package/src/schema-validation.ts +20 -4
- package/src/types.ts +4 -0
package/dist/config.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { deepMerge } from '@gobing-ai/ts-utils';
|
|
2
2
|
import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
+
/** Zod schema for the application configuration object, providing defaults for app, database, and logging sections. */
|
|
4
5
|
export const configSchema = z.object({
|
|
5
6
|
app: z
|
|
6
7
|
.object({
|
|
@@ -54,6 +55,7 @@ export function parseYamlObject(text) {
|
|
|
54
55
|
export function stringifyYamlObject(value) {
|
|
55
56
|
return stringifyYaml(value);
|
|
56
57
|
}
|
|
58
|
+
/** Error thrown when configuration validation fails, carrying the Zod validation issues for diagnostics. */
|
|
57
59
|
export class ConfigLoadError extends Error {
|
|
58
60
|
issues;
|
|
59
61
|
constructor(message, issues = []) {
|
|
@@ -64,22 +66,31 @@ export class ConfigLoadError extends Error {
|
|
|
64
66
|
}
|
|
65
67
|
// These accessors read `process.env` directly and are node-bun only (ADR-008). On
|
|
66
68
|
// `cloudflare-workers` there is no `process`; inject config explicitly rather than calling these.
|
|
69
|
+
/** Returns the value of `process.env.NODE_ENV`, or `"development"` as default. Node/Bun only. */
|
|
67
70
|
export function getNodeEnv() {
|
|
68
71
|
return process.env.NODE_ENV ?? 'development';
|
|
69
72
|
}
|
|
73
|
+
/** Returns `true` when `NODE_ENV` is `"test"`. Node/Bun only. */
|
|
70
74
|
export function isTestEnv() {
|
|
71
75
|
return getNodeEnv() === 'test';
|
|
72
76
|
}
|
|
77
|
+
/** Returns `process.env` as a plain object. Node/Bun only. */
|
|
73
78
|
export function getProcessEnv() {
|
|
74
79
|
return process.env;
|
|
75
80
|
}
|
|
81
|
+
/** Returns `process.env.DATABASE_URL`, or `undefined` if not set. Node/Bun only. */
|
|
76
82
|
export function getDatabaseUrl() {
|
|
77
83
|
return process.env.DATABASE_URL;
|
|
78
84
|
}
|
|
85
|
+
/** Returns the user's home directory (`HOME`, falling back to `USERPROFILE` on Windows), or `undefined` if unset. Node/Bun only. */
|
|
86
|
+
export function getHomeDir() {
|
|
87
|
+
return process.env.HOME ?? process.env.USERPROFILE;
|
|
88
|
+
}
|
|
79
89
|
/** Node-bun only: interpolates `${VAR}` from `process.env` (see note above). */
|
|
80
90
|
export function interpolateEnv(value) {
|
|
81
91
|
return value.replace(ENV_INTERPOLATION_RE, (_match, name) => process.env[name] ?? `\${${name}}`);
|
|
82
92
|
}
|
|
93
|
+
/** Recursively interpolates `${VAR}` environment variables in all string leaves of a nested object or array. Node/Bun only. */
|
|
83
94
|
export function interpolateTree(value) {
|
|
84
95
|
if (typeof value === 'string')
|
|
85
96
|
return interpolateEnv(value);
|
|
@@ -90,6 +101,7 @@ export function interpolateTree(value) {
|
|
|
90
101
|
}
|
|
91
102
|
return value;
|
|
92
103
|
}
|
|
104
|
+
/** Interpolates env vars, merges overrides, validates against {@link configSchema}, and returns a frozen {@link Config}. */
|
|
93
105
|
export function buildConfigFromObject(raw, options = {}) {
|
|
94
106
|
const interpolated = interpolateTree(raw);
|
|
95
107
|
const merged = options.overrides
|
|
@@ -101,6 +113,7 @@ export function buildConfigFromObject(raw, options = {}) {
|
|
|
101
113
|
}
|
|
102
114
|
return deepFreeze(result.data);
|
|
103
115
|
}
|
|
116
|
+
/** Parses a YAML configuration string into a raw object, throwing {@link ConfigLoadError} on failure. */
|
|
104
117
|
export function parseConfigYaml(yamlText) {
|
|
105
118
|
try {
|
|
106
119
|
return parseYamlObject(yamlText);
|
|
@@ -111,6 +124,7 @@ export function parseConfigYaml(yamlText) {
|
|
|
111
124
|
throw new ConfigLoadError(`Config YAML parsing failed: ${error.message}`);
|
|
112
125
|
}
|
|
113
126
|
}
|
|
127
|
+
/** Parses YAML text and builds a validated {@link Config}, equivalent to `buildConfigFromObject(parseConfigYaml(…))`. */
|
|
114
128
|
export function buildConfigFromYaml(yamlText, options = {}) {
|
|
115
129
|
return buildConfigFromObject(parseConfigYaml(yamlText), options);
|
|
116
130
|
}
|
package/dist/context.d.ts
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import type { Config } from './config';
|
|
2
|
-
import type { FileSystem } from './
|
|
2
|
+
import type { FileSystem } from './file-system';
|
|
3
|
+
import type { ProcessExecutor as ProcessExecutorService } from './process-executor';
|
|
3
4
|
import type { RuntimeCapabilities, RuntimeName } from './types';
|
|
5
|
+
/** Execution scope of a runtime context — determines service lifecycle and availability. */
|
|
4
6
|
export type RuntimeScope = 'process' | 'server-request' | 'scheduled-event' | 'test';
|
|
7
|
+
/** Map of named services available to a runtime context, including the required `config` and `fileSystem`. */
|
|
5
8
|
export interface RuntimeServiceMap {
|
|
6
9
|
config: Config;
|
|
7
10
|
fileSystem: FileSystem;
|
|
11
|
+
processExecutor?: ProcessExecutorService;
|
|
8
12
|
[serviceName: string]: unknown;
|
|
9
13
|
}
|
|
14
|
+
/** Options for constructing a {@link RuntimeContext}. */
|
|
10
15
|
export interface RuntimeContextOptions<TServices extends RuntimeServiceMap = RuntimeServiceMap> {
|
|
11
16
|
scope?: RuntimeScope;
|
|
12
17
|
runtimeName?: RuntimeName;
|
|
13
18
|
capabilities?: RuntimeCapabilities;
|
|
14
19
|
services?: Partial<TServices>;
|
|
15
20
|
}
|
|
21
|
+
/** Injectable service container scoped to a runtime environment (process, request, event, or test). */
|
|
16
22
|
export declare class RuntimeContext<TServices extends RuntimeServiceMap = RuntimeServiceMap> {
|
|
17
23
|
readonly scope: RuntimeScope;
|
|
18
24
|
readonly runtimeName: RuntimeName;
|
|
@@ -25,5 +31,26 @@ export declare class RuntimeContext<TServices extends RuntimeServiceMap = Runtim
|
|
|
25
31
|
has<K extends keyof TServices>(key: K): boolean;
|
|
26
32
|
dispose(): Promise<void>;
|
|
27
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Create a {@link RuntimeContext} wired to the auto-detected runtime factory.
|
|
36
|
+
*
|
|
37
|
+
* Loads the platform-specific factory via {@link loadRuntimeFactory},
|
|
38
|
+
* auto-wires FileSystem, ProcessExecutor, and Config, then returns a
|
|
39
|
+
* ready-to-use context. Call this at the entry point of any app or worker.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* const ctx = await createRuntimeContextFromFactory();
|
|
44
|
+
* const fs = ctx.require('fileSystem');
|
|
45
|
+
* const config = ctx.require('config');
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function createRuntimeContextFromFactory<TServices extends RuntimeServiceMap = RuntimeServiceMap>(options?: RuntimeContextOptions<TServices>): Promise<RuntimeContext<TServices>>;
|
|
49
|
+
/**
|
|
50
|
+
* @deprecated Use {@link createRuntimeContextFromFactory} instead —
|
|
51
|
+
* it auto-detects the platform and wires the correct services from the factory.
|
|
52
|
+
* This function is kept for backward compatibility with synchronous callers
|
|
53
|
+
* that manually configure services.
|
|
54
|
+
*/
|
|
28
55
|
export declare function createRuntimeContext<TServices extends RuntimeServiceMap = RuntimeServiceMap>(options?: RuntimeContextOptions<TServices>): RuntimeContext<TServices>;
|
|
29
56
|
//# sourceMappingURL=context.d.ts.map
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,KAAK,EAAE,eAAe,IAAI,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAChE,4FAA4F;AAC5F,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,MAAM,CAAC;AAErF,8GAA8G;AAC9G,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,CAAC,EAAE,sBAAsB,CAAC;IACzC,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;CAClC;AAED,yDAAyD;AACzD,MAAM,WAAW,qBAAqB,CAAC,SAAS,SAAS,iBAAiB,GAAG,iBAAiB;IAC1F,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;CACjC;AAED,uGAAuG;AACvG,qBAAa,cAAc,CAAC,SAAS,SAAS,iBAAiB,GAAG,iBAAiB;IAC/E,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,QAAQ,CAAC,QAAQ,mDAA0D;gBAE/D,OAAO,GAAE,qBAAqB,CAAC,SAAS,CAAM;IA2B1D,QAAQ,CAAC,CAAC,SAAS,MAAM,SAAS,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAKxE,GAAG,CAAC,CAAC,SAAS,MAAM,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS;IAIhE,OAAO,CAAC,CAAC,SAAS,MAAM,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IAQxD,GAAG,CAAC,CAAC,SAAS,MAAM,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO;IAIzC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAejC;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,+BAA+B,CAAC,SAAS,SAAS,iBAAiB,GAAG,iBAAiB,EACzG,OAAO,CAAC,EAAE,qBAAqB,CAAC,SAAS,CAAC,GAC3C,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAiBpC;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,SAAS,iBAAiB,GAAG,iBAAiB,EACxF,OAAO,GAAE,qBAAqB,CAAC,SAAS,CAAM,GAC/C,cAAc,CAAC,SAAS,CAAC,CAE3B"}
|
package/dist/context.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { buildConfigFromObject } from './config.js';
|
|
2
|
-
import {
|
|
2
|
+
import { createNodeFileSystem } from './file-system-node.js';
|
|
3
|
+
import { loadRuntimeFactory } from './platform.js';
|
|
4
|
+
import { ProcessExecutor } from './process-executor.js';
|
|
5
|
+
/** Injectable service container scoped to a runtime environment (process, request, event, or test). */
|
|
3
6
|
export class RuntimeContext {
|
|
4
7
|
scope;
|
|
5
8
|
runtimeName;
|
|
@@ -16,7 +19,10 @@ export class RuntimeContext {
|
|
|
16
19
|
hasPersistentStorage: true,
|
|
17
20
|
};
|
|
18
21
|
this.register('config', (options.services?.config ?? buildConfigFromObject({})));
|
|
19
|
-
this.register('fileSystem', (options.services?.fileSystem ??
|
|
22
|
+
this.register('fileSystem', (options.services?.fileSystem ?? createNodeFileSystem()));
|
|
23
|
+
if (this.capabilities.hasProcessExecution && options.services?.processExecutor === undefined) {
|
|
24
|
+
this.register('processExecutor', new ProcessExecutor());
|
|
25
|
+
}
|
|
20
26
|
for (const [key, value] of Object.entries(options.services ?? {})) {
|
|
21
27
|
if (value !== undefined) {
|
|
22
28
|
this.register(key, value);
|
|
@@ -60,6 +66,43 @@ export class RuntimeContext {
|
|
|
60
66
|
function isDisposable(value) {
|
|
61
67
|
return typeof value === 'object' && value !== null && 'dispose' in value && typeof value.dispose === 'function';
|
|
62
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Create a {@link RuntimeContext} wired to the auto-detected runtime factory.
|
|
71
|
+
*
|
|
72
|
+
* Loads the platform-specific factory via {@link loadRuntimeFactory},
|
|
73
|
+
* auto-wires FileSystem, ProcessExecutor, and Config, then returns a
|
|
74
|
+
* ready-to-use context. Call this at the entry point of any app or worker.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* const ctx = await createRuntimeContextFromFactory();
|
|
79
|
+
* const fs = ctx.require('fileSystem');
|
|
80
|
+
* const config = ctx.require('config');
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export async function createRuntimeContextFromFactory(options) {
|
|
84
|
+
const factory = await loadRuntimeFactory();
|
|
85
|
+
const config = await factory.loadConfig();
|
|
86
|
+
const fileSystem = factory.createFileSystem();
|
|
87
|
+
const processExecutor = factory.capabilities.hasProcessExecution ? factory.createProcessExecutor() : undefined;
|
|
88
|
+
return new RuntimeContext({
|
|
89
|
+
scope: 'process',
|
|
90
|
+
runtimeName: factory.runtimeName,
|
|
91
|
+
capabilities: factory.capabilities,
|
|
92
|
+
services: {
|
|
93
|
+
config,
|
|
94
|
+
fileSystem,
|
|
95
|
+
...(processExecutor !== undefined ? { processExecutor } : {}),
|
|
96
|
+
...options?.services,
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* @deprecated Use {@link createRuntimeContextFromFactory} instead —
|
|
102
|
+
* it auto-detects the platform and wires the correct services from the factory.
|
|
103
|
+
* This function is kept for backward compatibility with synchronous callers
|
|
104
|
+
* that manually configure services.
|
|
105
|
+
*/
|
|
63
106
|
export function createRuntimeContext(options = {}) {
|
|
64
107
|
return new RuntimeContext(options);
|
|
65
108
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudflare Workers {@link FileSystem} stub.
|
|
3
|
+
*
|
|
4
|
+
* CF Workers have only an ephemeral, per-request virtual filesystem.
|
|
5
|
+
* Persistent file operations are not available. This stub throws clear
|
|
6
|
+
* errors directing developers to use D1, KV, or R2 instead.
|
|
7
|
+
*
|
|
8
|
+
* Non-mutating operations (`resolve`, `getProjectRoot`) return
|
|
9
|
+
* Worker-appropriate values without throwing.
|
|
10
|
+
*
|
|
11
|
+
* Note: Cloudflare Workers with `nodejs_compat` + `compatibility_date >= 2025-09-01`
|
|
12
|
+
* DO expose `node:fs` as an ephemeral, per-request virtual filesystem.
|
|
13
|
+
* We deliberately do NOT use it — the ephemeral nature means files written
|
|
14
|
+
* in one request silently vanish in the next. Throwing with guidance toward
|
|
15
|
+
* D1/KV/R2 is better DX than silent data loss.
|
|
16
|
+
*/
|
|
17
|
+
import type { FileSystem } from './file-system';
|
|
18
|
+
/**
|
|
19
|
+
* Create a Cloudflare Workers {@link FileSystem} stub.
|
|
20
|
+
*
|
|
21
|
+
* `resolve()` and `getProjectRoot()` work as path utilities.
|
|
22
|
+
* All other methods throw with guidance toward CF-native storage.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createCfFileSystem(): FileSystem;
|
|
25
|
+
//# sourceMappingURL=file-system-cf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-system-cf.d.ts","sourceRoot":"","sources":["../src/file-system-cf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhD;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,UAAU,CA8C/C"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudflare Workers {@link FileSystem} stub.
|
|
3
|
+
*
|
|
4
|
+
* CF Workers have only an ephemeral, per-request virtual filesystem.
|
|
5
|
+
* Persistent file operations are not available. This stub throws clear
|
|
6
|
+
* errors directing developers to use D1, KV, or R2 instead.
|
|
7
|
+
*
|
|
8
|
+
* Non-mutating operations (`resolve`, `getProjectRoot`) return
|
|
9
|
+
* Worker-appropriate values without throwing.
|
|
10
|
+
*
|
|
11
|
+
* Note: Cloudflare Workers with `nodejs_compat` + `compatibility_date >= 2025-09-01`
|
|
12
|
+
* DO expose `node:fs` as an ephemeral, per-request virtual filesystem.
|
|
13
|
+
* We deliberately do NOT use it — the ephemeral nature means files written
|
|
14
|
+
* in one request silently vanish in the next. Throwing with guidance toward
|
|
15
|
+
* D1/KV/R2 is better DX than silent data loss.
|
|
16
|
+
*/
|
|
17
|
+
const UNSUPPORTED = 'FileSystem is not available on Cloudflare Workers. Use D1, KV, or R2 for persistent storage.';
|
|
18
|
+
/**
|
|
19
|
+
* Create a Cloudflare Workers {@link FileSystem} stub.
|
|
20
|
+
*
|
|
21
|
+
* `resolve()` and `getProjectRoot()` work as path utilities.
|
|
22
|
+
* All other methods throw with guidance toward CF-native storage.
|
|
23
|
+
*/
|
|
24
|
+
export function createCfFileSystem() {
|
|
25
|
+
return {
|
|
26
|
+
getProjectRoot: () => '/bundle',
|
|
27
|
+
resolve: (...segments) => {
|
|
28
|
+
const joined = segments.join('/').replaceAll(/\/+/g, '/');
|
|
29
|
+
return joined.startsWith('/') ? joined : `/${joined}`;
|
|
30
|
+
},
|
|
31
|
+
exists: (_path) => false,
|
|
32
|
+
readFile: (_path) => {
|
|
33
|
+
throw new Error(`FileSystem.readFile: ${UNSUPPORTED}`);
|
|
34
|
+
},
|
|
35
|
+
writeFile: (_path, _content) => {
|
|
36
|
+
throw new Error(`FileSystem.writeFile: ${UNSUPPORTED}`);
|
|
37
|
+
},
|
|
38
|
+
appendFile: (_path, _content) => {
|
|
39
|
+
throw new Error(`FileSystem.appendFile: ${UNSUPPORTED}`);
|
|
40
|
+
},
|
|
41
|
+
ensureDir: (_path) => {
|
|
42
|
+
// No-op: CF Workers virtual filesystem handles directory
|
|
43
|
+
// creation internally when files are written.
|
|
44
|
+
},
|
|
45
|
+
readDir: (_path) => {
|
|
46
|
+
throw new Error(`FileSystem.readDir: ${UNSUPPORTED}`);
|
|
47
|
+
},
|
|
48
|
+
deleteFile: (_path) => {
|
|
49
|
+
throw new Error(`FileSystem.deleteFile: ${UNSUPPORTED}`);
|
|
50
|
+
},
|
|
51
|
+
createWriteStream: (_path) => {
|
|
52
|
+
throw new Error(`FileSystem.createWriteStream: ${UNSUPPORTED}`);
|
|
53
|
+
},
|
|
54
|
+
copy: (_src, _dest) => {
|
|
55
|
+
throw new Error(`FileSystem.copy: ${UNSUPPORTED}`);
|
|
56
|
+
},
|
|
57
|
+
stat: (_path) => null,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `node:fs`-backed {@link FileSystem} implementation for Bun/Node.js.
|
|
3
|
+
*
|
|
4
|
+
* This is the production implementation for local development, VPS, and
|
|
5
|
+
* any environment with a real filesystem. Tests should inject a virtual
|
|
6
|
+
* file system.
|
|
7
|
+
*
|
|
8
|
+
* The implementation uses `node:fs` sync APIs by default. Bun polyfills
|
|
9
|
+
* `node:fs` fully, so this works on both runtimes without a Bun-specific
|
|
10
|
+
* variant.
|
|
11
|
+
*/
|
|
12
|
+
import type { FileSystem } from './file-system';
|
|
13
|
+
/**
|
|
14
|
+
* Create a {@link FileSystem} backed by `node:fs`.
|
|
15
|
+
*
|
|
16
|
+
* @param root - Project root directory (default: walks up from `process.cwd()` looking for `bun.lock` or `package.json`).
|
|
17
|
+
*/
|
|
18
|
+
export declare function createNodeFileSystem(root?: string): FileSystem;
|
|
19
|
+
/**
|
|
20
|
+
* Find the project root by walking up from `startDir` looking for a `bun.lock`
|
|
21
|
+
* or `package.json` marker. Uses `existsSync`, so it works on both Node and Bun.
|
|
22
|
+
*
|
|
23
|
+
* This is the single project-root discovery implementation; the deprecated
|
|
24
|
+
* {@link import('./fs').getProjectRoot} delegates here.
|
|
25
|
+
*
|
|
26
|
+
* @internal — exported for reuse by config loading.
|
|
27
|
+
*/
|
|
28
|
+
export declare function findProjectRoot(startDir: string): string;
|
|
29
|
+
//# sourceMappingURL=file-system-node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-system-node.d.ts","sourceRoot":"","sources":["../src/file-system-node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAgBH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAuD9D;AAWD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAaxD"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `node:fs`-backed {@link FileSystem} implementation for Bun/Node.js.
|
|
3
|
+
*
|
|
4
|
+
* This is the production implementation for local development, VPS, and
|
|
5
|
+
* any environment with a real filesystem. Tests should inject a virtual
|
|
6
|
+
* file system.
|
|
7
|
+
*
|
|
8
|
+
* The implementation uses `node:fs` sync APIs by default. Bun polyfills
|
|
9
|
+
* `node:fs` fully, so this works on both runtimes without a Bun-specific
|
|
10
|
+
* variant.
|
|
11
|
+
*/
|
|
12
|
+
import { appendFileSync, cpSync, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, } from 'node:fs';
|
|
13
|
+
import { dirname, resolve as resolvePath } from 'node:path';
|
|
14
|
+
/**
|
|
15
|
+
* Create a {@link FileSystem} backed by `node:fs`.
|
|
16
|
+
*
|
|
17
|
+
* @param root - Project root directory (default: walks up from `process.cwd()` looking for `bun.lock` or `package.json`).
|
|
18
|
+
*/
|
|
19
|
+
export function createNodeFileSystem(root) {
|
|
20
|
+
const projectRoot = root ?? findProjectRoot(process.cwd());
|
|
21
|
+
return {
|
|
22
|
+
getProjectRoot: () => projectRoot,
|
|
23
|
+
resolve: (...segments) => resolvePath(projectRoot, ...segments),
|
|
24
|
+
exists: (path) => existsSync(path),
|
|
25
|
+
readFile: (path) => readFileSync(path, 'utf-8'),
|
|
26
|
+
writeFile: (path, content) => {
|
|
27
|
+
ensureParentDir(path);
|
|
28
|
+
writeFileSync(path, content, 'utf-8');
|
|
29
|
+
},
|
|
30
|
+
appendFile: (path, content) => {
|
|
31
|
+
ensureParentDir(path);
|
|
32
|
+
appendFileSync(path, content, 'utf-8');
|
|
33
|
+
},
|
|
34
|
+
ensureDir: (path) => {
|
|
35
|
+
mkdirSync(path, { recursive: true });
|
|
36
|
+
},
|
|
37
|
+
readDir: (path) => readdirSync(path),
|
|
38
|
+
deleteFile: (path) => {
|
|
39
|
+
rmSync(path, { recursive: true, force: true });
|
|
40
|
+
},
|
|
41
|
+
createWriteStream: (path) => {
|
|
42
|
+
ensureParentDir(path);
|
|
43
|
+
return createWriteStream(path, { flags: 'a' });
|
|
44
|
+
},
|
|
45
|
+
copy: (src, dest) => {
|
|
46
|
+
cpSync(src, dest, { recursive: true });
|
|
47
|
+
},
|
|
48
|
+
stat: (path) => {
|
|
49
|
+
try {
|
|
50
|
+
const s = statSync(path);
|
|
51
|
+
return {
|
|
52
|
+
isFile: () => s.isFile(),
|
|
53
|
+
isDirectory: () => s.isDirectory(),
|
|
54
|
+
size: s.size,
|
|
55
|
+
mtimeMs: s.mtimeMs,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
65
|
+
function ensureParentDir(filePath) {
|
|
66
|
+
const dir = dirname(filePath);
|
|
67
|
+
if (!existsSync(dir)) {
|
|
68
|
+
mkdirSync(dir, { recursive: true });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Find the project root by walking up from `startDir` looking for a `bun.lock`
|
|
73
|
+
* or `package.json` marker. Uses `existsSync`, so it works on both Node and Bun.
|
|
74
|
+
*
|
|
75
|
+
* This is the single project-root discovery implementation; the deprecated
|
|
76
|
+
* {@link import('./fs.js').getProjectRoot} delegates here.
|
|
77
|
+
*
|
|
78
|
+
* @internal — exported for reuse by config loading.
|
|
79
|
+
*/
|
|
80
|
+
export function findProjectRoot(startDir) {
|
|
81
|
+
let dir = resolvePath(startDir);
|
|
82
|
+
const root = resolvePath('/');
|
|
83
|
+
while (dir !== root) {
|
|
84
|
+
if (existsSync(resolvePath(dir, 'bun.lock')) || existsSync(resolvePath(dir, 'package.json'))) {
|
|
85
|
+
return dir;
|
|
86
|
+
}
|
|
87
|
+
const parent = resolvePath(dir, '..');
|
|
88
|
+
if (parent === dir)
|
|
89
|
+
break;
|
|
90
|
+
dir = parent;
|
|
91
|
+
}
|
|
92
|
+
// Fallback: return the directory we started from.
|
|
93
|
+
return startDir;
|
|
94
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** Portable file stat subset. */
|
|
2
|
+
export interface FileStat {
|
|
3
|
+
isFile(): boolean;
|
|
4
|
+
isDirectory(): boolean;
|
|
5
|
+
size: number;
|
|
6
|
+
mtimeMs: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Runtime-agnostic file system abstraction.
|
|
10
|
+
*
|
|
11
|
+
* Bun/Node backend uses `node:fs`. Cloudflare Workers backend provides stubs
|
|
12
|
+
* that throw clear "not available" errors, directing developers to use D1,
|
|
13
|
+
* KV, or R2 for persistent storage.
|
|
14
|
+
*
|
|
15
|
+
* All code outside `packages/runtime/src/file-system*.ts` MUST use this
|
|
16
|
+
* interface — never import `node:fs` or call `Bun.write`/`Bun.file` directly.
|
|
17
|
+
*/
|
|
18
|
+
export interface FileSystem {
|
|
19
|
+
/** Check whether a path exists. */
|
|
20
|
+
exists(path: string): boolean | Promise<boolean>;
|
|
21
|
+
/** Read file contents as UTF-8 string. Throws if not found. */
|
|
22
|
+
readFile(path: string): string | Promise<string>;
|
|
23
|
+
/** Write file contents, creating parent directories as needed. */
|
|
24
|
+
writeFile(path: string, content: string): void | Promise<void>;
|
|
25
|
+
/** Append content to a file, creating it if it doesn't exist. */
|
|
26
|
+
appendFile(path: string, content: string): void | Promise<void>;
|
|
27
|
+
/** Ensure a directory exists, creating it (and parents) recursively if needed. */
|
|
28
|
+
ensureDir(path: string): void | Promise<void>;
|
|
29
|
+
/** List directory entries (names only, not full paths). */
|
|
30
|
+
readDir(path: string): string[] | Promise<string[]>;
|
|
31
|
+
/** Delete a file or directory recursively. */
|
|
32
|
+
deleteFile(path: string): void | Promise<void>;
|
|
33
|
+
/** Recursively copy a file or directory. */
|
|
34
|
+
copy(src: string, dest: string): void | Promise<void>;
|
|
35
|
+
/** Get file or directory stats. Returns `null` if the path doesn't exist. */
|
|
36
|
+
stat(path: string): FileStat | null | Promise<FileStat | null>;
|
|
37
|
+
/** Create a writable stream for append-only output (Node/Bun only). Throws on CF Workers. */
|
|
38
|
+
createWriteStream(path: string): {
|
|
39
|
+
write(chunk: string): void;
|
|
40
|
+
end(): void;
|
|
41
|
+
};
|
|
42
|
+
/** Resolve path segments relative to the project root. */
|
|
43
|
+
resolve(...segments: string[]): string;
|
|
44
|
+
/** Get the project root directory path. */
|
|
45
|
+
getProjectRoot(): string;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=file-system.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-system.d.ts","sourceRoot":"","sources":["../src/file-system.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,MAAM,WAAW,QAAQ;IACrB,MAAM,IAAI,OAAO,CAAC;IAClB,WAAW,IAAI,OAAO,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,UAAU;IACvB,mCAAmC;IACnC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEjD,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjD,kEAAkE;IAClE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/D,iEAAiE;IACjE,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhE,kFAAkF;IAClF,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9C,2DAA2D;IAC3D,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEpD,8CAA8C;IAC9C,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/C,4CAA4C;IAC5C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtD,6EAA6E;IAC7E,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IAE/D,6FAA6F;IAC7F,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,GAAG,IAAI,IAAI,CAAA;KAAE,CAAC;IAE7E,0DAA0D;IAC1D,OAAO,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAEvC,2CAA2C;IAC3C,cAAc,IAAI,MAAM,CAAC;CAC5B"}
|
|
File without changes
|
package/dist/fs.d.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
/** Portable file stat interface — mirrors the subset of `node:fs.Stats` used by the runtime. */
|
|
1
2
|
export interface FileStat {
|
|
2
3
|
isFile(): boolean;
|
|
3
4
|
isDirectory(): boolean;
|
|
4
5
|
size: number;
|
|
5
6
|
mtimeMs: number;
|
|
6
7
|
}
|
|
8
|
+
/** Write-only append stream for log output. */
|
|
7
9
|
export interface LogStream {
|
|
8
10
|
write(chunk: string): void;
|
|
9
11
|
end(): void;
|
|
10
12
|
}
|
|
13
|
+
/** @deprecated Use {@link import('./file-system').FileSystem} instead — the new interface has union return types and does not require a separate SyncFileSystem. */
|
|
11
14
|
export interface FileSystem {
|
|
12
15
|
readFile(path: string): Promise<string>;
|
|
13
16
|
writeFile(path: string, content: string): Promise<void>;
|
|
@@ -22,6 +25,7 @@ export interface FileSystem {
|
|
|
22
25
|
rename(src: string, dest: string): Promise<void>;
|
|
23
26
|
createLogStream(path: string): LogStream;
|
|
24
27
|
}
|
|
28
|
+
/** @deprecated Use {@link import('./file-system').FileSystem} instead — its union return types make a separate sync interface unnecessary. */
|
|
25
29
|
export interface SyncFileSystem {
|
|
26
30
|
readFile(path: string): string;
|
|
27
31
|
writeFile(path: string, content: string): void;
|
|
@@ -31,6 +35,8 @@ export interface SyncFileSystem {
|
|
|
31
35
|
stat(path: string): FileStat | null;
|
|
32
36
|
unlink(path: string): void;
|
|
33
37
|
}
|
|
38
|
+
/** {@link FileSystem} backed by `node:fs/promises`. Lazy-loads the module to avoid top-level import cost. */
|
|
39
|
+
/** @deprecated Use createNodeFileSystem() from './file-system-node' instead. */
|
|
34
40
|
export declare class NodeFileSystem implements FileSystem {
|
|
35
41
|
readFile(path: string): Promise<string>;
|
|
36
42
|
writeFile(path: string, content: string): Promise<void>;
|
|
@@ -45,6 +51,8 @@ export declare class NodeFileSystem implements FileSystem {
|
|
|
45
51
|
rename(src: string, dest: string): Promise<void>;
|
|
46
52
|
createLogStream(path: string): LogStream;
|
|
47
53
|
}
|
|
54
|
+
/** {@link SyncFileSystem} backed by `node:fs` synchronous APIs. */
|
|
55
|
+
/** @deprecated Use createNodeFileSystem() from './file-system-node' instead — its FileSystem interface has union return types, eliminating the need for a separate sync implementation. */
|
|
48
56
|
export declare class NodeSyncFileSystem implements SyncFileSystem {
|
|
49
57
|
readFile(path: string): string;
|
|
50
58
|
writeFile(path: string, content: string): void;
|
|
@@ -54,6 +62,8 @@ export declare class NodeSyncFileSystem implements SyncFileSystem {
|
|
|
54
62
|
stat(path: string): FileStat | null;
|
|
55
63
|
unlink(path: string): void;
|
|
56
64
|
}
|
|
65
|
+
/** {@link FileSystem} stub for Cloudflare Workers — all file operations throw. Use D1, KV, or R2 instead. */
|
|
66
|
+
/** @deprecated Use createCfFileSystem() from './file-system-cf' instead. */
|
|
57
67
|
export declare class CloudflareFileSystem implements FileSystem {
|
|
58
68
|
readFile(path: string): Promise<string>;
|
|
59
69
|
writeFile(path: string, _content: string): Promise<void>;
|
|
@@ -68,16 +78,36 @@ export declare class CloudflareFileSystem implements FileSystem {
|
|
|
68
78
|
rename(src: string, _dest: string): Promise<void>;
|
|
69
79
|
createLogStream(path: string): LogStream;
|
|
70
80
|
}
|
|
81
|
+
/** Swaps the active global file system, returning a restore function for the previous instance. */
|
|
82
|
+
/** @deprecated Use RuntimeFactory.createFileSystem() or ctx.require('fileSystem') instead. The global swap is replaced by factory-based DI. */
|
|
71
83
|
export declare function setFileSystem(fileSystem: FileSystem): () => void;
|
|
84
|
+
/** Returns the currently active global {@link FileSystem} instance. */
|
|
85
|
+
/** @deprecated Use RuntimeFactory.createFileSystem() or ctx.require('fileSystem') instead. */
|
|
72
86
|
export declare function getFs(): FileSystem;
|
|
87
|
+
/** Creates parent directories for a file path before writing. */
|
|
73
88
|
export declare function ensureDirForFile(path: string, fs?: FileSystem): Promise<void>;
|
|
89
|
+
/** Synchronous variant of {@link ensureDirForFile}. */
|
|
90
|
+
/** @deprecated The new createNodeFileSystem() handles parent-directory creation internally. */
|
|
74
91
|
export declare function ensureDirForFileSync(path: string, fs: SyncFileSystem): void;
|
|
92
|
+
/** Atomically writes a file by writing to a temp path then renaming, avoiding partial writes on crash. */
|
|
75
93
|
export declare function atomicWriteFile(path: string, content: string, fs?: FileSystem): Promise<void>;
|
|
94
|
+
/** Atomically writes a value as JSON with trailing newline. */
|
|
76
95
|
export declare function atomicWriteJson(path: string, value: unknown, fs?: FileSystem): Promise<void>;
|
|
96
|
+
/** Reads and parses a JSON file. */
|
|
77
97
|
export declare function readJsonFile<T = unknown>(path: string, fs?: FileSystem): Promise<T>;
|
|
98
|
+
/** Writes a value as JSON with 2-space indentation and trailing newline. */
|
|
78
99
|
export declare function writeJsonFile(path: string, value: unknown, fs?: FileSystem): Promise<void>;
|
|
79
|
-
|
|
100
|
+
/** Recursively walks a directory, returning sorted paths to all files, optionally excluding entries by name. */
|
|
101
|
+
export declare function walkDir(path: string, fs?: FileSystem, exclude?: Set<string>): Promise<string[]>;
|
|
102
|
+
/**
|
|
103
|
+
* Walks up from `startDir` looking for a `package.json` or `bun.lock` to locate the project root.
|
|
104
|
+
*
|
|
105
|
+
* @deprecated Use {@link import('./file-system-node').findProjectRoot} (or `createNodeFileSystem().getProjectRoot()`).
|
|
106
|
+
* This delegates to the single shared implementation.
|
|
107
|
+
*/
|
|
80
108
|
export declare function getProjectRoot(startDir?: string): string;
|
|
109
|
+
/** Resolves path segments relative to the project root. */
|
|
81
110
|
export declare function resolveProjectPath(...segments: string[]): string;
|
|
111
|
+
/** Creates a {@link LogStream} at the given path using the active file system. */
|
|
82
112
|
export declare function createLogStream(path: string, fs?: FileSystem): LogStream;
|
|
83
113
|
//# sourceMappingURL=fs.d.ts.map
|
package/dist/fs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"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"}
|