iron-session 6.2.0-beta.0 → 6.2.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/README.md +59 -3
- package/dist/index.js +48 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +43 -12
- package/dist/index.mjs.map +1 -1
- package/edge/dist/index.d.ts +4 -66
- package/edge/dist/index.js +51 -20
- package/edge/dist/index.js.map +1 -1
- package/edge/dist/index.mjs +46 -16
- package/edge/dist/index.mjs.map +1 -1
- package/edge/index.d.ts +4 -66
- package/edge/index.js +51 -20
- package/edge/index.js.map +1 -1
- package/edge/index.mjs +46 -16
- package/edge/index.mjs.map +1 -1
- package/edge/index.ts +3 -1
- package/express/dist/index.js +6 -1
- package/express/dist/index.js.map +1 -1
- package/express/dist/index.mjs +5 -1
- package/express/dist/index.mjs.map +1 -1
- package/express/index.js +6 -1
- package/express/index.js.map +1 -1
- package/express/index.mjs +5 -1
- package/express/index.mjs.map +1 -1
- package/next/dist/index.js +16 -3
- package/next/dist/index.js.map +1 -1
- package/next/dist/index.mjs +15 -3
- package/next/dist/index.mjs.map +1 -1
- package/next/index.js +16 -3
- package/next/index.js.map +1 -1
- package/next/index.mjs +15 -3
- package/next/index.mjs.map +1 -1
- package/package.json +17 -14
package/edge/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts","../../src/core.ts"],"sourcesContent":["import {\n createGetIronSession,\n createSealData,\n createUnsealData,\n} from \"../src/core\";\n\nconst getCrypto = (): Crypto => {\n if (typeof globalThis.crypto?.subtle === \"object\") return globalThis.crypto;\n // @ts-ignore crypto.webcrypto is not available in dom, but is there in newer node versions\n if (typeof globalThis.crypto?.webcrypto?.subtle === \"object\")\n // @ts-ignore same as above\n return globalThis.crypto.webcrypto;\n throw new Error(\n \"no native implementation of WebCrypto is available in current context\",\n );\n};\n\nconst _crypto = getCrypto();\n\nexport * from \"../src/core\";\nexport const unsealData = createUnsealData(_crypto);\nexport const sealData = createSealData(_crypto);\nexport const getIronSession = createGetIronSession(\n _crypto,\n unsealData,\n sealData,\n);\n","import * as Iron from \"iron-webcrypto\";\nimport type { CookieSerializeOptions } from \"cookie\";\nimport cookie from \"cookie\";\nimport type { IncomingMessage, ServerResponse } from \"http\";\n\n// default time allowed to check for iron seal validity when ttl passed\n// see https://hapi.dev/family/iron/api/?v=6.0.0#options\nconst timestampSkewSec = 60;\n\ntype passwordsMap = { [id: string]: string };\ntype password = string | passwordsMap;\n\nconst fourteenDaysInSeconds = 15 * 24 * 3600;\n\n// We store a token major version to handle data format changes when any. So that when you upgrade the cookies\n// can be kept alive between upgrades, no need to disconnect everyone.\nconst currentMajorVersion = 2;\nconst versionDelimiter = \"~\";\n\nconst defaultOptions: {\n ttl: number;\n cookieOptions: CookieSerializeOptions;\n} = {\n ttl: fourteenDaysInSeconds,\n cookieOptions: {\n httpOnly: true,\n secure: true,\n sameSite: \"lax\",\n path: \"/\",\n },\n};\n\nexport interface IronSessionOptions {\n /**\n * This is the cookie name that will be used inside the browser. You should make sure it's unique given\n * your application. Example: vercel-session\n */\n cookieName: string;\n\n /**\n * This is the password(s) that will be used to encrypt the cookie. It can be either a string or an object\n * like {1: \"password\", 2: password}.\n *\n * When you provide multiple passwords then all of them will be used to decrypt the cookie and only the most\n * recent (= highest key, 2 in this example) password will be used to encrypt the cookie. This allow you\n * to use password rotation (security)\n */\n password: password;\n\n /**\n * This is the time in seconds that the session will be valid for. This also set the max-age attribute of\n * the cookie automatically (minus 60 seconds so that the cookie always expire before the session).\n */\n ttl?: number;\n\n /**\n * This is the options that will be passed to the cookie library.\n * You can see all of them here: https://github.com/jshttp/cookie#options-1.\n *\n * If you want to use \"session cookies\" (cookies that are deleted when the browser is closed) then you need\n * to pass cookieOptions: { maxAge: undefined }.\n */\n cookieOptions?: CookieSerializeOptions;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface IronSessionData {\n // If we allow for any keys, then there's no more type check on unknown properties\n // which is not good\n // If we allow for any keys, the later delete will work but I prefer to disable the\n // check at this stage and\n // provide good type checking instead\n // [key: string]: unknown;\n}\n\nexport type IronSession = IronSessionData & {\n /**\n * Destroys the session data and removes the cookie.\n */\n destroy: () => void;\n\n /**\n * Encrypts the session data and sets the cookie.\n */\n save: () => Promise<void>;\n};\n\ndeclare module \"http\" {\n interface IncomingMessage {\n session: IronSession;\n }\n}\n\ntype RequestType = IncomingMessage | Request;\ntype ResponseType = ServerResponse | Response;\n\nexport function createGetIronSession(\n _crypto: Crypto,\n unsealData: ReturnType<typeof createUnsealData>,\n sealData: ReturnType<typeof createSealData>,\n) {\n return async (\n req: RequestType,\n res: ResponseType,\n userSessionOptions: IronSessionOptions,\n ): Promise<IronSession> => {\n if (\n !req ||\n !res ||\n !userSessionOptions ||\n !userSessionOptions.cookieName ||\n !userSessionOptions.password\n ) {\n throw new Error(\n `iron-session: Bad usage. Minimum usage is const session = await getIronSession(req, res, { cookieName: \"...\", password: \"...\". Check the usage here: https://github.com/vvo/iron-session`,\n );\n }\n\n const passwordsAsMap = normalizeStringPasswordToMap(\n userSessionOptions.password,\n );\n\n Object.values(\n normalizeStringPasswordToMap(userSessionOptions.password),\n ).forEach((password) => {\n if (password.length < 32) {\n throw new Error(\n `iron-session: Bad usage. Password must be at least 32 characters long.`,\n );\n }\n });\n\n const options: Required<IronSessionOptions> = {\n ...defaultOptions,\n ...userSessionOptions,\n cookieOptions: {\n ...defaultOptions.cookieOptions,\n ...(userSessionOptions.cookieOptions || {}),\n },\n };\n\n if (options.ttl === 0) {\n // ttl = 0 means no expiration\n // but in reality cookies have to expire (can't have no max-age)\n // 2147483647 is the max value for max-age in cookies\n // see https://stackoverflow.com/a/11685301/147079\n options.ttl = 2147483647;\n }\n\n if (\n userSessionOptions.cookieOptions &&\n \"maxAge\" in userSessionOptions.cookieOptions\n ) {\n // session cookie, do not set maxAge, consider token as infinite\n if (userSessionOptions.cookieOptions.maxAge === undefined) {\n options.ttl = 0;\n } else {\n options.cookieOptions.maxAge = computeCookieMaxAge(\n userSessionOptions.cookieOptions.maxAge,\n );\n }\n } else {\n options.cookieOptions.maxAge = computeCookieMaxAge(options.ttl);\n }\n\n const sealFromCookies = cookie.parse(\n \"credentials\" in req\n ? req.headers.get(\"cookie\") || \"\"\n : req.headers.cookie || \"\",\n )[options.cookieName];\n\n const session =\n sealFromCookies === undefined\n ? {}\n : await unsealData<IronSessionData>(sealFromCookies, {\n password: passwordsAsMap,\n ttl: options.ttl,\n });\n\n Object.defineProperties(session, {\n save: {\n value: async function save() {\n if (\"headersSent\" in res && res.headersSent === true) {\n throw new Error(\n `iron-session: Cannot set session cookie: session.save() was called after headers were sent. Make sure to call it before any res.send() or res.end()`,\n );\n }\n const seal = await sealData(session, {\n password: passwordsAsMap,\n ttl: options.ttl,\n });\n const cookieValue = cookie.serialize(\n options.cookieName,\n seal,\n options.cookieOptions,\n );\n\n if (cookieValue.length > 4096) {\n throw new Error(\n `iron-session: Cookie length is too big ${cookieValue.length}, browsers will refuse it. Try to remove some data.`,\n );\n }\n\n addToCookies(cookieValue, res);\n },\n },\n destroy: {\n value: function destroy() {\n Object.keys(session).forEach((key) => {\n // @ts-ignore See comment on the IronSessionData interface\n delete session[key];\n });\n\n const cookieValue = cookie.serialize(options.cookieName, \"\", {\n ...options.cookieOptions,\n maxAge: 0,\n });\n addToCookies(cookieValue, res);\n },\n },\n });\n\n return session as IronSession;\n };\n}\n\nfunction addToCookies(cookieValue: string, res: ResponseType) {\n if (\"headers\" in res) {\n res.headers.append(\"set-cookie\", cookieValue);\n return;\n }\n\n let existingSetCookie =\n (res.getHeader(\"set-cookie\") as string[] | string) ?? [];\n if (typeof existingSetCookie === \"string\") {\n existingSetCookie = [existingSetCookie];\n }\n res.setHeader(\"set-cookie\", [...existingSetCookie, cookieValue]);\n}\n\nfunction computeCookieMaxAge(ttl: number) {\n // The next line makes sure browser will expire cookies before seals are considered expired by the server.\n // It also allows for clock difference of 60 seconds maximum between server and clients.\n // It also makes sure to expire the cookie immediately when value is 0\n return ttl - timestampSkewSec;\n}\n\nexport function createUnsealData(_crypto: Crypto) {\n return async <T = Record<string, unknown>>(\n seal: string,\n {\n password,\n ttl = fourteenDaysInSeconds,\n }: { password: password; ttl?: number },\n ): Promise<T> => {\n const passwordsAsMap = normalizeStringPasswordToMap(password);\n const { sealWithoutVersion, tokenVersion } = parseSeal(seal);\n\n try {\n const data = await Iron.unseal(\n _crypto,\n sealWithoutVersion,\n passwordsAsMap,\n { ...Iron.defaults, ttl: ttl * 1000 },\n );\n\n if (tokenVersion === 2) {\n return data as T;\n }\n\n return {\n // @ts-expect-error `persistent` does not exist on newer tokens\n ...data.persistent,\n };\n } catch (error) {\n if (error instanceof Error) {\n if (\n error.message === \"Expired seal\" ||\n error.message === \"Bad hmac value\" ||\n error.message === \"Cannot find password: \" ||\n error.message === \"Incorrect number of sealed components\"\n ) {\n // if seal expired or\n // if seal is not valid (encrypted using a different password, when passwords are badly rotated) or\n // if we can't find back the password in the seal\n // then we just start a new session over\n return {} as T;\n }\n }\n\n throw error;\n }\n };\n}\n\nfunction parseSeal(seal: string): {\n sealWithoutVersion: string;\n tokenVersion: number | null;\n} {\n if (seal[seal.length - 2] === versionDelimiter) {\n const [sealWithoutVersion, tokenVersionAsString] =\n seal.split(versionDelimiter);\n return {\n sealWithoutVersion,\n tokenVersion: parseInt(tokenVersionAsString, 10),\n };\n }\n\n return { sealWithoutVersion: seal, tokenVersion: null };\n}\n\nexport function createSealData(_crypto: Crypto) {\n return async (\n data: unknown,\n {\n password,\n ttl = fourteenDaysInSeconds,\n }: { password: password; ttl?: number },\n ) => {\n const passwordsAsMap = normalizeStringPasswordToMap(password);\n\n const mostRecentPasswordId = Math.max(\n ...Object.keys(passwordsAsMap).map((id) => parseInt(id, 10)),\n );\n\n const passwordForSeal = {\n id: mostRecentPasswordId.toString(),\n secret: passwordsAsMap[mostRecentPasswordId],\n };\n\n const seal = await Iron.seal(_crypto, data, passwordForSeal, {\n ...Iron.defaults,\n ttl: ttl * 1000,\n });\n\n return `${seal}${versionDelimiter}${currentMajorVersion}`;\n };\n}\n\nfunction normalizeStringPasswordToMap(password: password) {\n return typeof password === \"string\" ? { 1: password } : password;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../index.ts","../../src/core.ts"],"sourcesContent":["// This allows the types to be linked from the main module instead of duplicated\nexport type { IronSessionOptions, IronSessionData } from \"iron-session\";\n\nimport {\n createGetIronSession,\n createSealData,\n createUnsealData,\n} from \"../src/core\";\n\nconst getCrypto = (): Crypto => {\n if (typeof globalThis.crypto?.subtle === \"object\") return globalThis.crypto;\n // @ts-ignore crypto.webcrypto is not available in dom, but is there in newer node versions\n if (typeof globalThis.crypto?.webcrypto?.subtle === \"object\")\n // @ts-ignore same as above\n return globalThis.crypto.webcrypto;\n throw new Error(\n \"no native implementation of WebCrypto is available in current context\",\n );\n};\n\nconst _crypto = getCrypto();\n\nexport const unsealData = createUnsealData(_crypto);\nexport const sealData = createSealData(_crypto);\nexport const getIronSession = createGetIronSession(\n _crypto,\n unsealData,\n sealData,\n);\n","import * as Iron from \"iron-webcrypto\";\nimport type { CookieSerializeOptions } from \"cookie\";\nimport cookie from \"cookie\";\nimport type { IncomingMessage, ServerResponse } from \"http\";\n\n// default time allowed to check for iron seal validity when ttl passed\n// see https://hapi.dev/family/iron/api/?v=6.0.0#options\nconst timestampSkewSec = 60;\n\ntype passwordsMap = { [id: string]: string };\ntype password = string | passwordsMap;\n\nconst fourteenDaysInSeconds = 15 * 24 * 3600;\n\n// We store a token major version to handle data format changes when any. So that when you upgrade the cookies\n// can be kept alive between upgrades, no need to disconnect everyone.\nconst currentMajorVersion = 2;\nconst versionDelimiter = \"~\";\n\nconst defaultOptions: {\n ttl: number;\n cookieOptions: CookieSerializeOptions;\n} = {\n ttl: fourteenDaysInSeconds,\n cookieOptions: {\n httpOnly: true,\n secure: true,\n sameSite: \"lax\",\n path: \"/\",\n },\n};\n\nexport interface IronSessionOptions {\n /**\n * This is the cookie name that will be used inside the browser. You should make sure it's unique given\n * your application. Example: vercel-session\n */\n cookieName: string;\n\n /**\n * This is the password(s) that will be used to encrypt the cookie. It can be either a string or an object\n * like {1: \"password\", 2: password}.\n *\n * When you provide multiple passwords then all of them will be used to decrypt the cookie and only the most\n * recent (= highest key, 2 in this example) password will be used to encrypt the cookie. This allow you\n * to use password rotation (security)\n */\n password: password;\n\n /**\n * This is the time in seconds that the session will be valid for. This also set the max-age attribute of\n * the cookie automatically (minus 60 seconds so that the cookie always expire before the session).\n */\n ttl?: number;\n\n /**\n * This is the options that will be passed to the cookie library.\n * You can see all of them here: https://github.com/jshttp/cookie#options-1.\n *\n * If you want to use \"session cookies\" (cookies that are deleted when the browser is closed) then you need\n * to pass cookieOptions: { maxAge: undefined }.\n */\n cookieOptions?: CookieSerializeOptions;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface IronSessionData {\n // If we allow for any keys, then there's no more type check on unknown properties\n // which is not good\n // If we allow for any keys, the later delete will work but I prefer to disable the\n // check at this stage and\n // provide good type checking instead\n // [key: string]: unknown;\n}\n\nexport type IronSession = IronSessionData & {\n /**\n * Destroys the session data and removes the cookie.\n */\n destroy: () => void;\n\n /**\n * Encrypts the session data and sets the cookie.\n */\n save: () => Promise<void>;\n};\n\ndeclare module \"http\" {\n interface IncomingMessage {\n session: IronSession;\n }\n}\n\ntype RequestType = IncomingMessage | Request;\ntype ResponseType = ServerResponse | Response;\n\nexport function createGetIronSession(\n _crypto: Crypto,\n unsealData: ReturnType<typeof createUnsealData>,\n sealData: ReturnType<typeof createSealData>,\n) {\n return async (\n req: RequestType,\n res: ResponseType,\n userSessionOptions: IronSessionOptions,\n ): Promise<IronSession> => {\n if (\n !req ||\n !res ||\n !userSessionOptions ||\n !userSessionOptions.cookieName ||\n !userSessionOptions.password\n ) {\n throw new Error(\n `iron-session: Bad usage. Minimum usage is const session = await getIronSession(req, res, { cookieName: \"...\", password: \"...\". Check the usage here: https://github.com/vvo/iron-session`,\n );\n }\n\n const passwordsAsMap = normalizeStringPasswordToMap(\n userSessionOptions.password,\n );\n\n Object.values(\n normalizeStringPasswordToMap(userSessionOptions.password),\n ).forEach((password) => {\n if (password.length < 32) {\n throw new Error(\n `iron-session: Bad usage. Password must be at least 32 characters long.`,\n );\n }\n });\n\n const options: Required<IronSessionOptions> = {\n ...defaultOptions,\n ...userSessionOptions,\n cookieOptions: {\n ...defaultOptions.cookieOptions,\n ...(userSessionOptions.cookieOptions || {}),\n },\n };\n\n if (options.ttl === 0) {\n // ttl = 0 means no expiration\n // but in reality cookies have to expire (can't have no max-age)\n // 2147483647 is the max value for max-age in cookies\n // see https://stackoverflow.com/a/11685301/147079\n options.ttl = 2147483647;\n }\n\n if (\n userSessionOptions.cookieOptions &&\n \"maxAge\" in userSessionOptions.cookieOptions\n ) {\n // session cookie, do not set maxAge, consider token as infinite\n if (userSessionOptions.cookieOptions.maxAge === undefined) {\n options.ttl = 0;\n } else {\n options.cookieOptions.maxAge = computeCookieMaxAge(\n userSessionOptions.cookieOptions.maxAge,\n );\n }\n } else {\n options.cookieOptions.maxAge = computeCookieMaxAge(options.ttl);\n }\n\n const sealFromCookies = cookie.parse(\n \"credentials\" in req\n ? req.headers.get(\"cookie\") || \"\"\n : req.headers.cookie || \"\",\n )[options.cookieName];\n\n const session =\n sealFromCookies === undefined\n ? {}\n : await unsealData<IronSessionData>(sealFromCookies, {\n password: passwordsAsMap,\n ttl: options.ttl,\n });\n\n Object.defineProperties(session, {\n save: {\n value: async function save() {\n if (\"headersSent\" in res && res.headersSent === true) {\n throw new Error(\n `iron-session: Cannot set session cookie: session.save() was called after headers were sent. Make sure to call it before any res.send() or res.end()`,\n );\n }\n const seal = await sealData(session, {\n password: passwordsAsMap,\n ttl: options.ttl,\n });\n const cookieValue = cookie.serialize(\n options.cookieName,\n seal,\n options.cookieOptions,\n );\n\n if (cookieValue.length > 4096) {\n throw new Error(\n `iron-session: Cookie length is too big ${cookieValue.length}, browsers will refuse it. Try to remove some data.`,\n );\n }\n\n addToCookies(cookieValue, res);\n },\n },\n destroy: {\n value: function destroy() {\n Object.keys(session).forEach((key) => {\n // @ts-ignore See comment on the IronSessionData interface\n delete session[key];\n });\n\n const cookieValue = cookie.serialize(options.cookieName, \"\", {\n ...options.cookieOptions,\n maxAge: 0,\n });\n addToCookies(cookieValue, res);\n },\n },\n });\n\n return session as IronSession;\n };\n}\n\nfunction addToCookies(cookieValue: string, res: ResponseType) {\n if (\"headers\" in res) {\n res.headers.append(\"set-cookie\", cookieValue);\n return;\n }\n\n let existingSetCookie =\n (res.getHeader(\"set-cookie\") as string[] | string) ?? [];\n if (typeof existingSetCookie === \"string\") {\n existingSetCookie = [existingSetCookie];\n }\n res.setHeader(\"set-cookie\", [...existingSetCookie, cookieValue]);\n}\n\nfunction computeCookieMaxAge(ttl: number) {\n // The next line makes sure browser will expire cookies before seals are considered expired by the server.\n // It also allows for clock difference of 60 seconds maximum between server and clients.\n // It also makes sure to expire the cookie immediately when value is 0\n return ttl - timestampSkewSec;\n}\n\nexport function createUnsealData(_crypto: Crypto) {\n return async <T = Record<string, unknown>>(\n seal: string,\n {\n password,\n ttl = fourteenDaysInSeconds,\n }: { password: password; ttl?: number },\n ): Promise<T> => {\n const passwordsAsMap = normalizeStringPasswordToMap(password);\n const { sealWithoutVersion, tokenVersion } = parseSeal(seal);\n\n try {\n const data = await Iron.unseal(\n _crypto,\n sealWithoutVersion,\n passwordsAsMap,\n { ...Iron.defaults, ttl: ttl * 1000 },\n );\n\n if (tokenVersion === 2) {\n return data as T;\n }\n\n return {\n // @ts-expect-error `persistent` does not exist on newer tokens\n ...data.persistent,\n };\n } catch (error) {\n if (error instanceof Error) {\n if (\n error.message === \"Expired seal\" ||\n error.message === \"Bad hmac value\" ||\n error.message === \"Cannot find password: \" ||\n error.message === \"Incorrect number of sealed components\"\n ) {\n // if seal expired or\n // if seal is not valid (encrypted using a different password, when passwords are badly rotated) or\n // if we can't find back the password in the seal\n // then we just start a new session over\n return {} as T;\n }\n }\n\n throw error;\n }\n };\n}\n\nfunction parseSeal(seal: string): {\n sealWithoutVersion: string;\n tokenVersion: number | null;\n} {\n if (seal[seal.length - 2] === versionDelimiter) {\n const [sealWithoutVersion, tokenVersionAsString] =\n seal.split(versionDelimiter);\n return {\n sealWithoutVersion,\n tokenVersion: parseInt(tokenVersionAsString, 10),\n };\n }\n\n return { sealWithoutVersion: seal, tokenVersion: null };\n}\n\nexport function createSealData(_crypto: Crypto) {\n return async (\n data: unknown,\n {\n password,\n ttl = fourteenDaysInSeconds,\n }: { password: password; ttl?: number },\n ) => {\n const passwordsAsMap = normalizeStringPasswordToMap(password);\n\n const mostRecentPasswordId = Math.max(\n ...Object.keys(passwordsAsMap).map((id) => parseInt(id, 10)),\n );\n\n const passwordForSeal = {\n id: mostRecentPasswordId.toString(),\n secret: passwordsAsMap[mostRecentPasswordId],\n };\n\n const seal = await Iron.seal(_crypto, data, passwordForSeal, {\n ...Iron.defaults,\n ttl: ttl * 1000,\n });\n\n return `${seal}${versionDelimiter}${currentMajorVersion}`;\n };\n}\n\nfunction normalizeStringPasswordToMap(password: password) {\n return typeof password === \"string\" ? { 1: password } : password;\n}\n"],"mappings":"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","names":["_crypto","unsealData","sealData","cookie","seal"]}
|
package/edge/index.mjs
CHANGED
|
@@ -17,12 +17,20 @@ var defaultOptions = {
|
|
|
17
17
|
function createGetIronSession(_crypto2, unsealData2, sealData2) {
|
|
18
18
|
return async (req, res, userSessionOptions) => {
|
|
19
19
|
if (!req || !res || !userSessionOptions || !userSessionOptions.cookieName || !userSessionOptions.password) {
|
|
20
|
-
throw new Error(
|
|
20
|
+
throw new Error(
|
|
21
|
+
`iron-session: Bad usage. Minimum usage is const session = await getIronSession(req, res, { cookieName: "...", password: "...". Check the usage here: https://github.com/vvo/iron-session`
|
|
22
|
+
);
|
|
21
23
|
}
|
|
22
|
-
const passwordsAsMap = normalizeStringPasswordToMap(
|
|
23
|
-
|
|
24
|
+
const passwordsAsMap = normalizeStringPasswordToMap(
|
|
25
|
+
userSessionOptions.password
|
|
26
|
+
);
|
|
27
|
+
Object.values(
|
|
28
|
+
normalizeStringPasswordToMap(userSessionOptions.password)
|
|
29
|
+
).forEach((password) => {
|
|
24
30
|
if (password.length < 32) {
|
|
25
|
-
throw new Error(
|
|
31
|
+
throw new Error(
|
|
32
|
+
`iron-session: Bad usage. Password must be at least 32 characters long.`
|
|
33
|
+
);
|
|
26
34
|
}
|
|
27
35
|
});
|
|
28
36
|
const options = {
|
|
@@ -40,12 +48,16 @@ function createGetIronSession(_crypto2, unsealData2, sealData2) {
|
|
|
40
48
|
if (userSessionOptions.cookieOptions.maxAge === void 0) {
|
|
41
49
|
options.ttl = 0;
|
|
42
50
|
} else {
|
|
43
|
-
options.cookieOptions.maxAge = computeCookieMaxAge(
|
|
51
|
+
options.cookieOptions.maxAge = computeCookieMaxAge(
|
|
52
|
+
userSessionOptions.cookieOptions.maxAge
|
|
53
|
+
);
|
|
44
54
|
}
|
|
45
55
|
} else {
|
|
46
56
|
options.cookieOptions.maxAge = computeCookieMaxAge(options.ttl);
|
|
47
57
|
}
|
|
48
|
-
const sealFromCookies = cookie.parse(
|
|
58
|
+
const sealFromCookies = cookie.parse(
|
|
59
|
+
"credentials" in req ? req.headers.get("cookie") || "" : req.headers.cookie || ""
|
|
60
|
+
)[options.cookieName];
|
|
49
61
|
const session = sealFromCookies === void 0 ? {} : await unsealData2(sealFromCookies, {
|
|
50
62
|
password: passwordsAsMap,
|
|
51
63
|
ttl: options.ttl
|
|
@@ -54,15 +66,23 @@ function createGetIronSession(_crypto2, unsealData2, sealData2) {
|
|
|
54
66
|
save: {
|
|
55
67
|
value: async function save() {
|
|
56
68
|
if ("headersSent" in res && res.headersSent === true) {
|
|
57
|
-
throw new Error(
|
|
69
|
+
throw new Error(
|
|
70
|
+
`iron-session: Cannot set session cookie: session.save() was called after headers were sent. Make sure to call it before any res.send() or res.end()`
|
|
71
|
+
);
|
|
58
72
|
}
|
|
59
73
|
const seal2 = await sealData2(session, {
|
|
60
74
|
password: passwordsAsMap,
|
|
61
75
|
ttl: options.ttl
|
|
62
76
|
});
|
|
63
|
-
const cookieValue = cookie.serialize(
|
|
77
|
+
const cookieValue = cookie.serialize(
|
|
78
|
+
options.cookieName,
|
|
79
|
+
seal2,
|
|
80
|
+
options.cookieOptions
|
|
81
|
+
);
|
|
64
82
|
if (cookieValue.length > 4096) {
|
|
65
|
-
throw new Error(
|
|
83
|
+
throw new Error(
|
|
84
|
+
`iron-session: Cookie length is too big ${cookieValue.length}, browsers will refuse it. Try to remove some data.`
|
|
85
|
+
);
|
|
66
86
|
}
|
|
67
87
|
addToCookies(cookieValue, res);
|
|
68
88
|
}
|
|
@@ -106,7 +126,12 @@ function createUnsealData(_crypto2) {
|
|
|
106
126
|
const passwordsAsMap = normalizeStringPasswordToMap(password);
|
|
107
127
|
const { sealWithoutVersion, tokenVersion } = parseSeal(seal2);
|
|
108
128
|
try {
|
|
109
|
-
const data = await Iron.unseal(
|
|
129
|
+
const data = await Iron.unseal(
|
|
130
|
+
_crypto2,
|
|
131
|
+
sealWithoutVersion,
|
|
132
|
+
passwordsAsMap,
|
|
133
|
+
{ ...Iron.defaults, ttl: ttl * 1e3 }
|
|
134
|
+
);
|
|
110
135
|
if (tokenVersion === 2) {
|
|
111
136
|
return data;
|
|
112
137
|
}
|
|
@@ -139,7 +164,9 @@ function createSealData(_crypto2) {
|
|
|
139
164
|
ttl = fourteenDaysInSeconds
|
|
140
165
|
}) => {
|
|
141
166
|
const passwordsAsMap = normalizeStringPasswordToMap(password);
|
|
142
|
-
const mostRecentPasswordId = Math.max(
|
|
167
|
+
const mostRecentPasswordId = Math.max(
|
|
168
|
+
...Object.keys(passwordsAsMap).map((id) => parseInt(id, 10))
|
|
169
|
+
);
|
|
143
170
|
const passwordForSeal = {
|
|
144
171
|
id: mostRecentPasswordId.toString(),
|
|
145
172
|
secret: passwordsAsMap[mostRecentPasswordId]
|
|
@@ -162,16 +189,19 @@ var getCrypto = () => {
|
|
|
162
189
|
return globalThis.crypto;
|
|
163
190
|
if (typeof ((_c = (_b = globalThis.crypto) == null ? void 0 : _b.webcrypto) == null ? void 0 : _c.subtle) === "object")
|
|
164
191
|
return globalThis.crypto.webcrypto;
|
|
165
|
-
throw new Error(
|
|
192
|
+
throw new Error(
|
|
193
|
+
"no native implementation of WebCrypto is available in current context"
|
|
194
|
+
);
|
|
166
195
|
};
|
|
167
196
|
var _crypto = getCrypto();
|
|
168
197
|
var unsealData = createUnsealData(_crypto);
|
|
169
198
|
var sealData = createSealData(_crypto);
|
|
170
|
-
var getIronSession = createGetIronSession(
|
|
199
|
+
var getIronSession = createGetIronSession(
|
|
200
|
+
_crypto,
|
|
201
|
+
unsealData,
|
|
202
|
+
sealData
|
|
203
|
+
);
|
|
171
204
|
export {
|
|
172
|
-
createGetIronSession,
|
|
173
|
-
createSealData,
|
|
174
|
-
createUnsealData,
|
|
175
205
|
getIronSession,
|
|
176
206
|
sealData,
|
|
177
207
|
unsealData
|
package/edge/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core.ts","../index.ts"],"sourcesContent":["import * as Iron from \"iron-webcrypto\";\nimport type { CookieSerializeOptions } from \"cookie\";\nimport cookie from \"cookie\";\nimport type { IncomingMessage, ServerResponse } from \"http\";\n\n// default time allowed to check for iron seal validity when ttl passed\n// see https://hapi.dev/family/iron/api/?v=6.0.0#options\nconst timestampSkewSec = 60;\n\ntype passwordsMap = { [id: string]: string };\ntype password = string | passwordsMap;\n\nconst fourteenDaysInSeconds = 15 * 24 * 3600;\n\n// We store a token major version to handle data format changes when any. So that when you upgrade the cookies\n// can be kept alive between upgrades, no need to disconnect everyone.\nconst currentMajorVersion = 2;\nconst versionDelimiter = \"~\";\n\nconst defaultOptions: {\n ttl: number;\n cookieOptions: CookieSerializeOptions;\n} = {\n ttl: fourteenDaysInSeconds,\n cookieOptions: {\n httpOnly: true,\n secure: true,\n sameSite: \"lax\",\n path: \"/\",\n },\n};\n\nexport interface IronSessionOptions {\n /**\n * This is the cookie name that will be used inside the browser. You should make sure it's unique given\n * your application. Example: vercel-session\n */\n cookieName: string;\n\n /**\n * This is the password(s) that will be used to encrypt the cookie. It can be either a string or an object\n * like {1: \"password\", 2: password}.\n *\n * When you provide multiple passwords then all of them will be used to decrypt the cookie and only the most\n * recent (= highest key, 2 in this example) password will be used to encrypt the cookie. This allow you\n * to use password rotation (security)\n */\n password: password;\n\n /**\n * This is the time in seconds that the session will be valid for. This also set the max-age attribute of\n * the cookie automatically (minus 60 seconds so that the cookie always expire before the session).\n */\n ttl?: number;\n\n /**\n * This is the options that will be passed to the cookie library.\n * You can see all of them here: https://github.com/jshttp/cookie#options-1.\n *\n * If you want to use \"session cookies\" (cookies that are deleted when the browser is closed) then you need\n * to pass cookieOptions: { maxAge: undefined }.\n */\n cookieOptions?: CookieSerializeOptions;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface IronSessionData {\n // If we allow for any keys, then there's no more type check on unknown properties\n // which is not good\n // If we allow for any keys, the later delete will work but I prefer to disable the\n // check at this stage and\n // provide good type checking instead\n // [key: string]: unknown;\n}\n\nexport type IronSession = IronSessionData & {\n /**\n * Destroys the session data and removes the cookie.\n */\n destroy: () => void;\n\n /**\n * Encrypts the session data and sets the cookie.\n */\n save: () => Promise<void>;\n};\n\ndeclare module \"http\" {\n interface IncomingMessage {\n session: IronSession;\n }\n}\n\ntype RequestType = IncomingMessage | Request;\ntype ResponseType = ServerResponse | Response;\n\nexport function createGetIronSession(\n _crypto: Crypto,\n unsealData: ReturnType<typeof createUnsealData>,\n sealData: ReturnType<typeof createSealData>,\n) {\n return async (\n req: RequestType,\n res: ResponseType,\n userSessionOptions: IronSessionOptions,\n ): Promise<IronSession> => {\n if (\n !req ||\n !res ||\n !userSessionOptions ||\n !userSessionOptions.cookieName ||\n !userSessionOptions.password\n ) {\n throw new Error(\n `iron-session: Bad usage. Minimum usage is const session = await getIronSession(req, res, { cookieName: \"...\", password: \"...\". Check the usage here: https://github.com/vvo/iron-session`,\n );\n }\n\n const passwordsAsMap = normalizeStringPasswordToMap(\n userSessionOptions.password,\n );\n\n Object.values(\n normalizeStringPasswordToMap(userSessionOptions.password),\n ).forEach((password) => {\n if (password.length < 32) {\n throw new Error(\n `iron-session: Bad usage. Password must be at least 32 characters long.`,\n );\n }\n });\n\n const options: Required<IronSessionOptions> = {\n ...defaultOptions,\n ...userSessionOptions,\n cookieOptions: {\n ...defaultOptions.cookieOptions,\n ...(userSessionOptions.cookieOptions || {}),\n },\n };\n\n if (options.ttl === 0) {\n // ttl = 0 means no expiration\n // but in reality cookies have to expire (can't have no max-age)\n // 2147483647 is the max value for max-age in cookies\n // see https://stackoverflow.com/a/11685301/147079\n options.ttl = 2147483647;\n }\n\n if (\n userSessionOptions.cookieOptions &&\n \"maxAge\" in userSessionOptions.cookieOptions\n ) {\n // session cookie, do not set maxAge, consider token as infinite\n if (userSessionOptions.cookieOptions.maxAge === undefined) {\n options.ttl = 0;\n } else {\n options.cookieOptions.maxAge = computeCookieMaxAge(\n userSessionOptions.cookieOptions.maxAge,\n );\n }\n } else {\n options.cookieOptions.maxAge = computeCookieMaxAge(options.ttl);\n }\n\n const sealFromCookies = cookie.parse(\n \"credentials\" in req\n ? req.headers.get(\"cookie\") || \"\"\n : req.headers.cookie || \"\",\n )[options.cookieName];\n\n const session =\n sealFromCookies === undefined\n ? {}\n : await unsealData<IronSessionData>(sealFromCookies, {\n password: passwordsAsMap,\n ttl: options.ttl,\n });\n\n Object.defineProperties(session, {\n save: {\n value: async function save() {\n if (\"headersSent\" in res && res.headersSent === true) {\n throw new Error(\n `iron-session: Cannot set session cookie: session.save() was called after headers were sent. Make sure to call it before any res.send() or res.end()`,\n );\n }\n const seal = await sealData(session, {\n password: passwordsAsMap,\n ttl: options.ttl,\n });\n const cookieValue = cookie.serialize(\n options.cookieName,\n seal,\n options.cookieOptions,\n );\n\n if (cookieValue.length > 4096) {\n throw new Error(\n `iron-session: Cookie length is too big ${cookieValue.length}, browsers will refuse it. Try to remove some data.`,\n );\n }\n\n addToCookies(cookieValue, res);\n },\n },\n destroy: {\n value: function destroy() {\n Object.keys(session).forEach((key) => {\n // @ts-ignore See comment on the IronSessionData interface\n delete session[key];\n });\n\n const cookieValue = cookie.serialize(options.cookieName, \"\", {\n ...options.cookieOptions,\n maxAge: 0,\n });\n addToCookies(cookieValue, res);\n },\n },\n });\n\n return session as IronSession;\n };\n}\n\nfunction addToCookies(cookieValue: string, res: ResponseType) {\n if (\"headers\" in res) {\n res.headers.append(\"set-cookie\", cookieValue);\n return;\n }\n\n let existingSetCookie =\n (res.getHeader(\"set-cookie\") as string[] | string) ?? [];\n if (typeof existingSetCookie === \"string\") {\n existingSetCookie = [existingSetCookie];\n }\n res.setHeader(\"set-cookie\", [...existingSetCookie, cookieValue]);\n}\n\nfunction computeCookieMaxAge(ttl: number) {\n // The next line makes sure browser will expire cookies before seals are considered expired by the server.\n // It also allows for clock difference of 60 seconds maximum between server and clients.\n // It also makes sure to expire the cookie immediately when value is 0\n return ttl - timestampSkewSec;\n}\n\nexport function createUnsealData(_crypto: Crypto) {\n return async <T = Record<string, unknown>>(\n seal: string,\n {\n password,\n ttl = fourteenDaysInSeconds,\n }: { password: password; ttl?: number },\n ): Promise<T> => {\n const passwordsAsMap = normalizeStringPasswordToMap(password);\n const { sealWithoutVersion, tokenVersion } = parseSeal(seal);\n\n try {\n const data = await Iron.unseal(\n _crypto,\n sealWithoutVersion,\n passwordsAsMap,\n { ...Iron.defaults, ttl: ttl * 1000 },\n );\n\n if (tokenVersion === 2) {\n return data as T;\n }\n\n return {\n // @ts-expect-error `persistent` does not exist on newer tokens\n ...data.persistent,\n };\n } catch (error) {\n if (error instanceof Error) {\n if (\n error.message === \"Expired seal\" ||\n error.message === \"Bad hmac value\" ||\n error.message === \"Cannot find password: \" ||\n error.message === \"Incorrect number of sealed components\"\n ) {\n // if seal expired or\n // if seal is not valid (encrypted using a different password, when passwords are badly rotated) or\n // if we can't find back the password in the seal\n // then we just start a new session over\n return {} as T;\n }\n }\n\n throw error;\n }\n };\n}\n\nfunction parseSeal(seal: string): {\n sealWithoutVersion: string;\n tokenVersion: number | null;\n} {\n if (seal[seal.length - 2] === versionDelimiter) {\n const [sealWithoutVersion, tokenVersionAsString] =\n seal.split(versionDelimiter);\n return {\n sealWithoutVersion,\n tokenVersion: parseInt(tokenVersionAsString, 10),\n };\n }\n\n return { sealWithoutVersion: seal, tokenVersion: null };\n}\n\nexport function createSealData(_crypto: Crypto) {\n return async (\n data: unknown,\n {\n password,\n ttl = fourteenDaysInSeconds,\n }: { password: password; ttl?: number },\n ) => {\n const passwordsAsMap = normalizeStringPasswordToMap(password);\n\n const mostRecentPasswordId = Math.max(\n ...Object.keys(passwordsAsMap).map((id) => parseInt(id, 10)),\n );\n\n const passwordForSeal = {\n id: mostRecentPasswordId.toString(),\n secret: passwordsAsMap[mostRecentPasswordId],\n };\n\n const seal = await Iron.seal(_crypto, data, passwordForSeal, {\n ...Iron.defaults,\n ttl: ttl * 1000,\n });\n\n return `${seal}${versionDelimiter}${currentMajorVersion}`;\n };\n}\n\nfunction normalizeStringPasswordToMap(password: password) {\n return typeof password === \"string\" ? { 1: password } : password;\n}\n","import {\n createGetIronSession,\n createSealData,\n createUnsealData,\n} from \"../src/core\";\n\nconst getCrypto = (): Crypto => {\n if (typeof globalThis.crypto?.subtle === \"object\") return globalThis.crypto;\n // @ts-ignore crypto.webcrypto is not available in dom, but is there in newer node versions\n if (typeof globalThis.crypto?.webcrypto?.subtle === \"object\")\n // @ts-ignore same as above\n return globalThis.crypto.webcrypto;\n throw new Error(\n \"no native implementation of WebCrypto is available in current context\",\n );\n};\n\nconst _crypto = getCrypto();\n\nexport * from \"../src/core\";\nexport const unsealData = createUnsealData(_crypto);\nexport const sealData = createSealData(_crypto);\nexport const getIronSession = createGetIronSession(\n _crypto,\n unsealData,\n sealData,\n);\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/core.ts","../index.ts"],"sourcesContent":["import * as Iron from \"iron-webcrypto\";\nimport type { CookieSerializeOptions } from \"cookie\";\nimport cookie from \"cookie\";\nimport type { IncomingMessage, ServerResponse } from \"http\";\n\n// default time allowed to check for iron seal validity when ttl passed\n// see https://hapi.dev/family/iron/api/?v=6.0.0#options\nconst timestampSkewSec = 60;\n\ntype passwordsMap = { [id: string]: string };\ntype password = string | passwordsMap;\n\nconst fourteenDaysInSeconds = 15 * 24 * 3600;\n\n// We store a token major version to handle data format changes when any. So that when you upgrade the cookies\n// can be kept alive between upgrades, no need to disconnect everyone.\nconst currentMajorVersion = 2;\nconst versionDelimiter = \"~\";\n\nconst defaultOptions: {\n ttl: number;\n cookieOptions: CookieSerializeOptions;\n} = {\n ttl: fourteenDaysInSeconds,\n cookieOptions: {\n httpOnly: true,\n secure: true,\n sameSite: \"lax\",\n path: \"/\",\n },\n};\n\nexport interface IronSessionOptions {\n /**\n * This is the cookie name that will be used inside the browser. You should make sure it's unique given\n * your application. Example: vercel-session\n */\n cookieName: string;\n\n /**\n * This is the password(s) that will be used to encrypt the cookie. It can be either a string or an object\n * like {1: \"password\", 2: password}.\n *\n * When you provide multiple passwords then all of them will be used to decrypt the cookie and only the most\n * recent (= highest key, 2 in this example) password will be used to encrypt the cookie. This allow you\n * to use password rotation (security)\n */\n password: password;\n\n /**\n * This is the time in seconds that the session will be valid for. This also set the max-age attribute of\n * the cookie automatically (minus 60 seconds so that the cookie always expire before the session).\n */\n ttl?: number;\n\n /**\n * This is the options that will be passed to the cookie library.\n * You can see all of them here: https://github.com/jshttp/cookie#options-1.\n *\n * If you want to use \"session cookies\" (cookies that are deleted when the browser is closed) then you need\n * to pass cookieOptions: { maxAge: undefined }.\n */\n cookieOptions?: CookieSerializeOptions;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface IronSessionData {\n // If we allow for any keys, then there's no more type check on unknown properties\n // which is not good\n // If we allow for any keys, the later delete will work but I prefer to disable the\n // check at this stage and\n // provide good type checking instead\n // [key: string]: unknown;\n}\n\nexport type IronSession = IronSessionData & {\n /**\n * Destroys the session data and removes the cookie.\n */\n destroy: () => void;\n\n /**\n * Encrypts the session data and sets the cookie.\n */\n save: () => Promise<void>;\n};\n\ndeclare module \"http\" {\n interface IncomingMessage {\n session: IronSession;\n }\n}\n\ntype RequestType = IncomingMessage | Request;\ntype ResponseType = ServerResponse | Response;\n\nexport function createGetIronSession(\n _crypto: Crypto,\n unsealData: ReturnType<typeof createUnsealData>,\n sealData: ReturnType<typeof createSealData>,\n) {\n return async (\n req: RequestType,\n res: ResponseType,\n userSessionOptions: IronSessionOptions,\n ): Promise<IronSession> => {\n if (\n !req ||\n !res ||\n !userSessionOptions ||\n !userSessionOptions.cookieName ||\n !userSessionOptions.password\n ) {\n throw new Error(\n `iron-session: Bad usage. Minimum usage is const session = await getIronSession(req, res, { cookieName: \"...\", password: \"...\". Check the usage here: https://github.com/vvo/iron-session`,\n );\n }\n\n const passwordsAsMap = normalizeStringPasswordToMap(\n userSessionOptions.password,\n );\n\n Object.values(\n normalizeStringPasswordToMap(userSessionOptions.password),\n ).forEach((password) => {\n if (password.length < 32) {\n throw new Error(\n `iron-session: Bad usage. Password must be at least 32 characters long.`,\n );\n }\n });\n\n const options: Required<IronSessionOptions> = {\n ...defaultOptions,\n ...userSessionOptions,\n cookieOptions: {\n ...defaultOptions.cookieOptions,\n ...(userSessionOptions.cookieOptions || {}),\n },\n };\n\n if (options.ttl === 0) {\n // ttl = 0 means no expiration\n // but in reality cookies have to expire (can't have no max-age)\n // 2147483647 is the max value for max-age in cookies\n // see https://stackoverflow.com/a/11685301/147079\n options.ttl = 2147483647;\n }\n\n if (\n userSessionOptions.cookieOptions &&\n \"maxAge\" in userSessionOptions.cookieOptions\n ) {\n // session cookie, do not set maxAge, consider token as infinite\n if (userSessionOptions.cookieOptions.maxAge === undefined) {\n options.ttl = 0;\n } else {\n options.cookieOptions.maxAge = computeCookieMaxAge(\n userSessionOptions.cookieOptions.maxAge,\n );\n }\n } else {\n options.cookieOptions.maxAge = computeCookieMaxAge(options.ttl);\n }\n\n const sealFromCookies = cookie.parse(\n \"credentials\" in req\n ? req.headers.get(\"cookie\") || \"\"\n : req.headers.cookie || \"\",\n )[options.cookieName];\n\n const session =\n sealFromCookies === undefined\n ? {}\n : await unsealData<IronSessionData>(sealFromCookies, {\n password: passwordsAsMap,\n ttl: options.ttl,\n });\n\n Object.defineProperties(session, {\n save: {\n value: async function save() {\n if (\"headersSent\" in res && res.headersSent === true) {\n throw new Error(\n `iron-session: Cannot set session cookie: session.save() was called after headers were sent. Make sure to call it before any res.send() or res.end()`,\n );\n }\n const seal = await sealData(session, {\n password: passwordsAsMap,\n ttl: options.ttl,\n });\n const cookieValue = cookie.serialize(\n options.cookieName,\n seal,\n options.cookieOptions,\n );\n\n if (cookieValue.length > 4096) {\n throw new Error(\n `iron-session: Cookie length is too big ${cookieValue.length}, browsers will refuse it. Try to remove some data.`,\n );\n }\n\n addToCookies(cookieValue, res);\n },\n },\n destroy: {\n value: function destroy() {\n Object.keys(session).forEach((key) => {\n // @ts-ignore See comment on the IronSessionData interface\n delete session[key];\n });\n\n const cookieValue = cookie.serialize(options.cookieName, \"\", {\n ...options.cookieOptions,\n maxAge: 0,\n });\n addToCookies(cookieValue, res);\n },\n },\n });\n\n return session as IronSession;\n };\n}\n\nfunction addToCookies(cookieValue: string, res: ResponseType) {\n if (\"headers\" in res) {\n res.headers.append(\"set-cookie\", cookieValue);\n return;\n }\n\n let existingSetCookie =\n (res.getHeader(\"set-cookie\") as string[] | string) ?? [];\n if (typeof existingSetCookie === \"string\") {\n existingSetCookie = [existingSetCookie];\n }\n res.setHeader(\"set-cookie\", [...existingSetCookie, cookieValue]);\n}\n\nfunction computeCookieMaxAge(ttl: number) {\n // The next line makes sure browser will expire cookies before seals are considered expired by the server.\n // It also allows for clock difference of 60 seconds maximum between server and clients.\n // It also makes sure to expire the cookie immediately when value is 0\n return ttl - timestampSkewSec;\n}\n\nexport function createUnsealData(_crypto: Crypto) {\n return async <T = Record<string, unknown>>(\n seal: string,\n {\n password,\n ttl = fourteenDaysInSeconds,\n }: { password: password; ttl?: number },\n ): Promise<T> => {\n const passwordsAsMap = normalizeStringPasswordToMap(password);\n const { sealWithoutVersion, tokenVersion } = parseSeal(seal);\n\n try {\n const data = await Iron.unseal(\n _crypto,\n sealWithoutVersion,\n passwordsAsMap,\n { ...Iron.defaults, ttl: ttl * 1000 },\n );\n\n if (tokenVersion === 2) {\n return data as T;\n }\n\n return {\n // @ts-expect-error `persistent` does not exist on newer tokens\n ...data.persistent,\n };\n } catch (error) {\n if (error instanceof Error) {\n if (\n error.message === \"Expired seal\" ||\n error.message === \"Bad hmac value\" ||\n error.message === \"Cannot find password: \" ||\n error.message === \"Incorrect number of sealed components\"\n ) {\n // if seal expired or\n // if seal is not valid (encrypted using a different password, when passwords are badly rotated) or\n // if we can't find back the password in the seal\n // then we just start a new session over\n return {} as T;\n }\n }\n\n throw error;\n }\n };\n}\n\nfunction parseSeal(seal: string): {\n sealWithoutVersion: string;\n tokenVersion: number | null;\n} {\n if (seal[seal.length - 2] === versionDelimiter) {\n const [sealWithoutVersion, tokenVersionAsString] =\n seal.split(versionDelimiter);\n return {\n sealWithoutVersion,\n tokenVersion: parseInt(tokenVersionAsString, 10),\n };\n }\n\n return { sealWithoutVersion: seal, tokenVersion: null };\n}\n\nexport function createSealData(_crypto: Crypto) {\n return async (\n data: unknown,\n {\n password,\n ttl = fourteenDaysInSeconds,\n }: { password: password; ttl?: number },\n ) => {\n const passwordsAsMap = normalizeStringPasswordToMap(password);\n\n const mostRecentPasswordId = Math.max(\n ...Object.keys(passwordsAsMap).map((id) => parseInt(id, 10)),\n );\n\n const passwordForSeal = {\n id: mostRecentPasswordId.toString(),\n secret: passwordsAsMap[mostRecentPasswordId],\n };\n\n const seal = await Iron.seal(_crypto, data, passwordForSeal, {\n ...Iron.defaults,\n ttl: ttl * 1000,\n });\n\n return `${seal}${versionDelimiter}${currentMajorVersion}`;\n };\n}\n\nfunction normalizeStringPasswordToMap(password: password) {\n return typeof password === \"string\" ? { 1: password } : password;\n}\n","// This allows the types to be linked from the main module instead of duplicated\nexport type { IronSessionOptions, IronSessionData } from \"iron-session\";\n\nimport {\n createGetIronSession,\n createSealData,\n createUnsealData,\n} from \"../src/core\";\n\nconst getCrypto = (): Crypto => {\n if (typeof globalThis.crypto?.subtle === \"object\") return globalThis.crypto;\n // @ts-ignore crypto.webcrypto is not available in dom, but is there in newer node versions\n if (typeof globalThis.crypto?.webcrypto?.subtle === \"object\")\n // @ts-ignore same as above\n return globalThis.crypto.webcrypto;\n throw new Error(\n \"no native implementation of WebCrypto is available in current context\",\n );\n};\n\nconst _crypto = getCrypto();\n\nexport const unsealData = createUnsealData(_crypto);\nexport const sealData = createSealData(_crypto);\nexport const getIronSession = createGetIronSession(\n _crypto,\n unsealData,\n sealData,\n);\n"],"mappings":"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","names":["_crypto","unsealData","sealData","seal"]}
|
package/edge/index.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// This allows the types to be linked from the main module instead of duplicated
|
|
2
|
+
export type { IronSessionOptions, IronSessionData } from "iron-session";
|
|
3
|
+
|
|
1
4
|
import {
|
|
2
5
|
createGetIronSession,
|
|
3
6
|
createSealData,
|
|
@@ -17,7 +20,6 @@ const getCrypto = (): Crypto => {
|
|
|
17
20
|
|
|
18
21
|
const _crypto = getCrypto();
|
|
19
22
|
|
|
20
|
-
export * from "../src/core";
|
|
21
23
|
export const unsealData = createUnsealData(_crypto);
|
|
22
24
|
export const sealData = createSealData(_crypto);
|
|
23
25
|
export const getIronSession = createGetIronSession(
|
package/express/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
2
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -50,7 +51,11 @@ function getPropertyDescriptorForReqSession(session) {
|
|
|
50
51
|
function ironSession(sessionOptions) {
|
|
51
52
|
return async function ironSessionMiddleware(req, res, next) {
|
|
52
53
|
const session = await (0, import_iron_session.getIronSession)(req, res, sessionOptions);
|
|
53
|
-
Object.defineProperty(
|
|
54
|
+
Object.defineProperty(
|
|
55
|
+
req,
|
|
56
|
+
"session",
|
|
57
|
+
getPropertyDescriptorForReqSession(session)
|
|
58
|
+
);
|
|
54
59
|
next();
|
|
55
60
|
};
|
|
56
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts","../../src/getPropertyDescriptorForReqSession.ts"],"sourcesContent":["import type { IronSessionOptions } from \"iron-session\";\nimport { getIronSession } from \"iron-session\";\nimport type { Request, Response, NextFunction } from \"express\";\nimport getPropertyDescriptorForReqSession from \"../src/getPropertyDescriptorForReqSession\";\n\nexport function ironSession(\n sessionOptions: IronSessionOptions,\n): (req: Request, res: Response, next: NextFunction) => Promise<void> {\n return async function ironSessionMiddleware(req, res, next) {\n const session = await getIronSession(req, res, sessionOptions);\n Object.defineProperty(\n req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n\n next();\n };\n}\n","import type { IronSession } from \".\";\n\nexport default function getPropertyDescriptorForReqSession(\n session: IronSession,\n): PropertyDescriptor {\n return {\n enumerable: true,\n get() {\n return session;\n },\n set(value) {\n const keys = Object.keys(value);\n const currentKeys = Object.keys(session);\n\n currentKeys.forEach((key) => {\n if (!keys.includes(key)) {\n // @ts-ignore See comment in IronSessionData interface\n delete session[key];\n }\n });\n\n keys.forEach((key) => {\n // @ts-ignore See comment in IronSessionData interface\n session[key] = value[key];\n });\n },\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../index.ts","../../src/getPropertyDescriptorForReqSession.ts"],"sourcesContent":["import type { IronSessionOptions } from \"iron-session\";\nimport { getIronSession } from \"iron-session\";\nimport type { Request, Response, NextFunction } from \"express\";\nimport getPropertyDescriptorForReqSession from \"../src/getPropertyDescriptorForReqSession\";\n\nexport function ironSession(\n sessionOptions: IronSessionOptions,\n): (req: Request, res: Response, next: NextFunction) => Promise<void> {\n return async function ironSessionMiddleware(req, res, next) {\n const session = await getIronSession(req, res, sessionOptions);\n Object.defineProperty(\n req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n\n next();\n };\n}\n","import type { IronSession } from \".\";\n\nexport default function getPropertyDescriptorForReqSession(\n session: IronSession,\n): PropertyDescriptor {\n return {\n enumerable: true,\n get() {\n return session;\n },\n set(value) {\n const keys = Object.keys(value);\n const currentKeys = Object.keys(session);\n\n currentKeys.forEach((key) => {\n if (!keys.includes(key)) {\n // @ts-ignore See comment in IronSessionData interface\n delete session[key];\n }\n });\n\n keys.forEach((key) => {\n // @ts-ignore See comment in IronSessionData interface\n session[key] = value[key];\n });\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,0BAA+B;;;ACChB,SAAR,mCACL,SACoB;AACpB,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,MAAM;AACJ,aAAO;AAAA,IACT;AAAA,IACA,IAAI,OAAO;AACT,YAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,YAAM,cAAc,OAAO,KAAK,OAAO;AAEvC,kBAAY,QAAQ,CAAC,QAAQ;AAC3B,YAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AAEvB,iBAAO,QAAQ;AAAA,QACjB;AAAA,MACF,CAAC;AAED,WAAK,QAAQ,CAAC,QAAQ;AAEpB,gBAAQ,OAAO,MAAM;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ADtBO,SAAS,YACd,gBACoE;AACpE,SAAO,eAAe,sBAAsB,KAAK,KAAK,MAAM;AAC1D,UAAM,UAAU,UAAM,oCAAe,KAAK,KAAK,cAAc;AAC7D,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,mCAAmC,OAAO;AAAA,IAC5C;AAEA,SAAK;AAAA,EACP;AACF;","names":[]}
|
package/express/dist/index.mjs
CHANGED
|
@@ -27,7 +27,11 @@ function getPropertyDescriptorForReqSession(session) {
|
|
|
27
27
|
function ironSession(sessionOptions) {
|
|
28
28
|
return async function ironSessionMiddleware(req, res, next) {
|
|
29
29
|
const session = await getIronSession(req, res, sessionOptions);
|
|
30
|
-
Object.defineProperty(
|
|
30
|
+
Object.defineProperty(
|
|
31
|
+
req,
|
|
32
|
+
"session",
|
|
33
|
+
getPropertyDescriptorForReqSession(session)
|
|
34
|
+
);
|
|
31
35
|
next();
|
|
32
36
|
};
|
|
33
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts","../../src/getPropertyDescriptorForReqSession.ts"],"sourcesContent":["import type { IronSessionOptions } from \"iron-session\";\nimport { getIronSession } from \"iron-session\";\nimport type { Request, Response, NextFunction } from \"express\";\nimport getPropertyDescriptorForReqSession from \"../src/getPropertyDescriptorForReqSession\";\n\nexport function ironSession(\n sessionOptions: IronSessionOptions,\n): (req: Request, res: Response, next: NextFunction) => Promise<void> {\n return async function ironSessionMiddleware(req, res, next) {\n const session = await getIronSession(req, res, sessionOptions);\n Object.defineProperty(\n req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n\n next();\n };\n}\n","import type { IronSession } from \".\";\n\nexport default function getPropertyDescriptorForReqSession(\n session: IronSession,\n): PropertyDescriptor {\n return {\n enumerable: true,\n get() {\n return session;\n },\n set(value) {\n const keys = Object.keys(value);\n const currentKeys = Object.keys(session);\n\n currentKeys.forEach((key) => {\n if (!keys.includes(key)) {\n // @ts-ignore See comment in IronSessionData interface\n delete session[key];\n }\n });\n\n keys.forEach((key) => {\n // @ts-ignore See comment in IronSessionData interface\n session[key] = value[key];\n });\n },\n };\n}\n"],"mappings":";AACA;;;
|
|
1
|
+
{"version":3,"sources":["../index.ts","../../src/getPropertyDescriptorForReqSession.ts"],"sourcesContent":["import type { IronSessionOptions } from \"iron-session\";\nimport { getIronSession } from \"iron-session\";\nimport type { Request, Response, NextFunction } from \"express\";\nimport getPropertyDescriptorForReqSession from \"../src/getPropertyDescriptorForReqSession\";\n\nexport function ironSession(\n sessionOptions: IronSessionOptions,\n): (req: Request, res: Response, next: NextFunction) => Promise<void> {\n return async function ironSessionMiddleware(req, res, next) {\n const session = await getIronSession(req, res, sessionOptions);\n Object.defineProperty(\n req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n\n next();\n };\n}\n","import type { IronSession } from \".\";\n\nexport default function getPropertyDescriptorForReqSession(\n session: IronSession,\n): PropertyDescriptor {\n return {\n enumerable: true,\n get() {\n return session;\n },\n set(value) {\n const keys = Object.keys(value);\n const currentKeys = Object.keys(session);\n\n currentKeys.forEach((key) => {\n if (!keys.includes(key)) {\n // @ts-ignore See comment in IronSessionData interface\n delete session[key];\n }\n });\n\n keys.forEach((key) => {\n // @ts-ignore See comment in IronSessionData interface\n session[key] = value[key];\n });\n },\n };\n}\n"],"mappings":";AACA,SAAS,sBAAsB;;;ACChB,SAAR,mCACL,SACoB;AACpB,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,MAAM;AACJ,aAAO;AAAA,IACT;AAAA,IACA,IAAI,OAAO;AACT,YAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,YAAM,cAAc,OAAO,KAAK,OAAO;AAEvC,kBAAY,QAAQ,CAAC,QAAQ;AAC3B,YAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AAEvB,iBAAO,QAAQ;AAAA,QACjB;AAAA,MACF,CAAC;AAED,WAAK,QAAQ,CAAC,QAAQ;AAEpB,gBAAQ,OAAO,MAAM;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ADtBO,SAAS,YACd,gBACoE;AACpE,SAAO,eAAe,sBAAsB,KAAK,KAAK,MAAM;AAC1D,UAAM,UAAU,MAAM,eAAe,KAAK,KAAK,cAAc;AAC7D,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,mCAAmC,OAAO;AAAA,IAC5C;AAEA,SAAK;AAAA,EACP;AACF;","names":[]}
|
package/express/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
2
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -50,7 +51,11 @@ function getPropertyDescriptorForReqSession(session) {
|
|
|
50
51
|
function ironSession(sessionOptions) {
|
|
51
52
|
return async function ironSessionMiddleware(req, res, next) {
|
|
52
53
|
const session = await (0, import_iron_session.getIronSession)(req, res, sessionOptions);
|
|
53
|
-
Object.defineProperty(
|
|
54
|
+
Object.defineProperty(
|
|
55
|
+
req,
|
|
56
|
+
"session",
|
|
57
|
+
getPropertyDescriptorForReqSession(session)
|
|
58
|
+
);
|
|
54
59
|
next();
|
|
55
60
|
};
|
|
56
61
|
}
|
package/express/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts","../../src/getPropertyDescriptorForReqSession.ts"],"sourcesContent":["import type { IronSessionOptions } from \"iron-session\";\nimport { getIronSession } from \"iron-session\";\nimport type { Request, Response, NextFunction } from \"express\";\nimport getPropertyDescriptorForReqSession from \"../src/getPropertyDescriptorForReqSession\";\n\nexport function ironSession(\n sessionOptions: IronSessionOptions,\n): (req: Request, res: Response, next: NextFunction) => Promise<void> {\n return async function ironSessionMiddleware(req, res, next) {\n const session = await getIronSession(req, res, sessionOptions);\n Object.defineProperty(\n req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n\n next();\n };\n}\n","import type { IronSession } from \".\";\n\nexport default function getPropertyDescriptorForReqSession(\n session: IronSession,\n): PropertyDescriptor {\n return {\n enumerable: true,\n get() {\n return session;\n },\n set(value) {\n const keys = Object.keys(value);\n const currentKeys = Object.keys(session);\n\n currentKeys.forEach((key) => {\n if (!keys.includes(key)) {\n // @ts-ignore See comment in IronSessionData interface\n delete session[key];\n }\n });\n\n keys.forEach((key) => {\n // @ts-ignore See comment in IronSessionData interface\n session[key] = value[key];\n });\n },\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../index.ts","../../src/getPropertyDescriptorForReqSession.ts"],"sourcesContent":["import type { IronSessionOptions } from \"iron-session\";\nimport { getIronSession } from \"iron-session\";\nimport type { Request, Response, NextFunction } from \"express\";\nimport getPropertyDescriptorForReqSession from \"../src/getPropertyDescriptorForReqSession\";\n\nexport function ironSession(\n sessionOptions: IronSessionOptions,\n): (req: Request, res: Response, next: NextFunction) => Promise<void> {\n return async function ironSessionMiddleware(req, res, next) {\n const session = await getIronSession(req, res, sessionOptions);\n Object.defineProperty(\n req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n\n next();\n };\n}\n","import type { IronSession } from \".\";\n\nexport default function getPropertyDescriptorForReqSession(\n session: IronSession,\n): PropertyDescriptor {\n return {\n enumerable: true,\n get() {\n return session;\n },\n set(value) {\n const keys = Object.keys(value);\n const currentKeys = Object.keys(session);\n\n currentKeys.forEach((key) => {\n if (!keys.includes(key)) {\n // @ts-ignore See comment in IronSessionData interface\n delete session[key];\n }\n });\n\n keys.forEach((key) => {\n // @ts-ignore See comment in IronSessionData interface\n session[key] = value[key];\n });\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,0BAA+B;;;ACChB,SAAR,mCACL,SACoB;AACpB,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,MAAM;AACJ,aAAO;AAAA,IACT;AAAA,IACA,IAAI,OAAO;AACT,YAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,YAAM,cAAc,OAAO,KAAK,OAAO;AAEvC,kBAAY,QAAQ,CAAC,QAAQ;AAC3B,YAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AAEvB,iBAAO,QAAQ;AAAA,QACjB;AAAA,MACF,CAAC;AAED,WAAK,QAAQ,CAAC,QAAQ;AAEpB,gBAAQ,OAAO,MAAM;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ADtBO,SAAS,YACd,gBACoE;AACpE,SAAO,eAAe,sBAAsB,KAAK,KAAK,MAAM;AAC1D,UAAM,UAAU,UAAM,oCAAe,KAAK,KAAK,cAAc;AAC7D,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,mCAAmC,OAAO;AAAA,IAC5C;AAEA,SAAK;AAAA,EACP;AACF;","names":[]}
|
package/express/index.mjs
CHANGED
|
@@ -27,7 +27,11 @@ function getPropertyDescriptorForReqSession(session) {
|
|
|
27
27
|
function ironSession(sessionOptions) {
|
|
28
28
|
return async function ironSessionMiddleware(req, res, next) {
|
|
29
29
|
const session = await getIronSession(req, res, sessionOptions);
|
|
30
|
-
Object.defineProperty(
|
|
30
|
+
Object.defineProperty(
|
|
31
|
+
req,
|
|
32
|
+
"session",
|
|
33
|
+
getPropertyDescriptorForReqSession(session)
|
|
34
|
+
);
|
|
31
35
|
next();
|
|
32
36
|
};
|
|
33
37
|
}
|
package/express/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts","../../src/getPropertyDescriptorForReqSession.ts"],"sourcesContent":["import type { IronSessionOptions } from \"iron-session\";\nimport { getIronSession } from \"iron-session\";\nimport type { Request, Response, NextFunction } from \"express\";\nimport getPropertyDescriptorForReqSession from \"../src/getPropertyDescriptorForReqSession\";\n\nexport function ironSession(\n sessionOptions: IronSessionOptions,\n): (req: Request, res: Response, next: NextFunction) => Promise<void> {\n return async function ironSessionMiddleware(req, res, next) {\n const session = await getIronSession(req, res, sessionOptions);\n Object.defineProperty(\n req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n\n next();\n };\n}\n","import type { IronSession } from \".\";\n\nexport default function getPropertyDescriptorForReqSession(\n session: IronSession,\n): PropertyDescriptor {\n return {\n enumerable: true,\n get() {\n return session;\n },\n set(value) {\n const keys = Object.keys(value);\n const currentKeys = Object.keys(session);\n\n currentKeys.forEach((key) => {\n if (!keys.includes(key)) {\n // @ts-ignore See comment in IronSessionData interface\n delete session[key];\n }\n });\n\n keys.forEach((key) => {\n // @ts-ignore See comment in IronSessionData interface\n session[key] = value[key];\n });\n },\n };\n}\n"],"mappings":";AACA;;;
|
|
1
|
+
{"version":3,"sources":["../index.ts","../../src/getPropertyDescriptorForReqSession.ts"],"sourcesContent":["import type { IronSessionOptions } from \"iron-session\";\nimport { getIronSession } from \"iron-session\";\nimport type { Request, Response, NextFunction } from \"express\";\nimport getPropertyDescriptorForReqSession from \"../src/getPropertyDescriptorForReqSession\";\n\nexport function ironSession(\n sessionOptions: IronSessionOptions,\n): (req: Request, res: Response, next: NextFunction) => Promise<void> {\n return async function ironSessionMiddleware(req, res, next) {\n const session = await getIronSession(req, res, sessionOptions);\n Object.defineProperty(\n req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n\n next();\n };\n}\n","import type { IronSession } from \".\";\n\nexport default function getPropertyDescriptorForReqSession(\n session: IronSession,\n): PropertyDescriptor {\n return {\n enumerable: true,\n get() {\n return session;\n },\n set(value) {\n const keys = Object.keys(value);\n const currentKeys = Object.keys(session);\n\n currentKeys.forEach((key) => {\n if (!keys.includes(key)) {\n // @ts-ignore See comment in IronSessionData interface\n delete session[key];\n }\n });\n\n keys.forEach((key) => {\n // @ts-ignore See comment in IronSessionData interface\n session[key] = value[key];\n });\n },\n };\n}\n"],"mappings":";AACA,SAAS,sBAAsB;;;ACChB,SAAR,mCACL,SACoB;AACpB,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,MAAM;AACJ,aAAO;AAAA,IACT;AAAA,IACA,IAAI,OAAO;AACT,YAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,YAAM,cAAc,OAAO,KAAK,OAAO;AAEvC,kBAAY,QAAQ,CAAC,QAAQ;AAC3B,YAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AAEvB,iBAAO,QAAQ;AAAA,QACjB;AAAA,MACF,CAAC;AAED,WAAK,QAAQ,CAAC,QAAQ;AAEpB,gBAAQ,OAAO,MAAM;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ADtBO,SAAS,YACd,gBACoE;AACpE,SAAO,eAAe,sBAAsB,KAAK,KAAK,MAAM;AAC1D,UAAM,UAAU,MAAM,eAAe,KAAK,KAAK,cAAc;AAC7D,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,mCAAmC,OAAO;AAAA,IAC5C;AAEA,SAAK;AAAA,EACP;AACF;","names":[]}
|
package/next/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
2
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -57,7 +58,11 @@ function withIronSessionApiRoute(handler, options) {
|
|
|
57
58
|
sessionOptions = options;
|
|
58
59
|
}
|
|
59
60
|
const session = await (0, import_iron_session.getIronSession)(req, res, sessionOptions);
|
|
60
|
-
Object.defineProperty(
|
|
61
|
+
Object.defineProperty(
|
|
62
|
+
req,
|
|
63
|
+
"session",
|
|
64
|
+
getPropertyDescriptorForReqSession(session)
|
|
65
|
+
);
|
|
61
66
|
return handler(req, res);
|
|
62
67
|
};
|
|
63
68
|
}
|
|
@@ -69,8 +74,16 @@ function withIronSessionSsr(handler, options) {
|
|
|
69
74
|
} else {
|
|
70
75
|
sessionOptions = options;
|
|
71
76
|
}
|
|
72
|
-
const session = await (0, import_iron_session.getIronSession)(
|
|
73
|
-
|
|
77
|
+
const session = await (0, import_iron_session.getIronSession)(
|
|
78
|
+
context.req,
|
|
79
|
+
context.res,
|
|
80
|
+
sessionOptions
|
|
81
|
+
);
|
|
82
|
+
Object.defineProperty(
|
|
83
|
+
context.req,
|
|
84
|
+
"session",
|
|
85
|
+
getPropertyDescriptorForReqSession(session)
|
|
86
|
+
);
|
|
74
87
|
return handler(context);
|
|
75
88
|
};
|
|
76
89
|
}
|
package/next/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts","../../src/getPropertyDescriptorForReqSession.ts"],"sourcesContent":["import type {\n NextApiHandler,\n GetServerSidePropsContext,\n GetServerSidePropsResult,\n NextApiRequest,\n NextApiResponse,\n} from \"next\";\nimport type { IronSessionOptions } from \"iron-session\";\nimport { getIronSession } from \"iron-session\";\nimport getPropertyDescriptorForReqSession from \"../src/getPropertyDescriptorForReqSession\";\nimport { IncomingMessage, ServerResponse } from \"http\";\n\n// Argument types based on getIronSession function\ntype GetIronSessionApiOptions = (\n request: NextApiRequest,\n response: NextApiResponse,\n) => Promise<IronSessionOptions> | IronSessionOptions;\n\nexport function withIronSessionApiRoute(\n handler: NextApiHandler,\n options: IronSessionOptions | GetIronSessionApiOptions,\n): NextApiHandler {\n return async function nextApiHandlerWrappedWithIronSession(req, res) {\n let sessionOptions: IronSessionOptions;\n\n // If options is a function, call it and assign the results back.\n if (options instanceof Function) {\n sessionOptions = await options(req, res);\n } else {\n sessionOptions = options;\n }\n\n const session = await getIronSession(req, res, sessionOptions);\n\n // we define req.session as being enumerable (so console.log(req) shows it)\n // and we also want to allow people to do:\n // req.session = { admin: true }; or req.session = {...req.session, admin: true};\n // req.session.save();\n Object.defineProperty(\n req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n return handler(req, res);\n };\n}\n\n// Argument type based on the SSR context\ntype GetIronSessionSSROptions = (\n request: IncomingMessage,\n response: ServerResponse,\n) => Promise<IronSessionOptions> | IronSessionOptions;\n\nexport function withIronSessionSsr<\n P extends { [key: string]: unknown } = { [key: string]: unknown },\n>(\n handler: (\n context: GetServerSidePropsContext,\n ) => GetServerSidePropsResult<P> | Promise<GetServerSidePropsResult<P>>,\n options: IronSessionOptions | GetIronSessionSSROptions,\n) {\n return async function nextGetServerSidePropsHandlerWrappedWithIronSession(\n context: GetServerSidePropsContext,\n ) {\n let sessionOptions: IronSessionOptions;\n\n // If options is a function, call it and assign the results back.\n if (options instanceof Function) {\n sessionOptions = await options(context.req, context.res);\n } else {\n sessionOptions = options;\n }\n\n const session = await getIronSession(\n context.req,\n context.res,\n sessionOptions,\n );\n\n Object.defineProperty(\n context.req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n return handler(context);\n };\n}\n","import type { IronSession } from \".\";\n\nexport default function getPropertyDescriptorForReqSession(\n session: IronSession,\n): PropertyDescriptor {\n return {\n enumerable: true,\n get() {\n return session;\n },\n set(value) {\n const keys = Object.keys(value);\n const currentKeys = Object.keys(session);\n\n currentKeys.forEach((key) => {\n if (!keys.includes(key)) {\n // @ts-ignore See comment in IronSessionData interface\n delete session[key];\n }\n });\n\n keys.forEach((key) => {\n // @ts-ignore See comment in IronSessionData interface\n session[key] = value[key];\n });\n },\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../index.ts","../../src/getPropertyDescriptorForReqSession.ts"],"sourcesContent":["import type {\n NextApiHandler,\n GetServerSidePropsContext,\n GetServerSidePropsResult,\n NextApiRequest,\n NextApiResponse,\n} from \"next\";\nimport type { IronSessionOptions } from \"iron-session\";\nimport { getIronSession } from \"iron-session\";\nimport getPropertyDescriptorForReqSession from \"../src/getPropertyDescriptorForReqSession\";\nimport { IncomingMessage, ServerResponse } from \"http\";\n\n// Argument types based on getIronSession function\ntype GetIronSessionApiOptions = (\n request: NextApiRequest,\n response: NextApiResponse,\n) => Promise<IronSessionOptions> | IronSessionOptions;\n\nexport function withIronSessionApiRoute(\n handler: NextApiHandler,\n options: IronSessionOptions | GetIronSessionApiOptions,\n): NextApiHandler {\n return async function nextApiHandlerWrappedWithIronSession(req, res) {\n let sessionOptions: IronSessionOptions;\n\n // If options is a function, call it and assign the results back.\n if (options instanceof Function) {\n sessionOptions = await options(req, res);\n } else {\n sessionOptions = options;\n }\n\n const session = await getIronSession(req, res, sessionOptions);\n\n // we define req.session as being enumerable (so console.log(req) shows it)\n // and we also want to allow people to do:\n // req.session = { admin: true }; or req.session = {...req.session, admin: true};\n // req.session.save();\n Object.defineProperty(\n req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n return handler(req, res);\n };\n}\n\n// Argument type based on the SSR context\ntype GetIronSessionSSROptions = (\n request: IncomingMessage,\n response: ServerResponse,\n) => Promise<IronSessionOptions> | IronSessionOptions;\n\nexport function withIronSessionSsr<\n P extends { [key: string]: unknown } = { [key: string]: unknown },\n>(\n handler: (\n context: GetServerSidePropsContext,\n ) => GetServerSidePropsResult<P> | Promise<GetServerSidePropsResult<P>>,\n options: IronSessionOptions | GetIronSessionSSROptions,\n) {\n return async function nextGetServerSidePropsHandlerWrappedWithIronSession(\n context: GetServerSidePropsContext,\n ) {\n let sessionOptions: IronSessionOptions;\n\n // If options is a function, call it and assign the results back.\n if (options instanceof Function) {\n sessionOptions = await options(context.req, context.res);\n } else {\n sessionOptions = options;\n }\n\n const session = await getIronSession(\n context.req,\n context.res,\n sessionOptions,\n );\n\n Object.defineProperty(\n context.req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n return handler(context);\n };\n}\n","import type { IronSession } from \".\";\n\nexport default function getPropertyDescriptorForReqSession(\n session: IronSession,\n): PropertyDescriptor {\n return {\n enumerable: true,\n get() {\n return session;\n },\n set(value) {\n const keys = Object.keys(value);\n const currentKeys = Object.keys(session);\n\n currentKeys.forEach((key) => {\n if (!keys.includes(key)) {\n // @ts-ignore See comment in IronSessionData interface\n delete session[key];\n }\n });\n\n keys.forEach((key) => {\n // @ts-ignore See comment in IronSessionData interface\n session[key] = value[key];\n });\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,0BAA+B;;;ACNhB,SAAR,mCACL,SACoB;AACpB,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,MAAM;AACJ,aAAO;AAAA,IACT;AAAA,IACA,IAAI,OAAO;AACT,YAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,YAAM,cAAc,OAAO,KAAK,OAAO;AAEvC,kBAAY,QAAQ,CAAC,QAAQ;AAC3B,YAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AAEvB,iBAAO,QAAQ;AAAA,QACjB;AAAA,MACF,CAAC;AAED,WAAK,QAAQ,CAAC,QAAQ;AAEpB,gBAAQ,OAAO,MAAM;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ADTO,SAAS,wBACd,SACA,SACgB;AAChB,SAAO,eAAe,qCAAqC,KAAK,KAAK;AACnE,QAAI;AAGJ,QAAI,mBAAmB,UAAU;AAC/B,uBAAiB,MAAM,QAAQ,KAAK,GAAG;AAAA,IACzC,OAAO;AACL,uBAAiB;AAAA,IACnB;AAEA,UAAM,UAAU,UAAM,oCAAe,KAAK,KAAK,cAAc;AAM7D,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,mCAAmC,OAAO;AAAA,IAC5C;AACA,WAAO,QAAQ,KAAK,GAAG;AAAA,EACzB;AACF;AAQO,SAAS,mBAGd,SAGA,SACA;AACA,SAAO,eAAe,oDACpB,SACA;AACA,QAAI;AAGJ,QAAI,mBAAmB,UAAU;AAC/B,uBAAiB,MAAM,QAAQ,QAAQ,KAAK,QAAQ,GAAG;AAAA,IACzD,OAAO;AACL,uBAAiB;AAAA,IACnB;AAEA,UAAM,UAAU,UAAM;AAAA,MACpB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,IACF;AAEA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR;AAAA,MACA,mCAAmC,OAAO;AAAA,IAC5C;AACA,WAAO,QAAQ,OAAO;AAAA,EACxB;AACF;","names":[]}
|
package/next/dist/index.mjs
CHANGED
|
@@ -33,7 +33,11 @@ function withIronSessionApiRoute(handler, options) {
|
|
|
33
33
|
sessionOptions = options;
|
|
34
34
|
}
|
|
35
35
|
const session = await getIronSession(req, res, sessionOptions);
|
|
36
|
-
Object.defineProperty(
|
|
36
|
+
Object.defineProperty(
|
|
37
|
+
req,
|
|
38
|
+
"session",
|
|
39
|
+
getPropertyDescriptorForReqSession(session)
|
|
40
|
+
);
|
|
37
41
|
return handler(req, res);
|
|
38
42
|
};
|
|
39
43
|
}
|
|
@@ -45,8 +49,16 @@ function withIronSessionSsr(handler, options) {
|
|
|
45
49
|
} else {
|
|
46
50
|
sessionOptions = options;
|
|
47
51
|
}
|
|
48
|
-
const session = await getIronSession(
|
|
49
|
-
|
|
52
|
+
const session = await getIronSession(
|
|
53
|
+
context.req,
|
|
54
|
+
context.res,
|
|
55
|
+
sessionOptions
|
|
56
|
+
);
|
|
57
|
+
Object.defineProperty(
|
|
58
|
+
context.req,
|
|
59
|
+
"session",
|
|
60
|
+
getPropertyDescriptorForReqSession(session)
|
|
61
|
+
);
|
|
50
62
|
return handler(context);
|
|
51
63
|
};
|
|
52
64
|
}
|
package/next/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts","../../src/getPropertyDescriptorForReqSession.ts"],"sourcesContent":["import type {\n NextApiHandler,\n GetServerSidePropsContext,\n GetServerSidePropsResult,\n NextApiRequest,\n NextApiResponse,\n} from \"next\";\nimport type { IronSessionOptions } from \"iron-session\";\nimport { getIronSession } from \"iron-session\";\nimport getPropertyDescriptorForReqSession from \"../src/getPropertyDescriptorForReqSession\";\nimport { IncomingMessage, ServerResponse } from \"http\";\n\n// Argument types based on getIronSession function\ntype GetIronSessionApiOptions = (\n request: NextApiRequest,\n response: NextApiResponse,\n) => Promise<IronSessionOptions> | IronSessionOptions;\n\nexport function withIronSessionApiRoute(\n handler: NextApiHandler,\n options: IronSessionOptions | GetIronSessionApiOptions,\n): NextApiHandler {\n return async function nextApiHandlerWrappedWithIronSession(req, res) {\n let sessionOptions: IronSessionOptions;\n\n // If options is a function, call it and assign the results back.\n if (options instanceof Function) {\n sessionOptions = await options(req, res);\n } else {\n sessionOptions = options;\n }\n\n const session = await getIronSession(req, res, sessionOptions);\n\n // we define req.session as being enumerable (so console.log(req) shows it)\n // and we also want to allow people to do:\n // req.session = { admin: true }; or req.session = {...req.session, admin: true};\n // req.session.save();\n Object.defineProperty(\n req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n return handler(req, res);\n };\n}\n\n// Argument type based on the SSR context\ntype GetIronSessionSSROptions = (\n request: IncomingMessage,\n response: ServerResponse,\n) => Promise<IronSessionOptions> | IronSessionOptions;\n\nexport function withIronSessionSsr<\n P extends { [key: string]: unknown } = { [key: string]: unknown },\n>(\n handler: (\n context: GetServerSidePropsContext,\n ) => GetServerSidePropsResult<P> | Promise<GetServerSidePropsResult<P>>,\n options: IronSessionOptions | GetIronSessionSSROptions,\n) {\n return async function nextGetServerSidePropsHandlerWrappedWithIronSession(\n context: GetServerSidePropsContext,\n ) {\n let sessionOptions: IronSessionOptions;\n\n // If options is a function, call it and assign the results back.\n if (options instanceof Function) {\n sessionOptions = await options(context.req, context.res);\n } else {\n sessionOptions = options;\n }\n\n const session = await getIronSession(\n context.req,\n context.res,\n sessionOptions,\n );\n\n Object.defineProperty(\n context.req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n return handler(context);\n };\n}\n","import type { IronSession } from \".\";\n\nexport default function getPropertyDescriptorForReqSession(\n session: IronSession,\n): PropertyDescriptor {\n return {\n enumerable: true,\n get() {\n return session;\n },\n set(value) {\n const keys = Object.keys(value);\n const currentKeys = Object.keys(session);\n\n currentKeys.forEach((key) => {\n if (!keys.includes(key)) {\n // @ts-ignore See comment in IronSessionData interface\n delete session[key];\n }\n });\n\n keys.forEach((key) => {\n // @ts-ignore See comment in IronSessionData interface\n session[key] = value[key];\n });\n },\n };\n}\n"],"mappings":";AAQA;;;
|
|
1
|
+
{"version":3,"sources":["../index.ts","../../src/getPropertyDescriptorForReqSession.ts"],"sourcesContent":["import type {\n NextApiHandler,\n GetServerSidePropsContext,\n GetServerSidePropsResult,\n NextApiRequest,\n NextApiResponse,\n} from \"next\";\nimport type { IronSessionOptions } from \"iron-session\";\nimport { getIronSession } from \"iron-session\";\nimport getPropertyDescriptorForReqSession from \"../src/getPropertyDescriptorForReqSession\";\nimport { IncomingMessage, ServerResponse } from \"http\";\n\n// Argument types based on getIronSession function\ntype GetIronSessionApiOptions = (\n request: NextApiRequest,\n response: NextApiResponse,\n) => Promise<IronSessionOptions> | IronSessionOptions;\n\nexport function withIronSessionApiRoute(\n handler: NextApiHandler,\n options: IronSessionOptions | GetIronSessionApiOptions,\n): NextApiHandler {\n return async function nextApiHandlerWrappedWithIronSession(req, res) {\n let sessionOptions: IronSessionOptions;\n\n // If options is a function, call it and assign the results back.\n if (options instanceof Function) {\n sessionOptions = await options(req, res);\n } else {\n sessionOptions = options;\n }\n\n const session = await getIronSession(req, res, sessionOptions);\n\n // we define req.session as being enumerable (so console.log(req) shows it)\n // and we also want to allow people to do:\n // req.session = { admin: true }; or req.session = {...req.session, admin: true};\n // req.session.save();\n Object.defineProperty(\n req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n return handler(req, res);\n };\n}\n\n// Argument type based on the SSR context\ntype GetIronSessionSSROptions = (\n request: IncomingMessage,\n response: ServerResponse,\n) => Promise<IronSessionOptions> | IronSessionOptions;\n\nexport function withIronSessionSsr<\n P extends { [key: string]: unknown } = { [key: string]: unknown },\n>(\n handler: (\n context: GetServerSidePropsContext,\n ) => GetServerSidePropsResult<P> | Promise<GetServerSidePropsResult<P>>,\n options: IronSessionOptions | GetIronSessionSSROptions,\n) {\n return async function nextGetServerSidePropsHandlerWrappedWithIronSession(\n context: GetServerSidePropsContext,\n ) {\n let sessionOptions: IronSessionOptions;\n\n // If options is a function, call it and assign the results back.\n if (options instanceof Function) {\n sessionOptions = await options(context.req, context.res);\n } else {\n sessionOptions = options;\n }\n\n const session = await getIronSession(\n context.req,\n context.res,\n sessionOptions,\n );\n\n Object.defineProperty(\n context.req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n return handler(context);\n };\n}\n","import type { IronSession } from \".\";\n\nexport default function getPropertyDescriptorForReqSession(\n session: IronSession,\n): PropertyDescriptor {\n return {\n enumerable: true,\n get() {\n return session;\n },\n set(value) {\n const keys = Object.keys(value);\n const currentKeys = Object.keys(session);\n\n currentKeys.forEach((key) => {\n if (!keys.includes(key)) {\n // @ts-ignore See comment in IronSessionData interface\n delete session[key];\n }\n });\n\n keys.forEach((key) => {\n // @ts-ignore See comment in IronSessionData interface\n session[key] = value[key];\n });\n },\n };\n}\n"],"mappings":";AAQA,SAAS,sBAAsB;;;ACNhB,SAAR,mCACL,SACoB;AACpB,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,MAAM;AACJ,aAAO;AAAA,IACT;AAAA,IACA,IAAI,OAAO;AACT,YAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,YAAM,cAAc,OAAO,KAAK,OAAO;AAEvC,kBAAY,QAAQ,CAAC,QAAQ;AAC3B,YAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AAEvB,iBAAO,QAAQ;AAAA,QACjB;AAAA,MACF,CAAC;AAED,WAAK,QAAQ,CAAC,QAAQ;AAEpB,gBAAQ,OAAO,MAAM;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ADTO,SAAS,wBACd,SACA,SACgB;AAChB,SAAO,eAAe,qCAAqC,KAAK,KAAK;AACnE,QAAI;AAGJ,QAAI,mBAAmB,UAAU;AAC/B,uBAAiB,MAAM,QAAQ,KAAK,GAAG;AAAA,IACzC,OAAO;AACL,uBAAiB;AAAA,IACnB;AAEA,UAAM,UAAU,MAAM,eAAe,KAAK,KAAK,cAAc;AAM7D,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,mCAAmC,OAAO;AAAA,IAC5C;AACA,WAAO,QAAQ,KAAK,GAAG;AAAA,EACzB;AACF;AAQO,SAAS,mBAGd,SAGA,SACA;AACA,SAAO,eAAe,oDACpB,SACA;AACA,QAAI;AAGJ,QAAI,mBAAmB,UAAU;AAC/B,uBAAiB,MAAM,QAAQ,QAAQ,KAAK,QAAQ,GAAG;AAAA,IACzD,OAAO;AACL,uBAAiB;AAAA,IACnB;AAEA,UAAM,UAAU,MAAM;AAAA,MACpB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,IACF;AAEA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR;AAAA,MACA,mCAAmC,OAAO;AAAA,IAC5C;AACA,WAAO,QAAQ,OAAO;AAAA,EACxB;AACF;","names":[]}
|
package/next/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
2
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -57,7 +58,11 @@ function withIronSessionApiRoute(handler, options) {
|
|
|
57
58
|
sessionOptions = options;
|
|
58
59
|
}
|
|
59
60
|
const session = await (0, import_iron_session.getIronSession)(req, res, sessionOptions);
|
|
60
|
-
Object.defineProperty(
|
|
61
|
+
Object.defineProperty(
|
|
62
|
+
req,
|
|
63
|
+
"session",
|
|
64
|
+
getPropertyDescriptorForReqSession(session)
|
|
65
|
+
);
|
|
61
66
|
return handler(req, res);
|
|
62
67
|
};
|
|
63
68
|
}
|
|
@@ -69,8 +74,16 @@ function withIronSessionSsr(handler, options) {
|
|
|
69
74
|
} else {
|
|
70
75
|
sessionOptions = options;
|
|
71
76
|
}
|
|
72
|
-
const session = await (0, import_iron_session.getIronSession)(
|
|
73
|
-
|
|
77
|
+
const session = await (0, import_iron_session.getIronSession)(
|
|
78
|
+
context.req,
|
|
79
|
+
context.res,
|
|
80
|
+
sessionOptions
|
|
81
|
+
);
|
|
82
|
+
Object.defineProperty(
|
|
83
|
+
context.req,
|
|
84
|
+
"session",
|
|
85
|
+
getPropertyDescriptorForReqSession(session)
|
|
86
|
+
);
|
|
74
87
|
return handler(context);
|
|
75
88
|
};
|
|
76
89
|
}
|
package/next/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts","../../src/getPropertyDescriptorForReqSession.ts"],"sourcesContent":["import type {\n NextApiHandler,\n GetServerSidePropsContext,\n GetServerSidePropsResult,\n NextApiRequest,\n NextApiResponse,\n} from \"next\";\nimport type { IronSessionOptions } from \"iron-session\";\nimport { getIronSession } from \"iron-session\";\nimport getPropertyDescriptorForReqSession from \"../src/getPropertyDescriptorForReqSession\";\nimport { IncomingMessage, ServerResponse } from \"http\";\n\n// Argument types based on getIronSession function\ntype GetIronSessionApiOptions = (\n request: NextApiRequest,\n response: NextApiResponse,\n) => Promise<IronSessionOptions> | IronSessionOptions;\n\nexport function withIronSessionApiRoute(\n handler: NextApiHandler,\n options: IronSessionOptions | GetIronSessionApiOptions,\n): NextApiHandler {\n return async function nextApiHandlerWrappedWithIronSession(req, res) {\n let sessionOptions: IronSessionOptions;\n\n // If options is a function, call it and assign the results back.\n if (options instanceof Function) {\n sessionOptions = await options(req, res);\n } else {\n sessionOptions = options;\n }\n\n const session = await getIronSession(req, res, sessionOptions);\n\n // we define req.session as being enumerable (so console.log(req) shows it)\n // and we also want to allow people to do:\n // req.session = { admin: true }; or req.session = {...req.session, admin: true};\n // req.session.save();\n Object.defineProperty(\n req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n return handler(req, res);\n };\n}\n\n// Argument type based on the SSR context\ntype GetIronSessionSSROptions = (\n request: IncomingMessage,\n response: ServerResponse,\n) => Promise<IronSessionOptions> | IronSessionOptions;\n\nexport function withIronSessionSsr<\n P extends { [key: string]: unknown } = { [key: string]: unknown },\n>(\n handler: (\n context: GetServerSidePropsContext,\n ) => GetServerSidePropsResult<P> | Promise<GetServerSidePropsResult<P>>,\n options: IronSessionOptions | GetIronSessionSSROptions,\n) {\n return async function nextGetServerSidePropsHandlerWrappedWithIronSession(\n context: GetServerSidePropsContext,\n ) {\n let sessionOptions: IronSessionOptions;\n\n // If options is a function, call it and assign the results back.\n if (options instanceof Function) {\n sessionOptions = await options(context.req, context.res);\n } else {\n sessionOptions = options;\n }\n\n const session = await getIronSession(\n context.req,\n context.res,\n sessionOptions,\n );\n\n Object.defineProperty(\n context.req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n return handler(context);\n };\n}\n","import type { IronSession } from \".\";\n\nexport default function getPropertyDescriptorForReqSession(\n session: IronSession,\n): PropertyDescriptor {\n return {\n enumerable: true,\n get() {\n return session;\n },\n set(value) {\n const keys = Object.keys(value);\n const currentKeys = Object.keys(session);\n\n currentKeys.forEach((key) => {\n if (!keys.includes(key)) {\n // @ts-ignore See comment in IronSessionData interface\n delete session[key];\n }\n });\n\n keys.forEach((key) => {\n // @ts-ignore See comment in IronSessionData interface\n session[key] = value[key];\n });\n },\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../index.ts","../../src/getPropertyDescriptorForReqSession.ts"],"sourcesContent":["import type {\n NextApiHandler,\n GetServerSidePropsContext,\n GetServerSidePropsResult,\n NextApiRequest,\n NextApiResponse,\n} from \"next\";\nimport type { IronSessionOptions } from \"iron-session\";\nimport { getIronSession } from \"iron-session\";\nimport getPropertyDescriptorForReqSession from \"../src/getPropertyDescriptorForReqSession\";\nimport { IncomingMessage, ServerResponse } from \"http\";\n\n// Argument types based on getIronSession function\ntype GetIronSessionApiOptions = (\n request: NextApiRequest,\n response: NextApiResponse,\n) => Promise<IronSessionOptions> | IronSessionOptions;\n\nexport function withIronSessionApiRoute(\n handler: NextApiHandler,\n options: IronSessionOptions | GetIronSessionApiOptions,\n): NextApiHandler {\n return async function nextApiHandlerWrappedWithIronSession(req, res) {\n let sessionOptions: IronSessionOptions;\n\n // If options is a function, call it and assign the results back.\n if (options instanceof Function) {\n sessionOptions = await options(req, res);\n } else {\n sessionOptions = options;\n }\n\n const session = await getIronSession(req, res, sessionOptions);\n\n // we define req.session as being enumerable (so console.log(req) shows it)\n // and we also want to allow people to do:\n // req.session = { admin: true }; or req.session = {...req.session, admin: true};\n // req.session.save();\n Object.defineProperty(\n req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n return handler(req, res);\n };\n}\n\n// Argument type based on the SSR context\ntype GetIronSessionSSROptions = (\n request: IncomingMessage,\n response: ServerResponse,\n) => Promise<IronSessionOptions> | IronSessionOptions;\n\nexport function withIronSessionSsr<\n P extends { [key: string]: unknown } = { [key: string]: unknown },\n>(\n handler: (\n context: GetServerSidePropsContext,\n ) => GetServerSidePropsResult<P> | Promise<GetServerSidePropsResult<P>>,\n options: IronSessionOptions | GetIronSessionSSROptions,\n) {\n return async function nextGetServerSidePropsHandlerWrappedWithIronSession(\n context: GetServerSidePropsContext,\n ) {\n let sessionOptions: IronSessionOptions;\n\n // If options is a function, call it and assign the results back.\n if (options instanceof Function) {\n sessionOptions = await options(context.req, context.res);\n } else {\n sessionOptions = options;\n }\n\n const session = await getIronSession(\n context.req,\n context.res,\n sessionOptions,\n );\n\n Object.defineProperty(\n context.req,\n \"session\",\n getPropertyDescriptorForReqSession(session),\n );\n return handler(context);\n };\n}\n","import type { IronSession } from \".\";\n\nexport default function getPropertyDescriptorForReqSession(\n session: IronSession,\n): PropertyDescriptor {\n return {\n enumerable: true,\n get() {\n return session;\n },\n set(value) {\n const keys = Object.keys(value);\n const currentKeys = Object.keys(session);\n\n currentKeys.forEach((key) => {\n if (!keys.includes(key)) {\n // @ts-ignore See comment in IronSessionData interface\n delete session[key];\n }\n });\n\n keys.forEach((key) => {\n // @ts-ignore See comment in IronSessionData interface\n session[key] = value[key];\n });\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,0BAA+B;;;ACNhB,SAAR,mCACL,SACoB;AACpB,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,MAAM;AACJ,aAAO;AAAA,IACT;AAAA,IACA,IAAI,OAAO;AACT,YAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,YAAM,cAAc,OAAO,KAAK,OAAO;AAEvC,kBAAY,QAAQ,CAAC,QAAQ;AAC3B,YAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AAEvB,iBAAO,QAAQ;AAAA,QACjB;AAAA,MACF,CAAC;AAED,WAAK,QAAQ,CAAC,QAAQ;AAEpB,gBAAQ,OAAO,MAAM;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ADTO,SAAS,wBACd,SACA,SACgB;AAChB,SAAO,eAAe,qCAAqC,KAAK,KAAK;AACnE,QAAI;AAGJ,QAAI,mBAAmB,UAAU;AAC/B,uBAAiB,MAAM,QAAQ,KAAK,GAAG;AAAA,IACzC,OAAO;AACL,uBAAiB;AAAA,IACnB;AAEA,UAAM,UAAU,UAAM,oCAAe,KAAK,KAAK,cAAc;AAM7D,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,mCAAmC,OAAO;AAAA,IAC5C;AACA,WAAO,QAAQ,KAAK,GAAG;AAAA,EACzB;AACF;AAQO,SAAS,mBAGd,SAGA,SACA;AACA,SAAO,eAAe,oDACpB,SACA;AACA,QAAI;AAGJ,QAAI,mBAAmB,UAAU;AAC/B,uBAAiB,MAAM,QAAQ,QAAQ,KAAK,QAAQ,GAAG;AAAA,IACzD,OAAO;AACL,uBAAiB;AAAA,IACnB;AAEA,UAAM,UAAU,UAAM;AAAA,MACpB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,IACF;AAEA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR;AAAA,MACA,mCAAmC,OAAO;AAAA,IAC5C;AACA,WAAO,QAAQ,OAAO;AAAA,EACxB;AACF;","names":[]}
|