@ripple-ts/adapter-vercel 0.2.214 → 0.2.216

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @ripple-ts/adapter-vercel
2
2
 
3
+ ## 0.2.216
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies []:
8
+ - @ripple-ts/adapter@0.2.216
9
+ - @ripple-ts/adapter-node@0.2.216
10
+
11
+ ## 0.2.215
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies []:
16
+ - @ripple-ts/adapter@0.2.215
17
+ - @ripple-ts/adapter-node@0.2.215
18
+
3
19
  ## 0.2.214
4
20
 
5
21
  ### Patch Changes
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Vercel adapter for Ripple metaframework (Build Output API v3)",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.2.214",
6
+ "version": "0.2.216",
7
7
  "type": "module",
8
8
  "module": "src/index.js",
9
9
  "main": "src/index.js",
@@ -19,8 +19,8 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "@vercel/nft": "^1.0.0",
22
- "@ripple-ts/adapter": "0.2.214",
23
- "@ripple-ts/adapter-node": "0.2.214"
22
+ "@ripple-ts/adapter": "0.2.216",
23
+ "@ripple-ts/adapter-node": "0.2.216"
24
24
  },
25
25
  "homepage": "https://ripple-ts.com",
26
26
  "repository": {
package/src/adapt.js CHANGED
@@ -161,10 +161,11 @@ async function trace_and_copy_dependencies(entry, func_dir, project_root) {
161
161
  /**
162
162
  * Generate the serverless function handler source code.
163
163
  *
164
- * Vercel's Node.js Serverless Functions invoke handlers with
165
- * `(IncomingMessage, ServerResponse)`, but Ripple's production handler is
166
- * `Request => Response`. The generated handler bridges these two worlds
167
- * using adapter-node's conversion utilities.
164
+ * Uses Vercel's native Web Standard API: the handler receives a Web Request
165
+ * and returns a Web Response. No Node.js (req, res) conversion needed.
166
+ *
167
+ * Same-origin fetch short-circuiting is handled at the framework level
168
+ * by patch_global_fetch in @ripple-ts/adapter.
168
169
  *
169
170
  * @param {string} server_entry_relative - Relative path from the function dir to
170
171
  * the server entry file
@@ -175,26 +176,19 @@ function generate_handler_source(server_entry_relative) {
175
176
  // Auto-generated by @ripple-ts/adapter-vercel
176
177
  // Vercel Serverless Function handler for Ripple
177
178
  //
178
- // Bridges Vercel's Node.js (req, res) interface with Ripple's Web
179
- // fetch-style handler (Request => Response).
179
+ // Uses Vercel's native Web Standard API (Request => Response).
180
+ // Same-origin fetch short-circuiting is handled at the framework level.
180
181
  import { handler } from ${JSON.stringify(server_entry_relative)};
181
- import { nodeRequestToWebRequest, webResponseToNodeResponse } from '@ripple-ts/adapter-node';
182
-
183
- export default async function (req, res) {
184
- const controller = new AbortController();
185
- req.on('close', () => controller.abort());
186
-
187
- try {
188
- const request = nodeRequestToWebRequest(req, controller.signal, true);
189
- const response = await handler(request);
190
- webResponseToNodeResponse(response, res, req.method ?? 'GET');
191
- } catch (err) {
192
- console.error('[ripple] Serverless handler error:', err);
193
- if (!res.headersSent) {
194
- res.statusCode = 500;
195
- res.end('Internal Server Error');
182
+
183
+ export default {
184
+ async fetch(request) {
185
+ try {
186
+ return await handler(request);
187
+ } catch (err) {
188
+ console.error('[ripple] Serverless handler error:', err);
189
+ return new Response('Internal Server Error', { status: 500 });
196
190
  }
197
- }
191
+ },
198
192
  };
199
193
  `;
200
194
  }
@@ -305,7 +299,9 @@ function generate_vercel_config(options) {
305
299
  * @returns {Promise<void>}
306
300
  */
307
301
  export async function adapt(options = {}) {
308
- const { outDir = 'dist', serverless = {}, isr = false } = options;
302
+ const { outDir = 'dist', serverless = {}, isr = false, verbose = true } = options;
303
+
304
+ const log = verbose ? console.log.bind(console) : () => {};
309
305
 
310
306
  const project_root = process.cwd();
311
307
  const build_dir = resolve(project_root, outDir);
@@ -336,7 +332,7 @@ export async function adapt(options = {}) {
336
332
  // Clean and create output directory
337
333
  // ------------------------------------------------------------------
338
334
 
339
- console.log('[adapter-vercel] Generating Vercel Build Output...');
335
+ log('[adapter-vercel] Generating Vercel Build Output...');
340
336
 
341
337
  rmSync(output_dir, { recursive: true, force: true });
342
338
  mkdirSync(output_dir, { recursive: true });
@@ -347,7 +343,7 @@ export async function adapt(options = {}) {
347
343
 
348
344
  const static_dir = join(output_dir, 'static');
349
345
 
350
- console.log('[adapter-vercel] Copying static assets...');
346
+ log('[adapter-vercel] Copying static assets...');
351
347
  copy_dir(client_dir, static_dir);
352
348
 
353
349
  // Remove index.html from static output — SSR handles the root route.
@@ -365,7 +361,7 @@ export async function adapt(options = {}) {
365
361
  const func_dir = join(output_dir, 'functions', 'index.func');
366
362
  mkdirSync(func_dir, { recursive: true });
367
363
 
368
- console.log('[adapter-vercel] Tracing server dependencies...');
364
+ log('[adapter-vercel] Tracing server dependencies...');
369
365
 
370
366
  // Trace and copy all dependencies of the server entry.
371
367
  // The trace result tells us the project-relative path where the entry
@@ -426,7 +422,7 @@ export async function adapt(options = {}) {
426
422
 
427
423
  vc_config.prerender = prerender;
428
424
 
429
- console.log(
425
+ log(
430
426
  `[adapter-vercel] ISR enabled (expiration: ${isr.expiration === false ? 'never' : isr.expiration + 's'})`,
431
427
  );
432
428
  }
@@ -437,7 +433,7 @@ export async function adapt(options = {}) {
437
433
  // 3. Generate the Build Output API config
438
434
  // ------------------------------------------------------------------
439
435
 
440
- console.log('[adapter-vercel] Writing config...');
436
+ log('[adapter-vercel] Writing config...');
441
437
 
442
438
  const vercel_config = generate_vercel_config(options);
443
439
  write(join(output_dir, 'config.json'), JSON.stringify(vercel_config, null, '\t'));
@@ -446,8 +442,8 @@ export async function adapt(options = {}) {
446
442
  // Summary
447
443
  // ------------------------------------------------------------------
448
444
 
449
- console.log('[adapter-vercel] Build output generated at .vercel/output/');
450
- console.log(` Static: ${static_dir}`);
451
- console.log(` Function: ${func_dir}`);
452
- console.log(` Runtime: ${runtime}`);
445
+ log('[adapter-vercel] Build output generated at .vercel/output/');
446
+ log(` Static: ${static_dir}`);
447
+ log(` Function: ${func_dir}`);
448
+ log(` Runtime: ${runtime}`);
453
449
  }
@@ -72,7 +72,7 @@ describe('adapt()', () => {
72
72
  const { adapt } = await import('../src/adapt.js');
73
73
  create_build_output(tmp_dir);
74
74
 
75
- await adapt();
75
+ await adapt({ verbose: false });
76
76
 
77
77
  const output_dir = join(tmp_dir, '.vercel', 'output');
78
78
 
@@ -97,7 +97,7 @@ describe('adapt()', () => {
97
97
  const { adapt } = await import('../src/adapt.js');
98
98
  create_build_output(tmp_dir);
99
99
 
100
- await adapt();
100
+ await adapt({ verbose: false });
101
101
 
102
102
  const config = JSON.parse(
103
103
  readFileSync(join(tmp_dir, '.vercel', 'output', 'config.json'), 'utf-8'),
@@ -128,7 +128,7 @@ describe('adapt()', () => {
128
128
  const { adapt } = await import('../src/adapt.js');
129
129
  create_build_output(tmp_dir);
130
130
 
131
- await adapt();
131
+ await adapt({ verbose: false });
132
132
 
133
133
  const vc_config = JSON.parse(
134
134
  readFileSync(
@@ -149,7 +149,7 @@ describe('adapt()', () => {
149
149
  const { adapt } = await import('../src/adapt.js');
150
150
  create_build_output(tmp_dir);
151
151
 
152
- await adapt();
152
+ await adapt({ verbose: false });
153
153
 
154
154
  const pkg = JSON.parse(
155
155
  readFileSync(
@@ -161,27 +161,36 @@ describe('adapt()', () => {
161
161
  expect(pkg.type).toBe('module');
162
162
  });
163
163
 
164
- it('generates handler that bridges Node.js req/res to Ripple fetch handler', async () => {
164
+ it('generates Web Standard handler using Vercel native fetch API', async () => {
165
165
  const { adapt } = await import('../src/adapt.js');
166
166
  create_build_output(tmp_dir);
167
167
 
168
- await adapt();
168
+ await adapt({ verbose: false });
169
169
 
170
170
  const handler_source = readFileSync(
171
171
  join(tmp_dir, '.vercel', 'output', 'functions', 'index.func', 'index.js'),
172
172
  'utf-8',
173
173
  );
174
174
 
175
+ // Uses static import (not dynamic await import)
175
176
  expect(handler_source).toContain('import { handler }');
176
- expect(handler_source).toContain(
177
- "import { nodeRequestToWebRequest, webResponseToNodeResponse } from '@ripple-ts/adapter-node'",
178
- );
179
- expect(handler_source).toContain('export default async function (req, res)');
180
- expect(handler_source).toContain('nodeRequestToWebRequest(req, controller.signal, true)');
181
- expect(handler_source).toContain('webResponseToNodeResponse(response, res,');
177
+
178
+ // Uses Vercel's native Web Standard export format
179
+ expect(handler_source).toContain('export default');
180
+ expect(handler_source).toContain('async fetch(request)');
181
+ expect(handler_source).toContain('handler(request)');
182
+
183
+ // No Node.js (req, res) bridge — no adapter-node dependency
184
+ expect(handler_source).not.toContain('adapter-node');
185
+ expect(handler_source).not.toContain('webResponseToNodeResponse');
186
+ expect(handler_source).not.toContain('bufferRequestBody');
187
+ expect(handler_source).not.toContain('(req, res)');
188
+
189
+ // No self-referential fetch hack — handled at framework level
190
+ expect(handler_source).not.toContain('_selfHosts');
191
+ expect(handler_source).not.toContain('_realFetch');
182
192
 
183
193
  // Handler should import the server entry at its project-relative path
184
- // (dist/server/entry.js), not just "entry.js"
185
194
  expect(handler_source).toContain('dist/server/entry.js');
186
195
  });
187
196
 
@@ -189,7 +198,7 @@ describe('adapt()', () => {
189
198
  const { adapt } = await import('../src/adapt.js');
190
199
  create_build_output(tmp_dir, { outDir: 'build' });
191
200
 
192
- await adapt({ outDir: 'build' });
201
+ await adapt({ verbose: false, outDir: 'build' });
193
202
 
194
203
  expect(existsSync(join(tmp_dir, '.vercel', 'output', 'config.json'))).toBe(true);
195
204
  expect(existsSync(join(tmp_dir, '.vercel', 'output', 'functions', 'index.func'))).toBe(true);
@@ -200,6 +209,7 @@ describe('adapt()', () => {
200
209
  create_build_output(tmp_dir);
201
210
 
202
211
  await adapt({
212
+ verbose: false,
203
213
  serverless: {
204
214
  runtime: 'nodejs22.x',
205
215
  regions: ['iad1', 'sfo1'],
@@ -226,6 +236,7 @@ describe('adapt()', () => {
226
236
  create_build_output(tmp_dir);
227
237
 
228
238
  await adapt({
239
+ verbose: false,
229
240
  redirects: [{ source: '/old', destination: '/new', permanent: true }],
230
241
  });
231
242
 
@@ -246,6 +257,7 @@ describe('adapt()', () => {
246
257
  create_build_output(tmp_dir);
247
258
 
248
259
  await adapt({
260
+ verbose: false,
249
261
  headers: [
250
262
  {
251
263
  source: '/(.*)',
@@ -270,6 +282,7 @@ describe('adapt()', () => {
270
282
  create_build_output(tmp_dir);
271
283
 
272
284
  await adapt({
285
+ verbose: false,
273
286
  images: {
274
287
  sizes: [640, 1080, 1920],
275
288
  domains: ['example.com'],
@@ -297,7 +310,7 @@ describe('adapt()', () => {
297
310
  mkdirSync(stale_dir, { recursive: true });
298
311
  writeFileSync(join(stale_dir, 'old-file.txt'), 'stale');
299
312
 
300
- await adapt();
313
+ await adapt({ verbose: false });
301
314
 
302
315
  // Stale file should be gone
303
316
  expect(existsSync(join(stale_dir, 'old-file.txt'))).toBe(false);
@@ -309,7 +322,7 @@ describe('adapt()', () => {
309
322
  const { adapt } = await import('../src/adapt.js');
310
323
  create_build_output(tmp_dir);
311
324
 
312
- await adapt({ trailingSlash: true });
325
+ await adapt({ verbose: false, trailingSlash: true });
313
326
 
314
327
  const config = JSON.parse(
315
328
  readFileSync(join(tmp_dir, '.vercel', 'output', 'config.json'), 'utf-8'),
@@ -322,7 +335,7 @@ describe('adapt()', () => {
322
335
  const { adapt } = await import('../src/adapt.js');
323
336
  create_build_output(tmp_dir);
324
337
 
325
- await adapt({ cleanUrls: false });
338
+ await adapt({ verbose: false, cleanUrls: false });
326
339
 
327
340
  const config = JSON.parse(
328
341
  readFileSync(join(tmp_dir, '.vercel', 'output', 'config.json'), 'utf-8'),
@@ -340,6 +353,7 @@ describe('adapt()', () => {
340
353
  create_build_output(tmp_dir);
341
354
 
342
355
  await adapt({
356
+ verbose: false,
343
357
  isr: {
344
358
  expiration: 60,
345
359
  },
@@ -361,6 +375,7 @@ describe('adapt()', () => {
361
375
  create_build_output(tmp_dir);
362
376
 
363
377
  await adapt({
378
+ verbose: false,
364
379
  isr: {
365
380
  expiration: false,
366
381
  },
@@ -382,6 +397,7 @@ describe('adapt()', () => {
382
397
  create_build_output(tmp_dir);
383
398
 
384
399
  await adapt({
400
+ verbose: false,
385
401
  isr: {
386
402
  expiration: 300,
387
403
  bypassToken: 'my-secret-token',
@@ -405,7 +421,7 @@ describe('adapt()', () => {
405
421
  const { adapt } = await import('../src/adapt.js');
406
422
  create_build_output(tmp_dir);
407
423
 
408
- await adapt({ isr: false });
424
+ await adapt({ verbose: false, isr: false });
409
425
 
410
426
  const vc_config = JSON.parse(
411
427
  readFileSync(
@@ -421,7 +437,7 @@ describe('adapt()', () => {
421
437
  const { adapt } = await import('../src/adapt.js');
422
438
  create_build_output(tmp_dir);
423
439
 
424
- await adapt();
440
+ await adapt({ verbose: false });
425
441
 
426
442
  const vc_config = JSON.parse(
427
443
  readFileSync(
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "compilerOptions": {
3
+ "allowJs": true,
4
+ "noEmit": true
5
+ },
6
+ "include": ["./src/**/*", "./tests/**/*"],
7
+ "exclude": ["dist", "node_modules"]
8
+ }
package/types/index.d.ts CHANGED
@@ -214,6 +214,12 @@ export interface AdaptOptions {
214
214
  * Enforce trailing slash behavior.
215
215
  */
216
216
  trailingSlash?: boolean;
217
+
218
+ /**
219
+ * Print progress messages to stdout.
220
+ * @default true
221
+ */
222
+ verbose?: boolean;
217
223
  }
218
224
 
219
225
  /**