@copypatch/node 2.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Efe Arabacı
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # @copypatch/node
2
+
3
+ Node.js 20+ adapters and the `copypatch` project-scaffolding CLI for a `@copypatch/backend` runtime.
4
+
5
+ ```ts
6
+ import { createNodeHandler } from '@copypatch/node';
7
+ import { createServer } from 'node:http';
8
+
9
+ createServer(createNodeHandler(backend)).listen(3000);
10
+ ```
11
+
12
+ `expressMiddleware` must be mounted before body parsers and SPA fallbacks. `fastifyCopyPatchHandler` uses `request.raw` and `reply.hijack()`, so register it before content parsers. `createHonoHandler` returns the backend's native `Response`.
13
+
14
+ ```sh
15
+ copypatch init --framework next --storage sqlite
16
+ copypatch doctor
17
+ printf 'a passphrase' | copypatch hash --stdin
18
+ ```
19
+
20
+ `init` writes a server-only `copypatch.config.ts`, an environment example, and
21
+ one embedded same-origin v2 mount. It supports `next`, `astro`,
22
+ `react-router`, and `vite-node` with either `sqlite` or `postgres` storage.
23
+ The Next.js mount uses the canonical App Router path
24
+ `app/__copypatch/api/v2/[...path]/route.ts`; Astro uses the equivalent
25
+ `src/pages/__copypatch/api/v2/[...path].ts` endpoint. Re-running `init` is
26
+ safe: matching generated files are left intact, conflicting files are never
27
+ overwritten, and `--dry-run` writes nothing.
28
+
29
+ The CLI has no `serve` command. Mount a framework adapter in the host application instead.
30
+
31
+ `hash --stdin` avoids exposing a passphrase through process arguments. `--passphrase` is retained for compatibility but may be visible to other local processes.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../../src/cli/bin.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from './index.js';
3
+ const result = await runCli(process.argv.slice(2));
4
+ process.exitCode = result.exitCode;
5
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../../src/cli/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { type Storage } from './templates.js';
2
+ export { createInitFiles, type Framework, type InitFile, type Storage } from './templates.js';
3
+ export interface CliDependencies {
4
+ cwd?: string;
5
+ env?: NodeJS.ProcessEnv;
6
+ write?: (message: string) => void;
7
+ readSecret?: () => Promise<string>;
8
+ migrate?: (options: {
9
+ storage: Storage;
10
+ cwd: string;
11
+ }) => Promise<void>;
12
+ }
13
+ export interface CliResult {
14
+ exitCode: 0 | 1 | 2;
15
+ }
16
+ export declare function runCli(argv: readonly string[], dependencies?: CliDependencies): Promise<CliResult>;
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAmC,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE/E,OAAO,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9F,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACzE;AAED,MAAM,WAAW,SAAS;IAAG,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CAAE;AAEnD,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,YAAY,GAAE,eAAoB,GAAG,OAAO,CAAC,SAAS,CAAC,CAU5G"}
@@ -0,0 +1,194 @@
1
+ import { hash } from '@node-rs/argon2';
2
+ import { access, mkdir, readFile, writeFile } from 'node:fs/promises';
3
+ import { constants } from 'node:fs';
4
+ import { isAbsolute, resolve, sep } from 'node:path';
5
+ import { createInitFiles } from './templates.js';
6
+ export { createInitFiles } from './templates.js';
7
+ export async function runCli(argv, dependencies = {}) {
8
+ const write = dependencies.write ?? ((message) => process.stdout.write(message));
9
+ const [command, ...args] = argv;
10
+ if (!command || command === '--help' || command === '-h')
11
+ return usage(write, 0);
12
+ if (command === 'serve')
13
+ return fail(write, 'The copypatch CLI does not provide a serve command. Mount an adapter in your application instead.\n', 2);
14
+ if (command === 'init')
15
+ return init(args, dependencies, write);
16
+ if (command === 'migrate')
17
+ return migrate(args, dependencies, write);
18
+ if (command === 'doctor')
19
+ return doctor(args, dependencies, write);
20
+ if (command === 'hash')
21
+ return hashPassphrase(args, dependencies, write);
22
+ return fail(write, `Unknown command: ${command}\n`, 2);
23
+ }
24
+ async function init(args, dependencies, write) {
25
+ const parsed = parse(args);
26
+ const framework = parsed.value('--framework');
27
+ const storage = parsed.value('--storage');
28
+ if (!isFramework(framework) || !isStorage(storage) || parsed.invalid)
29
+ return usage(write, 2);
30
+ const cwd = safeCwd(parsed.value('--cwd'), dependencies.cwd);
31
+ if (!cwd)
32
+ return fail(write, 'Refusing --cwd path traversal.\n', 1);
33
+ const files = createInitFiles({ framework, storage });
34
+ const outcomes = await Promise.all(files.map(async (file) => ({ file, path: resolve(cwd, file.path), current: await readOptional(resolve(cwd, file.path)) })));
35
+ if (outcomes.some(({ path }) => !inside(cwd, path)))
36
+ return fail(write, 'Refusing template path outside cwd.\n', 1);
37
+ const conflicts = outcomes.filter(({ current, file }) => current !== undefined && current !== file.contents);
38
+ if (conflicts.length > 0)
39
+ return fail(write, `Refusing to overwrite: ${conflicts.map(({ file }) => file.path).join(', ')}\n`, 1);
40
+ if (parsed.flag('--dry-run')) {
41
+ write(`Would create: ${outcomes.filter(({ current }) => current === undefined).map(({ file }) => file.path).join(', ') || 'nothing'}\n`);
42
+ return { exitCode: 0 };
43
+ }
44
+ for (const outcome of outcomes) {
45
+ if (outcome.current === undefined) {
46
+ await mkdir(resolve(outcome.path, '..'), { recursive: true });
47
+ await writeFile(outcome.path, outcome.file.contents, { encoding: 'utf8', flag: 'wx' });
48
+ write(`Created ${outcome.file.path}\n`);
49
+ }
50
+ }
51
+ return { exitCode: 0 };
52
+ }
53
+ async function migrate(args, dependencies, write) {
54
+ const parsed = parse(args);
55
+ const storage = parsed.value('--storage');
56
+ if (!isStorage(storage) || parsed.invalid)
57
+ return usage(write, 2);
58
+ const cwd = safeCwd(parsed.value('--cwd'), dependencies.cwd);
59
+ if (!cwd)
60
+ return fail(write, 'Refusing --cwd path traversal.\n', 1);
61
+ try {
62
+ if (dependencies.migrate)
63
+ await dependencies.migrate({ storage, cwd });
64
+ else
65
+ await migrateStorage(storage, cwd, dependencies.env ?? process.env);
66
+ }
67
+ catch {
68
+ return fail(write, 'Migration failed. Check your storage configuration and permissions.\n', 1);
69
+ }
70
+ write(`Applied ${storage} migrations.\n`);
71
+ return { exitCode: 0 };
72
+ }
73
+ async function doctor(args, dependencies, write) {
74
+ if (args.length > 0)
75
+ return usage(write, 2);
76
+ const cwd = dependencies.cwd ?? process.cwd();
77
+ const env = dependencies.env ?? process.env;
78
+ write(`cwd: ${cwd}\n`);
79
+ const configPath = resolve(cwd, 'copypatch.config.ts');
80
+ const config = await readOptional(configPath);
81
+ write(`filesystem: ${await exists(cwd) ? 'available' : 'missing'}\n`);
82
+ write(`config: ${config === undefined ? 'missing' : 'present'}\n`);
83
+ write(`backend: ${config?.includes('@copypatch/backend') ? 'configured' : 'mount required'}\n`);
84
+ write(`storage: ${storageFromConfig(config) ?? 'not configured'}\n`);
85
+ for (const key of Object.keys(env).filter((name) => name.startsWith('COPYPATCH_')).sort())
86
+ write(`${key}=[redacted]\n`);
87
+ return { exitCode: 0 };
88
+ }
89
+ async function hashPassphrase(args, dependencies, write) {
90
+ const parsed = parse(args);
91
+ if (parsed.invalid)
92
+ return usage(write, 2);
93
+ const explicit = parsed.value('--passphrase');
94
+ const stdin = parsed.flag('--stdin');
95
+ if (!explicit && !stdin)
96
+ return usage(write, 2);
97
+ if (explicit)
98
+ write('Warning: --passphrase may be visible in your process list; use --stdin instead.\n');
99
+ const secret = explicit ?? await (dependencies.readSecret?.() ?? readStdin());
100
+ if (!secret)
101
+ return fail(write, 'A non-empty passphrase is required.\n', 1);
102
+ write(`${await hash(secret, { algorithm: 2 })}\n`);
103
+ return { exitCode: 0 };
104
+ }
105
+ function parse(args) {
106
+ const values = new Map();
107
+ const flags = new Set();
108
+ let invalid = false;
109
+ for (let index = 0; index < args.length; index += 1) {
110
+ const item = args[index];
111
+ if (item === '--dry-run' || item === '--stdin') {
112
+ flags.add(item);
113
+ continue;
114
+ }
115
+ if (item === '--framework' || item === '--storage' || item === '--cwd' || item === '--passphrase') {
116
+ const value = args[index + 1];
117
+ if (!value || value.startsWith('--')) {
118
+ invalid = true;
119
+ continue;
120
+ }
121
+ values.set(item, value);
122
+ index += 1;
123
+ continue;
124
+ }
125
+ invalid = true;
126
+ }
127
+ return { flag: (name) => flags.has(name), value: (name) => values.get(name), invalid };
128
+ }
129
+ function safeCwd(value, fallback) {
130
+ if (value && !isAbsolute(value) && value.split(/[\\/]/).includes('..'))
131
+ return undefined;
132
+ return resolve(value ?? fallback ?? process.cwd());
133
+ }
134
+ function inside(root, target) { return target === root || target.startsWith(`${root}${sep}`); }
135
+ function isFramework(value) { return value === 'next' || value === 'astro' || value === 'react-router' || value === 'vite-node'; }
136
+ function isStorage(value) { return value === 'sqlite' || value === 'postgres'; }
137
+ function storageFromConfig(config) {
138
+ if (!config)
139
+ return undefined;
140
+ if (config.includes("from '@copypatch/storage-sqlite'"))
141
+ return 'sqlite';
142
+ if (config.includes("from '@copypatch/storage-postgres'"))
143
+ return 'postgres';
144
+ const legacy = config.match(/storage: '(sqlite|postgres)'/)?.[1];
145
+ return isStorage(legacy) ? legacy : undefined;
146
+ }
147
+ async function exists(path) { try {
148
+ await access(path, constants.F_OK);
149
+ return true;
150
+ }
151
+ catch {
152
+ return false;
153
+ } }
154
+ async function readOptional(path) { try {
155
+ return await readFile(path, 'utf8');
156
+ }
157
+ catch {
158
+ return undefined;
159
+ } }
160
+ async function readStdin() {
161
+ let value = '';
162
+ for await (const chunk of process.stdin)
163
+ value += String(chunk);
164
+ return value.trim();
165
+ }
166
+ async function migrateStorage(storage, cwd, env) {
167
+ if (storage === 'sqlite') {
168
+ const moduleName = '@copypatch/storage-sqlite';
169
+ const module = await import(moduleName);
170
+ const persistence = module.createSQLitePersistence(env.COPYPATCH_SQLITE_PATH ?? resolve(cwd, 'copypatch.sqlite'));
171
+ try {
172
+ await persistence.migrate();
173
+ }
174
+ finally {
175
+ persistence.close();
176
+ }
177
+ return;
178
+ }
179
+ const databaseUrl = env.COPYPATCH_DATABASE_URL;
180
+ if (!databaseUrl)
181
+ throw new Error('Missing PostgreSQL connection configuration.');
182
+ const moduleName = '@copypatch/storage-postgres';
183
+ const module = await import(moduleName);
184
+ const persistence = module.createPostgresPersistence(databaseUrl);
185
+ try {
186
+ await persistence.migrate();
187
+ }
188
+ finally {
189
+ await persistence.close();
190
+ }
191
+ }
192
+ function fail(write, message, exitCode) { write(message); return { exitCode }; }
193
+ function usage(write, exitCode) { write('Usage: copypatch init --framework next|astro|react-router|vite-node --storage sqlite|postgres [--dry-run] [--cwd PATH]\n'); return { exitCode }; }
194
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export type Framework = 'next' | 'astro' | 'react-router' | 'vite-node';
2
+ export type Storage = 'sqlite' | 'postgres';
3
+ export interface InitFile {
4
+ path: string;
5
+ contents: string;
6
+ }
7
+ export interface InitTemplateOptions {
8
+ framework: Framework;
9
+ storage: Storage;
10
+ }
11
+ /** Produces standalone, server-only files without changing an existing host route. */
12
+ export declare function createInitFiles(options: InitTemplateOptions): readonly InitFile[];
13
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/cli/templates.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,cAAc,GAAG,WAAW,CAAC;AACxE,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE5C,MAAM,WAAW,QAAQ;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;CAAE;AAC7D,MAAM,WAAW,mBAAmB;IAAG,SAAS,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;CAAE;AAIhF,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,SAAS,QAAQ,EAAE,CAMjF"}
@@ -0,0 +1,169 @@
1
+ const API_BASE_PATH = '/__copypatch/api/v2';
2
+ /** Produces standalone, server-only files without changing an existing host route. */
3
+ export function createInitFiles(options) {
4
+ return [
5
+ { path: 'copypatch.config.ts', contents: backendConfig(options.storage) },
6
+ { path: 'copypatch.env.example', contents: environmentExample(options.storage) },
7
+ ...frameworkFiles(options.framework),
8
+ ];
9
+ }
10
+ function backendConfig(storage) {
11
+ const persistence = storage === 'sqlite'
12
+ ? `import { resolve } from 'node:path';
13
+ import { createSQLitePersistence } from '@copypatch/storage-sqlite';
14
+
15
+ const sqlitePath = process.env.COPYPATCH_SQLITE_PATH ?? resolve(process.cwd(), 'copypatch.sqlite');
16
+ export const persistence = createSQLitePersistence(sqlitePath);`
17
+ : `import { createPostgresPersistence } from '@copypatch/storage-postgres';
18
+
19
+ const databaseUrl = requiredEnvironment('COPYPATCH_DATABASE_URL');
20
+ export const persistence = createPostgresPersistence(databaseUrl);`;
21
+ return `import { createCopyPatchBackend } from '@copypatch/backend';
22
+ ${persistence}
23
+
24
+ const passphraseHash = requiredEnvironment('COPYPATCH_PASSPHRASE_HASH');
25
+
26
+ let bootstrap: Promise<void> | undefined;
27
+
28
+ /** Run migrations once before this deployment accepts CopyPatch requests. */
29
+ export function bootstrapCopyPatch(): Promise<void> {
30
+ bootstrap ??= persistence.migrate();
31
+ return bootstrap;
32
+ }
33
+
34
+ export const backend = createCopyPatchBackend({ persistence, passphraseHash });
35
+
36
+ function requiredEnvironment(name: string): string {
37
+ const value = process.env[name];
38
+ if (!value) throw new Error(\`CopyPatch requires the \${name} environment variable.\`);
39
+ return value;
40
+ }
41
+ `;
42
+ }
43
+ function environmentExample(storage) {
44
+ return storage === 'sqlite'
45
+ ? `# Copy these names into your local environment or deployment secret manager.\n# Do not put a real passphrase or hash in this file.\nCOPYPATCH_PASSPHRASE_HASH=<argon2id-hash-from-copypatch-hash---stdin>\nCOPYPATCH_SQLITE_PATH=./copypatch.sqlite\n`
46
+ : `# Copy these names into your local environment or deployment secret manager.\n# Do not put a real passphrase, hash, or database credential in this file.\nCOPYPATCH_PASSPHRASE_HASH=<argon2id-hash-from-copypatch-hash---stdin>\nCOPYPATCH_DATABASE_URL=<postgres-connection-string>\n`;
47
+ }
48
+ function frameworkFiles(framework) {
49
+ switch (framework) {
50
+ case 'next': return [{
51
+ path: 'app/%5F%5Fcopypatch/api/v2/[...path]/route.ts',
52
+ contents: nextRoute(),
53
+ }];
54
+ case 'astro': return [{
55
+ path: 'src/pages/__copypatch/api/v2/[...path].ts',
56
+ contents: astroRoute(),
57
+ }];
58
+ case 'react-router': return [
59
+ { path: 'app/routes/copypatch-api.ts', contents: reactRouterRoute() },
60
+ { path: 'app/copypatch.routes.ts', contents: reactRouterRouteEntry() },
61
+ ];
62
+ case 'vite-node': return [{ path: 'src/copypatch.ts', contents: viteNodeMount() }];
63
+ }
64
+ }
65
+ function nextRoute() {
66
+ return `import { createCopyPatchRouteHandlers } from '@copypatch/next/server';
67
+ import { backend, bootstrapCopyPatch } from '../../../../../copypatch.config.js';
68
+
69
+ export const runtime = 'nodejs';
70
+
71
+ const routes = createCopyPatchRouteHandlers(backend);
72
+ type RouteHandler = (request: Request) => Promise<Response>;
73
+
74
+ function withBootstrap(handler: RouteHandler): RouteHandler {
75
+ return async (request) => {
76
+ await bootstrapCopyPatch();
77
+ return handler(request);
78
+ };
79
+ }
80
+
81
+ export const GET = withBootstrap(routes.GET);
82
+ export const POST = withBootstrap(routes.POST);
83
+ export const PUT = withBootstrap(routes.PUT);
84
+ export const PATCH = withBootstrap(routes.PATCH);
85
+ export const DELETE = withBootstrap(routes.DELETE);
86
+ export const HEAD = withBootstrap(routes.HEAD);
87
+ export const OPTIONS = withBootstrap(routes.OPTIONS);
88
+ `;
89
+ }
90
+ function astroRoute() {
91
+ return `import type { APIContext, APIRoute } from 'astro';
92
+ import { backend, bootstrapCopyPatch } from '../../../../../copypatch.config.js';
93
+
94
+ // This endpoint requires an Astro SSR adapter; it cannot run in a static-only build.
95
+ export const prerender = false;
96
+
97
+ const handle: APIRoute = async ({ request, clientAddress }: APIContext) => {
98
+ await bootstrapCopyPatch();
99
+ return backend.handle(request, { clientAddress });
100
+ };
101
+
102
+ export const GET = handle;
103
+ export const POST = handle;
104
+ export const PUT = handle;
105
+ export const PATCH = handle;
106
+ export const DELETE = handle;
107
+ export const HEAD = handle;
108
+ export const OPTIONS = handle;
109
+ `;
110
+ }
111
+ function reactRouterRoute() {
112
+ return `import { backend, bootstrapCopyPatch } from '../../copypatch.config.js';
113
+
114
+ async function handle(request: Request): Promise<Response> {
115
+ await bootstrapCopyPatch();
116
+ return backend.handle(request);
117
+ }
118
+
119
+ // No default export: React Router treats this as a resource route.
120
+ export function loader({ request }: { request: Request }): Promise<Response> {
121
+ return handle(request);
122
+ }
123
+
124
+ // React Router sends POST, PUT, PATCH, and DELETE requests to the action.
125
+ export function action({ request }: { request: Request }): Promise<Response> {
126
+ return handle(request);
127
+ }
128
+ `;
129
+ }
130
+ function reactRouterRouteEntry() {
131
+ return `import { route } from '@react-router/dev/routes';
132
+
133
+ // In app/routes.ts, import this value and add ...copyPatchRoutes to its default array.
134
+ export const copyPatchRoutes = [
135
+ route('${API_BASE_PATH}/*', './routes/copypatch-api.ts'),
136
+ ];
137
+ `;
138
+ }
139
+ function viteNodeMount() {
140
+ return `import type { IncomingMessage, ServerResponse } from 'node:http';
141
+ import { createNodeHandler } from '@copypatch/node';
142
+ import { backend, bootstrapCopyPatch } from '../copypatch.config.js';
143
+
144
+ const handler = createNodeHandler(backend);
145
+ export const copyPatchApiBasePath = '${API_BASE_PATH}';
146
+
147
+ type ConnectNext = (error?: Error) => void;
148
+
149
+ /** Mount before Vite middleware and any SPA fallback in the same Node process. */
150
+ export function createCopyPatchViteMiddleware(): (
151
+ request: IncomingMessage,
152
+ response: ServerResponse,
153
+ next: ConnectNext,
154
+ ) => void {
155
+ return (request, response, next) => {
156
+ const pathname = new URL(request.url ?? '/', 'http://copypatch.local').pathname;
157
+ if (pathname !== copyPatchApiBasePath && !pathname.startsWith(\`\${copyPatchApiBasePath}/\`)) {
158
+ next();
159
+ return;
160
+ }
161
+ void bootstrapCopyPatch().then(
162
+ () => handler(request, response),
163
+ () => next(new Error('CopyPatch bootstrap failed. Check server logs and storage configuration.')),
164
+ );
165
+ };
166
+ }
167
+ `;
168
+ }
169
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/cli/templates.ts"],"names":[],"mappings":"AAMA,MAAM,aAAa,GAAG,qBAAqB,CAAC;AAE5C,sFAAsF;AACtF,MAAM,UAAU,eAAe,CAAC,OAA4B;IAC1D,OAAO;QACL,EAAE,IAAI,EAAE,qBAAqB,EAAE,QAAQ,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;QACzE,EAAE,IAAI,EAAE,uBAAuB,EAAE,QAAQ,EAAE,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;QAChF,GAAG,cAAc,CAAC,OAAO,CAAC,SAAS,CAAC;KACrC,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,OAAgB;IACrC,MAAM,WAAW,GAAG,OAAO,KAAK,QAAQ;QACtC,CAAC,CAAC;;;;gEAI0D;QAC5D,CAAC,CAAC;;;mEAG6D,CAAC;IAElE,OAAO;EACP,WAAW;;;;;;;;;;;;;;;;;;;CAmBZ,CAAC;AACF,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAgB;IAC1C,OAAO,OAAO,KAAK,QAAQ;QACzB,CAAC,CAAC,uPAAuP;QACzP,CAAC,CAAC,wRAAwR,CAAC;AAC/R,CAAC;AAED,SAAS,cAAc,CAAC,SAAoB;IAC1C,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC;gBACnB,IAAI,EAAE,+CAA+C;gBACrD,QAAQ,EAAE,SAAS,EAAE;aACtB,CAAC,CAAC;QACH,KAAK,OAAO,CAAC,CAAC,OAAO,CAAC;gBACpB,IAAI,EAAE,2CAA2C;gBACjD,QAAQ,EAAE,UAAU,EAAE;aACvB,CAAC,CAAC;QACH,KAAK,cAAc,CAAC,CAAC,OAAO;YAC1B,EAAE,IAAI,EAAE,6BAA6B,EAAE,QAAQ,EAAE,gBAAgB,EAAE,EAAE;YACrE,EAAE,IAAI,EAAE,yBAAyB,EAAE,QAAQ,EAAE,qBAAqB,EAAE,EAAE;SACvE,CAAC;QACF,KAAK,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,CAAC,CAAC;IACrF,CAAC;AACH,CAAC;AAED,SAAS,SAAS;IAChB,OAAO;;;;;;;;;;;;;;;;;;;;;;CAsBR,CAAC;AACF,CAAC;AAED,SAAS,UAAU;IACjB,OAAO;;;;;;;;;;;;;;;;;;CAkBR,CAAC;AACF,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO;;;;;;;;;;;;;;;;CAgBR,CAAC;AACF,CAAC;AAED,SAAS,qBAAqB;IAC5B,OAAO;;;;WAIE,aAAa;;CAEvB,CAAC;AACF,CAAC;AAED,SAAS,aAAa;IACpB,OAAO;;;;;uCAK8B,aAAa;;;;;;;;;;;;;;;;;;;;;;CAsBnD,CAAC;AACF,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { type NodeHandlerOptions } from './native.js';
3
+ import type { BackendLike } from './types.js';
4
+ export interface ExpressRequest extends IncomingMessage {
5
+ body?: unknown;
6
+ }
7
+ export type ExpressNext = (error?: Error) => void;
8
+ /** Mount this middleware before Express body parsers and any SPA fallback. */
9
+ export declare function expressMiddleware<THostAuth = unknown>(backend: BackendLike<THostAuth>, options?: NodeHandlerOptions<THostAuth>): (request: ExpressRequest, response: ServerResponse, next: ExpressNext) => Promise<void>;
10
+ //# sourceMappingURL=express.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,cAAe,SAAQ,eAAe;IACrD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC;AAElD,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,SAAS,GAAG,OAAO,EACnD,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,EAC/B,OAAO,GAAE,kBAAkB,CAAC,SAAS,CAAM,GAC1C,CAAC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAYzF"}
@@ -0,0 +1,17 @@
1
+ import { handleNodeRequest } from './native.js';
2
+ /** Mount this middleware before Express body parsers and any SPA fallback. */
3
+ export function expressMiddleware(backend, options = {}) {
4
+ return async (request, response, next) => {
5
+ if (request.readableEnded && request.method !== 'GET' && request.method !== 'HEAD') {
6
+ next(new Error('CopyPatch Express middleware must be mounted before body parsers because the request body has already been consumed.'));
7
+ return;
8
+ }
9
+ try {
10
+ await handleNodeRequest(backend, request, response, options);
11
+ }
12
+ catch (error) {
13
+ next(error instanceof Error ? error : new Error('CopyPatch Express middleware failed.'));
14
+ }
15
+ };
16
+ }
17
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAA2B,MAAM,aAAa,CAAC;AASzE,8EAA8E;AAC9E,MAAM,UAAU,iBAAiB,CAC/B,OAA+B,EAC/B,UAAyC,EAAE;IAE3C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;QACvC,IAAI,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YACnF,IAAI,CAAC,IAAI,KAAK,CAAC,sHAAsH,CAAC,CAAC,CAAC;YACxI,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,MAAM,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC/D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { type NodeHandlerOptions } from './native.js';
3
+ import type { BackendLike } from './types.js';
4
+ export interface FastifyRequestLike {
5
+ raw: IncomingMessage;
6
+ }
7
+ export interface FastifyReplyLike {
8
+ raw: ServerResponse;
9
+ hijack(): void;
10
+ }
11
+ /** Register this route before Fastify content-type parsers so `request.raw` is still readable. */
12
+ export declare function fastifyCopyPatchHandler<THostAuth = unknown>(backend: BackendLike<THostAuth>, options?: NodeHandlerOptions<THostAuth>): (request: FastifyRequestLike, reply: FastifyReplyLike) => Promise<void>;
13
+ export declare function fastifyCopyPatchPlugin<THostAuth = unknown>(backend: BackendLike<THostAuth>, options?: NodeHandlerOptions<THostAuth>): {
14
+ handler: ReturnType<typeof fastifyCopyPatchHandler<THostAuth>>;
15
+ };
16
+ //# sourceMappingURL=fastify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../src/fastify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,kBAAkB;IAAG,GAAG,EAAE,eAAe,CAAC;CAAE;AAC7D,MAAM,WAAW,gBAAgB;IAAG,GAAG,EAAE,cAAc,CAAC;IAAC,MAAM,IAAI,IAAI,CAAC;CAAE;AAE1E,kGAAkG;AAClG,wBAAgB,uBAAuB,CAAC,SAAS,GAAG,OAAO,EACzD,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,EAC/B,OAAO,GAAE,kBAAkB,CAAC,SAAS,CAAM,GAC1C,CAAC,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAQzE;AAED,wBAAgB,sBAAsB,CAAC,SAAS,GAAG,OAAO,EACxD,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,EAC/B,OAAO,GAAE,kBAAkB,CAAC,SAAS,CAAM,GAC1C;IAAE,OAAO,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAA;CAAE,CAEpE"}
@@ -0,0 +1,15 @@
1
+ import { handleNodeRequest } from './native.js';
2
+ /** Register this route before Fastify content-type parsers so `request.raw` is still readable. */
3
+ export function fastifyCopyPatchHandler(backend, options = {}) {
4
+ return async (request, reply) => {
5
+ reply.hijack();
6
+ await handleNodeRequest(backend, request.raw, reply.raw, {
7
+ ...options,
8
+ ...(options.context ? { context: async (raw) => options.context(raw) } : {}),
9
+ });
10
+ };
11
+ }
12
+ export function fastifyCopyPatchPlugin(backend, options = {}) {
13
+ return { handler: fastifyCopyPatchHandler(backend, options) };
14
+ }
15
+ //# sourceMappingURL=fastify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.js","sourceRoot":"","sources":["../src/fastify.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAA2B,MAAM,aAAa,CAAC;AAMzE,kGAAkG;AAClG,MAAM,UAAU,uBAAuB,CACrC,OAA+B,EAC/B,UAAyC,EAAE;IAE3C,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC9B,KAAK,CAAC,MAAM,EAAE,CAAC;QACf,MAAM,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE;YACvD,GAAG,OAAO;YACV,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,GAAoB,EAAE,EAAE,CAAC,OAAO,CAAC,OAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/F,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,OAA+B,EAC/B,UAAyC,EAAE;IAE3C,OAAO,EAAE,OAAO,EAAE,uBAAuB,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;AAChE,CAAC"}
package/dist/hono.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import type { AdapterOptions, BackendLike } from './types.js';
2
+ export interface HonoContextLike {
3
+ req: {
4
+ raw: Request;
5
+ };
6
+ }
7
+ export declare function createHonoHandler<THostAuth = unknown>(backend: BackendLike<THostAuth>, options?: AdapterOptions<THostAuth, HonoContextLike>): (context: HonoContextLike) => Promise<Response>;
8
+ //# sourceMappingURL=hono.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,WAAW,eAAe;IAAG,GAAG,EAAE;QAAE,GAAG,EAAE,OAAO,CAAA;KAAE,CAAC;CAAE;AAE3D,wBAAgB,iBAAiB,CAAC,SAAS,GAAG,OAAO,EACnD,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,EAC/B,OAAO,GAAE,cAAc,CAAC,SAAS,EAAE,eAAe,CAAM,GACvD,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,QAAQ,CAAC,CAEjD"}
package/dist/hono.js ADDED
@@ -0,0 +1,4 @@
1
+ export function createHonoHandler(backend, options = {}) {
2
+ return async (context) => backend.handle(context.req.raw, await options.context?.(context));
3
+ }
4
+ //# sourceMappingURL=hono.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.js","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,iBAAiB,CAC/B,OAA+B,EAC/B,UAAsD,EAAE;IAExD,OAAO,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;AAC9F,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './native.js';
2
+ export * from './express.js';
3
+ export * from './fastify.js';
4
+ export * from './hono.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from './native.js';
2
+ export * from './express.js';
3
+ export * from './fastify.js';
4
+ export * from './hono.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { AdapterOptions, BackendLike } from './types.js';
3
+ export interface NodeHandlerOptions<THostAuth = unknown> extends AdapterOptions<THostAuth, IncomingMessage> {
4
+ origin?: string | undefined;
5
+ }
6
+ export declare function createNodeHandler<THostAuth = unknown>(backend: BackendLike<THostAuth>, options?: NodeHandlerOptions<THostAuth>): (request: IncomingMessage, response: ServerResponse) => void;
7
+ export declare function handleNodeRequest<THostAuth = unknown>(backend: BackendLike<THostAuth>, request: IncomingMessage, response: ServerResponse, options?: NodeHandlerOptions<THostAuth>): Promise<void>;
8
+ export declare function toRequest(request: IncomingMessage, configuredOrigin?: string): Request;
9
+ export declare function writeNodeResponse(response: Pick<ServerResponse, 'setHeader' | 'end' | 'write'> & {
10
+ writableEnded?: boolean;
11
+ }, result: Response): Promise<void>;
12
+ //# sourceMappingURL=native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGtF,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,WAAW,kBAAkB,CAAC,SAAS,GAAG,OAAO,CAAE,SAAQ,cAAc,CAAC,SAAS,EAAE,eAAe,CAAC;IACzG,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,wBAAgB,iBAAiB,CAAC,SAAS,GAAG,OAAO,EACnD,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,EAC/B,OAAO,GAAE,kBAAkB,CAAC,SAAS,CAAM,GAC1C,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,KAAK,IAAI,CAO9D;AAED,wBAAsB,iBAAiB,CAAC,SAAS,GAAG,OAAO,EACzD,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,EAC/B,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,cAAc,EACxB,OAAO,GAAE,kBAAkB,CAAC,SAAS,CAAM,GAC1C,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,eAAe,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAUtF;AASD,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,KAAK,GAAG,OAAO,CAAC,GAAG;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBpK"}
package/dist/native.js ADDED
@@ -0,0 +1,85 @@
1
+ import { Readable } from 'node:stream';
2
+ export function createNodeHandler(backend, options = {}) {
3
+ return (request, response) => {
4
+ void handleNodeRequest(backend, request, response, options).catch(() => {
5
+ if (!response.headersSent)
6
+ response.statusCode = 500;
7
+ if (!response.writableEnded)
8
+ response.end();
9
+ });
10
+ };
11
+ }
12
+ export async function handleNodeRequest(backend, request, response, options = {}) {
13
+ const abort = new AbortController();
14
+ const abortRequest = () => abort.abort();
15
+ request.once('aborted', abortRequest);
16
+ request.once('error', abortRequest);
17
+ if ('once' in response && typeof response.once === 'function')
18
+ response.once('close', abortRequest);
19
+ try {
20
+ const context = await options.context?.(request);
21
+ const address = context?.clientAddress ?? request.socket.remoteAddress;
22
+ const backendContext = {
23
+ ...context,
24
+ ...(address ? { clientAddress: address } : {}),
25
+ signal: abort.signal,
26
+ };
27
+ const result = await backend.handle(toRequest(request, options.origin), backendContext);
28
+ await writeNodeResponse(response, result);
29
+ }
30
+ finally {
31
+ request.off('aborted', abortRequest);
32
+ request.off('error', abortRequest);
33
+ if ('off' in response && typeof response.off === 'function')
34
+ response.off('close', abortRequest);
35
+ }
36
+ }
37
+ export function toRequest(request, configuredOrigin) {
38
+ const origin = configuredOrigin ?? requestOrigin(request.headers);
39
+ const method = request.method ?? 'GET';
40
+ const hasBody = method !== 'GET' && method !== 'HEAD';
41
+ return new Request(new URL(request.url ?? '/', origin), {
42
+ method,
43
+ headers: request.headers,
44
+ body: hasBody ? Readable.toWeb(request) : undefined,
45
+ duplex: hasBody ? 'half' : undefined,
46
+ });
47
+ }
48
+ function requestOrigin(headers) {
49
+ const host = headers.host ?? 'localhost';
50
+ const forwarded = headers['x-forwarded-proto'];
51
+ const protocol = typeof forwarded === 'string' ? forwarded.split(',')[0]?.trim() : 'http';
52
+ return `${protocol === 'https' ? 'https' : 'http'}://${host}`;
53
+ }
54
+ export async function writeNodeResponse(response, result) {
55
+ const setCookies = getSetCookies(result.headers);
56
+ result.headers.forEach((value, name) => {
57
+ if (name.toLowerCase() !== 'set-cookie')
58
+ response.setHeader(name, value);
59
+ });
60
+ if (setCookies.length > 0)
61
+ response.setHeader('set-cookie', setCookies);
62
+ const target = response;
63
+ target.statusCode = result.status;
64
+ if (!result.body) {
65
+ response.end();
66
+ return;
67
+ }
68
+ if (typeof response.write !== 'function') {
69
+ response.end(await result.text());
70
+ return;
71
+ }
72
+ for await (const chunk of Readable.fromWeb(result.body)) {
73
+ if (!response.write(chunk))
74
+ await new Promise((resolve) => target.once('drain', resolve));
75
+ }
76
+ response.end();
77
+ }
78
+ function getSetCookies(headers) {
79
+ const values = headers.getSetCookie?.();
80
+ if (values)
81
+ return values;
82
+ const joined = headers.get('set-cookie');
83
+ return joined ? [joined] : [];
84
+ }
85
+ //# sourceMappingURL=native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.js","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { CopyPatchBackend } from '@copypatch/backend';
2
+ import type { CopyPatchHandleContext } from '@copypatch/core';
3
+ export type HandleContextResolver<THostAuth = unknown, TRequest = unknown> = (request: TRequest) => CopyPatchHandleContext<THostAuth> | Promise<CopyPatchHandleContext<THostAuth>>;
4
+ export interface AdapterOptions<THostAuth = unknown, TRequest = unknown> {
5
+ context?: HandleContextResolver<THostAuth, TRequest> | undefined;
6
+ }
7
+ export type BackendLike<THostAuth = unknown> = Pick<CopyPatchBackend<THostAuth>, 'handle'>;
8
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAE9D,MAAM,MAAM,qBAAqB,CAAC,SAAS,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO,IAAI,CAC3E,OAAO,EAAE,QAAQ,KACd,sBAAsB,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC,CAAC;AAEpF,MAAM,WAAW,cAAc,CAAC,SAAS,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO;IACrE,OAAO,CAAC,EAAE,qBAAqB,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAC;CAClE;AAED,MAAM,MAAM,WAAW,CAAC,SAAS,GAAG,OAAO,IAAI,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@copypatch/node",
3
+ "version": "2.0.0",
4
+ "description": "Node.js adapters and project CLI for CopyPatch",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "bin": {
10
+ "copypatch": "./dist/cli/bin.js"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "default": "./dist/index.js"
17
+ },
18
+ "./cli": {
19
+ "types": "./dist/cli/index.d.ts",
20
+ "import": "./dist/cli/index.js",
21
+ "default": "./dist/cli/index.js"
22
+ }
23
+ },
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "engines": {
28
+ "node": ">=20.0.0"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public",
32
+ "registry": "https://registry.npmjs.org/"
33
+ },
34
+ "scripts": {
35
+ "build": "tsc -b tsconfig.json",
36
+ "typecheck": "tsc --noEmit",
37
+ "clean": "rm -rf dist"
38
+ },
39
+ "dependencies": {
40
+ "@copypatch/backend": "2.0.0",
41
+ "@copypatch/core": "2.0.0",
42
+ "@copypatch/storage-postgres": "2.0.0",
43
+ "@copypatch/storage-sqlite": "2.0.0",
44
+ "@node-rs/argon2": "^2.0.2"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^24.0.0",
48
+ "typescript": "^5.8.0"
49
+ }
50
+ }