@strivacity/sdk-next 4.0.0-beta.1 → 4.0.0-beta.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 +125 -59
- package/dist/server/handlers/api.cjs +1 -1
- package/dist/server/handlers/api.cjs.map +1 -1
- package/dist/server/handlers/api.mjs +1 -1
- package/dist/server/handlers/api.mjs.map +1 -1
- package/dist/server/handlers/route.cjs +1 -1
- package/dist/server/handlers/route.cjs.map +1 -1
- package/dist/server/handlers/route.mjs +1 -1
- package/dist/server/handlers/route.mjs.map +1 -1
- package/dist/server/sdk.cjs +1 -1
- package/dist/server/sdk.cjs.map +1 -1
- package/dist/server/sdk.mjs +1 -1
- package/dist/server/sdk.mjs.map +1 -1
- package/dist/server/storages.cjs +1 -1
- package/dist/server/storages.cjs.map +1 -1
- package/dist/server/storages.mjs +1 -1
- package/dist/server/storages.mjs.map +1 -1
- package/dist/server/types.d.ts +11 -3
- package/package.json +5 -11
- package/testing/tests/client/components.spec.ts +0 -10
- package/testing/tests/client/hooks.spec.ts +0 -10
- package/testing/tests/client/index.spec.ts +0 -106
- package/testing/tests/client/storages.spec.ts +0 -10
- package/testing/tests/client/utils.spec.ts +0 -10
- package/testing/tests/server/handlers/api.spec.ts +0 -110
- package/testing/tests/server/handlers/route.spec.ts +0 -173
- package/testing/tests/server/index.spec.ts +0 -103
- package/testing/tests/server/sdk.spec.ts +0 -250
- package/testing/tests/server/storages.spec.ts +0 -353
- package/testing/tests/server/utils.spec.ts +0 -110
package/dist/server/sdk.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createEncryptedCookieStorage as e}from"./storages.mjs";import{apiAppRouteHandlerFactory as t,apiPageRouteHandlerFactory as n}from"./handlers/api.mjs";import{appRouteHandlerFactory as r,pageRouteHandlerFactory as i}from"./handlers/route.mjs";import{ConfigurationError as a}from"@strivacity/sdk-core/utils/errors";import{NextResponse as o}from"next/server";import{createBaseServerSDK as s}from"@strivacity/sdk-core/server";function c(c){if(!c.storage){if(!c.secret)throw new a(`Secret is required for encrypted cookie storage`);c.cookieMaxAge??=2592e3,c.storage=e(c.secret,{defaultCookieOptions:{maxAge:c.cookieMaxAge}})}let l=s({toRequest:e=>e,redirect:(e,t)=>o.redirect(e,t)},c);function u(e){return(r,i)=>r instanceof Request?t(l)(e)(r,i??{}):n(l)(e)(r,i)}function d(e,t){return typeof e==`function`?r(l)(e,t):i(l)(e)}return{get options(){return l.options},withAuthGuard:d,withApiAuthRequired:u,getSession:e=>l.getSession(e),updateSession:(e,t)=>l.updateSession(e,t),refreshSession:e=>l.refreshSession(e),revokeSession:e=>l.revokeSession(e),getEntrySession:e=>l.getEntrySession(e),completeLogin:(e,t)=>l.completeLogin(e,t),logout:(e,t)=>l.logout(e,t),handleLogin:e=>l.handleLogin(e),handleRegister:e=>l.handleRegister(e),handleCallback:e=>l.handleCallback(e),handleRefresh:e=>l.handleRefresh(e),handleRevoke:e=>l.handleRevoke(e),handleEntry:e=>l.handleEntry(e),handleLogout:e=>l.handleLogout(e),handleBackChannelLogout:e=>l.handleBackChannelLogout(e),handler:async e=>await l.handler(e)??new o(`Not Found`,{status:404})}}export{c as createServerSDK};
|
|
1
|
+
import{createEncryptedCookieStorage as e}from"./storages.mjs";import{apiAppRouteHandlerFactory as t,apiPageRouteHandlerFactory as n}from"./handlers/api.mjs";import{appRouteHandlerFactory as r,pageRouteHandlerFactory as i}from"./handlers/route.mjs";import{ConfigurationError as a}from"@strivacity/sdk-core/utils/errors";import{NextResponse as o}from"next/server";import{createBaseServerSDK as s}from"@strivacity/sdk-core/server";function c(c){if(!c.storage){if(!c.secret)throw new a(`Secret is required for encrypted cookie storage`);c.cookieMaxAge??=2592e3,c.storage=e(c.secret,{defaultCookieOptions:{maxAge:c.cookieMaxAge}})}let l=s({toRequest:e=>e,redirect:(e,t)=>o.redirect(e,t)},c);function u(e){return(r,i)=>r instanceof Request?t(l)(e)(r,i??{}):n(l)(e)(r,i)}function d(e,t){return typeof e==`function`?r(l)(e,t):i(l)(e)}return{get options(){return l.options},withAuthGuard:d,withApiAuthRequired:u,getSession:(e,t)=>l.getSession(e,e instanceof Request?t:{autoRefresh:!1}),updateSession:(e,t)=>l.updateSession(e,t),refreshSession:e=>l.refreshSession(e),revokeSession:e=>l.revokeSession(e),getEntrySession:e=>l.getEntrySession(e),completeLogin:(e,t)=>l.completeLogin(e,t),logout:(e,t)=>l.logout(e,t),handleLogin:e=>l.handleLogin(e),handleRegister:e=>l.handleRegister(e),handleCallback:e=>l.handleCallback(e),handleRefresh:e=>l.handleRefresh(e),handleRevoke:e=>l.handleRevoke(e),handleEntry:e=>l.handleEntry(e),handleLogout:e=>l.handleLogout(e),handleBackChannelLogout:e=>l.handleBackChannelLogout(e),handler:async e=>await l.handler(e)??new o(`Not Found`,{status:404})}}export{c as createServerSDK};
|
|
2
2
|
//# sourceMappingURL=sdk.mjs.map
|
package/dist/server/sdk.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.mjs","names":[],"sources":["../../src/server/sdk.ts"],"sourcesContent":["import type { NextApiHandler, NextApiRequest, NextApiResponse } from 'next';\nimport type { ParsedUrlQuery } from 'node:querystring';\nimport type {\n\tNextServerSDK,\n\tNextServerSDKInitConfig,\n\tWithAuthGuardAppRouterOptions,\n\tWithAuthGuardPageRouterOptions,\n\tAppRouterPageRoute,\n\tAppRouterPageRouteOpts,\n\tPageRoute,\n\tAppRouteHandlerFn,\n\tAppRouteHandlerFnContext,\n\tPagesRouterRequest,\n} from './types';\nimport { NextResponse, type NextRequest } from 'next/server';\nimport { createBaseServerSDK } from '@strivacity/sdk-core/server';\nimport { ConfigurationError } from '@strivacity/sdk-core/utils/errors';\nimport { createEncryptedCookieStorage } from './storages';\nimport { apiAppRouteHandlerFactory, apiPageRouteHandlerFactory } from './handlers/api';\nimport { appRouteHandlerFactory, pageRouteHandlerFactory } from './handlers/route';\n\n/**\n * Creates a Next.js server SDK instance with the provided configuration.\n *\n * @param {NextServerSDKInitConfig} initConfig - The initialization configuration for the SDK.\n * @returns {NextServerSDK} The initialized Next.js server SDK instance.\n */\nexport function createServerSDK(initConfig: NextServerSDKInitConfig): NextServerSDK {\n\tif (!initConfig.storage) {\n\t\tif (!initConfig.secret) {\n\t\t\tthrow new ConfigurationError('Secret is required for encrypted cookie storage');\n\t\t}\n\n\t\tinitConfig.cookieMaxAge ??= 30 * 24 * 60 * 60;\n\t\tinitConfig.storage = createEncryptedCookieStorage(initConfig.secret, { defaultCookieOptions: { maxAge: initConfig.cookieMaxAge } });\n\t}\n\n\tconst base = createBaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>(\n\t\t{\n\t\t\ttoRequest: (req) => req as Request,\n\t\t\tredirect: (url, status) => NextResponse.redirect(url, status),\n\t\t},\n\t\tinitConfig,\n\t);\n\n\tfunction withApiAuthRequired(apiRoute: AppRouteHandlerFn): AppRouteHandlerFn;\n\tfunction withApiAuthRequired(apiRoute: NextApiHandler): NextApiHandler;\n\tfunction withApiAuthRequired(apiRoute: AppRouteHandlerFn | NextApiHandler): AppRouteHandlerFn | NextApiHandler {\n\t\treturn (req: NextRequest | Request | NextApiRequest, resOrCtx?: AppRouteHandlerFnContext | NextApiResponse) => {\n\t\t\tif (req instanceof Request) {\n\t\t\t\tconst appRouteHandler = apiAppRouteHandlerFactory(base);\n\t\t\t\tconst wrappedAppRoute = appRouteHandler(apiRoute as AppRouteHandlerFn);\n\t\t\t\treturn wrappedAppRoute(req, (resOrCtx ?? {}) as AppRouteHandlerFnContext);\n\t\t\t}\n\n\t\t\tconst pageRouteHandler = apiPageRouteHandlerFactory(base);\n\t\t\tconst wrappedPageRoute = pageRouteHandler(apiRoute as NextApiHandler);\n\t\t\treturn wrappedPageRoute(req, resOrCtx as NextApiResponse);\n\t\t};\n\t}\n\n\tfunction withAuthGuard(): PageRoute<Record<string, unknown>, ParsedUrlQuery>;\n\tfunction withAuthGuard<P extends Record<string, unknown> = Record<string, unknown>, Q extends ParsedUrlQuery = ParsedUrlQuery>(\n\t\topts: WithAuthGuardPageRouterOptions<P, Q>,\n\t): PageRoute<P, Q>;\n\tfunction withAuthGuard<P extends AppRouterPageRouteOpts = AppRouterPageRouteOpts>(\n\t\tfn: AppRouterPageRoute<P>,\n\t\topts?: WithAuthGuardAppRouterOptions<P>,\n\t): AppRouterPageRoute<P>;\n\tfunction withAuthGuard(\n\t\tfnOrOpts?: WithAuthGuardPageRouterOptions | AppRouterPageRoute,\n\t\topts?: WithAuthGuardAppRouterOptions,\n\t): PageRoute<Record<string, unknown>> | AppRouterPageRoute {\n\t\tif (typeof fnOrOpts === 'function') {\n\t\t\tconst appRouteHandler = appRouteHandlerFactory(base);\n\t\t\treturn appRouteHandler(fnOrOpts, opts);\n\t\t}\n\n\t\tconst pageRouteHandler = pageRouteHandlerFactory(base);\n\t\treturn pageRouteHandler(fnOrOpts);\n\t}\n\n\treturn {\n\t\tget options() {\n\t\t\treturn base.options;\n\t\t},\n\t\twithAuthGuard,\n\t\twithApiAuthRequired,\n\t\tgetSession: (req) => base.getSession(req),\n\t\tupdateSession: (
|
|
1
|
+
{"version":3,"file":"sdk.mjs","names":[],"sources":["../../src/server/sdk.ts"],"sourcesContent":["import type { NextApiHandler, NextApiRequest, NextApiResponse } from 'next';\nimport type { ParsedUrlQuery } from 'node:querystring';\nimport type {\n\tNextServerSDK,\n\tNextServerSDKInitConfig,\n\tWithAuthGuardAppRouterOptions,\n\tWithAuthGuardPageRouterOptions,\n\tAppRouterPageRoute,\n\tAppRouterPageRouteOpts,\n\tPageRoute,\n\tAppRouteHandlerFn,\n\tAppRouteHandlerFnContext,\n\tPagesRouterRequest,\n} from './types';\nimport { NextResponse, type NextRequest } from 'next/server';\nimport { createBaseServerSDK } from '@strivacity/sdk-core/server';\nimport { ConfigurationError } from '@strivacity/sdk-core/utils/errors';\nimport { createEncryptedCookieStorage } from './storages';\nimport { apiAppRouteHandlerFactory, apiPageRouteHandlerFactory } from './handlers/api';\nimport { appRouteHandlerFactory, pageRouteHandlerFactory } from './handlers/route';\n\n/**\n * Creates a Next.js server SDK instance with the provided configuration.\n *\n * @param {NextServerSDKInitConfig} initConfig - The initialization configuration for the SDK.\n * @returns {NextServerSDK} The initialized Next.js server SDK instance.\n */\nexport function createServerSDK(initConfig: NextServerSDKInitConfig): NextServerSDK {\n\tif (!initConfig.storage) {\n\t\tif (!initConfig.secret) {\n\t\t\tthrow new ConfigurationError('Secret is required for encrypted cookie storage');\n\t\t}\n\n\t\tinitConfig.cookieMaxAge ??= 30 * 24 * 60 * 60;\n\t\tinitConfig.storage = createEncryptedCookieStorage(initConfig.secret, { defaultCookieOptions: { maxAge: initConfig.cookieMaxAge } });\n\t}\n\n\tconst base = createBaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>(\n\t\t{\n\t\t\ttoRequest: (req) => req as Request,\n\t\t\tredirect: (url, status) => NextResponse.redirect(url, status),\n\t\t},\n\t\tinitConfig,\n\t);\n\n\tfunction withApiAuthRequired(apiRoute: AppRouteHandlerFn): AppRouteHandlerFn;\n\tfunction withApiAuthRequired(apiRoute: NextApiHandler): NextApiHandler;\n\tfunction withApiAuthRequired(apiRoute: AppRouteHandlerFn | NextApiHandler): AppRouteHandlerFn | NextApiHandler {\n\t\treturn (req: NextRequest | Request | NextApiRequest, resOrCtx?: AppRouteHandlerFnContext | NextApiResponse) => {\n\t\t\tif (req instanceof Request) {\n\t\t\t\tconst appRouteHandler = apiAppRouteHandlerFactory(base);\n\t\t\t\tconst wrappedAppRoute = appRouteHandler(apiRoute as AppRouteHandlerFn);\n\t\t\t\treturn wrappedAppRoute(req, (resOrCtx ?? {}) as AppRouteHandlerFnContext);\n\t\t\t}\n\n\t\t\tconst pageRouteHandler = apiPageRouteHandlerFactory(base);\n\t\t\tconst wrappedPageRoute = pageRouteHandler(apiRoute as NextApiHandler);\n\t\t\treturn wrappedPageRoute(req, resOrCtx as NextApiResponse);\n\t\t};\n\t}\n\n\tfunction withAuthGuard(): PageRoute<Record<string, unknown>, ParsedUrlQuery>;\n\tfunction withAuthGuard<P extends Record<string, unknown> = Record<string, unknown>, Q extends ParsedUrlQuery = ParsedUrlQuery>(\n\t\topts: WithAuthGuardPageRouterOptions<P, Q>,\n\t): PageRoute<P, Q>;\n\tfunction withAuthGuard<P extends AppRouterPageRouteOpts = AppRouterPageRouteOpts>(\n\t\tfn: AppRouterPageRoute<P>,\n\t\topts?: WithAuthGuardAppRouterOptions<P>,\n\t): AppRouterPageRoute<P>;\n\tfunction withAuthGuard(\n\t\tfnOrOpts?: WithAuthGuardPageRouterOptions | AppRouterPageRoute,\n\t\topts?: WithAuthGuardAppRouterOptions,\n\t): PageRoute<Record<string, unknown>> | AppRouterPageRoute {\n\t\tif (typeof fnOrOpts === 'function') {\n\t\t\tconst appRouteHandler = appRouteHandlerFactory(base);\n\t\t\treturn appRouteHandler(fnOrOpts, opts);\n\t\t}\n\n\t\tconst pageRouteHandler = pageRouteHandlerFactory(base);\n\t\treturn pageRouteHandler(fnOrOpts);\n\t}\n\n\treturn {\n\t\tget options() {\n\t\t\treturn base.options;\n\t\t},\n\t\twithAuthGuard,\n\t\twithApiAuthRequired,\n\t\t// NOTE: refreshes (with autoRefresh) only for App Router requests, whose route handlers can write the rotated cookie.\n\t\t// Server Components (no request) and Pages Router requests read the stored session: a refresh there could not be saved.\n\t\tgetSession: (req, params) => base.getSession(req, req instanceof Request ? params : { autoRefresh: false }),\n\t\tupdateSession: (session, req) => base.updateSession(session, req),\n\t\trefreshSession: (req) => base.refreshSession(req),\n\t\trevokeSession: (req) => base.revokeSession(req),\n\t\tgetEntrySession: (entryUrl) => base.getEntrySession(entryUrl),\n\t\tcompleteLogin: (params, req) => base.completeLogin(params, req),\n\t\tlogout: (postLogoutRedirectUri, req) => base.logout(postLogoutRedirectUri, req),\n\t\thandleLogin: (req) => base.handleLogin(req),\n\t\thandleRegister: (req) => base.handleRegister(req),\n\t\thandleCallback: (req) => base.handleCallback(req),\n\t\thandleRefresh: (req) => base.handleRefresh(req),\n\t\thandleRevoke: (req) => base.handleRevoke(req),\n\t\thandleEntry: (req) => base.handleEntry(req),\n\t\thandleLogout: (req) => base.handleLogout(req),\n\t\thandleBackChannelLogout: (req) => base.handleBackChannelLogout(req),\n\t\thandler: async (req) => (await base.handler(req)) ?? new NextResponse('Not Found', { status: 404 }),\n\t};\n}\n"],"mappings":"4aA2BA,SAAgB,EAAgB,EAAoD,CACnF,GAAI,CAAC,EAAW,QAAS,CACxB,GAAI,CAAC,EAAW,OACf,MAAM,IAAI,EAAmB,iDAAiD,EAG/E,EAAW,eAAiB,OAC5B,EAAW,QAAU,EAA6B,EAAW,OAAQ,CAAE,qBAAsB,CAAE,OAAQ,EAAW,YAAa,CAAE,CAAC,CACnI,CAEA,IAAM,EAAO,EACZ,CACC,UAAY,GAAQ,EACpB,UAAW,EAAK,IAAW,EAAa,SAAS,EAAK,CAAM,CAC7D,EACA,CACD,EAIA,SAAS,EAAoB,EAAkF,CAC9G,OAAQ,EAA6C,IAChD,aAAe,QACM,EAA0B,CAC1B,CAAA,CAAgB,CACjC,CAAA,CAAgB,EAAM,GAAY,CAAC,CAA8B,EAGhD,EAA2B,CAC3B,CAAA,CAAiB,CACnC,CAAA,CAAiB,EAAK,CAA2B,CAE1D,CAUA,SAAS,EACR,EACA,EAC0D,CAO1D,OANI,OAAO,GAAa,WACC,EAAuB,CACxC,CAAA,CAAgB,EAAU,CAAI,EAGb,EAAwB,CAC1C,CAAA,CAAiB,CAAQ,CACjC,CAEA,MAAO,CACN,IAAI,SAAU,CACb,OAAO,EAAK,OACb,EACA,gBACA,sBAGA,YAAa,EAAK,IAAW,EAAK,WAAW,EAAK,aAAe,QAAU,EAAS,CAAE,YAAa,EAAM,CAAC,EAC1G,eAAgB,EAAS,IAAQ,EAAK,cAAc,EAAS,CAAG,EAChE,eAAiB,GAAQ,EAAK,eAAe,CAAG,EAChD,cAAgB,GAAQ,EAAK,cAAc,CAAG,EAC9C,gBAAkB,GAAa,EAAK,gBAAgB,CAAQ,EAC5D,eAAgB,EAAQ,IAAQ,EAAK,cAAc,EAAQ,CAAG,EAC9D,QAAS,EAAuB,IAAQ,EAAK,OAAO,EAAuB,CAAG,EAC9E,YAAc,GAAQ,EAAK,YAAY,CAAG,EAC1C,eAAiB,GAAQ,EAAK,eAAe,CAAG,EAChD,eAAiB,GAAQ,EAAK,eAAe,CAAG,EAChD,cAAgB,GAAQ,EAAK,cAAc,CAAG,EAC9C,aAAe,GAAQ,EAAK,aAAa,CAAG,EAC5C,YAAc,GAAQ,EAAK,YAAY,CAAG,EAC1C,aAAe,GAAQ,EAAK,aAAa,CAAG,EAC5C,wBAA0B,GAAQ,EAAK,wBAAwB,CAAG,EAClE,QAAS,KAAO,IAAS,MAAM,EAAK,QAAQ,CAAG,GAAM,IAAI,EAAa,YAAa,CAAE,OAAQ,GAAI,CAAC,CACnG,CACD"}
|
package/dist/server/storages.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("next/server"),t=require("
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("next/server"),t=require("next/headers"),n=require("@strivacity/sdk-core/utils/common"),r=require("@strivacity/sdk-core/storages/server");function i(t,n){if(t instanceof e.NextRequest)return t.cookies.get(n)?.value??null;if(t instanceof Request){let e=(t.headers.get(`cookie`)??``).split(`;`).map(e=>e.trim()).find(e=>e.startsWith(`${n}=`));return e?decodeURIComponent(e.slice(n.length+1)):null}let r=(t.headers?.cookie??``).split(`;`).map(e=>e.trim()).find(e=>e.startsWith(`${n}=`));return r?decodeURIComponent(r.slice(n.length+1)):null}function a(n,a){return(0,r.createSessionIdCookieStorage)({toRequest:e=>e,redirect:(t,n)=>e.NextResponse.redirect(t,n),getSessionId:async(e,n)=>n?i(n,e)??null:(await(0,t.cookies)()).get(e)?.value},n,a)}function o(r,a){let o=(e,t)=>{let n=e.getHeader(`set-cookie`),r=Array.isArray(n)?n:n?[String(n)]:[];e.setHeader(`set-cookie`,[...r,t])};return{async get(n){return(r?i(r,n):null)||(a instanceof e.NextResponse?a.cookies.get(n)?.value:a||r?null:(await(0,t.cookies)()).get(n)?.value)},async set(r,i,s){a instanceof e.NextResponse?a.cookies.set(r,i,s):a?o(a,(0,n.buildCookieString)(r,i,s)):(await(0,t.cookies)()).set(r,i,s)},async delete(r,i){a instanceof e.NextResponse?a.cookies.set(r,``,{...i,maxAge:0}):a?o(a,(0,n.buildCookieString)(r,``,{...i,maxAge:0})):(await(0,t.cookies)()).delete(r)}}}function s(e,t){let n={httpOnly:!0,secure:!0,path:`/`,sameSite:`lax`,...t?.defaultCookieOptions};return{get:(t,n)=>(0,r.readEncryptedCookie)(o(n),t,e),set:(t,i,a,s,c)=>(0,r.writeEncryptedCookie)(o(a,s),t,i,e,{...n,...c}),delete:(e,t,i,a)=>(0,r.deleteEncryptedCookie)(o(t,i),e,{...n,...a})}}exports.createEncryptedCookieStorage=s,exports.createSessionIdCookieStorage=a;var c=require("@strivacity/sdk-react/storages");Object.keys(c).forEach(function(e){e!=="default"&&!Object.prototype.hasOwnProperty.call(exports,e)&&Object.defineProperty(exports,e,{enumerable:!0,get:function(){return c[e]}})});
|
|
2
2
|
//# sourceMappingURL=storages.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storages.cjs","names":[],"sources":["../../src/server/storages.ts"],"sourcesContent":["import type { NextServerStorage, PagesRouterRequest, SessionIdCookieStorageOptions, EncryptedCookieStorageOptions } from './types';\nimport { cookies } from 'next/headers';\nimport { NextRequest, NextResponse } from 'next/server';\nimport { buildCookieString } from '@strivacity/sdk-core/utils/common';\nimport { encryptString, decryptString } from '@strivacity/sdk-core/utils/crypto';\nimport { COOKIE_CONTEXT, COOKIE_CHUNK_SIZE } from '@strivacity/sdk-core/server';\nimport { createSessionIdCookieStorage as createSessionIdCookieStorageBase } from '@strivacity/sdk-core/storages/server';\n\nexport * from '@strivacity/sdk-react/storages';\n\n/**\n * Reads cookie value(s) for a given key directly from a NextRequest or PagesRouterRequest, without calling `cookies()` from next/headers.\n * Used for Pages Router / middleware support.\n *\n * @param req - The NextRequest or PagesRouterRequest object from which to read the cookie.\n * @param key - The name of the cookie to read.\n * @returns The cookie value as a string, or null if the cookie is not found.\n */\nfunction getCookieFromRequest(req: NextRequest | Request | PagesRouterRequest, key: string): string | null {\n\tif (req instanceof NextRequest) {\n\t\treturn req.cookies.get(key)?.value ?? null;\n\t}\n\n\tif (req instanceof Request) {\n\t\tconst cookieHeader = req.headers.get('cookie') ?? '';\n\t\tconst match = cookieHeader\n\t\t\t.split(';')\n\t\t\t.map((c) => c.trim())\n\t\t\t.find((c) => c.startsWith(`${key}=`));\n\n\t\treturn match ? decodeURIComponent(match.slice(key.length + 1)) : null;\n\t}\n\n\tconst cookieHeader = req.headers?.cookie ?? '';\n\tconst match = cookieHeader\n\t\t.split(';')\n\t\t.map((c: string) => c.trim())\n\t\t.find((c: string) => c.startsWith(`${key}=`));\n\n\treturn match ? decodeURIComponent(match.slice(key.length + 1)) : null;\n}\n\n/**\n * Creates a session storage that puts a random unique id value cookie on the client and keeping the actual session data in the given `storage`.\n *\n * @param {NextServerStorage} storage - The storage used to persist session data, keyed by a randomly generated session id.\n * @param {SessionIdCookieStorageOptions} [options] - Options for configuring the session-id cookie storage.\n * @returns {NextServerStorage} An object implementing the ServerStorage interface for managing sessions indexed by a session-id cookie.\n */\nexport function createSessionIdCookieStorage(storage: NextServerStorage, options?: SessionIdCookieStorageOptions): NextServerStorage {\n\treturn createSessionIdCookieStorageBase<NextRequest | Request | PagesRouterRequest>(\n\t\t{\n\t\t\ttoRequest: (req) => req as Request,\n\t\t\tredirect: (url, status) => NextResponse.redirect(url, status),\n\t\t\tgetSessionId: async (key, req) => {\n\t\t\t\tif (req) {\n\t\t\t\t\treturn getCookieFromRequest(req, key) ?? null;\n\t\t\t\t}\n\n\t\t\t\tconst store = await cookies();\n\n\t\t\t\treturn store.get(key)?.value;\n\t\t\t},\n\t\t},\n\t\tstorage,\n\t\toptions,\n\t);\n}\n\n/**\n * Creates an encrypted cookie session storage.\n * Only callable in server-side contexts (middleware, API routes, or server components).\n *\n * @param secret - The secret key used for encryption and decryption.\n * @param {EncryptedCookieStorageOptions} [options] - Options for configuring the encrypted cookie storage.\n * @param {Partial<ServerCookieOptions>} [options.defaultCookieOptions] - Default cookie attributes for the encrypted cookie.\n * @returns An object implementing the ServerStorage interface for managing encrypted cookies.\n */\nexport function createEncryptedCookieStorage(secret: string, options?: EncryptedCookieStorageOptions): NextServerStorage {\n\tconst defaultCookieOptions = {\n\t\thttpOnly: true,\n\t\tsecure: true,\n\t\tpath: '/',\n\t\tsameSite: 'lax' as const,\n\t\t...options?.defaultCookieOptions,\n\t};\n\n\tconst storage: NextServerStorage = {\n\t\tasync get(key, req) {\n\t\t\tif (req) {\n\t\t\t\tconst cookie = getCookieFromRequest(req, key);\n\n\t\t\t\tif (cookie) {\n\t\t\t\t\treturn await decryptString(cookie, secret, COOKIE_CONTEXT);\n\t\t\t\t}\n\n\t\t\t\tconst cookieChunks: Array<string> = [];\n\n\t\t\t\tfor (let i = 0; ; i++) {\n\t\t\t\t\tconst chunk = getCookieFromRequest(req, `${key}.${i}`);\n\n\t\t\t\t\tif (!chunk) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcookieChunks.push(chunk);\n\t\t\t\t}\n\n\t\t\t\tif (cookieChunks.length === 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\treturn await decryptString(cookieChunks.join(''), secret, COOKIE_CONTEXT);\n\t\t\t} else {\n\t\t\t\tconst store = await cookies();\n\t\t\t\tconst cookie = store.get(key)?.value;\n\n\t\t\t\tif (cookie) {\n\t\t\t\t\treturn await decryptString(cookie, secret, COOKIE_CONTEXT);\n\t\t\t\t}\n\n\t\t\t\tconst cookieChunks: Array<string> = [];\n\n\t\t\t\tfor (let i = 0; ; i++) {\n\t\t\t\t\tconst chunk = store.get(`${key}.${i}`)?.value;\n\n\t\t\t\t\tif (!chunk) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcookieChunks.push(chunk);\n\t\t\t\t}\n\n\t\t\t\tif (cookieChunks.length === 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\treturn await decryptString(cookieChunks.join(''), secret, COOKIE_CONTEXT);\n\t\t\t}\n\t\t},\n\t\tasync set(key, value, req, res, cookieOptions) {\n\t\t\tcookieOptions = { ...defaultCookieOptions, ...cookieOptions };\n\n\t\t\t// NOTE: Delete existing cookie(s) first to avoid leaving old chunks behind\n\t\t\tawait storage.delete(key, req, res);\n\n\t\t\tconst encrypted = await encryptString(value, secret, COOKIE_CONTEXT);\n\n\t\t\tif (res instanceof NextResponse) {\n\t\t\t\tif (encrypted.length <= COOKIE_CHUNK_SIZE) {\n\t\t\t\t\tres.cookies.set(key, encrypted, cookieOptions);\n\t\t\t\t} else {\n\t\t\t\t\tfor (let i = 0; i * COOKIE_CHUNK_SIZE < encrypted.length; i++) {\n\t\t\t\t\t\tres.cookies.set(`${key}.${i}`, encrypted.slice(i * COOKIE_CHUNK_SIZE, (i + 1) * COOKIE_CHUNK_SIZE), cookieOptions);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (res) {\n\t\t\t\tconst setCookies: Array<string> = [];\n\n\t\t\t\tif (encrypted.length <= COOKIE_CHUNK_SIZE) {\n\t\t\t\t\tsetCookies.push(buildCookieString(key, encrypted, cookieOptions));\n\t\t\t\t} else {\n\t\t\t\t\tfor (let i = 0; i * COOKIE_CHUNK_SIZE < encrypted.length; i++) {\n\t\t\t\t\t\tsetCookies.push(buildCookieString(`${key}.${i}`, encrypted.slice(i * COOKIE_CHUNK_SIZE, (i + 1) * COOKIE_CHUNK_SIZE), cookieOptions));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst existing = res.getHeader('set-cookie');\n\t\t\t\tconst existingArr = Array.isArray(existing) ? existing : existing ? [String(existing)] : [];\n\n\t\t\t\tres.setHeader('set-cookie', [...existingArr, ...setCookies]);\n\t\t\t} else {\n\t\t\t\tconst store = await cookies();\n\n\t\t\t\tif (encrypted.length <= COOKIE_CHUNK_SIZE) {\n\t\t\t\t\tstore.set(key, encrypted, cookieOptions);\n\t\t\t\t} else {\n\t\t\t\t\tfor (let i = 0; i * COOKIE_CHUNK_SIZE < encrypted.length; i++) {\n\t\t\t\t\t\tstore.set(`${key}.${i}`, encrypted.slice(i * COOKIE_CHUNK_SIZE, (i + 1) * COOKIE_CHUNK_SIZE), cookieOptions);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tasync delete(key, req, res, cookieOptions) {\n\t\t\tcookieOptions = { ...defaultCookieOptions, ...cookieOptions, maxAge: 0 };\n\n\t\t\tif (res instanceof NextResponse) {\n\t\t\t\tres.cookies.delete(key);\n\n\t\t\t\tfor (let i = 0; res.cookies.get(`${key}.${i}`); i++) {\n\t\t\t\t\tres.cookies.delete(`${key}.${i}`);\n\t\t\t\t}\n\t\t\t} else if (res) {\n\t\t\t\tconst setCookies: Array<string> = [];\n\n\t\t\t\tsetCookies.push(buildCookieString(key, '', cookieOptions));\n\n\t\t\t\tif (req) {\n\t\t\t\t\tfor (let i = 0; getCookieFromRequest(req, `${key}.${i}`) !== null; i++) {\n\t\t\t\t\t\tsetCookies.push(buildCookieString(`${key}.${i}`, '', cookieOptions));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst existing = res.getHeader('set-cookie');\n\t\t\t\tconst existingArr = Array.isArray(existing) ? existing : existing ? [String(existing)] : [];\n\n\t\t\t\tres.setHeader('set-cookie', [...existingArr, ...setCookies]);\n\t\t\t} else {\n\t\t\t\tconst store = await cookies();\n\n\t\t\t\tstore.delete(key);\n\n\t\t\t\tfor (let i = 0; store.get(`${key}.${i}`); i++) {\n\t\t\t\t\tstore.delete(`${key}.${i}`);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n\n\treturn storage;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"storages.cjs","names":[],"sources":["../../src/server/storages.ts"],"sourcesContent":["import type {\n\tCookieJar,\n\tCookieOptions,\n\tNextServerStorage,\n\tPagesRouterRequest,\n\tPagesRouterResponse,\n\tSessionIdCookieStorageOptions,\n\tEncryptedCookieStorageOptions,\n} from './types';\nimport { cookies } from 'next/headers';\nimport { NextRequest, NextResponse } from 'next/server';\nimport { buildCookieString } from '@strivacity/sdk-core/utils/common';\nimport {\n\tcreateSessionIdCookieStorage as createSessionIdCookieStorageBase,\n\treadEncryptedCookie,\n\twriteEncryptedCookie,\n\tdeleteEncryptedCookie,\n} from '@strivacity/sdk-core/storages/server';\n\nexport * from '@strivacity/sdk-react/storages';\n\n/**\n * Reads cookie value(s) for a given key directly from a NextRequest or PagesRouterRequest, without calling `cookies()` from next/headers.\n * Used for Pages Router / middleware support.\n *\n * @param req - The NextRequest or PagesRouterRequest object from which to read the cookie.\n * @param key - The name of the cookie to read.\n * @returns The cookie value as a string, or null if the cookie is not found.\n */\nfunction getCookieFromRequest(req: NextRequest | Request | PagesRouterRequest, key: string): string | null {\n\tif (req instanceof NextRequest) {\n\t\treturn req.cookies.get(key)?.value ?? null;\n\t}\n\n\tif (req instanceof Request) {\n\t\tconst cookieHeader = req.headers.get('cookie') ?? '';\n\t\tconst match = cookieHeader\n\t\t\t.split(';')\n\t\t\t.map((c) => c.trim())\n\t\t\t.find((c) => c.startsWith(`${key}=`));\n\n\t\treturn match ? decodeURIComponent(match.slice(key.length + 1)) : null;\n\t}\n\n\tconst cookieHeader = req.headers?.cookie ?? '';\n\tconst match = cookieHeader\n\t\t.split(';')\n\t\t.map((c: string) => c.trim())\n\t\t.find((c: string) => c.startsWith(`${key}=`));\n\n\treturn match ? decodeURIComponent(match.slice(key.length + 1)) : null;\n}\n\n/**\n * Creates a session storage that puts a random unique id value cookie on the client and keeping the actual session data in the given `storage`.\n *\n * @param {NextServerStorage} storage - The storage used to persist session data, keyed by a randomly generated session id.\n * @param {SessionIdCookieStorageOptions} [options] - Options for configuring the session-id cookie storage.\n * @returns {NextServerStorage} An object implementing the ServerStorage interface for managing sessions indexed by a session-id cookie.\n */\nexport function createSessionIdCookieStorage(storage: NextServerStorage, options?: SessionIdCookieStorageOptions): NextServerStorage {\n\treturn createSessionIdCookieStorageBase<NextRequest | Request | PagesRouterRequest>(\n\t\t{\n\t\t\ttoRequest: (req) => req as Request,\n\t\t\tredirect: (url, status) => NextResponse.redirect(url, status),\n\t\t\tgetSessionId: async (key, req) => {\n\t\t\t\tif (req) {\n\t\t\t\t\treturn getCookieFromRequest(req, key) ?? null;\n\t\t\t\t}\n\n\t\t\t\tconst store = await cookies();\n\n\t\t\t\treturn store.get(key)?.value;\n\t\t\t},\n\t\t},\n\t\tstorage,\n\t\toptions,\n\t);\n}\n\n/**\n * Builds the cookie access for one storage call. Writes go to the given response (App Router `NextResponse` or Pages Router\n * `res`), or to `cookies()` from next/headers when there is none. Reads come from the request, then from the response.\n *\n * @param req - The incoming request, if any.\n * @param res - The outgoing response, if any.\n * @returns The cookie jar.\n */\nfunction createJar(req?: NextRequest | Request | PagesRouterRequest, res?: NextResponse | PagesRouterResponse): CookieJar<CookieOptions> {\n\tconst appendSetCookie = (response: PagesRouterResponse, cookie: string) => {\n\t\tconst existing = response.getHeader('set-cookie');\n\t\tconst existingArr = Array.isArray(existing) ? existing : existing ? [String(existing)] : [];\n\n\t\tresponse.setHeader('set-cookie', [...existingArr, cookie]);\n\t};\n\n\treturn {\n\t\tasync get(name) {\n\t\t\tconst fromRequest = req ? getCookieFromRequest(req, name) : null;\n\n\t\t\tif (fromRequest) {\n\t\t\t\treturn fromRequest;\n\t\t\t}\n\t\t\tif (res instanceof NextResponse) {\n\t\t\t\treturn res.cookies.get(name)?.value;\n\t\t\t}\n\t\t\tif (res || req) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn (await cookies()).get(name)?.value;\n\t\t},\n\t\tasync set(name, value, cookieOptions) {\n\t\t\tif (res instanceof NextResponse) {\n\t\t\t\tres.cookies.set(name, value, cookieOptions);\n\t\t\t} else if (res) {\n\t\t\t\tappendSetCookie(res, buildCookieString(name, value, cookieOptions));\n\t\t\t} else {\n\t\t\t\t(await cookies()).set(name, value, cookieOptions);\n\t\t\t}\n\t\t},\n\t\tasync delete(name, cookieOptions) {\n\t\t\tif (res instanceof NextResponse) {\n\t\t\t\tres.cookies.set(name, '', { ...cookieOptions, maxAge: 0 });\n\t\t\t} else if (res) {\n\t\t\t\tappendSetCookie(res, buildCookieString(name, '', { ...cookieOptions, maxAge: 0 }));\n\t\t\t} else {\n\t\t\t\t(await cookies()).delete(name);\n\t\t\t}\n\t\t},\n\t};\n}\n\n/**\n * Creates an encrypted cookie session storage.\n * Only callable in server-side contexts (middleware, API routes, or server components).\n *\n * @param secret - The secret key used for encryption and decryption.\n * @param {EncryptedCookieStorageOptions} [options] - Options for configuring the encrypted cookie storage.\n * @param {Partial<ServerCookieOptions>} [options.defaultCookieOptions] - Default cookie attributes for the encrypted cookie.\n * @returns An object implementing the ServerStorage interface for managing encrypted cookies.\n */\nexport function createEncryptedCookieStorage(secret: string, options?: EncryptedCookieStorageOptions): NextServerStorage {\n\tconst defaultCookieOptions = {\n\t\thttpOnly: true,\n\t\tsecure: true,\n\t\tpath: '/',\n\t\tsameSite: 'lax' as const,\n\t\t...options?.defaultCookieOptions,\n\t};\n\n\treturn {\n\t\tget: (key, req) => readEncryptedCookie(createJar(req), key, secret),\n\t\tset: (key, value, req, res, cookieOptions) => writeEncryptedCookie(createJar(req, res), key, value, secret, { ...defaultCookieOptions, ...cookieOptions }),\n\t\tdelete: (key, req, res, cookieOptions) => deleteEncryptedCookie(createJar(req, res), key, { ...defaultCookieOptions, ...cookieOptions }),\n\t};\n}\n"],"mappings":"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"}
|
package/dist/server/storages.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{NextRequest as e,NextResponse as t}from"next/server";import{
|
|
1
|
+
import{NextRequest as e,NextResponse as t}from"next/server";import{cookies as n}from"next/headers";import{buildCookieString as r}from"@strivacity/sdk-core/utils/common";import{createSessionIdCookieStorage as i,deleteEncryptedCookie as a,readEncryptedCookie as o,writeEncryptedCookie as s}from"@strivacity/sdk-core/storages/server";export*from"@strivacity/sdk-react/storages";function c(t,n){if(t instanceof e)return t.cookies.get(n)?.value??null;if(t instanceof Request){let e=(t.headers.get(`cookie`)??``).split(`;`).map(e=>e.trim()).find(e=>e.startsWith(`${n}=`));return e?decodeURIComponent(e.slice(n.length+1)):null}let r=(t.headers?.cookie??``).split(`;`).map(e=>e.trim()).find(e=>e.startsWith(`${n}=`));return r?decodeURIComponent(r.slice(n.length+1)):null}function l(e,r){return i({toRequest:e=>e,redirect:(e,n)=>t.redirect(e,n),getSessionId:async(e,t)=>t?c(t,e)??null:(await n()).get(e)?.value},e,r)}function u(e,i){let a=(e,t)=>{let n=e.getHeader(`set-cookie`),r=Array.isArray(n)?n:n?[String(n)]:[];e.setHeader(`set-cookie`,[...r,t])};return{async get(r){return(e?c(e,r):null)||(i instanceof t?i.cookies.get(r)?.value:i||e?null:(await n()).get(r)?.value)},async set(e,o,s){i instanceof t?i.cookies.set(e,o,s):i?a(i,r(e,o,s)):(await n()).set(e,o,s)},async delete(e,o){i instanceof t?i.cookies.set(e,``,{...o,maxAge:0}):i?a(i,r(e,``,{...o,maxAge:0})):(await n()).delete(e)}}}function d(e,t){let n={httpOnly:!0,secure:!0,path:`/`,sameSite:`lax`,...t?.defaultCookieOptions};return{get:(t,n)=>o(u(n),t,e),set:(t,r,i,a,o)=>s(u(i,a),t,r,e,{...n,...o}),delete:(e,t,r,i)=>a(u(t,r),e,{...n,...i})}}export{d as createEncryptedCookieStorage,l as createSessionIdCookieStorage};
|
|
2
2
|
//# sourceMappingURL=storages.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storages.mjs","names":[],"sources":["../../src/server/storages.ts"],"sourcesContent":["import type { NextServerStorage, PagesRouterRequest, SessionIdCookieStorageOptions, EncryptedCookieStorageOptions } from './types';\nimport { cookies } from 'next/headers';\nimport { NextRequest, NextResponse } from 'next/server';\nimport { buildCookieString } from '@strivacity/sdk-core/utils/common';\nimport { encryptString, decryptString } from '@strivacity/sdk-core/utils/crypto';\nimport { COOKIE_CONTEXT, COOKIE_CHUNK_SIZE } from '@strivacity/sdk-core/server';\nimport { createSessionIdCookieStorage as createSessionIdCookieStorageBase } from '@strivacity/sdk-core/storages/server';\n\nexport * from '@strivacity/sdk-react/storages';\n\n/**\n * Reads cookie value(s) for a given key directly from a NextRequest or PagesRouterRequest, without calling `cookies()` from next/headers.\n * Used for Pages Router / middleware support.\n *\n * @param req - The NextRequest or PagesRouterRequest object from which to read the cookie.\n * @param key - The name of the cookie to read.\n * @returns The cookie value as a string, or null if the cookie is not found.\n */\nfunction getCookieFromRequest(req: NextRequest | Request | PagesRouterRequest, key: string): string | null {\n\tif (req instanceof NextRequest) {\n\t\treturn req.cookies.get(key)?.value ?? null;\n\t}\n\n\tif (req instanceof Request) {\n\t\tconst cookieHeader = req.headers.get('cookie') ?? '';\n\t\tconst match = cookieHeader\n\t\t\t.split(';')\n\t\t\t.map((c) => c.trim())\n\t\t\t.find((c) => c.startsWith(`${key}=`));\n\n\t\treturn match ? decodeURIComponent(match.slice(key.length + 1)) : null;\n\t}\n\n\tconst cookieHeader = req.headers?.cookie ?? '';\n\tconst match = cookieHeader\n\t\t.split(';')\n\t\t.map((c: string) => c.trim())\n\t\t.find((c: string) => c.startsWith(`${key}=`));\n\n\treturn match ? decodeURIComponent(match.slice(key.length + 1)) : null;\n}\n\n/**\n * Creates a session storage that puts a random unique id value cookie on the client and keeping the actual session data in the given `storage`.\n *\n * @param {NextServerStorage} storage - The storage used to persist session data, keyed by a randomly generated session id.\n * @param {SessionIdCookieStorageOptions} [options] - Options for configuring the session-id cookie storage.\n * @returns {NextServerStorage} An object implementing the ServerStorage interface for managing sessions indexed by a session-id cookie.\n */\nexport function createSessionIdCookieStorage(storage: NextServerStorage, options?: SessionIdCookieStorageOptions): NextServerStorage {\n\treturn createSessionIdCookieStorageBase<NextRequest | Request | PagesRouterRequest>(\n\t\t{\n\t\t\ttoRequest: (req) => req as Request,\n\t\t\tredirect: (url, status) => NextResponse.redirect(url, status),\n\t\t\tgetSessionId: async (key, req) => {\n\t\t\t\tif (req) {\n\t\t\t\t\treturn getCookieFromRequest(req, key) ?? null;\n\t\t\t\t}\n\n\t\t\t\tconst store = await cookies();\n\n\t\t\t\treturn store.get(key)?.value;\n\t\t\t},\n\t\t},\n\t\tstorage,\n\t\toptions,\n\t);\n}\n\n/**\n * Creates an encrypted cookie session storage.\n * Only callable in server-side contexts (middleware, API routes, or server components).\n *\n * @param secret - The secret key used for encryption and decryption.\n * @param {EncryptedCookieStorageOptions} [options] - Options for configuring the encrypted cookie storage.\n * @param {Partial<ServerCookieOptions>} [options.defaultCookieOptions] - Default cookie attributes for the encrypted cookie.\n * @returns An object implementing the ServerStorage interface for managing encrypted cookies.\n */\nexport function createEncryptedCookieStorage(secret: string, options?: EncryptedCookieStorageOptions): NextServerStorage {\n\tconst defaultCookieOptions = {\n\t\thttpOnly: true,\n\t\tsecure: true,\n\t\tpath: '/',\n\t\tsameSite: 'lax' as const,\n\t\t...options?.defaultCookieOptions,\n\t};\n\n\tconst storage: NextServerStorage = {\n\t\tasync get(key, req) {\n\t\t\tif (req) {\n\t\t\t\tconst cookie = getCookieFromRequest(req, key);\n\n\t\t\t\tif (cookie) {\n\t\t\t\t\treturn await decryptString(cookie, secret, COOKIE_CONTEXT);\n\t\t\t\t}\n\n\t\t\t\tconst cookieChunks: Array<string> = [];\n\n\t\t\t\tfor (let i = 0; ; i++) {\n\t\t\t\t\tconst chunk = getCookieFromRequest(req, `${key}.${i}`);\n\n\t\t\t\t\tif (!chunk) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcookieChunks.push(chunk);\n\t\t\t\t}\n\n\t\t\t\tif (cookieChunks.length === 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\treturn await decryptString(cookieChunks.join(''), secret, COOKIE_CONTEXT);\n\t\t\t} else {\n\t\t\t\tconst store = await cookies();\n\t\t\t\tconst cookie = store.get(key)?.value;\n\n\t\t\t\tif (cookie) {\n\t\t\t\t\treturn await decryptString(cookie, secret, COOKIE_CONTEXT);\n\t\t\t\t}\n\n\t\t\t\tconst cookieChunks: Array<string> = [];\n\n\t\t\t\tfor (let i = 0; ; i++) {\n\t\t\t\t\tconst chunk = store.get(`${key}.${i}`)?.value;\n\n\t\t\t\t\tif (!chunk) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcookieChunks.push(chunk);\n\t\t\t\t}\n\n\t\t\t\tif (cookieChunks.length === 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\treturn await decryptString(cookieChunks.join(''), secret, COOKIE_CONTEXT);\n\t\t\t}\n\t\t},\n\t\tasync set(key, value, req, res, cookieOptions) {\n\t\t\tcookieOptions = { ...defaultCookieOptions, ...cookieOptions };\n\n\t\t\t// NOTE: Delete existing cookie(s) first to avoid leaving old chunks behind\n\t\t\tawait storage.delete(key, req, res);\n\n\t\t\tconst encrypted = await encryptString(value, secret, COOKIE_CONTEXT);\n\n\t\t\tif (res instanceof NextResponse) {\n\t\t\t\tif (encrypted.length <= COOKIE_CHUNK_SIZE) {\n\t\t\t\t\tres.cookies.set(key, encrypted, cookieOptions);\n\t\t\t\t} else {\n\t\t\t\t\tfor (let i = 0; i * COOKIE_CHUNK_SIZE < encrypted.length; i++) {\n\t\t\t\t\t\tres.cookies.set(`${key}.${i}`, encrypted.slice(i * COOKIE_CHUNK_SIZE, (i + 1) * COOKIE_CHUNK_SIZE), cookieOptions);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (res) {\n\t\t\t\tconst setCookies: Array<string> = [];\n\n\t\t\t\tif (encrypted.length <= COOKIE_CHUNK_SIZE) {\n\t\t\t\t\tsetCookies.push(buildCookieString(key, encrypted, cookieOptions));\n\t\t\t\t} else {\n\t\t\t\t\tfor (let i = 0; i * COOKIE_CHUNK_SIZE < encrypted.length; i++) {\n\t\t\t\t\t\tsetCookies.push(buildCookieString(`${key}.${i}`, encrypted.slice(i * COOKIE_CHUNK_SIZE, (i + 1) * COOKIE_CHUNK_SIZE), cookieOptions));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst existing = res.getHeader('set-cookie');\n\t\t\t\tconst existingArr = Array.isArray(existing) ? existing : existing ? [String(existing)] : [];\n\n\t\t\t\tres.setHeader('set-cookie', [...existingArr, ...setCookies]);\n\t\t\t} else {\n\t\t\t\tconst store = await cookies();\n\n\t\t\t\tif (encrypted.length <= COOKIE_CHUNK_SIZE) {\n\t\t\t\t\tstore.set(key, encrypted, cookieOptions);\n\t\t\t\t} else {\n\t\t\t\t\tfor (let i = 0; i * COOKIE_CHUNK_SIZE < encrypted.length; i++) {\n\t\t\t\t\t\tstore.set(`${key}.${i}`, encrypted.slice(i * COOKIE_CHUNK_SIZE, (i + 1) * COOKIE_CHUNK_SIZE), cookieOptions);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tasync delete(key, req, res, cookieOptions) {\n\t\t\tcookieOptions = { ...defaultCookieOptions, ...cookieOptions, maxAge: 0 };\n\n\t\t\tif (res instanceof NextResponse) {\n\t\t\t\tres.cookies.delete(key);\n\n\t\t\t\tfor (let i = 0; res.cookies.get(`${key}.${i}`); i++) {\n\t\t\t\t\tres.cookies.delete(`${key}.${i}`);\n\t\t\t\t}\n\t\t\t} else if (res) {\n\t\t\t\tconst setCookies: Array<string> = [];\n\n\t\t\t\tsetCookies.push(buildCookieString(key, '', cookieOptions));\n\n\t\t\t\tif (req) {\n\t\t\t\t\tfor (let i = 0; getCookieFromRequest(req, `${key}.${i}`) !== null; i++) {\n\t\t\t\t\t\tsetCookies.push(buildCookieString(`${key}.${i}`, '', cookieOptions));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst existing = res.getHeader('set-cookie');\n\t\t\t\tconst existingArr = Array.isArray(existing) ? existing : existing ? [String(existing)] : [];\n\n\t\t\t\tres.setHeader('set-cookie', [...existingArr, ...setCookies]);\n\t\t\t} else {\n\t\t\t\tconst store = await cookies();\n\n\t\t\t\tstore.delete(key);\n\n\t\t\t\tfor (let i = 0; store.get(`${key}.${i}`); i++) {\n\t\t\t\t\tstore.delete(`${key}.${i}`);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n\n\treturn storage;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"storages.mjs","names":[],"sources":["../../src/server/storages.ts"],"sourcesContent":["import type {\n\tCookieJar,\n\tCookieOptions,\n\tNextServerStorage,\n\tPagesRouterRequest,\n\tPagesRouterResponse,\n\tSessionIdCookieStorageOptions,\n\tEncryptedCookieStorageOptions,\n} from './types';\nimport { cookies } from 'next/headers';\nimport { NextRequest, NextResponse } from 'next/server';\nimport { buildCookieString } from '@strivacity/sdk-core/utils/common';\nimport {\n\tcreateSessionIdCookieStorage as createSessionIdCookieStorageBase,\n\treadEncryptedCookie,\n\twriteEncryptedCookie,\n\tdeleteEncryptedCookie,\n} from '@strivacity/sdk-core/storages/server';\n\nexport * from '@strivacity/sdk-react/storages';\n\n/**\n * Reads cookie value(s) for a given key directly from a NextRequest or PagesRouterRequest, without calling `cookies()` from next/headers.\n * Used for Pages Router / middleware support.\n *\n * @param req - The NextRequest or PagesRouterRequest object from which to read the cookie.\n * @param key - The name of the cookie to read.\n * @returns The cookie value as a string, or null if the cookie is not found.\n */\nfunction getCookieFromRequest(req: NextRequest | Request | PagesRouterRequest, key: string): string | null {\n\tif (req instanceof NextRequest) {\n\t\treturn req.cookies.get(key)?.value ?? null;\n\t}\n\n\tif (req instanceof Request) {\n\t\tconst cookieHeader = req.headers.get('cookie') ?? '';\n\t\tconst match = cookieHeader\n\t\t\t.split(';')\n\t\t\t.map((c) => c.trim())\n\t\t\t.find((c) => c.startsWith(`${key}=`));\n\n\t\treturn match ? decodeURIComponent(match.slice(key.length + 1)) : null;\n\t}\n\n\tconst cookieHeader = req.headers?.cookie ?? '';\n\tconst match = cookieHeader\n\t\t.split(';')\n\t\t.map((c: string) => c.trim())\n\t\t.find((c: string) => c.startsWith(`${key}=`));\n\n\treturn match ? decodeURIComponent(match.slice(key.length + 1)) : null;\n}\n\n/**\n * Creates a session storage that puts a random unique id value cookie on the client and keeping the actual session data in the given `storage`.\n *\n * @param {NextServerStorage} storage - The storage used to persist session data, keyed by a randomly generated session id.\n * @param {SessionIdCookieStorageOptions} [options] - Options for configuring the session-id cookie storage.\n * @returns {NextServerStorage} An object implementing the ServerStorage interface for managing sessions indexed by a session-id cookie.\n */\nexport function createSessionIdCookieStorage(storage: NextServerStorage, options?: SessionIdCookieStorageOptions): NextServerStorage {\n\treturn createSessionIdCookieStorageBase<NextRequest | Request | PagesRouterRequest>(\n\t\t{\n\t\t\ttoRequest: (req) => req as Request,\n\t\t\tredirect: (url, status) => NextResponse.redirect(url, status),\n\t\t\tgetSessionId: async (key, req) => {\n\t\t\t\tif (req) {\n\t\t\t\t\treturn getCookieFromRequest(req, key) ?? null;\n\t\t\t\t}\n\n\t\t\t\tconst store = await cookies();\n\n\t\t\t\treturn store.get(key)?.value;\n\t\t\t},\n\t\t},\n\t\tstorage,\n\t\toptions,\n\t);\n}\n\n/**\n * Builds the cookie access for one storage call. Writes go to the given response (App Router `NextResponse` or Pages Router\n * `res`), or to `cookies()` from next/headers when there is none. Reads come from the request, then from the response.\n *\n * @param req - The incoming request, if any.\n * @param res - The outgoing response, if any.\n * @returns The cookie jar.\n */\nfunction createJar(req?: NextRequest | Request | PagesRouterRequest, res?: NextResponse | PagesRouterResponse): CookieJar<CookieOptions> {\n\tconst appendSetCookie = (response: PagesRouterResponse, cookie: string) => {\n\t\tconst existing = response.getHeader('set-cookie');\n\t\tconst existingArr = Array.isArray(existing) ? existing : existing ? [String(existing)] : [];\n\n\t\tresponse.setHeader('set-cookie', [...existingArr, cookie]);\n\t};\n\n\treturn {\n\t\tasync get(name) {\n\t\t\tconst fromRequest = req ? getCookieFromRequest(req, name) : null;\n\n\t\t\tif (fromRequest) {\n\t\t\t\treturn fromRequest;\n\t\t\t}\n\t\t\tif (res instanceof NextResponse) {\n\t\t\t\treturn res.cookies.get(name)?.value;\n\t\t\t}\n\t\t\tif (res || req) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn (await cookies()).get(name)?.value;\n\t\t},\n\t\tasync set(name, value, cookieOptions) {\n\t\t\tif (res instanceof NextResponse) {\n\t\t\t\tres.cookies.set(name, value, cookieOptions);\n\t\t\t} else if (res) {\n\t\t\t\tappendSetCookie(res, buildCookieString(name, value, cookieOptions));\n\t\t\t} else {\n\t\t\t\t(await cookies()).set(name, value, cookieOptions);\n\t\t\t}\n\t\t},\n\t\tasync delete(name, cookieOptions) {\n\t\t\tif (res instanceof NextResponse) {\n\t\t\t\tres.cookies.set(name, '', { ...cookieOptions, maxAge: 0 });\n\t\t\t} else if (res) {\n\t\t\t\tappendSetCookie(res, buildCookieString(name, '', { ...cookieOptions, maxAge: 0 }));\n\t\t\t} else {\n\t\t\t\t(await cookies()).delete(name);\n\t\t\t}\n\t\t},\n\t};\n}\n\n/**\n * Creates an encrypted cookie session storage.\n * Only callable in server-side contexts (middleware, API routes, or server components).\n *\n * @param secret - The secret key used for encryption and decryption.\n * @param {EncryptedCookieStorageOptions} [options] - Options for configuring the encrypted cookie storage.\n * @param {Partial<ServerCookieOptions>} [options.defaultCookieOptions] - Default cookie attributes for the encrypted cookie.\n * @returns An object implementing the ServerStorage interface for managing encrypted cookies.\n */\nexport function createEncryptedCookieStorage(secret: string, options?: EncryptedCookieStorageOptions): NextServerStorage {\n\tconst defaultCookieOptions = {\n\t\thttpOnly: true,\n\t\tsecure: true,\n\t\tpath: '/',\n\t\tsameSite: 'lax' as const,\n\t\t...options?.defaultCookieOptions,\n\t};\n\n\treturn {\n\t\tget: (key, req) => readEncryptedCookie(createJar(req), key, secret),\n\t\tset: (key, value, req, res, cookieOptions) => writeEncryptedCookie(createJar(req, res), key, value, secret, { ...defaultCookieOptions, ...cookieOptions }),\n\t\tdelete: (key, req, res, cookieOptions) => deleteEncryptedCookie(createJar(req, res), key, { ...defaultCookieOptions, ...cookieOptions }),\n\t};\n}\n"],"mappings":"uXA6BA,SAAS,EAAqB,EAAiD,EAA4B,CAC1G,GAAI,aAAe,EAClB,OAAO,EAAI,QAAQ,IAAI,CAAG,CAAC,EAAE,OAAS,KAGvC,GAAI,aAAe,QAAS,CAE3B,IAAM,GADe,EAAI,QAAQ,IAAI,QAAQ,GAAK,GAAA,CAEhD,MAAM,GAAG,CAAC,CACV,IAAK,GAAM,EAAE,KAAK,CAAC,CAAC,CACpB,KAAM,GAAM,EAAE,WAAW,GAAG,EAAI,EAAE,CAAC,EAErC,OAAO,EAAQ,mBAAmB,EAAM,MAAM,EAAI,OAAS,CAAC,CAAC,EAAI,IAClE,CAGA,IAAM,GADe,EAAI,SAAS,QAAU,GAAA,CAE1C,MAAM,GAAG,CAAC,CACV,IAAK,GAAc,EAAE,KAAK,CAAC,CAAC,CAC5B,KAAM,GAAc,EAAE,WAAW,GAAG,EAAI,EAAE,CAAC,EAE7C,OAAO,EAAQ,mBAAmB,EAAM,MAAM,EAAI,OAAS,CAAC,CAAC,EAAI,IAClE,CASA,SAAgB,EAA6B,EAA4B,EAA4D,CACpI,OAAO,EACN,CACC,UAAY,GAAQ,EACpB,UAAW,EAAK,IAAW,EAAa,SAAS,EAAK,CAAM,EAC5D,aAAc,MAAO,EAAK,IACrB,EACI,EAAqB,EAAK,CAAG,GAAK,MAKnC,MAFa,EAAQ,EAAA,CAEf,IAAI,CAAG,CAAC,EAAE,KAEzB,EACA,EACA,CACD,CACD,CAUA,SAAS,EAAU,EAAkD,EAAoE,CACxI,IAAM,GAAmB,EAA+B,IAAmB,CAC1E,IAAM,EAAW,EAAS,UAAU,YAAY,EAC1C,EAAc,MAAM,QAAQ,CAAQ,EAAI,EAAW,EAAW,CAAC,OAAO,CAAQ,CAAC,EAAI,CAAC,EAE1F,EAAS,UAAU,aAAc,CAAC,GAAG,EAAa,CAAM,CAAC,CAC1D,EAEA,MAAO,CACN,MAAM,IAAI,EAAM,CAaf,OAZoB,EAAM,EAAqB,EAAK,CAAI,EAAI,QAKxD,aAAe,EACX,EAAI,QAAQ,IAAI,CAAI,CAAC,EAAE,MAE3B,GAAO,EACH,MAGA,MAAM,EAAQ,EAAA,CAAG,IAAI,CAAI,CAAC,EAAE,MACrC,EACA,MAAM,IAAI,EAAM,EAAO,EAAe,CACjC,aAAe,EAClB,EAAI,QAAQ,IAAI,EAAM,EAAO,CAAa,EAChC,EACV,EAAgB,EAAK,EAAkB,EAAM,EAAO,CAAa,CAAC,GAEjE,MAAM,EAAQ,EAAA,CAAG,IAAI,EAAM,EAAO,CAAa,CAElD,EACA,MAAM,OAAO,EAAM,EAAe,CAC7B,aAAe,EAClB,EAAI,QAAQ,IAAI,EAAM,GAAI,CAAE,GAAG,EAAe,OAAQ,CAAE,CAAC,EAC/C,EACV,EAAgB,EAAK,EAAkB,EAAM,GAAI,CAAE,GAAG,EAAe,OAAQ,CAAE,CAAC,CAAC,GAEhF,MAAM,EAAQ,EAAA,CAAG,OAAO,CAAI,CAE/B,CACD,CACD,CAWA,SAAgB,EAA6B,EAAgB,EAA4D,CACxH,IAAM,EAAuB,CAC5B,SAAU,GACV,OAAQ,GACR,KAAM,IACN,SAAU,MACV,GAAG,GAAS,oBACb,EAEA,MAAO,CACN,KAAM,EAAK,IAAQ,EAAoB,EAAU,CAAG,EAAG,EAAK,CAAM,EAClE,KAAM,EAAK,EAAO,EAAK,EAAK,IAAkB,EAAqB,EAAU,EAAK,CAAG,EAAG,EAAK,EAAO,EAAQ,CAAE,GAAG,EAAsB,GAAG,CAAc,CAAC,EACzJ,QAAS,EAAK,EAAK,EAAK,IAAkB,EAAsB,EAAU,EAAK,CAAG,EAAG,EAAK,CAAE,GAAG,EAAsB,GAAG,CAAc,CAAC,CACxI,CACD"}
|
package/dist/server/types.d.ts
CHANGED
|
@@ -81,9 +81,17 @@ export type NextServerStorage = SDKStorage<[
|
|
|
81
81
|
]> & {
|
|
82
82
|
deleteByLogoutToken?(token: LogoutTokenClaims): Promise<void>;
|
|
83
83
|
};
|
|
84
|
-
export type NextServerSDKOptions<Storage extends NextServerStorage = NextServerStorage, StateStorage extends SDKStorage = SDKStorage> = ServerSDKOptions<Storage, StateStorage>;
|
|
85
|
-
export type NextServerSDKInitConfig<Storage extends NextServerStorage = NextServerStorage, StateStorage extends SDKStorage = SDKStorage> = ServerSDKInitConfig & Partial<NextServerSDKOptions<Storage, StateStorage>>;
|
|
86
|
-
export type NextServerSDK<TEvent extends NextRequest | Request | PagesRouterRequest | undefined = NextRequest | Request | PagesRouterRequest | undefined> = BaseServerSDK<TEvent> & {
|
|
84
|
+
export type NextServerSDKOptions<Storage extends NextServerStorage = NextServerStorage, StateStorage extends SDKStorage = SDKStorage> = ServerSDKOptions<NextRequest | Request | PagesRouterRequest | undefined, Storage, StateStorage>;
|
|
85
|
+
export type NextServerSDKInitConfig<Storage extends NextServerStorage = NextServerStorage, StateStorage extends SDKStorage = SDKStorage> = ServerSDKInitConfig<NextRequest | Request | PagesRouterRequest | undefined> & Partial<NextServerSDKOptions<Storage, StateStorage>>;
|
|
86
|
+
export type NextServerSDK<TEvent extends NextRequest | Request | PagesRouterRequest | undefined = NextRequest | Request | PagesRouterRequest | undefined> = Omit<BaseServerSDK<TEvent>, 'handler'> & {
|
|
87
|
+
/**
|
|
88
|
+
* Dispatches an incoming request to the matching auth route handler based on `authUrlPrefix`, or answers `404 Not Found`
|
|
89
|
+
* if no auth route matched. Export it as `GET` and `POST` from the `app/auth/[...strivacity]/route.ts` catch-all route.
|
|
90
|
+
*
|
|
91
|
+
* @param {TEvent} req - The incoming request.
|
|
92
|
+
* @returns {Promise<Response>} The handler's response.
|
|
93
|
+
*/
|
|
94
|
+
handler(req: TEvent): Promise<Response>;
|
|
87
95
|
/**
|
|
88
96
|
* Wraps a React component with an authentication guard. If the user is not authenticated, they will be redirected to the login page.
|
|
89
97
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strivacity/sdk-next",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.2",
|
|
4
4
|
"description": "Strivacity Next.js SDK client",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "strivacity <opensource@strivacity.com>",
|
|
@@ -9,15 +9,9 @@
|
|
|
9
9
|
"url": "https://github.com/Strivacity/sdk-js"
|
|
10
10
|
},
|
|
11
11
|
"sideEffects": false,
|
|
12
|
-
"main": "./dist/client.cjs",
|
|
13
|
-
"types": "./dist/
|
|
12
|
+
"main": "./dist/client/index.cjs",
|
|
13
|
+
"types": "./dist/client/index.d.ts",
|
|
14
14
|
"exports": {
|
|
15
|
-
".": {
|
|
16
|
-
"types": "./dist/index.d.ts",
|
|
17
|
-
"import": "./dist/index.mjs",
|
|
18
|
-
"require": "./dist/index.cjs",
|
|
19
|
-
"default": "./dist/index.mjs"
|
|
20
|
-
},
|
|
21
15
|
"./client": {
|
|
22
16
|
"types": "./dist/client/index.d.ts",
|
|
23
17
|
"import": "./dist/client/index.mjs",
|
|
@@ -56,8 +50,8 @@
|
|
|
56
50
|
}
|
|
57
51
|
},
|
|
58
52
|
"dependencies": {
|
|
59
|
-
"@strivacity/sdk-core": "4.0.0-beta.
|
|
60
|
-
"@strivacity/sdk-react": "4.0.0-beta.
|
|
53
|
+
"@strivacity/sdk-core": "4.0.0-beta.2",
|
|
54
|
+
"@strivacity/sdk-react": "4.0.0-beta.2"
|
|
61
55
|
},
|
|
62
56
|
"peerDependencies": {
|
|
63
57
|
"next": ">=15"
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { test, expect } from 'vitest';
|
|
2
|
-
import * as nextComponents from '../../../src/client/components';
|
|
3
|
-
import * as reactComponents from '@strivacity/sdk-react/components';
|
|
4
|
-
|
|
5
|
-
test('re-exports components from the react sdk', () => {
|
|
6
|
-
const reactKeys = Object.keys(reactComponents);
|
|
7
|
-
|
|
8
|
-
expect(reactKeys.length).toBeGreaterThan(0);
|
|
9
|
-
expect(Object.keys(nextComponents).sort()).toEqual(reactKeys.sort());
|
|
10
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { test, expect } from 'vitest';
|
|
2
|
-
import * as nextHooks from '../../../src/client/hooks';
|
|
3
|
-
import * as reactHooks from '@strivacity/sdk-react/hooks';
|
|
4
|
-
|
|
5
|
-
test('re-exports hooks from the react sdk', () => {
|
|
6
|
-
const reactKeys = Object.keys(reactHooks);
|
|
7
|
-
|
|
8
|
-
expect(reactKeys.length).toBeGreaterThan(0);
|
|
9
|
-
expect(Object.keys(nextHooks).sort()).toEqual(reactKeys.sort());
|
|
10
|
-
});
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { test, expect } from 'vitest';
|
|
2
|
-
import * as clientIndex from '../../../src/client/index';
|
|
3
|
-
|
|
4
|
-
test('should export the correct things', () => {
|
|
5
|
-
const expectedExports = [
|
|
6
|
-
'AlgorithmTypeList',
|
|
7
|
-
'BACKCHANNEL_LOGOUT_EVENT',
|
|
8
|
-
'COOKIE_CHUNK_SIZE',
|
|
9
|
-
'COOKIE_CONTEXT',
|
|
10
|
-
'ConfigurationError',
|
|
11
|
-
'DEFAULT_COOKIE_MAX_AGE',
|
|
12
|
-
'DISALLOWED_PROXY_HEADERS',
|
|
13
|
-
'FallbackError',
|
|
14
|
-
'GrantTypeList',
|
|
15
|
-
'InternalError',
|
|
16
|
-
'NetworkError',
|
|
17
|
-
'OidcError',
|
|
18
|
-
'PopupBlockedError',
|
|
19
|
-
'PopupClosedError',
|
|
20
|
-
'ProtocolError',
|
|
21
|
-
'RETURN_TO_COOKIE',
|
|
22
|
-
'ResponseModeList',
|
|
23
|
-
'ResponseTypeList',
|
|
24
|
-
'STRIVACITY_SDK',
|
|
25
|
-
'ServerError',
|
|
26
|
-
'SessionExpiredError',
|
|
27
|
-
'StyAuthProvider',
|
|
28
|
-
'SubjectTypeList',
|
|
29
|
-
'TokenEndpointAuthMethodList',
|
|
30
|
-
'UnsupportedFlowError',
|
|
31
|
-
'assertWebAuthnCredential',
|
|
32
|
-
'buildAuthorizationUrl',
|
|
33
|
-
'buildCookieString',
|
|
34
|
-
'buildEndSessionUrl',
|
|
35
|
-
'createBaseFlow',
|
|
36
|
-
'createCacheAPIStorage',
|
|
37
|
-
'createDefaultLogging',
|
|
38
|
-
'createEmbeddedFlow',
|
|
39
|
-
'createEncryptedCookieStorage',
|
|
40
|
-
'createHttpClient',
|
|
41
|
-
'createIndexedDBStorage',
|
|
42
|
-
'createLocalStorage',
|
|
43
|
-
'createMemoryStorage',
|
|
44
|
-
'createNativeFlow',
|
|
45
|
-
'createPopupFlow',
|
|
46
|
-
'createRedirectFlow',
|
|
47
|
-
'createServerMemoryStorage',
|
|
48
|
-
'createServerStateStorage',
|
|
49
|
-
'createSession',
|
|
50
|
-
'createSessionIdCookieStorage',
|
|
51
|
-
'createSessionStorage',
|
|
52
|
-
'createState',
|
|
53
|
-
'createWebAuthnCredential',
|
|
54
|
-
'createWorkerStorage',
|
|
55
|
-
'decodeBase64URL',
|
|
56
|
-
'decodeJwt',
|
|
57
|
-
'decryptString',
|
|
58
|
-
'defaultOptions',
|
|
59
|
-
'encodeBase64URL',
|
|
60
|
-
'encryptString',
|
|
61
|
-
'exchangeCode',
|
|
62
|
-
'fetchFlowEntry',
|
|
63
|
-
'finalizeLoginSession',
|
|
64
|
-
'flushSetCookies',
|
|
65
|
-
'generateCodeChallenge',
|
|
66
|
-
'generateCodeVerifier',
|
|
67
|
-
'generateJwt',
|
|
68
|
-
'generateRandomHex',
|
|
69
|
-
'getDefaultFlowState',
|
|
70
|
-
'getDiscoveryDocument',
|
|
71
|
-
'getSDKOptions',
|
|
72
|
-
'getServerSDKOptions',
|
|
73
|
-
'handleWorkerStorageRequests',
|
|
74
|
-
'injectScript',
|
|
75
|
-
'isSessionExpired',
|
|
76
|
-
'loadSession',
|
|
77
|
-
'parseCookieHeader',
|
|
78
|
-
'parseState',
|
|
79
|
-
'popupCallbackHandler',
|
|
80
|
-
'popupUrlHandler',
|
|
81
|
-
'proxyResponse',
|
|
82
|
-
'pushSetCookie',
|
|
83
|
-
'redirectCallbackHandler',
|
|
84
|
-
'redirectUrlHandler',
|
|
85
|
-
'refreshToken',
|
|
86
|
-
'revokeToken',
|
|
87
|
-
'serializeCookie',
|
|
88
|
-
'serializeSession',
|
|
89
|
-
'serializeState',
|
|
90
|
-
'submitLoginForm',
|
|
91
|
-
'throwHttpError',
|
|
92
|
-
'throwTokenEndpointError',
|
|
93
|
-
'timestamp',
|
|
94
|
-
'toSafeRedirect',
|
|
95
|
-
'unflattenObject',
|
|
96
|
-
'useNativeLogin',
|
|
97
|
-
'useNativeLoginContext',
|
|
98
|
-
'useStrivacity',
|
|
99
|
-
'verifyIdToken',
|
|
100
|
-
'verifyJwt',
|
|
101
|
-
'withAuthGuard',
|
|
102
|
-
];
|
|
103
|
-
|
|
104
|
-
expect(Object.keys(clientIndex)).toHaveLength(expectedExports.length);
|
|
105
|
-
expect(Object.keys(clientIndex).sort()).toEqual(expectedExports.sort());
|
|
106
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { test, expect } from 'vitest';
|
|
2
|
-
import * as nextStorages from '../../../src/client/storages';
|
|
3
|
-
import * as reactStorages from '@strivacity/sdk-react/storages';
|
|
4
|
-
|
|
5
|
-
test('re-exports storages from the react sdk', () => {
|
|
6
|
-
const reactKeys = Object.keys(reactStorages);
|
|
7
|
-
|
|
8
|
-
expect(reactKeys.length).toBeGreaterThan(0);
|
|
9
|
-
expect(Object.keys(nextStorages).sort()).toEqual(reactKeys.sort());
|
|
10
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { test, expect } from 'vitest';
|
|
2
|
-
import * as nextUtils from '../../../src/client/utils';
|
|
3
|
-
import * as reactUtils from '@strivacity/sdk-react/utils';
|
|
4
|
-
|
|
5
|
-
test('re-exports utilities from the react sdk', () => {
|
|
6
|
-
const reactKeys = Object.keys(reactUtils);
|
|
7
|
-
|
|
8
|
-
expect(reactKeys.length).toBeGreaterThan(0);
|
|
9
|
-
expect(Object.keys(nextUtils).sort()).toEqual(reactKeys.sort());
|
|
10
|
-
});
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import type { Mock } from 'vitest';
|
|
2
|
-
import { describe, test, expect, vi } from 'vitest';
|
|
3
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
4
|
-
import { createMockBaseServerSDK } from '@strivacity/testing/mocks/sdk';
|
|
5
|
-
import { apiAppRouteHandlerFactory, apiPageRouteHandlerFactory } from '../../../../src/server/handlers/api';
|
|
6
|
-
import type { BaseServerSDK, PagesRouterRequest } from '../../../../src/server/types';
|
|
7
|
-
|
|
8
|
-
describe('apiAppRouteHandlerFactory', () => {
|
|
9
|
-
test('returns a 401 response and does not call the route when there is no session', async () => {
|
|
10
|
-
const sdk = createMockBaseServerSDK<BaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>>();
|
|
11
|
-
const apiRoute = vi.fn();
|
|
12
|
-
const handler = apiAppRouteHandlerFactory(sdk)(apiRoute);
|
|
13
|
-
|
|
14
|
-
const response = await handler(new NextRequest('https://brandtegrity.io/api/secret'), {});
|
|
15
|
-
|
|
16
|
-
expect(response.status).toBe(401);
|
|
17
|
-
await expect(response.json()).resolves.toEqual({
|
|
18
|
-
error: 'not_authenticated',
|
|
19
|
-
description: 'The user does not have an active session or is not authenticated',
|
|
20
|
-
});
|
|
21
|
-
expect(apiRoute).not.toHaveBeenCalled();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test('calls the route with the request and params when there is a session', async () => {
|
|
25
|
-
const sdk = createMockBaseServerSDK<BaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>>({ getSession: vi.fn().mockResolvedValue({}) });
|
|
26
|
-
const apiRoute = vi.fn().mockResolvedValue(NextResponse.json({ ok: true }));
|
|
27
|
-
const handler = apiAppRouteHandlerFactory(sdk)(apiRoute);
|
|
28
|
-
const req = new NextRequest('https://brandtegrity.io/api/secret');
|
|
29
|
-
const params = { params: Promise.resolve({ id: '1' }) };
|
|
30
|
-
|
|
31
|
-
await handler(req, params);
|
|
32
|
-
|
|
33
|
-
expect(apiRoute).toHaveBeenCalledWith(req, params);
|
|
34
|
-
expect(sdk.getSession).toHaveBeenCalledWith(req);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test('returns the route NextResponse unchanged', async () => {
|
|
38
|
-
const sdk = createMockBaseServerSDK<BaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>>({ getSession: vi.fn().mockResolvedValue({}) });
|
|
39
|
-
const routeResponse = NextResponse.json({ ok: true });
|
|
40
|
-
const apiRoute = vi.fn().mockResolvedValue(routeResponse);
|
|
41
|
-
const handler = apiAppRouteHandlerFactory(sdk)(apiRoute);
|
|
42
|
-
|
|
43
|
-
const response = await handler(new NextRequest('https://brandtegrity.io/api/secret'), {});
|
|
44
|
-
|
|
45
|
-
expect(response).toBe(routeResponse);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test('wraps a plain Response returned by the route into a NextResponse', async () => {
|
|
49
|
-
const sdk = createMockBaseServerSDK<BaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>>({ getSession: vi.fn().mockResolvedValue({}) });
|
|
50
|
-
const apiRoute = vi.fn().mockResolvedValue(new Response('plain body', { status: 201, headers: { 'x-custom': 'yes' } }));
|
|
51
|
-
const handler = apiAppRouteHandlerFactory(sdk)(apiRoute);
|
|
52
|
-
|
|
53
|
-
const response = await handler(new NextRequest('https://brandtegrity.io/api/secret'), {});
|
|
54
|
-
|
|
55
|
-
expect(response).toBeInstanceOf(NextResponse);
|
|
56
|
-
expect(response.status).toBe(201);
|
|
57
|
-
expect(response.headers.get('x-custom')).toBe('yes');
|
|
58
|
-
await expect(response.text()).resolves.toBe('plain body');
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
test('converts a plain Request to a NextRequest before checking the session and calling the route', async () => {
|
|
62
|
-
const sdk = createMockBaseServerSDK<BaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>>({ getSession: vi.fn().mockResolvedValue({}) });
|
|
63
|
-
const apiRoute = vi.fn().mockResolvedValue(NextResponse.json({ ok: true }));
|
|
64
|
-
const handler = apiAppRouteHandlerFactory(sdk)(apiRoute);
|
|
65
|
-
const req = new Request('https://brandtegrity.io/api/secret');
|
|
66
|
-
|
|
67
|
-
await handler(req, {});
|
|
68
|
-
|
|
69
|
-
const usedRequest = (sdk.getSession as Mock).mock.calls[0][0] as NextRequest;
|
|
70
|
-
expect(usedRequest).toBeInstanceOf(NextRequest);
|
|
71
|
-
expect(usedRequest.url).toBe(req.url);
|
|
72
|
-
expect(apiRoute).toHaveBeenCalledWith(usedRequest, {});
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
describe('apiPageRouteHandlerFactory', () => {
|
|
77
|
-
function createFakeRes() {
|
|
78
|
-
const json = vi.fn();
|
|
79
|
-
const status = vi.fn().mockReturnValue({ json });
|
|
80
|
-
|
|
81
|
-
return { status, json };
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
test('responds with 401 and does not call the route when there is no session', async () => {
|
|
85
|
-
const sdk = createMockBaseServerSDK<BaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>>();
|
|
86
|
-
const apiRoute = vi.fn();
|
|
87
|
-
const handler = apiPageRouteHandlerFactory(sdk)(apiRoute);
|
|
88
|
-
const req = {} as PagesRouterRequest;
|
|
89
|
-
const res = createFakeRes();
|
|
90
|
-
|
|
91
|
-
await handler(req, res as never);
|
|
92
|
-
|
|
93
|
-
expect(res.status).toHaveBeenCalledWith(401);
|
|
94
|
-
expect(res.json).toHaveBeenCalledWith({ error: 'not_authenticated', description: 'The user does not have an active session or is not authenticated' });
|
|
95
|
-
expect(apiRoute).not.toHaveBeenCalled();
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
test('calls the route with the request and response when there is a session', async () => {
|
|
99
|
-
const sdk = createMockBaseServerSDK<BaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>>({ getSession: vi.fn().mockResolvedValue({}) });
|
|
100
|
-
const apiRoute = vi.fn();
|
|
101
|
-
const handler = apiPageRouteHandlerFactory(sdk)(apiRoute);
|
|
102
|
-
const req = {} as PagesRouterRequest;
|
|
103
|
-
const res = createFakeRes();
|
|
104
|
-
|
|
105
|
-
await handler(req, res as never);
|
|
106
|
-
|
|
107
|
-
expect(apiRoute).toHaveBeenCalledWith(req, res);
|
|
108
|
-
expect(res.status).not.toHaveBeenCalled();
|
|
109
|
-
});
|
|
110
|
-
});
|