@sqrzro/server 2.0.0-bz.29 → 2.0.0-bz.30
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/dist/auth/index.cjs +59 -0
- package/dist/auth/index.cjs.map +1 -0
- package/dist/auth/index.d.cts +100 -0
- package/dist/auth/index.d.ts +100 -6
- package/dist/auth/index.js +21 -6
- package/dist/auth/index.js.map +1 -0
- package/dist/cache/index.cjs +10 -0
- package/dist/cache/index.cjs.map +1 -0
- package/dist/cache/index.d.cts +4 -0
- package/dist/cache/index.d.ts +4 -1
- package/dist/cache/index.js +7 -1
- package/dist/cache/index.js.map +1 -0
- package/dist/database/schema.cjs +16 -0
- package/dist/database/schema.cjs.map +1 -0
- package/dist/database/schema.d.cts +288 -0
- package/dist/database/schema.d.ts +38 -34
- package/dist/database/schema.js +7 -42
- package/dist/database/schema.js.map +1 -0
- package/dist/forms/index.cjs +22 -0
- package/dist/forms/index.cjs.map +1 -0
- package/dist/forms/index.d.cts +50 -0
- package/dist/forms/index.d.ts +50 -3
- package/dist/forms/index.js +8 -3
- package/dist/forms/index.js.map +1 -0
- package/dist/lists/index.cjs +9 -0
- package/dist/lists/index.cjs.map +1 -0
- package/dist/lists/{ListService.d.ts → index.d.cts} +5 -3
- package/dist/lists/index.d.ts +18 -1
- package/dist/lists/index.js +7 -1
- package/dist/lists/index.js.map +1 -0
- package/dist/mail/index.cjs +9 -0
- package/dist/mail/index.cjs.map +1 -0
- package/dist/mail/index.d.cts +13 -0
- package/dist/mail/index.d.ts +13 -1
- package/dist/mail/index.js +5 -1
- package/dist/mail/index.js.map +1 -0
- package/dist/middleware.cjs +9 -0
- package/dist/middleware.cjs.map +1 -0
- package/dist/middleware.d.cts +5 -0
- package/dist/middleware.d.ts +5 -3
- package/dist/middleware.js +6 -45
- package/dist/middleware.js.map +1 -0
- package/dist/url/index.cjs +12 -0
- package/dist/url/index.cjs.map +1 -0
- package/dist/url/{URLService.d.ts → index.d.cts} +6 -4
- package/dist/url/index.d.ts +33 -1
- package/dist/url/index.js +7 -1
- package/dist/url/index.js.map +1 -0
- package/jest.config.js +7 -0
- package/package.json +56 -29
- package/dist/auth/AuthService.d.ts +0 -14
- package/dist/auth/AuthService.js +0 -135
- package/dist/auth/ClientService.d.ts +0 -11
- package/dist/auth/ClientService.js +0 -47
- package/dist/auth/LoginRequest.d.ts +0 -4
- package/dist/auth/LoginRequest.js +0 -8
- package/dist/auth/MFARequest.d.ts +0 -4
- package/dist/auth/MFARequest.js +0 -9
- package/dist/auth/MFAService.d.ts +0 -6
- package/dist/auth/MFAService.js +0 -105
- package/dist/auth/PasswordRequest.d.ts +0 -4
- package/dist/auth/PasswordRequest.js +0 -12
- package/dist/auth/PasswordResetRequest.d.ts +0 -4
- package/dist/auth/PasswordResetRequest.js +0 -13
- package/dist/auth/PasswordService.d.ts +0 -8
- package/dist/auth/PasswordService.js +0 -54
- package/dist/auth/SessionService.d.ts +0 -42
- package/dist/auth/SessionService.js +0 -127
- package/dist/auth/interfaces.d.ts +0 -20
- package/dist/auth/interfaces.js +0 -1
- package/dist/cache/CacheService.d.ts +0 -2
- package/dist/cache/CacheService.js +0 -27
- package/dist/database/DatabaseService.d.ts +0 -7
- package/dist/database/DatabaseService.js +0 -12
- package/dist/forms/FormService.d.ts +0 -18
- package/dist/forms/FormService.js +0 -98
- package/dist/forms/ImageService.d.ts +0 -7
- package/dist/forms/ImageService.js +0 -19
- package/dist/forms/ValidationError.d.ts +0 -4
- package/dist/forms/ValidationError.js +0 -7
- package/dist/forms/ValidationService.d.ts +0 -20
- package/dist/forms/ValidationService.js +0 -59
- package/dist/forms/lang.d.ts +0 -2
- package/dist/forms/lang.js +0 -115
- package/dist/lists/ListService.js +0 -28
- package/dist/mail/MailService.d.ts +0 -12
- package/dist/mail/MailService.js +0 -55
- package/dist/url/URLService.js +0 -61
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lists/ListService.ts"],"names":["getFromObject","DEFAULT_SORT","DEFAULT_DIR","DEFAULT_PAGE","DEFAULT_LIMIT","createPaginationArgs","page","createFindManyArgs","searchParams","allowedFilters","dir","sort","filters","getList","fn","args","err"],"mappings":"AACA,OAAS,iBAAAA,MAAqB,kBAY9B,IAAMC,EAAe,KACfC,EAAc,MACdC,EAAe,EACfC,EAAgB,GAQtB,SAASC,EAAqBC,EAAsB,CAChD,MAAO,CAAE,MAAOA,EAAO,GAAKF,EAAe,KAAMA,CAAc,CACnE,CAEA,SAASG,EACLC,EACAC,EAA2B,CAAC,EAChB,CACZ,GAAM,CAAE,IAAAC,EAAK,KAAAJ,EAAM,KAAAK,EAAM,GAAGC,CAAQ,EAAIJ,GAAgB,CAAC,EAEzD,MAAO,CACH,GAAGH,EAAqBC,EAAO,SAASA,EAAM,EAAE,EAAIH,CAAY,EAChE,QAAS,CAAE,CAACQ,GAAQV,CAAY,EAAGS,GAAOR,CAAY,EACtD,MAAOF,EAAcY,EAASH,CAAc,CAChD,CACJ,CAEA,eAAsBI,EAAW,CAC7B,eAAAJ,EACA,GAAAK,EACA,aAAAN,CACJ,EAA4C,CACxC,GAAI,CACA,IAAMO,EAAOR,EAAmBC,EAAcC,CAAc,EAC5D,MAAO,CAAC,MAAMK,EAAGC,CAAI,EAAG,IAAI,CAChC,OAASC,EAAK,CACV,OAAIA,aAAe,MACR,CAAC,KAAMA,CAAG,EAEd,CAAC,KAAM,IAAI,MAAM,qCAAqC,CAAC,CAClE,CACJ","sourcesContent":["import type { Errorable } from '@sqrzro/interfaces';\nimport { getFromObject } from '@sqrzro/utility';\n\ninterface PaginationArgs {\n skip: number;\n take: number;\n}\n\ninterface FindManyArgs extends PaginationArgs {\n orderBy: Record<string, string>;\n where: Record<string, string>;\n}\n\nconst DEFAULT_SORT = 'id';\nconst DEFAULT_DIR = 'asc';\nconst DEFAULT_PAGE = 1;\nconst DEFAULT_LIMIT = 10;\n\ninterface GetListArgs<T> {\n allowedFilters?: string[];\n fn: (args: FindManyArgs) => Promise<T[]>;\n searchParams?: Record<string, string>;\n}\n\nfunction createPaginationArgs(page): PaginationArgs {\n return { skip: (page - 1) * DEFAULT_LIMIT, take: DEFAULT_LIMIT };\n}\n\nfunction createFindManyArgs(\n searchParams?: Record<string, string>,\n allowedFilters: string[] = []\n): FindManyArgs {\n const { dir, page, sort, ...filters } = searchParams || {};\n\n return {\n ...createPaginationArgs(page ? parseInt(page, 10) : DEFAULT_PAGE),\n orderBy: { [sort || DEFAULT_SORT]: dir || DEFAULT_DIR },\n where: getFromObject(filters, allowedFilters),\n };\n}\n\nexport async function getList<T>({\n allowedFilters,\n fn,\n searchParams,\n}: GetListArgs<T>): Promise<Errorable<T[]>> {\n try {\n const args = createFindManyArgs(searchParams, allowedFilters);\n return [await fn(args), null];\n } catch (err) {\n if (err instanceof Error) {\n return [null, err];\n }\n return [null, new Error('[getList] An unknown error occurred')];\n }\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
async function m(e,t){return Promise.resolve(async()=>Promise.resolve({subject:e,template:t}))}async function i(e,t){let{subject:r,template:s}=await e(),n=(await import('react-dom/server')).default;return {subject:r,html:n.renderToStaticMarkup(s(t))}}function c(){if(!process.env.MAIL_FROM)throw new Error("Mail from address has not been set");let e=/^(?<name>[^<]+)<(?<email>[^>]+)>$/u.exec(process.env.MAIL_FROM);if(!e?.groups?.name||!e?.groups?.email)throw new Error('Mail from address is not the correct format. It should be "Name <email>".');return {email:e.groups.email.trim(),name:e.groups.name.trim()}}async function p(e,t,r){if(!process.env.MAIL_API_URL)throw new Error("Mail URL has not been set");if(!process.env.MAIL_API_KEY)throw new Error("Mail API key has not been set");let s=c(),{subject:n,html:a}=await i(await e,t);try{return (await(await fetch(process.env.MAIL_API_URL,{method:"POST",headers:{"Api-Token":process.env.MAIL_API_KEY,"Content-Type":"application/json"},body:JSON.stringify({from:s,html:a,subject:n,to:[{email:r}]})})).json()).success}catch(o){return console.log("err",o),!1}}
|
|
4
|
+
|
|
5
|
+
exports.createMail = m;
|
|
6
|
+
exports.getMail = i;
|
|
7
|
+
exports.sendMail = p;
|
|
8
|
+
//# sourceMappingURL=out.js.map
|
|
9
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/mail/MailService.ts"],"names":["createMail","subject","template","getMail","mail","data","ReactDOMServer","getSenderDetails","matches","sendMail","to","from","html","err"],"mappings":"AAOA,eAAsBA,EAClBC,EACAC,EACkB,CAClB,OAAO,QAAQ,QAAQ,SAAY,QAAQ,QAAQ,CAAE,QAAAD,EAAS,SAAAC,CAAS,CAAC,CAAC,CAC7E,CAEA,eAAsBC,EAClBC,EACAC,EAC0C,CAC1C,GAAM,CAAE,QAAAJ,EAAS,SAAAC,CAAS,EAAI,MAAME,EAAK,EACnCE,GAAkB,KAAM,QAAO,kBAAkB,GAAG,QAE1D,MAAO,CACH,QAAAL,EACA,KAAMK,EAAe,qBAAqBJ,EAASG,CAAI,CAAC,CAC5D,CACJ,CAEA,SAASE,GAAoD,CACzD,GAAI,CAAC,QAAQ,IAAI,UACb,MAAM,IAAI,MAAM,oCAAoC,EAGxD,IAAMC,EAAU,qCAAqC,KAAK,QAAQ,IAAI,SAAS,EAE/E,GAAI,CAACA,GAAS,QAAQ,MAAQ,CAACA,GAAS,QAAQ,MAC5C,MAAM,IAAI,MACN,2EACJ,EAGJ,MAAO,CACH,MAAOA,EAAQ,OAAO,MAAM,KAAK,EACjC,KAAMA,EAAQ,OAAO,KAAK,KAAK,CACnC,CACJ,CAEA,eAAsBC,EAClBL,EACAC,EACAK,EACgB,CAChB,GAAI,CAAC,QAAQ,IAAI,aACb,MAAM,IAAI,MAAM,2BAA2B,EAG/C,GAAI,CAAC,QAAQ,IAAI,aACb,MAAM,IAAI,MAAM,+BAA+B,EAGnD,IAAMC,EAAOJ,EAAiB,EACxB,CAAE,QAAAN,EAAS,KAAAW,CAAK,EAAI,MAAMT,EAAQ,MAAMC,EAAMC,CAAI,EAExD,GAAI,CAYA,OADc,MAVG,MAAM,MAAM,QAAQ,IAAI,aAAc,CACnD,OAAQ,OACR,QAAS,CAAE,YAAa,QAAQ,IAAI,aAAc,eAAgB,kBAAmB,EACrF,KAAM,KAAK,UAAU,CACjB,KAAAM,EACA,KAAAC,EACA,QAAAX,EACA,GAAI,CAAC,CAAE,MAAOS,CAAG,CAAC,CACtB,CAAC,CACL,CAAC,GAC4B,KAAK,GACtB,OAChB,OAASG,EAAK,CAEV,eAAQ,IAAI,MAAOA,CAAG,EAGf,EACX,CACJ","sourcesContent":["export interface MailObject<T extends object> {\n subject: string;\n template: (data: T) => React.ReactElement;\n}\n\ntype MailFn<T extends object> = () => Promise<MailObject<T>>;\n\nexport async function createMail<T extends object>(\n subject: string,\n template: (data: T) => React.ReactElement\n): Promise<MailFn<T>> {\n return Promise.resolve(async () => Promise.resolve({ subject, template }));\n}\n\nexport async function getMail<T extends object>(\n mail: MailFn<T>,\n data: T\n): Promise<{ subject: string; html: string }> {\n const { subject, template } = await mail();\n const ReactDOMServer = (await import('react-dom/server')).default;\n\n return {\n subject,\n html: ReactDOMServer.renderToStaticMarkup(template(data)),\n };\n}\n\nfunction getSenderDetails(): { email: string; name: string } {\n if (!process.env.MAIL_FROM) {\n throw new Error('Mail from address has not been set');\n }\n\n const matches = /^(?<name>[^<]+)<(?<email>[^>]+)>$/u.exec(process.env.MAIL_FROM);\n\n if (!matches?.groups?.name || !matches?.groups?.email) {\n throw new Error(\n 'Mail from address is not the correct format. It should be \"Name <email>\".'\n );\n }\n\n return {\n email: matches.groups.email.trim(),\n name: matches.groups.name.trim(),\n };\n}\n\nexport async function sendMail<T extends object>(\n mail: Promise<MailFn<T>>,\n data: T,\n to: string\n): Promise<boolean> {\n if (!process.env.MAIL_API_URL) {\n throw new Error('Mail URL has not been set');\n }\n\n if (!process.env.MAIL_API_KEY) {\n throw new Error('Mail API key has not been set');\n }\n\n const from = getSenderDetails();\n const { subject, html } = await getMail(await mail, data);\n\n try {\n const response = await fetch(process.env.MAIL_API_URL, {\n method: 'POST',\n headers: { 'Api-Token': process.env.MAIL_API_KEY, 'Content-Type': 'application/json' },\n body: JSON.stringify({\n from,\n html,\n subject,\n to: [{ email: to }],\n }),\n });\n const json = (await response.json()) as { success: boolean };\n return json.success;\n } catch (err) {\n /* eslint-disable-next-line no-console */\n console.log('err', err);\n /* eslint-disable-next-line no-warning-comments */\n // TODO: Log error to Sentry\n return false;\n }\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface MailObject<T extends object> {
|
|
2
|
+
subject: string;
|
|
3
|
+
template: (data: T) => React.ReactElement;
|
|
4
|
+
}
|
|
5
|
+
type MailFn<T extends object> = () => Promise<MailObject<T>>;
|
|
6
|
+
declare function createMail<T extends object>(subject: string, template: (data: T) => React.ReactElement): Promise<MailFn<T>>;
|
|
7
|
+
declare function getMail<T extends object>(mail: MailFn<T>, data: T): Promise<{
|
|
8
|
+
subject: string;
|
|
9
|
+
html: string;
|
|
10
|
+
}>;
|
|
11
|
+
declare function sendMail<T extends object>(mail: Promise<MailFn<T>>, data: T, to: string): Promise<boolean>;
|
|
12
|
+
|
|
13
|
+
export { type MailObject, createMail, getMail, sendMail };
|
package/dist/mail/index.d.ts
CHANGED
|
@@ -1 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
interface MailObject<T extends object> {
|
|
2
|
+
subject: string;
|
|
3
|
+
template: (data: T) => React.ReactElement;
|
|
4
|
+
}
|
|
5
|
+
type MailFn<T extends object> = () => Promise<MailObject<T>>;
|
|
6
|
+
declare function createMail<T extends object>(subject: string, template: (data: T) => React.ReactElement): Promise<MailFn<T>>;
|
|
7
|
+
declare function getMail<T extends object>(mail: MailFn<T>, data: T): Promise<{
|
|
8
|
+
subject: string;
|
|
9
|
+
html: string;
|
|
10
|
+
}>;
|
|
11
|
+
declare function sendMail<T extends object>(mail: Promise<MailFn<T>>, data: T, to: string): Promise<boolean>;
|
|
12
|
+
|
|
13
|
+
export { type MailObject, createMail, getMail, sendMail };
|
package/dist/mail/index.js
CHANGED
|
@@ -1 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
async function m(e,t){return Promise.resolve(async()=>Promise.resolve({subject:e,template:t}))}async function i(e,t){let{subject:r,template:s}=await e(),n=(await import('react-dom/server')).default;return {subject:r,html:n.renderToStaticMarkup(s(t))}}function c(){if(!process.env.MAIL_FROM)throw new Error("Mail from address has not been set");let e=/^(?<name>[^<]+)<(?<email>[^>]+)>$/u.exec(process.env.MAIL_FROM);if(!e?.groups?.name||!e?.groups?.email)throw new Error('Mail from address is not the correct format. It should be "Name <email>".');return {email:e.groups.email.trim(),name:e.groups.name.trim()}}async function p(e,t,r){if(!process.env.MAIL_API_URL)throw new Error("Mail URL has not been set");if(!process.env.MAIL_API_KEY)throw new Error("Mail API key has not been set");let s=c(),{subject:n,html:a}=await i(await e,t);try{return (await(await fetch(process.env.MAIL_API_URL,{method:"POST",headers:{"Api-Token":process.env.MAIL_API_KEY,"Content-Type":"application/json"},body:JSON.stringify({from:s,html:a,subject:n,to:[{email:r}]})})).json()).success}catch(o){return console.log("err",o),!1}}
|
|
2
|
+
|
|
3
|
+
export { m as createMail, i as getMail, p as sendMail };
|
|
4
|
+
//# sourceMappingURL=out.js.map
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/mail/MailService.ts"],"names":["createMail","subject","template","getMail","mail","data","ReactDOMServer","getSenderDetails","matches","sendMail","to","from","html","err"],"mappings":"AAOA,eAAsBA,EAClBC,EACAC,EACkB,CAClB,OAAO,QAAQ,QAAQ,SAAY,QAAQ,QAAQ,CAAE,QAAAD,EAAS,SAAAC,CAAS,CAAC,CAAC,CAC7E,CAEA,eAAsBC,EAClBC,EACAC,EAC0C,CAC1C,GAAM,CAAE,QAAAJ,EAAS,SAAAC,CAAS,EAAI,MAAME,EAAK,EACnCE,GAAkB,KAAM,QAAO,kBAAkB,GAAG,QAE1D,MAAO,CACH,QAAAL,EACA,KAAMK,EAAe,qBAAqBJ,EAASG,CAAI,CAAC,CAC5D,CACJ,CAEA,SAASE,GAAoD,CACzD,GAAI,CAAC,QAAQ,IAAI,UACb,MAAM,IAAI,MAAM,oCAAoC,EAGxD,IAAMC,EAAU,qCAAqC,KAAK,QAAQ,IAAI,SAAS,EAE/E,GAAI,CAACA,GAAS,QAAQ,MAAQ,CAACA,GAAS,QAAQ,MAC5C,MAAM,IAAI,MACN,2EACJ,EAGJ,MAAO,CACH,MAAOA,EAAQ,OAAO,MAAM,KAAK,EACjC,KAAMA,EAAQ,OAAO,KAAK,KAAK,CACnC,CACJ,CAEA,eAAsBC,EAClBL,EACAC,EACAK,EACgB,CAChB,GAAI,CAAC,QAAQ,IAAI,aACb,MAAM,IAAI,MAAM,2BAA2B,EAG/C,GAAI,CAAC,QAAQ,IAAI,aACb,MAAM,IAAI,MAAM,+BAA+B,EAGnD,IAAMC,EAAOJ,EAAiB,EACxB,CAAE,QAAAN,EAAS,KAAAW,CAAK,EAAI,MAAMT,EAAQ,MAAMC,EAAMC,CAAI,EAExD,GAAI,CAYA,OADc,MAVG,MAAM,MAAM,QAAQ,IAAI,aAAc,CACnD,OAAQ,OACR,QAAS,CAAE,YAAa,QAAQ,IAAI,aAAc,eAAgB,kBAAmB,EACrF,KAAM,KAAK,UAAU,CACjB,KAAAM,EACA,KAAAC,EACA,QAAAX,EACA,GAAI,CAAC,CAAE,MAAOS,CAAG,CAAC,CACtB,CAAC,CACL,CAAC,GAC4B,KAAK,GACtB,OAChB,OAASG,EAAK,CAEV,eAAQ,IAAI,MAAOA,CAAG,EAGf,EACX,CACJ","sourcesContent":["export interface MailObject<T extends object> {\n subject: string;\n template: (data: T) => React.ReactElement;\n}\n\ntype MailFn<T extends object> = () => Promise<MailObject<T>>;\n\nexport async function createMail<T extends object>(\n subject: string,\n template: (data: T) => React.ReactElement\n): Promise<MailFn<T>> {\n return Promise.resolve(async () => Promise.resolve({ subject, template }));\n}\n\nexport async function getMail<T extends object>(\n mail: MailFn<T>,\n data: T\n): Promise<{ subject: string; html: string }> {\n const { subject, template } = await mail();\n const ReactDOMServer = (await import('react-dom/server')).default;\n\n return {\n subject,\n html: ReactDOMServer.renderToStaticMarkup(template(data)),\n };\n}\n\nfunction getSenderDetails(): { email: string; name: string } {\n if (!process.env.MAIL_FROM) {\n throw new Error('Mail from address has not been set');\n }\n\n const matches = /^(?<name>[^<]+)<(?<email>[^>]+)>$/u.exec(process.env.MAIL_FROM);\n\n if (!matches?.groups?.name || !matches?.groups?.email) {\n throw new Error(\n 'Mail from address is not the correct format. It should be \"Name <email>\".'\n );\n }\n\n return {\n email: matches.groups.email.trim(),\n name: matches.groups.name.trim(),\n };\n}\n\nexport async function sendMail<T extends object>(\n mail: Promise<MailFn<T>>,\n data: T,\n to: string\n): Promise<boolean> {\n if (!process.env.MAIL_API_URL) {\n throw new Error('Mail URL has not been set');\n }\n\n if (!process.env.MAIL_API_KEY) {\n throw new Error('Mail API key has not been set');\n }\n\n const from = getSenderDetails();\n const { subject, html } = await getMail(await mail, data);\n\n try {\n const response = await fetch(process.env.MAIL_API_URL, {\n method: 'POST',\n headers: { 'Api-Token': process.env.MAIL_API_KEY, 'Content-Type': 'application/json' },\n body: JSON.stringify({\n from,\n html,\n subject,\n to: [{ email: to }],\n }),\n });\n const json = (await response.json()) as { success: boolean };\n return json.success;\n } catch (err) {\n /* eslint-disable-next-line no-console */\n console.log('err', err);\n /* eslint-disable-next-line no-warning-comments */\n // TODO: Log error to Sentry\n return false;\n }\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var server = require('next/server');
|
|
4
|
+
|
|
5
|
+
var c="/auth/login";function r(e,n){return n.headers.set("x-origin",e.nextUrl.origin),n.headers.set("x-pathname",e.nextUrl.pathname),n.headers.set("x-search-params",e.nextUrl.searchParams.toString()),n}function p(e){return e.toString().replace(e.origin,"")}function i(e,n=c){return e.nextUrl.pathname===n?r(e,server.NextResponse.next()):r(e,server.NextResponse.redirect(`${e.nextUrl.origin}${n}?r=${encodeURIComponent(p(e.nextUrl))}`))}function x(){let e=new Headers;return process.env.VERCEL_PROTECTION_BYPASS&&e.append("x-vercel-protection-bypass",process.env.VERCEL_PROTECTION_BYPASS),{headers:e}}async function R(e,n){if(e.nextUrl.pathname==="/api/session")return r(e,n?n():server.NextResponse.next());let o=e.cookies.get(process.env.AUTH_COOKIE_NAME||"auth_session")?.value||"";try{let s=await(await fetch(`${e.nextUrl.origin}/api/session?id=${o}&pathname=${e.nextUrl.pathname}`,x())).json();return s.redirect===null?r(e,n?n():server.NextResponse.next()):i(e,s.redirect)}catch{return i(e)}}
|
|
6
|
+
|
|
7
|
+
exports.handleMiddleware = R;
|
|
8
|
+
//# sourceMappingURL=out.js.map
|
|
9
|
+
//# sourceMappingURL=middleware.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/middleware.ts"],"names":["NextResponse","DEFAULT_REDIRECT","applyHeaders","request","response","getRelativeUrl","url","redirect","pathname","bypassProtection","headers","handleMiddleware","nextFn","sessionID","json"],"mappings":"AAAA,OAAS,gBAAAA,MAAoB,cAG7B,IAAMC,EAAmB,cAEzB,SAASC,EAAaC,EAAsBC,EAAsC,CAC9E,OAAAA,EAAS,QAAQ,IAAI,WAAYD,EAAQ,QAAQ,MAAM,EACvDC,EAAS,QAAQ,IAAI,aAAcD,EAAQ,QAAQ,QAAQ,EAC3DC,EAAS,QAAQ,IAAI,kBAAmBD,EAAQ,QAAQ,aAAa,SAAS,CAAC,EACxEC,CACX,CAEA,SAASC,EAAeC,EAAqC,CACzD,OAAOA,EAAI,SAAS,EAAE,QAAQA,EAAI,OAAQ,EAAE,CAChD,CAEA,SAASC,EAASJ,EAAsBK,EAAWP,EAAgC,CAC/E,OAAIE,EAAQ,QAAQ,WAAaK,EACtBN,EAAaC,EAASH,EAAa,KAAK,CAAC,EAG7CE,EACHC,EACAH,EAAa,SACT,GAAGG,EAAQ,QAAQ,MAAM,GAAGK,CAAQ,MAAM,mBACtCH,EAAeF,EAAQ,OAAO,CAClC,CAAC,EACL,CACJ,CACJ,CAMA,SAASM,GAAgC,CACrC,IAAMC,EAAU,IAAI,QAEpB,OAAI,QAAQ,IAAI,0BACZA,EAAQ,OAAO,6BAA8B,QAAQ,IAAI,wBAAwB,EAG9E,CAAE,QAAAA,CAAQ,CACrB,CAEA,eAAsBC,EAClBR,EACAS,EACqB,CAErB,GAAIT,EAAQ,QAAQ,WAAa,eAC7B,OAAOD,EAAaC,EAASS,EAASA,EAAO,EAAIZ,EAAa,KAAK,CAAC,EAGxE,IAAMa,EACFV,EAAQ,QAAQ,IAAI,QAAQ,IAAI,kBAAoB,cAAc,GAAG,OAAS,GAElF,GAAI,CAKA,IAAMW,EAAQ,MAJE,MAAM,MAClB,GAAGX,EAAQ,QAAQ,MAAM,mBAAmBU,CAAS,aAAaV,EAAQ,QAAQ,QAAQ,GAC1FM,EAAiB,CACrB,GAC4B,KAAK,EAEjC,OAAIK,EAAK,WAAa,KACXZ,EAAaC,EAASS,EAASA,EAAO,EAAIZ,EAAa,KAAK,CAAC,EAGjEO,EAASJ,EAASW,EAAK,QAAQ,CAC1C,MAAc,CACV,OAAOP,EAASJ,CAAO,CAC3B,CACJ","sourcesContent":["import { NextResponse } from 'next/server';\nimport type { NextRequest } from 'next/server';\n\nconst DEFAULT_REDIRECT = '/auth/login';\n\nfunction applyHeaders(request: NextRequest, response: NextResponse): NextResponse {\n response.headers.set('x-origin', request.nextUrl.origin);\n response.headers.set('x-pathname', request.nextUrl.pathname);\n response.headers.set('x-search-params', request.nextUrl.searchParams.toString());\n return response;\n}\n\nfunction getRelativeUrl(url: NextRequest['nextUrl']): string {\n return url.toString().replace(url.origin, '');\n}\n\nfunction redirect(request: NextRequest, pathname = DEFAULT_REDIRECT): NextResponse {\n if (request.nextUrl.pathname === pathname) {\n return applyHeaders(request, NextResponse.next());\n }\n\n return applyHeaders(\n request,\n NextResponse.redirect(\n `${request.nextUrl.origin}${pathname}?r=${encodeURIComponent(\n getRelativeUrl(request.nextUrl)\n )}`\n )\n );\n}\n\n/*\n * When deployed to Vercel in a preview environment, we need to bypass the protection when fetching\n * the session from the API.\n */\nfunction bypassProtection(): RequestInit {\n const headers = new Headers();\n\n if (process.env.VERCEL_PROTECTION_BYPASS) {\n headers.append('x-vercel-protection-bypass', process.env.VERCEL_PROTECTION_BYPASS);\n }\n\n return { headers };\n}\n\nexport async function handleMiddleware(\n request: NextRequest,\n nextFn?: () => NextResponse\n): Promise<NextResponse> {\n // If the URL is /api/session, we should just return the response, otherwise we end up in a loop\n if (request.nextUrl.pathname === '/api/session') {\n return applyHeaders(request, nextFn ? nextFn() : NextResponse.next());\n }\n\n const sessionID =\n request.cookies.get(process.env.AUTH_COOKIE_NAME || 'auth_session')?.value || '';\n\n try {\n const session = await fetch(\n `${request.nextUrl.origin}/api/session?id=${sessionID}&pathname=${request.nextUrl.pathname}`,\n bypassProtection()\n );\n const json = (await session.json()) as { redirect: string | null };\n\n if (json.redirect === null) {\n return applyHeaders(request, nextFn ? nextFn() : NextResponse.next());\n }\n\n return redirect(request, json.redirect);\n } catch (err) {\n return redirect(request);\n }\n}\n"]}
|
package/dist/middleware.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import { NextResponse } from 'next/server';
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
|
|
3
|
+
declare function handleMiddleware(request: NextRequest, nextFn?: () => NextResponse): Promise<NextResponse>;
|
|
4
|
+
|
|
5
|
+
export { handleMiddleware };
|
package/dist/middleware.js
CHANGED
|
@@ -1,46 +1,7 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
|
-
|
|
3
|
-
function
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
function getRelativeUrl(url) {
|
|
10
|
-
return url.toString().replace(url.origin, '');
|
|
11
|
-
}
|
|
12
|
-
function redirect(request, pathname = DEFAULT_REDIRECT) {
|
|
13
|
-
if (request.nextUrl.pathname === pathname) {
|
|
14
|
-
return applyHeaders(request, NextResponse.next());
|
|
15
|
-
}
|
|
16
|
-
return applyHeaders(request, NextResponse.redirect(`${request.nextUrl.origin}${pathname}?r=${encodeURIComponent(getRelativeUrl(request.nextUrl))}`));
|
|
17
|
-
}
|
|
18
|
-
/*
|
|
19
|
-
* When deployed to Vercel in a preview environment, we need to bypass the protection when fetching
|
|
20
|
-
* the session from the API.
|
|
21
|
-
*/
|
|
22
|
-
function bypassProtection() {
|
|
23
|
-
const headers = new Headers();
|
|
24
|
-
if (process.env.VERCEL_PROTECTION_BYPASS) {
|
|
25
|
-
headers.append('x-vercel-protection-bypass', process.env.VERCEL_PROTECTION_BYPASS);
|
|
26
|
-
}
|
|
27
|
-
return { headers };
|
|
28
|
-
}
|
|
29
|
-
export async function handleMiddleware(request, nextFn) {
|
|
30
|
-
// If the URL is /api/session, we should just return the response, otherwise we end up in a loop
|
|
31
|
-
if (request.nextUrl.pathname === '/api/session') {
|
|
32
|
-
return applyHeaders(request, nextFn ? nextFn() : NextResponse.next());
|
|
33
|
-
}
|
|
34
|
-
const sessionID = request.cookies.get(process.env.AUTH_COOKIE_NAME || 'auth_session')?.value || '';
|
|
35
|
-
try {
|
|
36
|
-
const session = await fetch(`${request.nextUrl.origin}/api/session?id=${sessionID}&pathname=${request.nextUrl.pathname}`, bypassProtection());
|
|
37
|
-
const json = (await session.json());
|
|
38
|
-
if (json.redirect === null) {
|
|
39
|
-
return applyHeaders(request, nextFn ? nextFn() : NextResponse.next());
|
|
40
|
-
}
|
|
41
|
-
return redirect(request, json.redirect);
|
|
42
|
-
}
|
|
43
|
-
catch (err) {
|
|
44
|
-
return redirect(request);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
2
|
+
|
|
3
|
+
var c="/auth/login";function r(e,n){return n.headers.set("x-origin",e.nextUrl.origin),n.headers.set("x-pathname",e.nextUrl.pathname),n.headers.set("x-search-params",e.nextUrl.searchParams.toString()),n}function p(e){return e.toString().replace(e.origin,"")}function i(e,n=c){return e.nextUrl.pathname===n?r(e,NextResponse.next()):r(e,NextResponse.redirect(`${e.nextUrl.origin}${n}?r=${encodeURIComponent(p(e.nextUrl))}`))}function x(){let e=new Headers;return process.env.VERCEL_PROTECTION_BYPASS&&e.append("x-vercel-protection-bypass",process.env.VERCEL_PROTECTION_BYPASS),{headers:e}}async function R(e,n){if(e.nextUrl.pathname==="/api/session")return r(e,n?n():NextResponse.next());let o=e.cookies.get(process.env.AUTH_COOKIE_NAME||"auth_session")?.value||"";try{let s=await(await fetch(`${e.nextUrl.origin}/api/session?id=${o}&pathname=${e.nextUrl.pathname}`,x())).json();return s.redirect===null?r(e,n?n():NextResponse.next()):i(e,s.redirect)}catch{return i(e)}}
|
|
4
|
+
|
|
5
|
+
export { R as handleMiddleware };
|
|
6
|
+
//# sourceMappingURL=out.js.map
|
|
7
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/middleware.ts"],"names":["NextResponse","DEFAULT_REDIRECT","applyHeaders","request","response","getRelativeUrl","url","redirect","pathname","bypassProtection","headers","handleMiddleware","nextFn","sessionID","json"],"mappings":"AAAA,OAAS,gBAAAA,MAAoB,cAG7B,IAAMC,EAAmB,cAEzB,SAASC,EAAaC,EAAsBC,EAAsC,CAC9E,OAAAA,EAAS,QAAQ,IAAI,WAAYD,EAAQ,QAAQ,MAAM,EACvDC,EAAS,QAAQ,IAAI,aAAcD,EAAQ,QAAQ,QAAQ,EAC3DC,EAAS,QAAQ,IAAI,kBAAmBD,EAAQ,QAAQ,aAAa,SAAS,CAAC,EACxEC,CACX,CAEA,SAASC,EAAeC,EAAqC,CACzD,OAAOA,EAAI,SAAS,EAAE,QAAQA,EAAI,OAAQ,EAAE,CAChD,CAEA,SAASC,EAASJ,EAAsBK,EAAWP,EAAgC,CAC/E,OAAIE,EAAQ,QAAQ,WAAaK,EACtBN,EAAaC,EAASH,EAAa,KAAK,CAAC,EAG7CE,EACHC,EACAH,EAAa,SACT,GAAGG,EAAQ,QAAQ,MAAM,GAAGK,CAAQ,MAAM,mBACtCH,EAAeF,EAAQ,OAAO,CAClC,CAAC,EACL,CACJ,CACJ,CAMA,SAASM,GAAgC,CACrC,IAAMC,EAAU,IAAI,QAEpB,OAAI,QAAQ,IAAI,0BACZA,EAAQ,OAAO,6BAA8B,QAAQ,IAAI,wBAAwB,EAG9E,CAAE,QAAAA,CAAQ,CACrB,CAEA,eAAsBC,EAClBR,EACAS,EACqB,CAErB,GAAIT,EAAQ,QAAQ,WAAa,eAC7B,OAAOD,EAAaC,EAASS,EAASA,EAAO,EAAIZ,EAAa,KAAK,CAAC,EAGxE,IAAMa,EACFV,EAAQ,QAAQ,IAAI,QAAQ,IAAI,kBAAoB,cAAc,GAAG,OAAS,GAElF,GAAI,CAKA,IAAMW,EAAQ,MAJE,MAAM,MAClB,GAAGX,EAAQ,QAAQ,MAAM,mBAAmBU,CAAS,aAAaV,EAAQ,QAAQ,QAAQ,GAC1FM,EAAiB,CACrB,GAC4B,KAAK,EAEjC,OAAIK,EAAK,WAAa,KACXZ,EAAaC,EAASS,EAASA,EAAO,EAAIZ,EAAa,KAAK,CAAC,EAGjEO,EAASJ,EAASW,EAAK,QAAQ,CAC1C,MAAc,CACV,OAAOP,EAASJ,CAAO,CAC3B,CACJ","sourcesContent":["import { NextResponse } from 'next/server';\nimport type { NextRequest } from 'next/server';\n\nconst DEFAULT_REDIRECT = '/auth/login';\n\nfunction applyHeaders(request: NextRequest, response: NextResponse): NextResponse {\n response.headers.set('x-origin', request.nextUrl.origin);\n response.headers.set('x-pathname', request.nextUrl.pathname);\n response.headers.set('x-search-params', request.nextUrl.searchParams.toString());\n return response;\n}\n\nfunction getRelativeUrl(url: NextRequest['nextUrl']): string {\n return url.toString().replace(url.origin, '');\n}\n\nfunction redirect(request: NextRequest, pathname = DEFAULT_REDIRECT): NextResponse {\n if (request.nextUrl.pathname === pathname) {\n return applyHeaders(request, NextResponse.next());\n }\n\n return applyHeaders(\n request,\n NextResponse.redirect(\n `${request.nextUrl.origin}${pathname}?r=${encodeURIComponent(\n getRelativeUrl(request.nextUrl)\n )}`\n )\n );\n}\n\n/*\n * When deployed to Vercel in a preview environment, we need to bypass the protection when fetching\n * the session from the API.\n */\nfunction bypassProtection(): RequestInit {\n const headers = new Headers();\n\n if (process.env.VERCEL_PROTECTION_BYPASS) {\n headers.append('x-vercel-protection-bypass', process.env.VERCEL_PROTECTION_BYPASS);\n }\n\n return { headers };\n}\n\nexport async function handleMiddleware(\n request: NextRequest,\n nextFn?: () => NextResponse\n): Promise<NextResponse> {\n // If the URL is /api/session, we should just return the response, otherwise we end up in a loop\n if (request.nextUrl.pathname === '/api/session') {\n return applyHeaders(request, nextFn ? nextFn() : NextResponse.next());\n }\n\n const sessionID =\n request.cookies.get(process.env.AUTH_COOKIE_NAME || 'auth_session')?.value || '';\n\n try {\n const session = await fetch(\n `${request.nextUrl.origin}/api/session?id=${sessionID}&pathname=${request.nextUrl.pathname}`,\n bypassProtection()\n );\n const json = (await session.json()) as { redirect: string | null };\n\n if (json.redirect === null) {\n return applyHeaders(request, nextFn ? nextFn() : NextResponse.next());\n }\n\n return redirect(request, json.redirect);\n } catch (err) {\n return redirect(request);\n }\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var headers = require('next/headers');
|
|
4
|
+
|
|
5
|
+
function s(){let t=headers.headers().get("x-origin");if(t)return t;let r=headers.headers().get("x-forwarded-proto"),o=headers.headers().get("x-forwarded-host");if(r&&o)return `${r}://${o}`;throw new Error("No origin could be determined")}function p(){let t=headers.headers().get("x-pathname");if(t)return t;throw new Error("No pathname could be determined. Please make sure middleware is being applied to the current request.")}function c(t){let r=s();if(!t)return r;let n=r.startsWith("https://")?"https://":"http://",i=`${r.replace(/^https?:\/\//u,"")}/${t}`.replace(/\/+/gu,"/");return `${n}${i}`}function a(t){return c(t)}
|
|
6
|
+
|
|
7
|
+
exports.getOrigin = s;
|
|
8
|
+
exports.getPathname = p;
|
|
9
|
+
exports.getURL = a;
|
|
10
|
+
exports.makeURL = c;
|
|
11
|
+
//# sourceMappingURL=out.js.map
|
|
12
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/url/URLService.ts"],"names":["headers","getOrigin","origin","proto","host","getPathname","pathname","makeURL","protocol","cleanURL","getURL"],"mappings":"AAAA,OAAS,WAAAA,MAAe,eAkBjB,SAASC,GAAoB,CAChC,IAAMC,EAASF,EAAQ,EAAE,IAAI,UAAU,EAEvC,GAAIE,EACA,OAAOA,EAGX,IAAMC,EAAQH,EAAQ,EAAE,IAAI,mBAAmB,EACzCI,EAAOJ,EAAQ,EAAE,IAAI,kBAAkB,EAE7C,GAAIG,GAASC,EACT,MAAO,GAAGD,CAAK,MAAMC,CAAI,GAG7B,MAAM,IAAI,MAAM,+BAA+B,CACnD,CAEO,SAASC,GAAsB,CAClC,IAAMC,EAAWN,EAAQ,EAAE,IAAI,YAAY,EAE3C,GAAIM,EACA,OAAOA,EAGX,MAAM,IAAI,MACN,uGACJ,CACJ,CAUO,SAASC,EAAQD,EAA2B,CAC/C,IAAMJ,EAASD,EAAU,EAEzB,GAAI,CAACK,EACD,OAAOJ,EAKX,IAAMM,EAFWN,EAAO,WAAW,UAAU,EAEjB,WAAa,UAGnCO,EAAW,GAFaP,EAAO,QAAQ,gBAAiB,EAAE,CAEvB,IAAII,CAAQ,GAAG,QAAQ,QAAS,GAAG,EAC5E,MAAO,GAAGE,CAAQ,GAAGC,CAAQ,EACjC,CAKO,SAASC,EAAOJ,EAA2B,CAC9C,OAAOC,EAAQD,CAAQ,CAC3B","sourcesContent":["import { headers } from 'next/headers';\n\n/**\n * Uses a number of methods to determine the current origin.\n *\n * First, it checks if an `x-origin` header. This will have been set by the `handleMiddleware`\n * function, further up the chain. For more information on how it is being set, see the\n * `middleware` documentation.\n *\n * There are some situations where middleware is not being applied, such as API routes (because the\n * redirection is not necessary, and API routes handle their own authentication). In these cases,\n * this function tries to piece together the origin from the `x-forwarded-proto` and\n * `x-forwarded-host` headers.\n *\n * Finally, if the origin cannot be determined, an error is thrown.\n *\n * @returns The origin of the current request.\n */\nexport function getOrigin(): string {\n const origin = headers().get('x-origin');\n\n if (origin) {\n return origin;\n }\n\n const proto = headers().get('x-forwarded-proto');\n const host = headers().get('x-forwarded-host');\n\n if (proto && host) {\n return `${proto}://${host}`;\n }\n\n throw new Error('No origin could be determined');\n}\n\nexport function getPathname(): string {\n const pathname = headers().get('x-pathname');\n\n if (pathname) {\n return pathname;\n }\n\n throw new Error(\n 'No pathname could be determined. Please make sure middleware is being applied to the current request.'\n );\n}\n\n/**\n * Builds a URL from the current origin and a given pathname. For more information on how the origin\n * is determined, see the `getOrigin` function. This function then just concatenates the origin and\n * the pathname, and performs some cleanup to ensure the URL is valid.\n *\n * @param pathname\n * @returns The URL, with the origin and pathname combined.\n */\nexport function makeURL(pathname?: string): string {\n const origin = getOrigin();\n\n if (!pathname) {\n return origin;\n }\n\n const isSecure = origin.startsWith('https://');\n\n const protocol = isSecure ? 'https://' : 'http://';\n const originWithoutProtocol = origin.replace(/^https?:\\/\\//u, '');\n\n const cleanURL = `${originWithoutProtocol}/${pathname}`.replace(/\\/+/gu, '/');\n return `${protocol}${cleanURL}`;\n}\n\n/**\n * @deprecated Use `makeURL` instead.\n */\nexport function getURL(pathname?: string): string {\n return makeURL(pathname);\n}\n"]}
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
*
|
|
15
15
|
* @returns The origin of the current request.
|
|
16
16
|
*/
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
declare function getOrigin(): string;
|
|
18
|
+
declare function getPathname(): string;
|
|
19
19
|
/**
|
|
20
20
|
* Builds a URL from the current origin and a given pathname. For more information on how the origin
|
|
21
21
|
* is determined, see the `getOrigin` function. This function then just concatenates the origin and
|
|
@@ -24,8 +24,10 @@ export declare function getPathname(): string;
|
|
|
24
24
|
* @param pathname
|
|
25
25
|
* @returns The URL, with the origin and pathname combined.
|
|
26
26
|
*/
|
|
27
|
-
|
|
27
|
+
declare function makeURL(pathname?: string): string;
|
|
28
28
|
/**
|
|
29
29
|
* @deprecated Use `makeURL` instead.
|
|
30
30
|
*/
|
|
31
|
-
|
|
31
|
+
declare function getURL(pathname?: string): string;
|
|
32
|
+
|
|
33
|
+
export { getOrigin, getPathname, getURL, makeURL };
|
package/dist/url/index.d.ts
CHANGED
|
@@ -1 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Uses a number of methods to determine the current origin.
|
|
3
|
+
*
|
|
4
|
+
* First, it checks if an `x-origin` header. This will have been set by the `handleMiddleware`
|
|
5
|
+
* function, further up the chain. For more information on how it is being set, see the
|
|
6
|
+
* `middleware` documentation.
|
|
7
|
+
*
|
|
8
|
+
* There are some situations where middleware is not being applied, such as API routes (because the
|
|
9
|
+
* redirection is not necessary, and API routes handle their own authentication). In these cases,
|
|
10
|
+
* this function tries to piece together the origin from the `x-forwarded-proto` and
|
|
11
|
+
* `x-forwarded-host` headers.
|
|
12
|
+
*
|
|
13
|
+
* Finally, if the origin cannot be determined, an error is thrown.
|
|
14
|
+
*
|
|
15
|
+
* @returns The origin of the current request.
|
|
16
|
+
*/
|
|
17
|
+
declare function getOrigin(): string;
|
|
18
|
+
declare function getPathname(): string;
|
|
19
|
+
/**
|
|
20
|
+
* Builds a URL from the current origin and a given pathname. For more information on how the origin
|
|
21
|
+
* is determined, see the `getOrigin` function. This function then just concatenates the origin and
|
|
22
|
+
* the pathname, and performs some cleanup to ensure the URL is valid.
|
|
23
|
+
*
|
|
24
|
+
* @param pathname
|
|
25
|
+
* @returns The URL, with the origin and pathname combined.
|
|
26
|
+
*/
|
|
27
|
+
declare function makeURL(pathname?: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* @deprecated Use `makeURL` instead.
|
|
30
|
+
*/
|
|
31
|
+
declare function getURL(pathname?: string): string;
|
|
32
|
+
|
|
33
|
+
export { getOrigin, getPathname, getURL, makeURL };
|
package/dist/url/index.js
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import { headers } from 'next/headers';
|
|
2
|
+
|
|
3
|
+
function s(){let t=headers().get("x-origin");if(t)return t;let r=headers().get("x-forwarded-proto"),o=headers().get("x-forwarded-host");if(r&&o)return `${r}://${o}`;throw new Error("No origin could be determined")}function p(){let t=headers().get("x-pathname");if(t)return t;throw new Error("No pathname could be determined. Please make sure middleware is being applied to the current request.")}function c(t){let r=s();if(!t)return r;let n=r.startsWith("https://")?"https://":"http://",i=`${r.replace(/^https?:\/\//u,"")}/${t}`.replace(/\/+/gu,"/");return `${n}${i}`}function a(t){return c(t)}
|
|
4
|
+
|
|
5
|
+
export { s as getOrigin, p as getPathname, a as getURL, c as makeURL };
|
|
6
|
+
//# sourceMappingURL=out.js.map
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/url/URLService.ts"],"names":["headers","getOrigin","origin","proto","host","getPathname","pathname","makeURL","protocol","cleanURL","getURL"],"mappings":"AAAA,OAAS,WAAAA,MAAe,eAkBjB,SAASC,GAAoB,CAChC,IAAMC,EAASF,EAAQ,EAAE,IAAI,UAAU,EAEvC,GAAIE,EACA,OAAOA,EAGX,IAAMC,EAAQH,EAAQ,EAAE,IAAI,mBAAmB,EACzCI,EAAOJ,EAAQ,EAAE,IAAI,kBAAkB,EAE7C,GAAIG,GAASC,EACT,MAAO,GAAGD,CAAK,MAAMC,CAAI,GAG7B,MAAM,IAAI,MAAM,+BAA+B,CACnD,CAEO,SAASC,GAAsB,CAClC,IAAMC,EAAWN,EAAQ,EAAE,IAAI,YAAY,EAE3C,GAAIM,EACA,OAAOA,EAGX,MAAM,IAAI,MACN,uGACJ,CACJ,CAUO,SAASC,EAAQD,EAA2B,CAC/C,IAAMJ,EAASD,EAAU,EAEzB,GAAI,CAACK,EACD,OAAOJ,EAKX,IAAMM,EAFWN,EAAO,WAAW,UAAU,EAEjB,WAAa,UAGnCO,EAAW,GAFaP,EAAO,QAAQ,gBAAiB,EAAE,CAEvB,IAAII,CAAQ,GAAG,QAAQ,QAAS,GAAG,EAC5E,MAAO,GAAGE,CAAQ,GAAGC,CAAQ,EACjC,CAKO,SAASC,EAAOJ,EAA2B,CAC9C,OAAOC,EAAQD,CAAQ,CAC3B","sourcesContent":["import { headers } from 'next/headers';\n\n/**\n * Uses a number of methods to determine the current origin.\n *\n * First, it checks if an `x-origin` header. This will have been set by the `handleMiddleware`\n * function, further up the chain. For more information on how it is being set, see the\n * `middleware` documentation.\n *\n * There are some situations where middleware is not being applied, such as API routes (because the\n * redirection is not necessary, and API routes handle their own authentication). In these cases,\n * this function tries to piece together the origin from the `x-forwarded-proto` and\n * `x-forwarded-host` headers.\n *\n * Finally, if the origin cannot be determined, an error is thrown.\n *\n * @returns The origin of the current request.\n */\nexport function getOrigin(): string {\n const origin = headers().get('x-origin');\n\n if (origin) {\n return origin;\n }\n\n const proto = headers().get('x-forwarded-proto');\n const host = headers().get('x-forwarded-host');\n\n if (proto && host) {\n return `${proto}://${host}`;\n }\n\n throw new Error('No origin could be determined');\n}\n\nexport function getPathname(): string {\n const pathname = headers().get('x-pathname');\n\n if (pathname) {\n return pathname;\n }\n\n throw new Error(\n 'No pathname could be determined. Please make sure middleware is being applied to the current request.'\n );\n}\n\n/**\n * Builds a URL from the current origin and a given pathname. For more information on how the origin\n * is determined, see the `getOrigin` function. This function then just concatenates the origin and\n * the pathname, and performs some cleanup to ensure the URL is valid.\n *\n * @param pathname\n * @returns The URL, with the origin and pathname combined.\n */\nexport function makeURL(pathname?: string): string {\n const origin = getOrigin();\n\n if (!pathname) {\n return origin;\n }\n\n const isSecure = origin.startsWith('https://');\n\n const protocol = isSecure ? 'https://' : 'http://';\n const originWithoutProtocol = origin.replace(/^https?:\\/\\//u, '');\n\n const cleanURL = `${originWithoutProtocol}/${pathname}`.replace(/\\/+/gu, '/');\n return `${protocol}${cleanURL}`;\n}\n\n/**\n * @deprecated Use `makeURL` instead.\n */\nexport function getURL(pathname?: string): string {\n return makeURL(pathname);\n}\n"]}
|
package/jest.config.js
ADDED
package/package.json
CHANGED
|
@@ -1,44 +1,71 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqrzro/server",
|
|
3
|
-
"version": "2.0.0-bz.
|
|
3
|
+
"version": "2.0.0-bz.30",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "ISC",
|
|
8
|
+
"exports": {
|
|
9
|
+
"./auth": {
|
|
10
|
+
"import": "./dist/auth/index.js",
|
|
11
|
+
"require": "./dist/auth/index.cjs",
|
|
12
|
+
"types": "./dist/auth/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./cache": {
|
|
15
|
+
"import": "./dist/cache/index.js",
|
|
16
|
+
"require": "./dist/cache/index.cjs",
|
|
17
|
+
"types": "./dist/cache/index.d.ts"
|
|
18
|
+
},
|
|
19
|
+
"./forms": {
|
|
20
|
+
"import": "./dist/forms/index.js",
|
|
21
|
+
"require": "./dist/forms/index.cjs",
|
|
22
|
+
"types": "./dist/forms/index.d.ts"
|
|
23
|
+
},
|
|
24
|
+
"./lists": {
|
|
25
|
+
"import": "./dist/lists/index.js",
|
|
26
|
+
"require": "./dist/lists/index.cjs",
|
|
27
|
+
"types": "./dist/lists/index.d.ts"
|
|
28
|
+
},
|
|
29
|
+
"./mail": {
|
|
30
|
+
"import": "./dist/mail/index.js",
|
|
31
|
+
"require": "./dist/mail/index.cjs",
|
|
32
|
+
"types": "./dist/mail/index.d.ts"
|
|
33
|
+
},
|
|
34
|
+
"./middleware": {
|
|
35
|
+
"import": "./dist/middleware.js",
|
|
36
|
+
"require": "./dist/middleware.cjs",
|
|
37
|
+
"types": "./dist/middleware.d.ts"
|
|
38
|
+
},
|
|
39
|
+
"./schema": {
|
|
40
|
+
"import": "./dist/database/schema.js",
|
|
41
|
+
"require": "./dist/database/schema.cjs",
|
|
42
|
+
"types": "./dist/database/schema.d.ts"
|
|
43
|
+
},
|
|
44
|
+
"./url": {
|
|
45
|
+
"import": "./dist/url.js",
|
|
46
|
+
"require": "./dist/url.cjs",
|
|
47
|
+
"types": "./dist/url.d.ts"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
8
50
|
"files": [
|
|
9
|
-
"dist",
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"cache.d.ts",
|
|
13
|
-
"cache.js",
|
|
14
|
-
"forms.d.ts",
|
|
15
|
-
"forms.js",
|
|
16
|
-
"lists.d.ts",
|
|
17
|
-
"lists.js",
|
|
18
|
-
"mail.d.ts",
|
|
19
|
-
"mail.js",
|
|
20
|
-
"middleware.d.ts",
|
|
21
|
-
"middleware.js",
|
|
22
|
-
"schema.d.ts",
|
|
23
|
-
"schema.js",
|
|
24
|
-
"url.d.ts",
|
|
25
|
-
"url.js"
|
|
51
|
+
"dist/**/*",
|
|
52
|
+
"*.js",
|
|
53
|
+
"*.d.ts"
|
|
26
54
|
],
|
|
27
55
|
"dependencies": {
|
|
28
|
-
"@lucia-auth/adapter-drizzle": "^1.0.
|
|
56
|
+
"@lucia-auth/adapter-drizzle": "^1.0.7",
|
|
29
57
|
"@sqrzro/interfaces": "bz",
|
|
30
58
|
"@sqrzro/utility": "bz",
|
|
31
59
|
"bcryptjs": "^2.4.3",
|
|
32
60
|
"drizzle-orm": "^0.29.5",
|
|
33
61
|
"joi": "^17.12.2",
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"next": "^14.1.3",
|
|
62
|
+
"lucia": "^3.1.1",
|
|
63
|
+
"next": "^14.1.4",
|
|
37
64
|
"otplib": "^12.0.1",
|
|
38
65
|
"path-to-regexp": "^6.2.1",
|
|
39
|
-
"postgres": "^3.4.
|
|
66
|
+
"postgres": "^3.4.4",
|
|
40
67
|
"qrcode": "^1.5.3",
|
|
41
|
-
"react-dom": "18.3.0-canary-
|
|
68
|
+
"react-dom": "18.3.0-canary-e373190fa-20240325",
|
|
42
69
|
"redis": "^4.6.13"
|
|
43
70
|
},
|
|
44
71
|
"devDependencies": {
|
|
@@ -47,8 +74,8 @@
|
|
|
47
74
|
"@types/bcryptjs": "^2.4.6",
|
|
48
75
|
"@types/jest": "^29.5.12",
|
|
49
76
|
"@types/qrcode": "^1.5.5",
|
|
50
|
-
"@types/react": "^18.2.
|
|
51
|
-
"@types/react-dom": "^18.2.
|
|
77
|
+
"@types/react": "^18.2.71",
|
|
78
|
+
"@types/react-dom": "^18.2.22",
|
|
52
79
|
"eslint": "^8.57.0",
|
|
53
80
|
"jest": "^29.7.0",
|
|
54
81
|
"prettier": "^3.2.5",
|
|
@@ -56,12 +83,12 @@
|
|
|
56
83
|
"ts-jest": "^29.1.2",
|
|
57
84
|
"tslib": "^2.6.2",
|
|
58
85
|
"tsup": "^8.0.2",
|
|
59
|
-
"typescript": "^5.4.
|
|
86
|
+
"typescript": "^5.4.3"
|
|
60
87
|
},
|
|
61
88
|
"scripts": {
|
|
62
|
-
"build": "pnpm clean &&
|
|
89
|
+
"build": "pnpm clean && tsup",
|
|
63
90
|
"clean": "rimraf ./dist",
|
|
64
|
-
"dev": "
|
|
91
|
+
"dev": "tsup --watch",
|
|
65
92
|
"lint": "tsc --noEmit && eslint \"./src/**/*.ts\"",
|
|
66
93
|
"prettier": "prettier --write \"./src/**/*.ts\"",
|
|
67
94
|
"start": "pnpm dev",
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { Errorable } from '@sqrzro/interfaces';
|
|
2
|
-
import type { LoginFormFields, PasswordFormFields, PasswordResetFormFields, UserObject } from './interfaces';
|
|
3
|
-
export declare function handleLogout(): Promise<void>;
|
|
4
|
-
export declare function getAllowedRoles(): number[];
|
|
5
|
-
export declare function handleLoginForm(formData: LoginFormFields): Promise<Errorable<string>>;
|
|
6
|
-
interface RegisterUserArgs {
|
|
7
|
-
email: string;
|
|
8
|
-
password?: string;
|
|
9
|
-
role?: number;
|
|
10
|
-
}
|
|
11
|
-
export declare function registerUser({ email, password, role, }: RegisterUserArgs): Promise<UserObject | null>;
|
|
12
|
-
export declare function handlePasswordForm(formData: PasswordFormFields, mailFn: (email: string, token: string) => Promise<boolean>): Promise<Errorable<boolean>>;
|
|
13
|
-
export declare function handlePasswordResetForm(formData: PasswordResetFormFields): Promise<Errorable<string | null>>;
|
|
14
|
-
export {};
|
package/dist/auth/AuthService.js
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { and, eq, inArray } from 'drizzle-orm';
|
|
2
|
-
import { db } from '../database/DatabaseService';
|
|
3
|
-
import { authResetTable, authUserTable } from '../database/schema';
|
|
4
|
-
import { submitForm } from '../forms/FormService';
|
|
5
|
-
import ValidationError from '../forms/ValidationError';
|
|
6
|
-
import { checkMFAEnabled } from './MFAService';
|
|
7
|
-
import { hashPassword, verifyPassword } from './PasswordService';
|
|
8
|
-
import { createUserSession, generateID, getScopeByID, getSessionID, invalidateSession, invalidateUserSessions, } from './SessionService';
|
|
9
|
-
import LoginRequest from './LoginRequest';
|
|
10
|
-
import PasswordRequest from './PasswordRequest';
|
|
11
|
-
import PasswordResetRequest from './PasswordResetRequest';
|
|
12
|
-
const RESET_TOKEN_LENGTH = 40;
|
|
13
|
-
// Set expiry to 1 hour (in ms)
|
|
14
|
-
const RESET_TOKEN_EXPIRY = 3600000;
|
|
15
|
-
export async function handleLogout() {
|
|
16
|
-
const id = getSessionID();
|
|
17
|
-
if (id) {
|
|
18
|
-
await invalidateSession(id);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
export function getAllowedRoles() {
|
|
22
|
-
const roles = process.env.AUTH_ALLOWED_ROLES;
|
|
23
|
-
if (!roles) {
|
|
24
|
-
throw new Error('AUTH_ALLOWED_ROLES is not defined. Authentication will not be possible.');
|
|
25
|
-
}
|
|
26
|
-
return roles
|
|
27
|
-
.split(',')
|
|
28
|
-
.map((role) => Number(role))
|
|
29
|
-
.filter((role) => !isNaN(role));
|
|
30
|
-
}
|
|
31
|
-
async function handleUserSession(userID) {
|
|
32
|
-
await createUserSession(userID, checkMFAEnabled() ? 'MFA' : 'AUTHED');
|
|
33
|
-
const scope = await getScopeByID('AUTHED');
|
|
34
|
-
return scope?.redirectOnAuth || null;
|
|
35
|
-
}
|
|
36
|
-
async function getUserByEmail(email) {
|
|
37
|
-
const [user] = await db
|
|
38
|
-
.select()
|
|
39
|
-
.from(authUserTable)
|
|
40
|
-
.where(and(eq(authUserTable.email, email), inArray(authUserTable.role, getAllowedRoles())))
|
|
41
|
-
.limit(1);
|
|
42
|
-
return user;
|
|
43
|
-
}
|
|
44
|
-
async function loginUser({ email, password }) {
|
|
45
|
-
const user = await getUserByEmail(email);
|
|
46
|
-
if (!user?.password || !(await verifyPassword(password, user.password))) {
|
|
47
|
-
throw new ValidationError({ email: '', password: '' });
|
|
48
|
-
}
|
|
49
|
-
const session = await handleUserSession(user.id);
|
|
50
|
-
if (!session) {
|
|
51
|
-
throw new ValidationError({ email: '', password: '' });
|
|
52
|
-
}
|
|
53
|
-
return session;
|
|
54
|
-
}
|
|
55
|
-
export async function handleLoginForm(formData) {
|
|
56
|
-
const response = await submitForm({
|
|
57
|
-
fn: loginUser,
|
|
58
|
-
formData,
|
|
59
|
-
request: LoginRequest,
|
|
60
|
-
});
|
|
61
|
-
return response;
|
|
62
|
-
}
|
|
63
|
-
export async function registerUser({ email, password, role, }) {
|
|
64
|
-
const hash = password ? await hashPassword(password) : null;
|
|
65
|
-
const [user] = await db
|
|
66
|
-
.insert(authUserTable)
|
|
67
|
-
.values({ id: generateID(), email, password: hash, role })
|
|
68
|
-
.returning();
|
|
69
|
-
return user;
|
|
70
|
-
}
|
|
71
|
-
async function createPasswordResetToken(email) {
|
|
72
|
-
const user = await getUserByEmail(email);
|
|
73
|
-
if (!user) {
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
await db.delete(authResetTable).where(eq(authResetTable.userId, user.id));
|
|
77
|
-
const id = generateID('', RESET_TOKEN_LENGTH);
|
|
78
|
-
await db.insert(authResetTable).values({
|
|
79
|
-
id,
|
|
80
|
-
userId: user.id,
|
|
81
|
-
expiresAt: new Date(new Date().getTime() + RESET_TOKEN_EXPIRY),
|
|
82
|
-
});
|
|
83
|
-
return id;
|
|
84
|
-
}
|
|
85
|
-
export async function handlePasswordForm(formData, mailFn) {
|
|
86
|
-
async function mutateFn(data) {
|
|
87
|
-
const token = await createPasswordResetToken(data.email);
|
|
88
|
-
if (!token) {
|
|
89
|
-
// Return true, even though the email doesn't exist (to prevent user enumeration)
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
return mailFn(data.email, token);
|
|
93
|
-
}
|
|
94
|
-
const response = await submitForm({
|
|
95
|
-
fn: mutateFn,
|
|
96
|
-
formData,
|
|
97
|
-
request: PasswordRequest,
|
|
98
|
-
});
|
|
99
|
-
return response;
|
|
100
|
-
}
|
|
101
|
-
async function validatePasswordResetToken(password, token) {
|
|
102
|
-
const [result] = await db
|
|
103
|
-
.select()
|
|
104
|
-
.from(authResetTable)
|
|
105
|
-
.where(eq(authResetTable.id, token))
|
|
106
|
-
.limit(1);
|
|
107
|
-
if (!result) {
|
|
108
|
-
return null;
|
|
109
|
-
}
|
|
110
|
-
await db.delete(authResetTable).where(eq(authResetTable.id, token));
|
|
111
|
-
if (!result || result.expiresAt < new Date()) {
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
await invalidateUserSessions(result.userId);
|
|
115
|
-
await db
|
|
116
|
-
.update(authUserTable)
|
|
117
|
-
.set({ password: await hashPassword(password) })
|
|
118
|
-
.where(and(eq(authUserTable.id, result.userId), inArray(authUserTable.role, getAllowedRoles())));
|
|
119
|
-
return result.userId;
|
|
120
|
-
}
|
|
121
|
-
export async function handlePasswordResetForm(formData) {
|
|
122
|
-
async function mutateFn(data) {
|
|
123
|
-
const userID = await validatePasswordResetToken(data.password, data.token);
|
|
124
|
-
if (!userID) {
|
|
125
|
-
return null;
|
|
126
|
-
}
|
|
127
|
-
return handleUserSession(userID);
|
|
128
|
-
}
|
|
129
|
-
const response = await submitForm({
|
|
130
|
-
fn: mutateFn,
|
|
131
|
-
formData,
|
|
132
|
-
request: PasswordResetRequest,
|
|
133
|
-
});
|
|
134
|
-
return response;
|
|
135
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { NextRequest } from 'next/server';
|
|
2
|
-
import type { AuthClient } from '../database/schema';
|
|
3
|
-
export declare function getClientByID(id: string): Promise<AuthClient | null>;
|
|
4
|
-
interface RegisterClientArgs {
|
|
5
|
-
alias: string;
|
|
6
|
-
id?: string;
|
|
7
|
-
secret?: string;
|
|
8
|
-
}
|
|
9
|
-
export declare function registerClient({ alias, id, secret, }: RegisterClientArgs): Promise<AuthClient | null>;
|
|
10
|
-
export declare function handleClientAuth(request: NextRequest): Promise<AuthClient | null>;
|
|
11
|
-
export {};
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { eq } from 'drizzle-orm';
|
|
2
|
-
import { db } from '../database/DatabaseService';
|
|
3
|
-
import { authClientTable } from '../database/schema';
|
|
4
|
-
import { hashPassword, verifyPassword } from './PasswordService';
|
|
5
|
-
import { generateID } from './SessionService';
|
|
6
|
-
const ID_LENGTH = 16;
|
|
7
|
-
const SECRET_LENGTH = 64;
|
|
8
|
-
export async function getClientByID(id) {
|
|
9
|
-
const [client] = await db
|
|
10
|
-
.select()
|
|
11
|
-
.from(authClientTable)
|
|
12
|
-
.where(eq(authClientTable.id, id))
|
|
13
|
-
.limit(1);
|
|
14
|
-
return client;
|
|
15
|
-
}
|
|
16
|
-
export async function registerClient({ alias, id, secret, }) {
|
|
17
|
-
const [client] = await db
|
|
18
|
-
.insert(authClientTable)
|
|
19
|
-
.values({
|
|
20
|
-
alias,
|
|
21
|
-
id: id || generateID('', ID_LENGTH),
|
|
22
|
-
secret: await hashPassword(secret || generateID('', SECRET_LENGTH)),
|
|
23
|
-
})
|
|
24
|
-
.returning();
|
|
25
|
-
return client;
|
|
26
|
-
}
|
|
27
|
-
export async function handleClientAuth(request) {
|
|
28
|
-
const { headers } = request;
|
|
29
|
-
const header = headers.get('authorization');
|
|
30
|
-
if (!header) {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
const auth = Buffer.from(header.replace('Basic ', ''), 'base64')
|
|
34
|
-
.toString('utf-8')
|
|
35
|
-
.replace(/:$/u, '');
|
|
36
|
-
const [id, ...secret] = auth.split('-');
|
|
37
|
-
const [client] = await db
|
|
38
|
-
.select()
|
|
39
|
-
.from(authClientTable)
|
|
40
|
-
.where(eq(authClientTable.id, id))
|
|
41
|
-
.limit(1);
|
|
42
|
-
if (!client) {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
const isVerified = await verifyPassword(secret.join(''), client.secret);
|
|
46
|
-
return isVerified ? client : null;
|
|
47
|
-
}
|