@nextsparkjs/core 0.1.0-beta.192 → 0.1.0-beta.194
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 +2 -2
- package/dist/components/app/layouts/PublicFooter.js +1 -1
- package/dist/components/app/layouts/PublicNavbar.js +1 -1
- package/dist/components/app/misc/ThemeToggle.d.ts.map +1 -1
- package/dist/components/app/misc/ThemeToggle.js +4 -3
- package/dist/lib/api/auth/permissions.d.ts +10 -0
- package/dist/lib/api/auth/permissions.d.ts.map +1 -1
- package/dist/lib/api/auth/permissions.js +7 -0
- package/dist/lib/api/rate-limit.d.ts.map +1 -1
- package/dist/lib/api/rate-limit.js +3 -0
- package/dist/lib/api/request-origin.d.ts +26 -0
- package/dist/lib/api/request-origin.d.ts.map +1 -0
- package/dist/lib/api/request-origin.js +46 -0
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +8 -12
- package/dist/lib/config/features-types.d.ts +5 -4
- package/dist/lib/config/features-types.d.ts.map +1 -1
- package/dist/lib/entities/external-api-generator.d.ts.map +1 -1
- package/dist/lib/entities/external-api-generator.js +3 -1
- package/dist/lib/selectors/auth-sel.d.ts +2 -7
- package/dist/lib/selectors/auth-sel.d.ts.map +1 -1
- package/dist/lib/selectors/auth-sel.js +1 -3
- package/dist/lib/selectors/by-domain/auth.d.ts +8 -0
- package/dist/lib/selectors/by-domain/auth.d.ts.map +1 -0
- package/dist/lib/selectors/by-domain/auth.js +10 -0
- package/dist/lib/selectors/by-domain/block-editor.d.ts +8 -0
- package/dist/lib/selectors/by-domain/block-editor.d.ts.map +1 -0
- package/dist/lib/selectors/by-domain/block-editor.js +10 -0
- package/dist/lib/selectors/by-domain/common.d.ts +8 -0
- package/dist/lib/selectors/by-domain/common.d.ts.map +1 -0
- package/dist/lib/selectors/by-domain/common.js +10 -0
- package/dist/lib/selectors/by-domain/dashboard.d.ts +8 -0
- package/dist/lib/selectors/by-domain/dashboard.d.ts.map +1 -0
- package/dist/lib/selectors/by-domain/dashboard.js +10 -0
- package/dist/lib/selectors/by-domain/devtools.d.ts +8 -0
- package/dist/lib/selectors/by-domain/devtools.d.ts.map +1 -0
- package/dist/lib/selectors/by-domain/devtools.js +10 -0
- package/dist/lib/selectors/by-domain/entities.d.ts +8 -0
- package/dist/lib/selectors/by-domain/entities.d.ts.map +1 -0
- package/dist/lib/selectors/by-domain/entities.js +10 -0
- package/dist/lib/selectors/by-domain/global-search.d.ts +8 -0
- package/dist/lib/selectors/by-domain/global-search.d.ts.map +1 -0
- package/dist/lib/selectors/by-domain/global-search.js +10 -0
- package/dist/lib/selectors/by-domain/media.d.ts +8 -0
- package/dist/lib/selectors/by-domain/media.d.ts.map +1 -0
- package/dist/lib/selectors/by-domain/media.js +10 -0
- package/dist/lib/selectors/by-domain/patterns.d.ts +8 -0
- package/dist/lib/selectors/by-domain/patterns.d.ts.map +1 -0
- package/dist/lib/selectors/by-domain/patterns.js +10 -0
- package/dist/lib/selectors/by-domain/public.d.ts +8 -0
- package/dist/lib/selectors/by-domain/public.d.ts.map +1 -0
- package/dist/lib/selectors/by-domain/public.js +10 -0
- package/dist/lib/selectors/by-domain/settings.d.ts +8 -0
- package/dist/lib/selectors/by-domain/settings.d.ts.map +1 -0
- package/dist/lib/selectors/by-domain/settings.js +10 -0
- package/dist/lib/selectors/by-domain/superadmin.d.ts +8 -0
- package/dist/lib/selectors/by-domain/superadmin.d.ts.map +1 -0
- package/dist/lib/selectors/by-domain/superadmin.js +10 -0
- package/dist/lib/selectors/by-domain/taxonomies.d.ts +8 -0
- package/dist/lib/selectors/by-domain/taxonomies.d.ts.map +1 -0
- package/dist/lib/selectors/by-domain/taxonomies.js +10 -0
- package/dist/lib/selectors/by-domain/teams.d.ts +8 -0
- package/dist/lib/selectors/by-domain/teams.d.ts.map +1 -0
- package/dist/lib/selectors/by-domain/teams.js +10 -0
- package/dist/lib/selectors/core-selectors.d.ts +1 -0
- package/dist/lib/selectors/core-selectors.d.ts.map +1 -1
- package/dist/lib/selectors/domains/public.selectors.d.ts +1 -0
- package/dist/lib/selectors/domains/public.selectors.d.ts.map +1 -1
- package/dist/lib/selectors/domains/public.selectors.js +3 -1
- package/dist/lib/selectors/selectors.d.ts +2 -0
- package/dist/lib/selectors/selectors.d.ts.map +1 -1
- package/dist/lib/services/subscription.service.d.ts.map +1 -1
- package/dist/lib/services/subscription.service.js +3 -0
- package/dist/lib/theme/ThemeProvider.d.ts.map +1 -1
- package/dist/lib/theme/ThemeProvider.js +7 -5
- package/dist/lib/utils/cors.d.ts +7 -0
- package/dist/lib/utils/cors.d.ts.map +1 -1
- package/dist/lib/utils/cors.js +8 -0
- package/dist/routes/(auth)/accept-invite/[token]/page.js +1 -1
- package/dist/routes/(auth)/forgot-password/page.js +1 -1
- package/dist/routes/(auth)/reset-password/page.js +1 -1
- package/dist/routes/(auth)/signup/page.cc.d.ts +2 -2
- package/dist/routes/(auth)/signup/page.d.ts +1 -1
- package/dist/routes/(auth)/signup/page.d.ts.map +1 -1
- package/dist/routes/(auth)/signup/page.js +1 -5
- package/dist/routes/(auth)/verify-email/page.js +1 -1
- package/dist/routes/(public)/docs/[section]/[page]/page.cc.js +1 -1
- package/dist/routes/(public)/docs/[section]/[page]/page.js +1 -1
- package/dist/routes/(public)/docs/layout.js +1 -1
- package/dist/routes/(public)/docs/page.js +1 -1
- package/dist/routes/_internal/default-public-layout.d.ts +5 -0
- package/dist/routes/_internal/default-public-layout.d.ts.map +1 -1
- package/dist/routes/_internal/default-public-layout.js +1 -2
- package/dist/routes/api/v1/users/[id]/meta/[key]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/users/[id]/meta/[key]/route.js +13 -0
- package/dist/routes/api/v1/users/[id]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/users/[id]/route.js +17 -0
- package/dist/routes/devtools/blocks/[slug]/page.d.ts +4 -1
- package/dist/routes/devtools/blocks/[slug]/page.d.ts.map +1 -1
- package/dist/routes/devtools/blocks/[slug]/page.js +2 -1
- package/dist/templates/features/blog/blocks/post-content/component.tsx +1 -1
- package/dist/templates/features/blog/entities/posts/posts.config.ts +0 -11
- package/dist/templates/features/pages/blocks/hero/component.tsx +1 -1
- package/dist/templates/features/pages/entities/pages/pages.config.ts +0 -11
- package/dist/templates/projects/blog/lib/block-selectors.ts +29 -0
- package/dist/templates/projects/blog/lib/selectors.ts +2 -9
- package/dist/templates/projects/blog/package.json +4 -7
- package/dist/templates/projects/crm/lib/block-selectors.ts +29 -0
- package/dist/templates/projects/crm/lib/selectors.ts +2 -9
- package/dist/templates/projects/crm/package.json +4 -4
- package/dist/templates/projects/crm/templates/dashboard/(main)/layout.tsx +2 -17
- package/dist/templates/projects/crm/templates/shared/CRMSidebarContext.tsx +23 -0
- package/dist/templates/projects/productivity/entities/boards/boards.service.ts +18 -18
- package/dist/templates/projects/productivity/entities/cards/cards.service.ts +18 -18
- package/dist/templates/projects/productivity/entities/lists/lists.service.ts +18 -18
- package/dist/templates/projects/productivity/lib/block-selectors.ts +29 -0
- package/dist/templates/projects/productivity/lib/selectors.ts +2 -9
- package/dist/templates/projects/productivity/package.json +4 -4
- package/dist/templates/projects/starter/lib/block-selectors.ts +28 -0
- package/dist/templates/projects/starter/lib/selectors.ts +2 -11
- package/package.json +12 -5
- package/scripts/build/auth-readiness.mjs +4 -0
- package/scripts/build/registry/__tests__/build-output.test.mjs +1 -1
- package/scripts/build/registry/__tests__/project-mode-root-first.test.mjs +6 -6
- package/scripts/build/registry/__tests__/write-places.test.mjs +1 -1
- package/scripts/build/registry/contracts/__tests__/contracts-wire.test.mjs +1 -1
- package/scripts/build/registry/contracts/__tests__/contracts.test.mjs +1 -1
- package/scripts/build/registry/contracts/render.mjs +3 -3
- package/scripts/build/registry/host/README.md +2 -2
- package/scripts/build/registry/host/__tests__/facade-emitter.test.mjs +9 -9
- package/scripts/build/registry/host/__tests__/host-mode.test.mjs +1 -1
- package/scripts/build/registry/host/__tests__/host-project-composition.test.mjs +1 -1
- package/scripts/build/registry/host/__tests__/host-project.test.mjs +2 -2
- package/scripts/build/registry/host/__tests__/host-robustness.test.mjs +65 -2
- package/scripts/build/registry/host/facade-emitter.mjs +2 -2
- package/scripts/build/registry/host/generation.mjs +54 -0
- package/scripts/build/registry/host/next-route-exports.json +2 -2
- package/scripts/build/registry/host/prepare.mjs +3 -0
- package/scripts/db/migration-time-limit.mjs +216 -34
- package/scripts/db/run-migrations.mjs +11 -179
- package/scripts/db/verify-theme-migrations.mjs +1 -1
- package/templates/features/blog/blocks/post-content/component.tsx +1 -1
- package/templates/features/blog/entities/posts/posts.config.ts +0 -11
- package/templates/features/pages/blocks/hero/component.tsx +1 -1
- package/templates/features/pages/entities/pages/pages.config.ts +0 -11
- package/templates/projects/blog/lib/block-selectors.ts +29 -0
- package/templates/projects/blog/lib/selectors.ts +2 -9
- package/templates/projects/blog/package.json +4 -7
- package/templates/projects/crm/lib/block-selectors.ts +29 -0
- package/templates/projects/crm/lib/selectors.ts +2 -9
- package/templates/projects/crm/package.json +4 -4
- package/templates/projects/crm/templates/dashboard/(main)/layout.tsx +2 -17
- package/templates/projects/crm/templates/shared/CRMSidebarContext.tsx +23 -0
- package/templates/projects/productivity/entities/boards/boards.service.ts +18 -18
- package/templates/projects/productivity/entities/cards/cards.service.ts +18 -18
- package/templates/projects/productivity/entities/lists/lists.service.ts +18 -18
- package/templates/projects/productivity/lib/block-selectors.ts +29 -0
- package/templates/projects/productivity/lib/selectors.ts +2 -9
- package/templates/projects/productivity/package.json +4 -4
- package/templates/projects/starter/lib/block-selectors.ts +28 -0
- package/templates/projects/starter/lib/selectors.ts +2 -11
package/README.md
CHANGED
|
@@ -5,8 +5,6 @@ The complete SaaS framework for Next.js. Build production-ready SaaS application
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install @nextsparkjs/core
|
|
9
|
-
# or
|
|
10
8
|
pnpm add @nextsparkjs/core
|
|
11
9
|
```
|
|
12
10
|
|
|
@@ -16,6 +14,8 @@ pnpm add @nextsparkjs/core
|
|
|
16
14
|
# Create a new NextSpark project
|
|
17
15
|
npx create-nextspark-app my-app
|
|
18
16
|
cd my-app
|
|
17
|
+
# set DATABASE_URL in .env (BETTER_AUTH_SECRET is already generated)
|
|
18
|
+
pnpm db:migrate
|
|
19
19
|
pnpm dev
|
|
20
20
|
```
|
|
21
21
|
|
|
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import Link from "next/link";
|
|
3
3
|
import { Separator } from "../../ui/separator.js";
|
|
4
4
|
import { useTranslations } from "next-intl";
|
|
5
|
-
import { sel } from "
|
|
5
|
+
import { sel } from "@nextsparkjs/core/selectors/public";
|
|
6
6
|
import { APP_NAME } from "../../../lib/config/public-config-client.js";
|
|
7
7
|
import { CurrentYear } from "./CurrentYear.js";
|
|
8
8
|
function PublicFooter() {
|
|
@@ -7,7 +7,7 @@ import { Button } from "../../ui/button.js";
|
|
|
7
7
|
import { ThemeToggle } from "../misc/ThemeToggle.js";
|
|
8
8
|
import { Menu, X } from "lucide-react";
|
|
9
9
|
import { useState } from "react";
|
|
10
|
-
import { sel } from "
|
|
10
|
+
import { sel } from "@nextsparkjs/core/selectors/public";
|
|
11
11
|
import { useTranslations } from "next-intl";
|
|
12
12
|
import { APP_NAME } from "../../../lib/config/public-config-client.js";
|
|
13
13
|
function AuthActionsSkeleton({ layout }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemeToggle.d.ts","sourceRoot":"","sources":["../../../../src/components/app/misc/ThemeToggle.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ThemeToggle.d.ts","sourceRoot":"","sources":["../../../../src/components/app/misc/ThemeToggle.tsx"],"names":[],"mappings":"AAmBA,wBAAgB,WAAW,4CA6H1B"}
|
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
DropdownMenuTrigger
|
|
11
11
|
} from "../../ui/dropdown-menu.js";
|
|
12
12
|
import { useEffect, useState, useCallback } from "react";
|
|
13
|
-
import { createAriaLabel
|
|
13
|
+
import { createAriaLabel } from "../../../lib/test/utils.js";
|
|
14
|
+
import { sel } from "@nextsparkjs/core/selectors/public";
|
|
14
15
|
import { useTranslations } from "next-intl";
|
|
15
16
|
import { hasSessionHint } from "../../../lib/auth/session-hint.js";
|
|
16
17
|
import { withBasePath } from "../../../lib/base-path.js";
|
|
@@ -61,7 +62,7 @@ function ThemeToggle() {
|
|
|
61
62
|
size: "icon",
|
|
62
63
|
disabled: true,
|
|
63
64
|
"aria-label": t("theme.loading"),
|
|
64
|
-
"data-cy": sel("
|
|
65
|
+
"data-cy": sel("public.navbar.themeToggle"),
|
|
65
66
|
children: [
|
|
66
67
|
/* @__PURE__ */ jsx(Sun, { className: "h-5 w-5", "aria-hidden": "true" }),
|
|
67
68
|
/* @__PURE__ */ jsx("span", { className: "sr-only", children: t("theme.loading") })
|
|
@@ -92,7 +93,7 @@ function ThemeToggle() {
|
|
|
92
93
|
}),
|
|
93
94
|
"aria-haspopup": "true",
|
|
94
95
|
"aria-expanded": "false",
|
|
95
|
-
"data-cy": sel("
|
|
96
|
+
"data-cy": sel("public.navbar.themeToggle"),
|
|
96
97
|
children: [
|
|
97
98
|
/* @__PURE__ */ jsx(Sun, { className: "h-5 w-5 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0", "aria-hidden": "true" }),
|
|
98
99
|
/* @__PURE__ */ jsx(Moon, { className: "absolute h-5 w-5 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100", "aria-hidden": "true" }),
|
|
@@ -27,4 +27,14 @@ export declare function isSuperAdmin(authResult: DualAuthResult): boolean;
|
|
|
27
27
|
* @returns true si tiene permisos de admin
|
|
28
28
|
*/
|
|
29
29
|
export declare function hasAdminPermission(authResult: DualAuthResult, requiredScope?: string | string[]): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Whether the caller may read or edit the user `target` (an id or an email, as
|
|
32
|
+
* the /users/:id routes accept both): the user themselves, or a superadmin.
|
|
33
|
+
* An API key is its owner, so it gets the same answer, but a superadmin key
|
|
34
|
+
* must also carry `requiredScope`.
|
|
35
|
+
*
|
|
36
|
+
* Application-layer check: row-level security does not cover a deployment that
|
|
37
|
+
* has not cut over to the non-owner runtime role.
|
|
38
|
+
*/
|
|
39
|
+
export declare function canAccessUser(authResult: DualAuthResult, target: string, requiredScope?: string | string[]): boolean;
|
|
30
40
|
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/auth/permissions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAGjD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,cAAc,GAAG,OAAO,CAOhE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,cAAc,EAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAChC,OAAO,CAYT"}
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/auth/permissions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAGjD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,cAAc,GAAG,OAAO,CAOhE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,cAAc,EAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAChC,OAAO,CAYT;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,cAAc,EAC1B,MAAM,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAChC,OAAO,CAOT"}
|
|
@@ -14,7 +14,14 @@ function hasAdminPermission(authResult, requiredScope) {
|
|
|
14
14
|
}
|
|
15
15
|
return true;
|
|
16
16
|
}
|
|
17
|
+
function canAccessUser(authResult, target, requiredScope) {
|
|
18
|
+
if (!authResult.success || !authResult.user) return false;
|
|
19
|
+
if (hasAdminPermission(authResult, requiredScope)) return true;
|
|
20
|
+
const { id, email } = authResult.user;
|
|
21
|
+
return target === id || !!email && target === email;
|
|
22
|
+
}
|
|
17
23
|
export {
|
|
24
|
+
canAccessUser,
|
|
18
25
|
hasAdminPermission,
|
|
19
26
|
isSuperAdmin
|
|
20
27
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../src/lib/api/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIxD,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../src/lib/api/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIxD,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,MAAa,EACpB,QAAQ,GAAE,MAAc,GACvB,eAAe,CAyCjB;AAED;;;GAGG;AACH,YAAY,EAAE,aAAa,EAAE,CAAC;AAE9B;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,aAAqB,GAC1B,OAAO,CAAC,eAAe,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6CpD;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,eAAe,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAwB5G;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,IAAI,OAAO,CAEzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EAAE,GACf,YAAY,GAAG,IAAI,CAkCrB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EAAE,GACf,YAAY,CASd;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,OAAO,EAAE,EAC/C,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,IAEtD,SAAS,WAAW,EAAE,GAAG,MAAM,CAAC,KAAG,OAAO,CAAC,YAAY,CAAC,CAwCvE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG;IAChD,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACtB,GAAG,IAAI,CAaP;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAGlD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,KAAK,CAAC;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC,CASD;AAED;;GAEG;AACH,wBAAgB,sBAAsB;;;;;EAErC;AAsGD,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,OAAO,EAAE,EACnD,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,EACpE,IAAI,GAAE,aAAqB,IAEb,SAAS,WAAW,EAAE,GAAG,MAAM,CAAC,KAAG,OAAO,CAAC,YAAY,CAAC,CAsCvE"}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
checkRateLimit as checkRedisRateLimit,
|
|
7
7
|
maybeRedisConfigured
|
|
8
8
|
} from "../rate-limit-redis.js";
|
|
9
|
+
import { checkRequestOrigin } from "./request-origin.js";
|
|
9
10
|
function checkRateLimit(identifier, limit = 1e3, windowMs = 6e4) {
|
|
10
11
|
const now = Date.now();
|
|
11
12
|
const cacheKey = getCacheKey("rate_limit", identifier);
|
|
@@ -239,6 +240,8 @@ function isRateLimitingDisabled() {
|
|
|
239
240
|
}
|
|
240
241
|
function withRateLimitTier(handler, tier = "api") {
|
|
241
242
|
return async (request, ...args) => {
|
|
243
|
+
const originRefused = checkRequestOrigin(request);
|
|
244
|
+
if (originRefused) return originRefused;
|
|
242
245
|
if (isRateLimitingDisabled()) {
|
|
243
246
|
return handler(request, ...args);
|
|
244
247
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request origin check for cookie-authenticated writes.
|
|
3
|
+
*
|
|
4
|
+
* A POST/PUT/PATCH/DELETE that authenticates with the session cookie must come
|
|
5
|
+
* from an origin the app trusts: its own (NEXT_PUBLIC_APP_URL / BETTER_AUTH_URL)
|
|
6
|
+
* or one in the list Better Auth already trusts for sign-in (see
|
|
7
|
+
* getTrustedOrigins). withRateLimitTier runs it before every handler it wraps.
|
|
8
|
+
*
|
|
9
|
+
* What passes without a trusted origin, and why:
|
|
10
|
+
* - Reads (GET/HEAD/OPTIONS).
|
|
11
|
+
* - Requests without the session cookie: there is no session for them to use.
|
|
12
|
+
* - Requests with an `Authorization: Bearer` token or an x-api-key header (API
|
|
13
|
+
* keys, the mobile client's bearer token). A browser adds those only when the page's script
|
|
14
|
+
* sets them, and a script on another origin needs CORS approval first.
|
|
15
|
+
* - Requests with neither Origin nor Referer, unless their body is one an HTML
|
|
16
|
+
* form can send. Browsers send Origin on every write, so these come from
|
|
17
|
+
* native or server-side clients; requiring a non-form content type keeps
|
|
18
|
+
* a body without origin information from ever being read as a form post.
|
|
19
|
+
*/
|
|
20
|
+
import { NextResponse } from 'next/server';
|
|
21
|
+
/**
|
|
22
|
+
* Returns a 403 response when a cookie-authenticated write does not come from a
|
|
23
|
+
* trusted origin, or null when the request may proceed.
|
|
24
|
+
*/
|
|
25
|
+
export declare function checkRequestOrigin(request: Request): NextResponse | null;
|
|
26
|
+
//# sourceMappingURL=request-origin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-origin.d.ts","sourceRoot":"","sources":["../../../src/lib/api/request-origin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AA6B1C;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CAsBxE"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { APP_CONFIG_MERGED } from "../config/index.js";
|
|
3
|
+
import { hasSessionCookie } from "../auth/session-hint.js";
|
|
4
|
+
import { getTrustedOrigins, isOriginAllowed, normalizeOrigin } from "../utils/cors.js";
|
|
5
|
+
const WRITE_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
6
|
+
const FORM_CONTENT_TYPES = /* @__PURE__ */ new Set(["text/plain", "application/x-www-form-urlencoded", "multipart/form-data"]);
|
|
7
|
+
function requestOrigin(headers) {
|
|
8
|
+
const origin = headers.get("origin");
|
|
9
|
+
if (origin) return origin;
|
|
10
|
+
const referer = headers.get("referer");
|
|
11
|
+
if (!referer) return null;
|
|
12
|
+
try {
|
|
13
|
+
return new URL(referer).origin;
|
|
14
|
+
} catch {
|
|
15
|
+
return "null";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function hasHeaderCredential(headers) {
|
|
19
|
+
var _a;
|
|
20
|
+
if ((_a = headers.get("x-api-key")) == null ? void 0 : _a.trim()) return true;
|
|
21
|
+
return /^bearer\s+\S/i.test(headers.get("authorization") ?? "");
|
|
22
|
+
}
|
|
23
|
+
function checkRequestOrigin(request) {
|
|
24
|
+
if (!WRITE_METHODS.has(request.method.toUpperCase())) return null;
|
|
25
|
+
const headers = request.headers;
|
|
26
|
+
if (!hasSessionCookie(headers.get("cookie"))) return null;
|
|
27
|
+
if (hasHeaderCredential(headers)) return null;
|
|
28
|
+
const origin = requestOrigin(headers);
|
|
29
|
+
if (origin === null) {
|
|
30
|
+
const contentType = (headers.get("content-type") ?? "").split(";")[0].trim().toLowerCase();
|
|
31
|
+
if (!FORM_CONTENT_TYPES.has(contentType)) return null;
|
|
32
|
+
return NextResponse.json(
|
|
33
|
+
{ success: false, error: "This request needs an Origin header", code: "ORIGIN_REQUIRED" },
|
|
34
|
+
{ status: 403 }
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
const normalized = normalizeOrigin(origin);
|
|
38
|
+
if (isOriginAllowed(normalized, getTrustedOrigins(APP_CONFIG_MERGED, normalized))) return null;
|
|
39
|
+
return NextResponse.json(
|
|
40
|
+
{ success: false, error: "Request origin not allowed", code: "ORIGIN_NOT_ALLOWED" },
|
|
41
|
+
{ status: 403 }
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
checkRequestOrigin
|
|
46
|
+
};
|
package/dist/lib/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAUA,OAAO,EAAgF,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAkBvH;;;;;;;;;;;;;GAaG;AACH,wBAAsB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQlF;AAED;;;;;;;;;GASG;AACH,wBAAsB,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEnF;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsHD,eAAO,MAAM,IAAI,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAUA,OAAO,EAAgF,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAkBvH;;;;;;;;;;;;;GAaG;AACH,wBAAsB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQlF;AAED;;;;;;;;;GASG;AACH,wBAAsB,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEnF;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsHD,eAAO,MAAM,IAAI,qEA8Wf,CAAC;AAEH,MAAM,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;AACjD,MAAM,MAAM,WAAW,GAAG,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,GAAG;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,kBAAkB,EAAE,QAAQ,EAAE,CAAC;CAC/C,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5B,IAAI,EAAE,WAAW,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAO9B"}
|
package/dist/lib/auth.js
CHANGED
|
@@ -19,7 +19,7 @@ import { resolveSessionConfig } from "./auth/session-config.js";
|
|
|
19
19
|
import { resolveOtpConfig } from "./auth/otp-config.js";
|
|
20
20
|
import { isPasswordLoginEnabled } from "./auth/auth-methods.js";
|
|
21
21
|
import { isRuntimeEmailAvailable, isRuntimeGoogleAvailable } from "./auth/runtime-readiness.js";
|
|
22
|
-
import {
|
|
22
|
+
import { getTrustedOrigins } from "./utils/cors.js";
|
|
23
23
|
import { withBasePath } from "./base-path.js";
|
|
24
24
|
async function hasPendingInvitationForEmail(email) {
|
|
25
25
|
const row = await queryOne(
|
|
@@ -206,17 +206,7 @@ const auth = betterAuth({
|
|
|
206
206
|
// adding a wildcard entry (e.g. "https://*.vercel.app") to
|
|
207
207
|
// api.cors.additionalOrigins — better-auth's own trustedOrigins matching
|
|
208
208
|
// already supports the same wildcard syntax as isOriginAllowed() above.
|
|
209
|
-
trustedOrigins: async (request) =>
|
|
210
|
-
const origins = getCorsOrigins(APP_CONFIG_MERGED);
|
|
211
|
-
if (normalizeCorsEnvironment(process.env.NODE_ENV || "development") === "production") {
|
|
212
|
-
return origins;
|
|
213
|
-
}
|
|
214
|
-
const requestOrigin = request == null ? void 0 : request.headers.get("origin");
|
|
215
|
-
if (requestOrigin && isPrivateLanOrigin(requestOrigin)) {
|
|
216
|
-
return [...origins, requestOrigin];
|
|
217
|
-
}
|
|
218
|
-
return origins;
|
|
219
|
-
},
|
|
209
|
+
trustedOrigins: async (request) => getTrustedOrigins(APP_CONFIG_MERGED, request == null ? void 0 : request.headers.get("origin")),
|
|
220
210
|
// Redirect auth errors to our custom error page instead of Better Auth's default.
|
|
221
211
|
// Better Auth redirects to this path as-is, outside the Next.js router.
|
|
222
212
|
onAPIError: {
|
|
@@ -249,6 +239,12 @@ const auth = betterAuth({
|
|
|
249
239
|
nextCookies()
|
|
250
240
|
// MUST be the last plugin for Next.js cookie handling
|
|
251
241
|
],
|
|
242
|
+
// The proxy reads the session on every request; that lookup only reads the
|
|
243
|
+
// caller's own signed cookie, so it is kept out of the shared auth rate limit.
|
|
244
|
+
// The default limits (sign-in, sign-up, OTP, ...) stay.
|
|
245
|
+
rateLimit: {
|
|
246
|
+
customRules: { "/get-session": false }
|
|
247
|
+
},
|
|
252
248
|
session: {
|
|
253
249
|
// Configurable per theme via `auth.session` in app.config.ts (defaults:
|
|
254
250
|
// 7 days / renewed daily / 5-minute cookie cache).
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
* These are used to generate the feature-registry at build time.
|
|
6
6
|
*/
|
|
7
7
|
/**
|
|
8
|
-
* Feature categories for organization
|
|
8
|
+
* Feature categories for organization. The named ones are the platform's; a project template adds its own
|
|
9
|
+
* (the CRM's 'leads' and 'sales', the blog's 'public'), so any string is accepted.
|
|
9
10
|
*/
|
|
10
|
-
export type FeatureCategory = 'core' | 'entities' | 'content' | 'settings' | 'admin';
|
|
11
|
+
export type FeatureCategory = 'core' | 'entities' | 'content' | 'settings' | 'admin' | (string & {});
|
|
11
12
|
/**
|
|
12
13
|
* Feature definition in configuration
|
|
13
14
|
*/
|
|
@@ -42,9 +43,9 @@ export interface FeatureDefinition {
|
|
|
42
43
|
*/
|
|
43
44
|
export type FeaturesConfig = Record<string, FeatureDefinition>;
|
|
44
45
|
/**
|
|
45
|
-
* Flow categories for organization
|
|
46
|
+
* Flow categories for organization. Like feature categories, a project template may add its own.
|
|
46
47
|
*/
|
|
47
|
-
export type FlowCategory = 'acquisition' | 'navigation' | 'content' | 'admin' | 'settings';
|
|
48
|
+
export type FlowCategory = 'acquisition' | 'navigation' | 'content' | 'admin' | 'settings' | (string & {});
|
|
48
49
|
/**
|
|
49
50
|
* A step in a user flow/journey
|
|
50
51
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features-types.d.ts","sourceRoot":"","sources":["../../../src/lib/config/features-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH
|
|
1
|
+
{"version":3,"file":"features-types.d.ts","sourceRoot":"","sources":["../../../src/lib/config/features-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;;GAGG;AACH,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,UAAU,GACV,SAAS,GACT,UAAU,GACV,OAAO,GACP,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAEjB;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAA;IAEZ,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAA;IAEnB,qCAAqC;IACrC,QAAQ,EAAE,eAAe,CAAA;IAEzB,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IAEnB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IAEtB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;AAM9D;;GAEG;AACH,MAAM,MAAM,YAAY,GACpB,aAAa,GACb,YAAY,GACZ,SAAS,GACT,OAAO,GACP,UAAU,GACV,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAEjB;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IAEf,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAA;IAEd,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAA;IAEnB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAA;IAEZ,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAA;IAEnB,kCAAkC;IAClC,QAAQ,EAAE,YAAY,CAAA;IAEtB,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb;;;OAGG;IACH,KAAK,EAAE,QAAQ,EAAE,CAAA;IAEjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IAEnB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;AAMxD;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,cAAc,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAErE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,WAAW,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAE/D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"external-api-generator.d.ts","sourceRoot":"","sources":["../../../src/lib/entities/external-api-generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EAAqB,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAK3C,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;IAC7D,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,eAAe,CAAC,EAAE;QAChB,QAAQ,EAAE,MAAM,CAAA;QAChB,WAAW,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,WAAW,CAAC,EAAE;QACZ,OAAO,EAAE,MAAM,EAAE,CAAA;QACjB,OAAO,EAAE,MAAM,EAAE,CAAA;QACjB,OAAO,EAAE,MAAM,EAAE,CAAA;KAClB,CAAA;CACF;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,YAAY,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,kBAAuB;mBAqFT,WAAW,YAAY;QAAE,MAAM,CAAC,EAAE;YAAE,EAAE,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;oBAAnD,WAAW,YAAY;QAAE,MAAM,CAAC,EAAE;YAAE,EAAE,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;qBAAnD,WAAW,YAAY;QAAE,MAAM,CAAC,EAAE;YAAE,EAAE,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;sBAAnD,WAAW,YAAY;QAAE,MAAM,CAAC,EAAE;YAAE,EAAE,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;uBAkGnD,WAAW;EAnHnC;
|
|
1
|
+
{"version":3,"file":"external-api-generator.d.ts","sourceRoot":"","sources":["../../../src/lib/entities/external-api-generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EAAqB,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAK3C,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;IAC7D,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,eAAe,CAAC,EAAE;QAChB,QAAQ,EAAE,MAAM,CAAA;QAChB,WAAW,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,WAAW,CAAC,EAAE;QACZ,OAAO,EAAE,MAAM,EAAE,CAAA;QACjB,OAAO,EAAE,MAAM,EAAE,CAAA;QACjB,OAAO,EAAE,MAAM,EAAE,CAAA;KAClB,CAAA;CACF;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,YAAY,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,kBAAuB;mBAqFT,WAAW,YAAY;QAAE,MAAM,CAAC,EAAE;YAAE,EAAE,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;oBAAnD,WAAW,YAAY;QAAE,MAAM,CAAC,EAAE;YAAE,EAAE,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;qBAAnD,WAAW,YAAY;QAAE,MAAM,CAAC,EAAE;YAAE,EAAE,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;sBAAnD,WAAW,YAAY;QAAE,MAAM,CAAC,EAAE;YAAE,EAAE,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;uBAkGnD,WAAW;EAnHnC;AA4KD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoMrD"}
|
|
@@ -153,7 +153,9 @@ function addCORSHeaders(response, corsOptions, request) {
|
|
|
153
153
|
response.headers.set("Access-Control-Allow-Methods", corsOptions.methods.join(", "));
|
|
154
154
|
response.headers.set("Access-Control-Allow-Headers", corsOptions.headers.join(", "));
|
|
155
155
|
response.headers.set("Access-Control-Max-Age", "86400");
|
|
156
|
-
|
|
156
|
+
if (origin && corsOptions.origins.includes(origin)) {
|
|
157
|
+
response.headers.set("Access-Control-Allow-Credentials", "true");
|
|
158
|
+
}
|
|
157
159
|
}
|
|
158
160
|
function createErrorResponse(status, message, details) {
|
|
159
161
|
return NextResponse.json({
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* `sel` resolves a path at runtime, so the module that binds it to CORE_SELECTORS ships every domain (superadmin,
|
|
5
|
-
* devtools, block editor, entities...) to each page that imports it. The auth forms only read `auth.*` paths.
|
|
6
|
-
*/
|
|
7
|
-
export declare const sel: (path: string, replacements?: import("./selector-factory").Replacements) => string;
|
|
1
|
+
/** `sel` for the auth pages: the `auth` domain only (see ./by-domain/auth). */
|
|
2
|
+
export { sel } from './by-domain/auth';
|
|
8
3
|
//# sourceMappingURL=auth-sel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-sel.d.ts","sourceRoot":"","sources":["../../../src/lib/selectors/auth-sel.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"auth-sel.d.ts","sourceRoot":"","sources":["../../../src/lib/selectors/auth-sel.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sel` bound to the `auth` domain only: `import { sel } from '@nextsparkjs/core/selectors/auth'`.
|
|
3
|
+
* Same paths and values as the barrel's `sel('auth.…')`, without shipping the other domains to the page.
|
|
4
|
+
*/
|
|
5
|
+
import { AUTH_SELECTORS } from '../domains/auth.selectors';
|
|
6
|
+
export { AUTH_SELECTORS };
|
|
7
|
+
export declare const sel: (path: string, replacements?: import("..").Replacements) => string, s: (path: string, replacements?: import("..").Replacements) => string, selDev: (path: string, replacements?: import("..").Replacements) => string | undefined, cySelector: (path: string, replacements?: import("..").Replacements) => string;
|
|
8
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../../src/lib/selectors/by-domain/auth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAE1D,OAAO,EAAE,cAAc,EAAE,CAAA;AACzB,eAAO,MAAQ,GAAG,sEAAE,CAAC,sEAAE,MAAM,kFAAE,UAAU,oEAAoD,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createSelectorHelpers } from "../selector-factory.js";
|
|
2
|
+
import { AUTH_SELECTORS } from "../domains/auth.selectors.js";
|
|
3
|
+
const { sel, s, selDev, cySelector } = createSelectorHelpers({ auth: AUTH_SELECTORS });
|
|
4
|
+
export {
|
|
5
|
+
AUTH_SELECTORS,
|
|
6
|
+
cySelector,
|
|
7
|
+
s,
|
|
8
|
+
sel,
|
|
9
|
+
selDev
|
|
10
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sel` bound to the `blockEditor` domain only: `import { sel } from '@nextsparkjs/core/selectors/block-editor'`.
|
|
3
|
+
* Same paths and values as the barrel's `sel('blockEditor.…')`, without shipping the other domains to the page.
|
|
4
|
+
*/
|
|
5
|
+
import { BLOCK_EDITOR_SELECTORS } from '../domains/block-editor.selectors';
|
|
6
|
+
export { BLOCK_EDITOR_SELECTORS };
|
|
7
|
+
export declare const sel: (path: string, replacements?: import("..").Replacements) => string, s: (path: string, replacements?: import("..").Replacements) => string, selDev: (path: string, replacements?: import("..").Replacements) => string | undefined, cySelector: (path: string, replacements?: import("..").Replacements) => string;
|
|
8
|
+
//# sourceMappingURL=block-editor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-editor.d.ts","sourceRoot":"","sources":["../../../../src/lib/selectors/by-domain/block-editor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAA;AAE1E,OAAO,EAAE,sBAAsB,EAAE,CAAA;AACjC,eAAO,MAAQ,GAAG,sEAAE,CAAC,sEAAE,MAAM,kFAAE,UAAU,oEAAmE,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createSelectorHelpers } from "../selector-factory.js";
|
|
2
|
+
import { BLOCK_EDITOR_SELECTORS } from "../domains/block-editor.selectors.js";
|
|
3
|
+
const { sel, s, selDev, cySelector } = createSelectorHelpers({ blockEditor: BLOCK_EDITOR_SELECTORS });
|
|
4
|
+
export {
|
|
5
|
+
BLOCK_EDITOR_SELECTORS,
|
|
6
|
+
cySelector,
|
|
7
|
+
s,
|
|
8
|
+
sel,
|
|
9
|
+
selDev
|
|
10
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sel` bound to the `common` domain only: `import { sel } from '@nextsparkjs/core/selectors/common'`.
|
|
3
|
+
* Same paths and values as the barrel's `sel('common.…')`, without shipping the other domains to the page.
|
|
4
|
+
*/
|
|
5
|
+
import { COMMON_SELECTORS } from '../domains/common.selectors';
|
|
6
|
+
export { COMMON_SELECTORS };
|
|
7
|
+
export declare const sel: (path: string, replacements?: import("..").Replacements) => string, s: (path: string, replacements?: import("..").Replacements) => string, selDev: (path: string, replacements?: import("..").Replacements) => string | undefined, cySelector: (path: string, replacements?: import("..").Replacements) => string;
|
|
8
|
+
//# sourceMappingURL=common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../../src/lib/selectors/by-domain/common.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAE9D,OAAO,EAAE,gBAAgB,EAAE,CAAA;AAC3B,eAAO,MAAQ,GAAG,sEAAE,CAAC,sEAAE,MAAM,kFAAE,UAAU,oEAAwD,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createSelectorHelpers } from "../selector-factory.js";
|
|
2
|
+
import { COMMON_SELECTORS } from "../domains/common.selectors.js";
|
|
3
|
+
const { sel, s, selDev, cySelector } = createSelectorHelpers({ common: COMMON_SELECTORS });
|
|
4
|
+
export {
|
|
5
|
+
COMMON_SELECTORS,
|
|
6
|
+
cySelector,
|
|
7
|
+
s,
|
|
8
|
+
sel,
|
|
9
|
+
selDev
|
|
10
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sel` bound to the `dashboard` domain only: `import { sel } from '@nextsparkjs/core/selectors/dashboard'`.
|
|
3
|
+
* Same paths and values as the barrel's `sel('dashboard.…')`, without shipping the other domains to the page.
|
|
4
|
+
*/
|
|
5
|
+
import { DASHBOARD_SELECTORS } from '../domains/dashboard.selectors';
|
|
6
|
+
export { DASHBOARD_SELECTORS };
|
|
7
|
+
export declare const sel: (path: string, replacements?: import("..").Replacements) => string, s: (path: string, replacements?: import("..").Replacements) => string, selDev: (path: string, replacements?: import("..").Replacements) => string | undefined, cySelector: (path: string, replacements?: import("..").Replacements) => string;
|
|
8
|
+
//# sourceMappingURL=dashboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../../../src/lib/selectors/by-domain/dashboard.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AAEpE,OAAO,EAAE,mBAAmB,EAAE,CAAA;AAC9B,eAAO,MAAQ,GAAG,sEAAE,CAAC,sEAAE,MAAM,kFAAE,UAAU,oEAA8D,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createSelectorHelpers } from "../selector-factory.js";
|
|
2
|
+
import { DASHBOARD_SELECTORS } from "../domains/dashboard.selectors.js";
|
|
3
|
+
const { sel, s, selDev, cySelector } = createSelectorHelpers({ dashboard: DASHBOARD_SELECTORS });
|
|
4
|
+
export {
|
|
5
|
+
DASHBOARD_SELECTORS,
|
|
6
|
+
cySelector,
|
|
7
|
+
s,
|
|
8
|
+
sel,
|
|
9
|
+
selDev
|
|
10
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sel` bound to the `devtools` domain only: `import { sel } from '@nextsparkjs/core/selectors/devtools'`.
|
|
3
|
+
* Same paths and values as the barrel's `sel('devtools.…')`, without shipping the other domains to the page.
|
|
4
|
+
*/
|
|
5
|
+
import { DEVTOOLS_SELECTORS } from '../domains/devtools.selectors';
|
|
6
|
+
export { DEVTOOLS_SELECTORS };
|
|
7
|
+
export declare const sel: (path: string, replacements?: import("..").Replacements) => string, s: (path: string, replacements?: import("..").Replacements) => string, selDev: (path: string, replacements?: import("..").Replacements) => string | undefined, cySelector: (path: string, replacements?: import("..").Replacements) => string;
|
|
8
|
+
//# sourceMappingURL=devtools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devtools.d.ts","sourceRoot":"","sources":["../../../../src/lib/selectors/by-domain/devtools.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAElE,OAAO,EAAE,kBAAkB,EAAE,CAAA;AAC7B,eAAO,MAAQ,GAAG,sEAAE,CAAC,sEAAE,MAAM,kFAAE,UAAU,oEAA4D,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createSelectorHelpers } from "../selector-factory.js";
|
|
2
|
+
import { DEVTOOLS_SELECTORS } from "../domains/devtools.selectors.js";
|
|
3
|
+
const { sel, s, selDev, cySelector } = createSelectorHelpers({ devtools: DEVTOOLS_SELECTORS });
|
|
4
|
+
export {
|
|
5
|
+
DEVTOOLS_SELECTORS,
|
|
6
|
+
cySelector,
|
|
7
|
+
s,
|
|
8
|
+
sel,
|
|
9
|
+
selDev
|
|
10
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sel` bound to the `entities` domain only: `import { sel } from '@nextsparkjs/core/selectors/entities'`.
|
|
3
|
+
* Same paths and values as the barrel's `sel('entities.…')`, without shipping the other domains to the page.
|
|
4
|
+
*/
|
|
5
|
+
import { ENTITIES_SELECTORS } from '../domains/entities.selectors';
|
|
6
|
+
export { ENTITIES_SELECTORS };
|
|
7
|
+
export declare const sel: (path: string, replacements?: import("..").Replacements) => string, s: (path: string, replacements?: import("..").Replacements) => string, selDev: (path: string, replacements?: import("..").Replacements) => string | undefined, cySelector: (path: string, replacements?: import("..").Replacements) => string;
|
|
8
|
+
//# sourceMappingURL=entities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../../../src/lib/selectors/by-domain/entities.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAElE,OAAO,EAAE,kBAAkB,EAAE,CAAA;AAC7B,eAAO,MAAQ,GAAG,sEAAE,CAAC,sEAAE,MAAM,kFAAE,UAAU,oEAA4D,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createSelectorHelpers } from "../selector-factory.js";
|
|
2
|
+
import { ENTITIES_SELECTORS } from "../domains/entities.selectors.js";
|
|
3
|
+
const { sel, s, selDev, cySelector } = createSelectorHelpers({ entities: ENTITIES_SELECTORS });
|
|
4
|
+
export {
|
|
5
|
+
ENTITIES_SELECTORS,
|
|
6
|
+
cySelector,
|
|
7
|
+
s,
|
|
8
|
+
sel,
|
|
9
|
+
selDev
|
|
10
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sel` bound to the `globalSearch` domain only: `import { sel } from '@nextsparkjs/core/selectors/global-search'`.
|
|
3
|
+
* Same paths and values as the barrel's `sel('globalSearch.…')`, without shipping the other domains to the page.
|
|
4
|
+
*/
|
|
5
|
+
import { GLOBAL_SEARCH_SELECTORS } from '../domains/global-search.selectors';
|
|
6
|
+
export { GLOBAL_SEARCH_SELECTORS };
|
|
7
|
+
export declare const sel: (path: string, replacements?: import("..").Replacements) => string, s: (path: string, replacements?: import("..").Replacements) => string, selDev: (path: string, replacements?: import("..").Replacements) => string | undefined, cySelector: (path: string, replacements?: import("..").Replacements) => string;
|
|
8
|
+
//# sourceMappingURL=global-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-search.d.ts","sourceRoot":"","sources":["../../../../src/lib/selectors/by-domain/global-search.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAA;AAE5E,OAAO,EAAE,uBAAuB,EAAE,CAAA;AAClC,eAAO,MAAQ,GAAG,sEAAE,CAAC,sEAAE,MAAM,kFAAE,UAAU,oEAAqE,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createSelectorHelpers } from "../selector-factory.js";
|
|
2
|
+
import { GLOBAL_SEARCH_SELECTORS } from "../domains/global-search.selectors.js";
|
|
3
|
+
const { sel, s, selDev, cySelector } = createSelectorHelpers({ globalSearch: GLOBAL_SEARCH_SELECTORS });
|
|
4
|
+
export {
|
|
5
|
+
GLOBAL_SEARCH_SELECTORS,
|
|
6
|
+
cySelector,
|
|
7
|
+
s,
|
|
8
|
+
sel,
|
|
9
|
+
selDev
|
|
10
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sel` bound to the `media` domain only: `import { sel } from '@nextsparkjs/core/selectors/media'`.
|
|
3
|
+
* Same paths and values as the barrel's `sel('media.…')`, without shipping the other domains to the page.
|
|
4
|
+
*/
|
|
5
|
+
import { MEDIA_SELECTORS } from '../domains/media.selectors';
|
|
6
|
+
export { MEDIA_SELECTORS };
|
|
7
|
+
export declare const sel: (path: string, replacements?: import("..").Replacements) => string, s: (path: string, replacements?: import("..").Replacements) => string, selDev: (path: string, replacements?: import("..").Replacements) => string | undefined, cySelector: (path: string, replacements?: import("..").Replacements) => string;
|
|
8
|
+
//# sourceMappingURL=media.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../../../src/lib/selectors/by-domain/media.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAE5D,OAAO,EAAE,eAAe,EAAE,CAAA;AAC1B,eAAO,MAAQ,GAAG,sEAAE,CAAC,sEAAE,MAAM,kFAAE,UAAU,oEAAsD,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createSelectorHelpers } from "../selector-factory.js";
|
|
2
|
+
import { MEDIA_SELECTORS } from "../domains/media.selectors.js";
|
|
3
|
+
const { sel, s, selDev, cySelector } = createSelectorHelpers({ media: MEDIA_SELECTORS });
|
|
4
|
+
export {
|
|
5
|
+
MEDIA_SELECTORS,
|
|
6
|
+
cySelector,
|
|
7
|
+
s,
|
|
8
|
+
sel,
|
|
9
|
+
selDev
|
|
10
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sel` bound to the `patterns` domain only: `import { sel } from '@nextsparkjs/core/selectors/patterns'`.
|
|
3
|
+
* Same paths and values as the barrel's `sel('patterns.…')`, without shipping the other domains to the page.
|
|
4
|
+
*/
|
|
5
|
+
import { PATTERNS_SELECTORS } from '../domains/patterns.selectors';
|
|
6
|
+
export { PATTERNS_SELECTORS };
|
|
7
|
+
export declare const sel: (path: string, replacements?: import("..").Replacements) => string, s: (path: string, replacements?: import("..").Replacements) => string, selDev: (path: string, replacements?: import("..").Replacements) => string | undefined, cySelector: (path: string, replacements?: import("..").Replacements) => string;
|
|
8
|
+
//# sourceMappingURL=patterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../../../src/lib/selectors/by-domain/patterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAElE,OAAO,EAAE,kBAAkB,EAAE,CAAA;AAC7B,eAAO,MAAQ,GAAG,sEAAE,CAAC,sEAAE,MAAM,kFAAE,UAAU,oEAA4D,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createSelectorHelpers } from "../selector-factory.js";
|
|
2
|
+
import { PATTERNS_SELECTORS } from "../domains/patterns.selectors.js";
|
|
3
|
+
const { sel, s, selDev, cySelector } = createSelectorHelpers({ patterns: PATTERNS_SELECTORS });
|
|
4
|
+
export {
|
|
5
|
+
PATTERNS_SELECTORS,
|
|
6
|
+
cySelector,
|
|
7
|
+
s,
|
|
8
|
+
sel,
|
|
9
|
+
selDev
|
|
10
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sel` bound to the `public` domain only: `import { sel } from '@nextsparkjs/core/selectors/public'`.
|
|
3
|
+
* Same paths and values as the barrel's `sel('public.…')`, without shipping the other domains to the page.
|
|
4
|
+
*/
|
|
5
|
+
import { PUBLIC_SELECTORS } from '../domains/public.selectors';
|
|
6
|
+
export { PUBLIC_SELECTORS };
|
|
7
|
+
export declare const sel: (path: string, replacements?: import("..").Replacements) => string, s: (path: string, replacements?: import("..").Replacements) => string, selDev: (path: string, replacements?: import("..").Replacements) => string | undefined, cySelector: (path: string, replacements?: import("..").Replacements) => string;
|
|
8
|
+
//# sourceMappingURL=public.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../../src/lib/selectors/by-domain/public.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAE9D,OAAO,EAAE,gBAAgB,EAAE,CAAA;AAC3B,eAAO,MAAQ,GAAG,sEAAE,CAAC,sEAAE,MAAM,kFAAE,UAAU,oEAAwD,CAAA"}
|