diff --git a/packages/gasket-nextjs/lib/layout/with-gasket-data.js b/packages/gasket-nextjs/lib/layout/with-gasket-data.js index b690f95f6..046002572 100644 --- a/packages/gasket-nextjs/lib/layout/with-gasket-data.js +++ b/packages/gasket-nextjs/lib/layout/with-gasket-data.js @@ -1,4 +1,4 @@ -import { request } from '../server'; +import { request } from '../request'; import { injectGasketData } from '../inject-gasket-data.js' import NextScript from 'next/script'; @@ -29,7 +29,7 @@ function lookupIndex(bodyChildren, index = -1) { export function withGasketData(gasket, options = { index: -1 }) { const { index } = options; return layout => async props => { - const req = request(); + const req = await request(); const gasketData = req ? await gasket.actions.getPublicGasketData?.(req) ?? {} : {}; const html = await layout({ ...props }); return injectGasketData(html, gasketData, lookupIndex, index); diff --git a/packages/gasket-nextjs/test/layout/with-gasket-data.test.js b/packages/gasket-nextjs/test/layout/with-gasket-data.test.js index 086f49fb6..f92e1c91f 100644 --- a/packages/gasket-nextjs/test/layout/with-gasket-data.test.js +++ b/packages/gasket-nextjs/test/layout/with-gasket-data.test.js @@ -1,7 +1,7 @@ import { jest, expect } from '@jest/globals'; import { createElement, Children } from 'react'; -jest.unstable_mockModule('../../lib/server/request.js', () => ({ +jest.unstable_mockModule('../../lib/request/index.js', () => ({ request: jest.fn().mockReturnValue({}) })); diff --git a/packages/gasket-plugin-command/package.json b/packages/gasket-plugin-command/package.json index c45d67bfe..4d21dbf4a 100644 --- a/packages/gasket-plugin-command/package.json +++ b/packages/gasket-plugin-command/package.json @@ -3,6 +3,7 @@ "version": "7.0.15", "description": "Plugin to enable other plugins to inject new gasket commands", "type": "module", + "main": "lib/index.js", "types": "lib/index.d.ts", "files": [ "lib" diff --git a/packages/gasket-plugin-https-proxy/package.json b/packages/gasket-plugin-https-proxy/package.json index 8344b56b9..83613f584 100644 --- a/packages/gasket-plugin-https-proxy/package.json +++ b/packages/gasket-plugin-https-proxy/package.json @@ -2,12 +2,12 @@ "name": "@gasket/plugin-https-proxy", "version": "7.0.0-canary.0", "description": "Adds support for running an https proxy", + "type": "module", "main": "lib/index.js", "types": "lib/index.d.ts", "files": [ "lib" ], - "type": "module", "scripts": { "lint": "eslint .", "lint:fix": "npm run lint -- --fix", @@ -55,10 +55,12 @@ "eslintConfig": { "extends": [ "godaddy", - "plugin:jest/recommended" + "plugin:jest/recommended", + "plugin:jsdoc/recommended-typescript-flavor" ], "plugins": [ - "unicorn" + "unicorn", + "jsdoc" ], "rules": { "unicorn/filename-case": "error" diff --git a/packages/gasket-plugin-metadata/lib/index.d.ts b/packages/gasket-plugin-metadata/lib/index.d.ts index 824cd5057..49a7acc44 100644 --- a/packages/gasket-plugin-metadata/lib/index.d.ts +++ b/packages/gasket-plugin-metadata/lib/index.d.ts @@ -128,9 +128,9 @@ declare module '@gasket/core' { } } -const plugin: Plugin = { +export default { name: '@gasket/plugin-metadata', + version: '', + description: '', hooks: {} }; - -export = plugin; diff --git a/packages/gasket-plugin-metadata/package.json b/packages/gasket-plugin-metadata/package.json index 1949e0fa5..a40b05972 100644 --- a/packages/gasket-plugin-metadata/package.json +++ b/packages/gasket-plugin-metadata/package.json @@ -2,12 +2,12 @@ "name": "@gasket/plugin-metadata", "version": "7.0.15", "description": "Adds metadata to gasket lifecycles", + "type": "module", "main": "lib/index.js", "types": "lib/index.d.ts", "files": [ "lib" ], - "type": "module", "scripts": { "lint": "eslint .", "lint:fix": "npm run lint -- --fix", diff --git a/packages/gasket-plugin-nextjs/generator/next/server.js b/packages/gasket-plugin-nextjs/generator/next/server.js index ff0a67b78..632655882 100644 --- a/packages/gasket-plugin-nextjs/generator/next/server.js +++ b/packages/gasket-plugin-nextjs/generator/next/server.js @@ -1,6 +1,5 @@ import gasket from './gasket.js'; -{{/if}} -{{#if nextDevProxy }} +{{#if nextDevProxy}} gasket.actions.startProxyServer(); {{else}} gasket.actions.startServer(); diff --git a/packages/gasket-preset-nextjs/lib/preset-config.js b/packages/gasket-preset-nextjs/lib/preset-config.js index aaafe308d..936c21f76 100644 --- a/packages/gasket-preset-nextjs/lib/preset-config.js +++ b/packages/gasket-preset-nextjs/lib/preset-config.js @@ -28,9 +28,7 @@ export default async function presetConfig(gasket, context) { plugins.push(pluginHttps); plugins.push(frameworkPlugin.default || frameworkPlugin); - } - - if (context.nextDevProxy) { + } else if (context.nextDevProxy) { plugins.push(pluginHttpsProxy); } diff --git a/packages/gasket-request/lib/index.d.ts b/packages/gasket-request/lib/index.d.ts index 15a6664b1..f2c212787 100644 --- a/packages/gasket-request/lib/index.d.ts +++ b/packages/gasket-request/lib/index.d.ts @@ -15,6 +15,13 @@ export type RequestLike = { */ async function objectFromCookieStore(cookieStore: CookieStore): Promise>; +/** + * Capture the search params as a key/value object + * Necessary to capture array values + * @see https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams + */ +async function objectFromSearchParams(searchParams: URLSearchParams): Record; + /** * Expected request shape for GasketActions */ @@ -44,8 +51,8 @@ export class WeakPromiseKeeper { */ export async function makeGasketRequest(req: RequestLike): Promise; -type RequestActionFn> = (gasket: Gasket, req: RequestLike, ...args: Args) => Promise; -type RequestActionWrapperFn> = (gasket: Gasket, req: GasketRequest, ...args: Args) => Promise; +type RequestActionFn> = (gasket: Gasket, req: GasketRequest, ...args: Args) => Promise; +type RequestActionWrapperFn> = (gasket: Gasket, req: RequestLike, ...args: Args) => Promise; export function withGasketRequest>(actionFn: RequestActionFn): RequestActionWrapperFn; export function withGasketRequestCache>(actionFn: RequestActionFn): RequestActionWrapperFn; diff --git a/packages/gasket-request/lib/request.js b/packages/gasket-request/lib/request.js index 051dab588..767123023 100644 --- a/packages/gasket-request/lib/request.js +++ b/packages/gasket-request/lib/request.js @@ -28,6 +28,19 @@ async function objectFromCookieStore(cookieStore) { }, {}); } +/** + * @type {import('./index.js').objectFromSearchParams} + */ +function objectFromSearchParams(searchParams) { + const entries = Object.fromEntries(searchParams); + const keys = Object.keys(entries); + return keys.reduce((acc, key) => { + const value = searchParams.getAll(key); + acc[key] = value.length === 1 ? value[0] : value; + return acc; + }, {}); +} + /** * @type {import('./index.js').makeGasketRequest} */ @@ -66,9 +79,9 @@ export async function makeGasketRequest(requestLike) { path ??= ''; return new GasketRequest(Object.seal({ - headers: headers.constructor.prototype.entries ? Object.fromEntries(headers.entries()) : headers, - cookies: cookies.constructor.prototype.getAll ? await objectFromCookieStore(cookies) : cookies, - query: query instanceof URLSearchParams ? Object.fromEntries(query) : query, + headers: 'entries' in headers ? Object.fromEntries(headers.entries()) : headers, + cookies: 'getAll' in cookies ? await objectFromCookieStore(cookies) : cookies, + query: query instanceof URLSearchParams ? objectFromSearchParams(query) : query, path })); }; diff --git a/packages/gasket-request/package.json b/packages/gasket-request/package.json index a1fa63168..8744b857d 100644 --- a/packages/gasket-request/package.json +++ b/packages/gasket-request/package.json @@ -28,10 +28,10 @@ "typecheck:watch": "tsc --watch", "build": "swc lib -d cjs --delete-dir-on-start --strip-leading-paths --out-file-extension cjs", "build:watch": "npm run build -- --watch", - "postbuild:replace": "replace '.js' '.cjs' cjs/*", - "postbuild:package": "node -e \"require('fs').writeFileSync('cjs/package.json', '{}')\"", "postbuild": "npm run postbuild:package && npm run postbuild:replace", - "prepublishOnly": "npm run build" + "prepublishOnly": "npm run build", + "postbuild:package": "node -e \"require('fs').writeFileSync('cjs/package.json', '{}')\"", + "postbuild:replace": "replace '.js' '.cjs' cjs/*" }, "repository": { "type": "git", diff --git a/packages/gasket-request/test/request.test.js b/packages/gasket-request/test/request.test.js index 1fab3bfd8..1e993922e 100644 --- a/packages/gasket-request/test/request.test.js +++ b/packages/gasket-request/test/request.test.js @@ -80,6 +80,22 @@ describe('makeGasketRequest', () => { expect(result.query).toEqual({ query1: 'value1', query2: 'value2' }); }); + it('handles URLSearchParams array values', async () => { + const headers = new Map([['header1', 'value1'], ['header2', 'value2']]); + const query = new URLSearchParams({ query1: 'value1', query2: 'value2' }); + query.append('query3', 'value3'); + query.append('query3', 'value4'); + const requestLike = { headers, cookies: {}, query }; + + const result = await makeGasketRequest(requestLike); + + expect(result.query).toEqual({ + query1: 'value1', + query2: 'value2', + query3: ['value3', 'value4'] + }); + }); + it('handles no query', async () => { const headers = new Map([['header1', 'value1'], ['header2', 'value2']]); const requestLike = { headers, cookies: {} }; @@ -89,7 +105,7 @@ describe('makeGasketRequest', () => { expect(result.query).toEqual({}); }); - it('handles CookieStore for cookies', async () => { + it('handles Next15 style CookieStore for cookies', async () => { const headers = new Map([['header1', 'value1'], ['header2', 'value2']]); const cookieStore = new MockCookieStore([ { name: 'cookie1', value: 'value1' }, @@ -102,6 +118,23 @@ describe('makeGasketRequest', () => { expect(result.cookies).toEqual({ cookie1: 'value1', cookie2: 'value2' }); }); + it('handles Next14 style CookieStore for cookies', async () => { + const headers = new Map([['header1', 'value1'], ['header2', 'value2']]); + const cookieStore = { + getAll() { + return [ + { name: 'cookie1', value: 'value1' }, + { name: 'cookie2', value: 'value2' } + ]; + } + }; + const requestLike = { headers, cookies: cookieStore }; + + const result = await makeGasketRequest(requestLike); + + expect(result.cookies).toEqual({ cookie1: 'value1', cookie2: 'value2' }); + }); + it('handles no cookies', async () => { const headers = new Map([['header1', 'value1'], ['header2', 'value2']]); const requestLike = { headers }; diff --git a/scripts/align-packages.js b/scripts/align-packages.js index 0784d43bb..87f85743d 100644 --- a/scripts/align-packages.js +++ b/scripts/align-packages.js @@ -127,6 +127,7 @@ const scriptsOrder = [ 'typecheck:watch', 'build', 'build:watch', + 'postbuild', 'prepack', 'postpack', 'prepublish',