@react-spa-scaffold/mcp 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -0
- package/dist/constants.js.map +1 -1
- package/dist/features/definitions/auth.d.ts +3 -0
- package/dist/features/definitions/auth.d.ts.map +1 -0
- package/dist/features/definitions/auth.js +17 -0
- package/dist/features/definitions/auth.js.map +1 -0
- package/dist/features/definitions/core.d.ts.map +1 -1
- package/dist/features/definitions/core.js +16 -1
- package/dist/features/definitions/core.js.map +1 -1
- package/dist/features/definitions/forms.d.ts.map +1 -1
- package/dist/features/definitions/forms.js +4 -0
- package/dist/features/definitions/forms.js.map +1 -1
- package/dist/features/definitions/index.d.ts +1 -0
- package/dist/features/definitions/index.d.ts.map +1 -1
- package/dist/features/definitions/index.js +1 -0
- package/dist/features/definitions/index.js.map +1 -1
- package/dist/features/definitions/mobile.d.ts.map +1 -1
- package/dist/features/definitions/mobile.js +11 -2
- package/dist/features/definitions/mobile.js.map +1 -1
- package/dist/features/definitions/observability.js +1 -1
- package/dist/features/definitions/observability.js.map +1 -1
- package/dist/features/definitions/routing.d.ts.map +1 -1
- package/dist/features/definitions/routing.js +2 -1
- package/dist/features/definitions/routing.js.map +1 -1
- package/dist/features/definitions/state.d.ts.map +1 -1
- package/dist/features/definitions/state.js +9 -2
- package/dist/features/definitions/state.js.map +1 -1
- package/dist/features/definitions/testing.d.ts.map +1 -1
- package/dist/features/definitions/testing.js +4 -2
- package/dist/features/definitions/testing.js.map +1 -1
- package/dist/features/registry.d.ts.map +1 -1
- package/dist/features/registry.js +2 -1
- package/dist/features/registry.js.map +1 -1
- package/dist/features/types.test.js +4 -2
- package/dist/features/types.test.js.map +1 -1
- package/dist/utils/scaffold/generators.d.ts.map +1 -1
- package/dist/utils/scaffold/generators.js +7 -0
- package/dist/utils/scaffold/generators.js.map +1 -1
- package/package.json +1 -1
- package/templates/.env.example +6 -0
- package/templates/.github/workflows/ci.yml +8 -3
- package/templates/CLAUDE.md +74 -1
- package/templates/docs/ARCHITECTURE.md +13 -12
- package/templates/docs/CODING_STANDARDS.md +65 -0
- package/templates/docs/E2E_TESTING.md +52 -7
- package/templates/e2e/fixtures/index.ts +13 -2
- package/templates/package.json +7 -3
- package/templates/playwright.config.ts +6 -1
- package/templates/src/components/layout/Header.tsx +2 -1
- package/templates/src/components/shared/AccountButton/AccountButton.test.tsx +30 -0
- package/templates/src/components/shared/AccountButton/AccountButton.tsx +38 -0
- package/templates/src/components/shared/AccountButton/index.ts +1 -0
- package/templates/src/components/shared/ErrorBoundary/ErrorBoundary.test.tsx +4 -4
- package/templates/src/components/shared/ErrorBoundary/ErrorBoundary.tsx +55 -53
- package/templates/src/components/shared/ProtectedRoute/ProtectedRoute.test.tsx +43 -0
- package/templates/src/components/shared/ProtectedRoute/ProtectedRoute.tsx +35 -0
- package/templates/src/components/shared/ProtectedRoute/index.ts +1 -0
- package/templates/src/components/shared/index.ts +4 -2
- package/templates/src/contexts/clerkContext.tsx +45 -0
- package/templates/src/hooks/index.ts +23 -2
- package/templates/src/hooks/useCopyFeedback.test.ts +129 -0
- package/templates/src/hooks/useCopyFeedback.ts +41 -0
- package/templates/src/hooks/useDebouncedCallback.test.ts +164 -0
- package/templates/src/hooks/useDebouncedCallback.ts +47 -0
- package/templates/src/hooks/useDocumentTitle.test.ts +59 -0
- package/templates/src/hooks/useDocumentTitle.ts +31 -0
- package/templates/src/hooks/useIOSViewportReset.test.ts +58 -0
- package/templates/src/hooks/useIOSViewportReset.ts +18 -0
- package/templates/src/hooks/useKeyboardShortcut.test.ts +86 -0
- package/templates/src/hooks/useKeyboardShortcuts.ts +44 -0
- package/templates/src/hooks/useLocalStorage.test.ts +111 -0
- package/templates/src/hooks/useLocalStorage.ts +77 -0
- package/templates/src/hooks/useSyncedFormData.test.ts +75 -0
- package/templates/src/hooks/useSyncedFormData.ts +21 -0
- package/templates/src/hooks/useSyncedState.test.ts +119 -0
- package/templates/src/hooks/useSyncedState.ts +30 -0
- package/templates/src/index.css +1 -0
- package/templates/src/lib/constants.ts +10 -0
- package/templates/src/lib/createSelectors.test.ts +136 -0
- package/templates/src/lib/createSelectors.ts +31 -0
- package/templates/src/lib/index.ts +1 -0
- package/templates/src/lib/sentry.ts +55 -0
- package/templates/src/lib/storage.ts +6 -2
- package/templates/src/main.tsx +18 -8
- package/templates/src/stores/preferencesStore.ts +34 -9
- package/templates/src/test/clerkMock.tsx +97 -0
- package/templates/src/test/index.ts +3 -0
- package/templates/src/test/providers.tsx +7 -4
- package/templates/src/test-setup.ts +16 -2
- package/templates/vitest.config.ts +9 -1
package/README.md
CHANGED
|
@@ -103,7 +103,7 @@ Or point directly to the built file:
|
|
|
103
103
|
|
|
104
104
|
## Available Features
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
15 feature modules that can be combined:
|
|
107
107
|
|
|
108
108
|
| Feature | Description | Required |
|
|
109
109
|
| --------------- | --------------------------------------------- | -------- |
|
|
@@ -121,6 +121,7 @@ Or point directly to the built file:
|
|
|
121
121
|
| `devtools` | ESLint + Prettier + Husky | Optional |
|
|
122
122
|
| `ci` | GitHub Actions + Dependabot | Optional |
|
|
123
123
|
| `observability` | Sentry error tracking | Optional |
|
|
124
|
+
| `auth` | Clerk authentication with modal sign-in | Optional |
|
|
124
125
|
|
|
125
126
|
## Tools
|
|
126
127
|
|
package/dist/constants.d.ts
CHANGED
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,mEAAmE;AACnE,eAAO,MAAM,OAAO
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,mEAAmE;AACnE,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;CAgBV,CAAC;AAEX,uCAAuC;AACvC,eAAO,MAAM,MAAM;;;CAGT,CAAC;AAEX,mCAAmC;AACnC,eAAO,MAAM,QAAQ;;;;;;;CAOX,CAAC"}
|
package/dist/constants.js
CHANGED
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,mEAAmE;AACnE,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,EAAE,EAAE,IAAI;IACR,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,KAAK;IACV,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,aAAa;IAC1B,QAAQ,EAAE,UAAU;IACpB,EAAE,EAAE,IAAI;IACR,aAAa,EAAE,eAAe;IAC9B,OAAO,EAAE,SAAS;
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,mEAAmE;AACnE,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,EAAE,EAAE,IAAI;IACR,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,KAAK;IACV,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,aAAa;IAC1B,QAAQ,EAAE,UAAU;IACpB,EAAE,EAAE,IAAI;IACR,aAAa,EAAE,eAAe;IAC9B,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;CACJ,CAAC;AAEX,uCAAuC;AACvC,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,cAAc;CACpB,CAAC;AAEX,mCAAmC;AACnC,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,WAAW,EAAE,oBAAoB;IACjC,YAAY,EAAE,qBAAqB;IACnC,OAAO,EAAE,gBAAgB;IACzB,IAAI,EAAE,aAAa;IACnB,GAAG,EAAE,YAAY;IACjB,MAAM,EAAE,eAAe;CACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,IAAI,EAAE,OAelB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const auth = {
|
|
2
|
+
name: 'Authentication',
|
|
3
|
+
description: 'Clerk authentication with modal-based sign-in and shadcn theme integration',
|
|
4
|
+
required: false,
|
|
5
|
+
requires: ['routing'], // Uses @clerk/react-router which requires React Router
|
|
6
|
+
dependencies: ['@clerk/react-router', '@clerk/themes'],
|
|
7
|
+
files: [
|
|
8
|
+
'src/contexts/clerkContext.tsx',
|
|
9
|
+
'src/components/shared/AccountButton/AccountButton.tsx',
|
|
10
|
+
'src/components/shared/AccountButton/index.ts',
|
|
11
|
+
'src/components/shared/ProtectedRoute/ProtectedRoute.tsx',
|
|
12
|
+
'src/components/shared/ProtectedRoute/index.ts',
|
|
13
|
+
],
|
|
14
|
+
testFiles: ['src/test/clerkMock.tsx'],
|
|
15
|
+
scripts: {},
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/features/definitions/auth.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,IAAI,GAAY;IAC3B,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,4EAA4E;IACzF,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,CAAC,SAAS,CAAC,EAAE,uDAAuD;IAC9E,YAAY,EAAE,CAAC,qBAAqB,EAAE,eAAe,CAAC;IACtD,KAAK,EAAE;QACL,+BAA+B;QAC/B,uDAAuD;QACvD,8CAA8C;QAC9C,yDAAyD;QACzD,+CAA+C;KAChD;IACD,SAAS,EAAE,CAAC,wBAAwB,CAAC;IACrC,OAAO,EAAE,EAAE;CACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/core.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/core.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,IAAI,EAAE,OA4ElB,CAAC"}
|
|
@@ -2,7 +2,15 @@ export const core = {
|
|
|
2
2
|
name: 'Core',
|
|
3
3
|
description: 'React 19 + TypeScript + Vite 7 + Tailwind CSS v4',
|
|
4
4
|
required: true,
|
|
5
|
-
dependencies: [
|
|
5
|
+
dependencies: [
|
|
6
|
+
'@fontsource-variable/inter',
|
|
7
|
+
'clsx',
|
|
8
|
+
'react',
|
|
9
|
+
'react-dom',
|
|
10
|
+
'react-hotkeys-hook',
|
|
11
|
+
'tailwind-merge',
|
|
12
|
+
'zod',
|
|
13
|
+
],
|
|
6
14
|
devDependencies: [
|
|
7
15
|
'@tailwindcss/vite',
|
|
8
16
|
'@types/node',
|
|
@@ -20,11 +28,15 @@ export const core = {
|
|
|
20
28
|
'src/index.css',
|
|
21
29
|
'src/vite-env.d.ts',
|
|
22
30
|
'src/lib/config.ts',
|
|
31
|
+
'src/lib/constants.ts',
|
|
23
32
|
'src/lib/env.ts',
|
|
24
33
|
'src/lib/utils.ts',
|
|
25
34
|
'src/lib/index.ts',
|
|
26
35
|
'src/types/index.ts',
|
|
27
36
|
'src/hooks/index.ts',
|
|
37
|
+
'src/hooks/useCopyFeedback.ts',
|
|
38
|
+
'src/hooks/useDebouncedCallback.ts',
|
|
39
|
+
'src/hooks/useKeyboardShortcuts.ts',
|
|
28
40
|
'src/components/shared/SEO/SEO.tsx',
|
|
29
41
|
'src/components/shared/SEO/index.ts',
|
|
30
42
|
'src/components/shared/ErrorBoundary/ErrorBoundary.tsx',
|
|
@@ -41,6 +53,9 @@ export const core = {
|
|
|
41
53
|
],
|
|
42
54
|
testFiles: [
|
|
43
55
|
'src/lib/utils.test.ts',
|
|
56
|
+
'src/hooks/useCopyFeedback.test.ts',
|
|
57
|
+
'src/hooks/useDebouncedCallback.test.ts',
|
|
58
|
+
'src/hooks/useKeyboardShortcut.test.ts',
|
|
44
59
|
'src/components/shared/SEO/SEO.test.tsx',
|
|
45
60
|
'src/components/shared/ErrorBoundary/ErrorBoundary.test.tsx',
|
|
46
61
|
'e2e/tests/home.spec.ts',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/features/definitions/core.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,IAAI,GAAY;IAC3B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,kDAAkD;IAC/D,QAAQ,EAAE,IAAI;IACd,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/features/definitions/core.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,IAAI,GAAY;IAC3B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,kDAAkD;IAC/D,QAAQ,EAAE,IAAI;IACd,YAAY,EAAE;QACZ,4BAA4B;QAC5B,MAAM;QACN,OAAO;QACP,WAAW;QACX,oBAAoB;QACpB,gBAAgB;QAChB,KAAK;KACN;IACD,eAAe,EAAE;QACf,mBAAmB;QACnB,aAAa;QACb,cAAc;QACd,kBAAkB;QAClB,sBAAsB;QACtB,8BAA8B;QAC9B,aAAa;QACb,YAAY;QACZ,MAAM;KACP;IACD,KAAK,EAAE;QACL,cAAc;QACd,aAAa;QACb,eAAe;QACf,mBAAmB;QACnB,mBAAmB;QACnB,sBAAsB;QACtB,gBAAgB;QAChB,kBAAkB;QAClB,kBAAkB;QAClB,oBAAoB;QACpB,oBAAoB;QACpB,8BAA8B;QAC9B,mCAAmC;QACnC,mCAAmC;QACnC,mCAAmC;QACnC,oCAAoC;QACpC,uDAAuD;QACvD,8CAA8C;QAC9C,gCAAgC;QAChC,YAAY;QACZ,gBAAgB;QAChB,eAAe;QACf,mBAAmB;QACnB,oBAAoB;QACpB,cAAc;QACd,YAAY;QACZ,oBAAoB;KACrB;IACD,SAAS,EAAE;QACT,uBAAuB;QACvB,mCAAmC;QACnC,wCAAwC;QACxC,uCAAuC;QACvC,wCAAwC;QACxC,4DAA4D;QAC5D,wBAAwB;KACzB;IACD,OAAO,EAAE;QACP,GAAG,EAAE,MAAM;QACX,KAAK,EAAE,sBAAsB;QAC7B,OAAO,EAAE,cAAc;QACvB,SAAS,EAAE,cAAc;KAC1B;IACD,WAAW,EAAE;QACX,gBAAgB;QAChB,eAAe;QACf,mBAAmB;QACnB,oBAAoB;QACpB,YAAY;QACZ,eAAe;KAChB;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forms.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/forms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"forms.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/forms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,KAAK,EAAE,OAyBnB,CAAC"}
|
|
@@ -6,6 +6,8 @@ export const forms = {
|
|
|
6
6
|
files: [
|
|
7
7
|
'src/lib/validations.ts',
|
|
8
8
|
'src/hooks/useRegisterForm.ts',
|
|
9
|
+
'src/hooks/useSyncedFormData.ts',
|
|
10
|
+
'src/hooks/useSyncedState.ts',
|
|
9
11
|
'src/components/ui/form-error.tsx',
|
|
10
12
|
'src/components/ui/input.tsx',
|
|
11
13
|
'src/components/ui/label.tsx',
|
|
@@ -16,6 +18,8 @@ export const forms = {
|
|
|
16
18
|
testFiles: [
|
|
17
19
|
'src/lib/validations.test.ts',
|
|
18
20
|
'src/hooks/useRegisterForm.test.tsx',
|
|
21
|
+
'src/hooks/useSyncedFormData.test.ts',
|
|
22
|
+
'src/hooks/useSyncedState.test.ts',
|
|
19
23
|
'src/components/shared/RegisterForm/RegisterForm.test.tsx',
|
|
20
24
|
],
|
|
21
25
|
scripts: {},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forms.js","sourceRoot":"","sources":["../../../src/features/definitions/forms.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,KAAK,GAAY;IAC5B,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,sDAAsD;IACnE,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,CAAC,qBAAqB,EAAE,iBAAiB,CAAC;IACxD,KAAK,EAAE;QACL,wBAAwB;QACxB,8BAA8B;QAC9B,kCAAkC;QAClC,6BAA6B;QAC7B,6BAA6B;QAC7B,4BAA4B;QAC5B,qDAAqD;QACrD,6CAA6C;KAC9C;IACD,SAAS,EAAE;QACT,6BAA6B;QAC7B,oCAAoC;QACpC,0DAA0D;KAC3D;IACD,OAAO,EAAE,EAAE;CACZ,CAAC"}
|
|
1
|
+
{"version":3,"file":"forms.js","sourceRoot":"","sources":["../../../src/features/definitions/forms.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,KAAK,GAAY;IAC5B,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,sDAAsD;IACnE,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,CAAC,qBAAqB,EAAE,iBAAiB,CAAC;IACxD,KAAK,EAAE;QACL,wBAAwB;QACxB,8BAA8B;QAC9B,gCAAgC;QAChC,6BAA6B;QAC7B,kCAAkC;QAClC,6BAA6B;QAC7B,6BAA6B;QAC7B,4BAA4B;QAC5B,qDAAqD;QACrD,6CAA6C;KAC9C;IACD,SAAS,EAAE;QACT,6BAA6B;QAC7B,oCAAoC;QACpC,qCAAqC;QACrC,kCAAkC;QAClC,0DAA0D;KAC3D;IACD,OAAO,EAAE,EAAE;CACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/features/definitions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/features/definitions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mobile.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/mobile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"mobile.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/mobile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,MAAM,EAAE,OAgBpB,CAAC"}
|
|
@@ -2,8 +2,17 @@ export const mobile = {
|
|
|
2
2
|
name: 'Mobile Support',
|
|
3
3
|
description: 'Responsive design utilities with viewport detection, breakpoints, and touch-aware sizing',
|
|
4
4
|
required: false,
|
|
5
|
-
files: [
|
|
6
|
-
|
|
5
|
+
files: [
|
|
6
|
+
'src/contexts/mobileContext.tsx',
|
|
7
|
+
'src/hooks/useMediaQuery.ts',
|
|
8
|
+
'src/hooks/useTouchSizes.ts',
|
|
9
|
+
'src/hooks/useIOSViewportReset.ts',
|
|
10
|
+
],
|
|
11
|
+
testFiles: [
|
|
12
|
+
'src/contexts/mobileContext.test.tsx',
|
|
13
|
+
'src/hooks/useMediaQuery.test.ts',
|
|
14
|
+
'src/hooks/useIOSViewportReset.test.ts',
|
|
15
|
+
],
|
|
7
16
|
scripts: {},
|
|
8
17
|
};
|
|
9
18
|
//# sourceMappingURL=mobile.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mobile.js","sourceRoot":"","sources":["../../../src/features/definitions/mobile.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,MAAM,GAAY;IAC7B,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,0FAA0F;IACvG,QAAQ,EAAE,KAAK;IACf,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"mobile.js","sourceRoot":"","sources":["../../../src/features/definitions/mobile.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,MAAM,GAAY;IAC7B,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,0FAA0F;IACvG,QAAQ,EAAE,KAAK;IACf,KAAK,EAAE;QACL,gCAAgC;QAChC,4BAA4B;QAC5B,4BAA4B;QAC5B,kCAAkC;KACnC;IACD,SAAS,EAAE;QACT,qCAAqC;QACrC,iCAAiC;QACjC,uCAAuC;KACxC;IACD,OAAO,EAAE,EAAE;CACZ,CAAC"}
|
|
@@ -4,7 +4,7 @@ export const observability = {
|
|
|
4
4
|
required: false,
|
|
5
5
|
dependencies: ['@sentry/react'],
|
|
6
6
|
devDependencies: ['@sentry/vite-plugin'],
|
|
7
|
-
files: ['src/lib/config.ts'],
|
|
7
|
+
files: ['src/lib/config.ts', 'src/lib/sentry.ts'],
|
|
8
8
|
scripts: {},
|
|
9
9
|
};
|
|
10
10
|
//# sourceMappingURL=observability.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observability.js","sourceRoot":"","sources":["../../../src/features/definitions/observability.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAY;IACpC,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,gFAAgF;IAC7F,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,CAAC,eAAe,CAAC;IAC/B,eAAe,EAAE,CAAC,qBAAqB,CAAC;IACxC,KAAK,EAAE,CAAC,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"observability.js","sourceRoot":"","sources":["../../../src/features/definitions/observability.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAY;IACpC,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,gFAAgF;IAC7F,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,CAAC,eAAe,CAAC;IAC/B,eAAe,EAAE,CAAC,qBAAqB,CAAC;IACxC,KAAK,EAAE,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;IACjD,OAAO,EAAE,EAAE;CACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/routing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/routing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,OAAO,EAAE,OAerB,CAAC"}
|
|
@@ -9,8 +9,9 @@ export const routing = {
|
|
|
9
9
|
'src/pages/index.ts',
|
|
10
10
|
'src/components/ui/loading.tsx',
|
|
11
11
|
'src/components/ui/visually-hidden.tsx',
|
|
12
|
+
'src/hooks/useDocumentTitle.ts',
|
|
12
13
|
],
|
|
13
|
-
testFiles: ['e2e/tests/navigation.spec.ts'],
|
|
14
|
+
testFiles: ['e2e/tests/navigation.spec.ts', 'src/hooks/useDocumentTitle.test.ts'],
|
|
14
15
|
scripts: {},
|
|
15
16
|
};
|
|
16
17
|
//# sourceMappingURL=routing.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routing.js","sourceRoot":"","sources":["../../../src/features/definitions/routing.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAY;IAC9B,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,sDAAsD;IACnE,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,CAAC,cAAc,CAAC;IAC9B,KAAK,EAAE;QACL,oBAAoB;QACpB,wBAAwB;QACxB,oBAAoB;QACpB,+BAA+B;QAC/B,uCAAuC;
|
|
1
|
+
{"version":3,"file":"routing.js","sourceRoot":"","sources":["../../../src/features/definitions/routing.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAY;IAC9B,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,sDAAsD;IACnE,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,CAAC,cAAc,CAAC;IAC9B,KAAK,EAAE;QACL,oBAAoB;QACpB,wBAAwB;QACxB,oBAAoB;QACpB,+BAA+B;QAC/B,uCAAuC;QACvC,+BAA+B;KAChC;IACD,SAAS,EAAE,CAAC,8BAA8B,EAAE,oCAAoC,CAAC;IACjF,OAAO,EAAE,EAAE;CACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,KAAK,EAAE,OAqBnB,CAAC"}
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
export const state = {
|
|
2
2
|
name: 'State Management',
|
|
3
|
-
description: 'Zustand with persistence, devtools, and
|
|
3
|
+
description: 'Zustand with persistence, devtools, versioning, and auto-generated selectors',
|
|
4
4
|
required: false,
|
|
5
5
|
dependencies: ['zustand'],
|
|
6
6
|
files: [
|
|
7
7
|
'src/stores/preferencesStore.ts',
|
|
8
8
|
'src/stores/index.ts',
|
|
9
|
+
'src/lib/createSelectors.ts',
|
|
9
10
|
'src/lib/storage.ts',
|
|
10
11
|
'src/lib/storageKeys.ts',
|
|
11
12
|
'src/types/preferences.ts',
|
|
13
|
+
'src/hooks/useLocalStorage.ts',
|
|
14
|
+
],
|
|
15
|
+
testFiles: [
|
|
16
|
+
'src/lib/storage.test.ts',
|
|
17
|
+
'src/lib/createSelectors.test.ts',
|
|
18
|
+
'src/stores/preferencesStore.test.ts',
|
|
19
|
+
'src/hooks/useLocalStorage.test.ts',
|
|
12
20
|
],
|
|
13
|
-
testFiles: ['src/lib/storage.test.ts', 'src/stores/preferencesStore.test.ts'],
|
|
14
21
|
scripts: {},
|
|
15
22
|
};
|
|
16
23
|
//# sourceMappingURL=state.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/features/definitions/state.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,KAAK,GAAY;IAC5B,IAAI,EAAE,kBAAkB;IACxB,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/features/definitions/state.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,KAAK,GAAY;IAC5B,IAAI,EAAE,kBAAkB;IACxB,WAAW,EAAE,8EAA8E;IAC3F,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,CAAC,SAAS,CAAC;IACzB,KAAK,EAAE;QACL,gCAAgC;QAChC,qBAAqB;QACrB,4BAA4B;QAC5B,oBAAoB;QACpB,wBAAwB;QACxB,0BAA0B;QAC1B,8BAA8B;KAC/B;IACD,SAAS,EAAE;QACT,yBAAyB;QACzB,iCAAiC;QACjC,qCAAqC;QACrC,mCAAmC;KACpC;IACD,OAAO,EAAE,EAAE;CACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/testing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../../src/features/definitions/testing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,OAAO,EAAE,OAwCrB,CAAC"}
|
|
@@ -32,8 +32,10 @@ export const testing = {
|
|
|
32
32
|
test: 'vitest run',
|
|
33
33
|
'test:watch': 'vitest',
|
|
34
34
|
'test:coverage': 'vitest run --coverage',
|
|
35
|
-
e2e: 'playwright test --project=
|
|
36
|
-
'e2e:
|
|
35
|
+
e2e: 'playwright test --project=desktop',
|
|
36
|
+
'e2e:mobile': 'playwright test --project=mobile',
|
|
37
|
+
'e2e:all': 'playwright test --project=desktop --project=mobile',
|
|
38
|
+
'e2e:ui': 'playwright test --ui',
|
|
37
39
|
},
|
|
38
40
|
configFiles: ['vitest.config.ts', 'playwright.config.ts', 'src/test-setup.ts'],
|
|
39
41
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../../../src/features/definitions/testing.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAY;IAC9B,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,6CAA6C;IAC1D,QAAQ,EAAE,KAAK;IACf,eAAe,EAAE;QACf,kBAAkB;QAClB,2BAA2B;QAC3B,wBAAwB;QACxB,6BAA6B;QAC7B,qBAAqB;QACrB,OAAO;QACP,KAAK;QACL,QAAQ;KACT;IACD,KAAK,EAAE;QACL,mBAAmB;QACnB,mBAAmB;QACnB,wBAAwB;QACxB,mBAAmB;QACnB,6BAA6B;QAC7B,6BAA6B;QAC7B,6BAA6B;QAC7B,6BAA6B;QAC7B,mBAAmB;QACnB,oBAAoB;QACpB,eAAe;QACf,YAAY;QACZ,kBAAkB;QAClB,sBAAsB;KACvB;IACD,OAAO,EAAE;QACP,IAAI,EAAE,YAAY;QAClB,YAAY,EAAE,QAAQ;QACtB,eAAe,EAAE,uBAAuB;QACxC,GAAG,EAAE,
|
|
1
|
+
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../../../src/features/definitions/testing.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAY;IAC9B,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,6CAA6C;IAC1D,QAAQ,EAAE,KAAK;IACf,eAAe,EAAE;QACf,kBAAkB;QAClB,2BAA2B;QAC3B,wBAAwB;QACxB,6BAA6B;QAC7B,qBAAqB;QACrB,OAAO;QACP,KAAK;QACL,QAAQ;KACT;IACD,KAAK,EAAE;QACL,mBAAmB;QACnB,mBAAmB;QACnB,wBAAwB;QACxB,mBAAmB;QACnB,6BAA6B;QAC7B,6BAA6B;QAC7B,6BAA6B;QAC7B,6BAA6B;QAC7B,mBAAmB;QACnB,oBAAoB;QACpB,eAAe;QACf,YAAY;QACZ,kBAAkB;QAClB,sBAAsB;KACvB;IACD,OAAO,EAAE;QACP,IAAI,EAAE,YAAY;QAClB,YAAY,EAAE,QAAQ;QACtB,eAAe,EAAE,uBAAuB;QACxC,GAAG,EAAE,mCAAmC;QACxC,YAAY,EAAE,kCAAkC;QAChD,SAAS,EAAE,oDAAoD;QAC/D,QAAQ,EAAE,sBAAsB;KACjC;IACD,WAAW,EAAE,CAAC,kBAAkB,EAAE,sBAAsB,EAAE,mBAAmB,CAAC;CAC/E,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/features/registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/features/registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAmBlD,8CAA8C;AAC9C,eAAO,MAAM,QAAQ,EAAE,eAgBtB,CAAC;AAEF,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Feature Registry - Aggregates all feature definitions.
|
|
3
3
|
*/
|
|
4
|
-
import { core, mobile, routing, ui, forms, state, api, i18n, testing, performance, devtools, ci, observability, theming, } from './definitions/index.js';
|
|
4
|
+
import { core, mobile, routing, ui, forms, state, api, i18n, testing, performance, devtools, ci, observability, theming, auth, } from './definitions/index.js';
|
|
5
5
|
/** All available features for scaffolding. */
|
|
6
6
|
export const FEATURES = {
|
|
7
7
|
core,
|
|
@@ -18,5 +18,6 @@ export const FEATURES = {
|
|
|
18
18
|
ci,
|
|
19
19
|
observability,
|
|
20
20
|
theming,
|
|
21
|
+
auth,
|
|
21
22
|
};
|
|
22
23
|
//# sourceMappingURL=registry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/features/registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,IAAI,EACJ,MAAM,EACN,OAAO,EACP,EAAE,EACF,KAAK,EACL,KAAK,EACL,GAAG,EACH,IAAI,EACJ,OAAO,EACP,WAAW,EACX,QAAQ,EACR,EAAE,EACF,aAAa,EACb,OAAO,
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/features/registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,IAAI,EACJ,MAAM,EACN,OAAO,EACP,EAAE,EACF,KAAK,EACL,KAAK,EACL,GAAG,EACH,IAAI,EACJ,OAAO,EACP,WAAW,EACX,QAAQ,EACR,EAAE,EACF,aAAa,EACb,OAAO,EACP,IAAI,GACL,MAAM,wBAAwB,CAAC;AAEhC,8CAA8C;AAC9C,MAAM,CAAC,MAAM,QAAQ,GAAoB;IACvC,IAAI;IACJ,MAAM;IACN,OAAO;IACP,EAAE;IACF,KAAK;IACL,KAAK;IACL,GAAG;IACH,IAAI;IACJ,OAAO;IACP,WAAW;IACX,QAAQ;IACR,EAAE;IACF,aAAa;IACb,OAAO;IACP,IAAI;CACL,CAAC"}
|
|
@@ -12,9 +12,10 @@ describe('FEATURE_IDS', () => {
|
|
|
12
12
|
expect(FEATURE_IDS).toContain('core');
|
|
13
13
|
expect(FEATURE_IDS).toContain('routing');
|
|
14
14
|
expect(FEATURE_IDS).toContain('testing');
|
|
15
|
+
expect(FEATURE_IDS).toContain('auth');
|
|
15
16
|
});
|
|
16
|
-
it('has
|
|
17
|
-
expect(FEATURE_IDS).toHaveLength(
|
|
17
|
+
it('has 15 features', () => {
|
|
18
|
+
expect(FEATURE_IDS).toHaveLength(15);
|
|
18
19
|
});
|
|
19
20
|
});
|
|
20
21
|
describe('isFeatureId', () => {
|
|
@@ -22,6 +23,7 @@ describe('isFeatureId', () => {
|
|
|
22
23
|
expect(isFeatureId('core')).toBe(true);
|
|
23
24
|
expect(isFeatureId('routing')).toBe(true);
|
|
24
25
|
expect(isFeatureId('theming')).toBe(true);
|
|
26
|
+
expect(isFeatureId('auth')).toBe(true);
|
|
25
27
|
});
|
|
26
28
|
it('returns false for invalid feature IDs', () => {
|
|
27
29
|
expect(isFeatureId('invalid')).toBe(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.test.js","sourceRoot":"","sources":["../../src/features/types.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEtD,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.test.js","sourceRoot":"","sources":["../../src/features/types.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEtD,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iBAAiB,EAAE,GAAG,EAAE;QACzB,MAAM,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../../src/utils/scaffold/generators.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../../src/utils/scaffold/generators.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,CAgDlE;AAED,0DAA0D;AAC1D,wBAAgB,aAAa,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,CA6E7D;AAED,mCAAmC;AACnC,wBAAgB,gBAAgB,IAAI,MAAM,CAazC"}
|
|
@@ -27,6 +27,9 @@ export function generateViteEnvDts(featureIds) {
|
|
|
27
27
|
if (featureIds.includes(FEATURE.PERFORMANCE)) {
|
|
28
28
|
envVars.push(' readonly VITE_PERF_TEST: string;');
|
|
29
29
|
}
|
|
30
|
+
if (featureIds.includes(FEATURE.AUTH)) {
|
|
31
|
+
envVars.push(' readonly VITE_CLERK_PUBLISHABLE_KEY: string;');
|
|
32
|
+
}
|
|
30
33
|
// Vite built-in env vars (always required for TypeScript)
|
|
31
34
|
envVars.push(" readonly MODE: 'development' | 'production' | 'test';");
|
|
32
35
|
envVars.push(' readonly DEV: boolean;');
|
|
@@ -63,6 +66,10 @@ export function generateEnvTs(featureIds) {
|
|
|
63
66
|
envFields.push(' VITE_SENTRY_DSN: import.meta.env.VITE_SENTRY_DSN,');
|
|
64
67
|
envFields.push(' VITE_SENTRY_ENABLED: import.meta.env.VITE_SENTRY_ENABLED,');
|
|
65
68
|
}
|
|
69
|
+
if (featureIds.includes(FEATURE.AUTH)) {
|
|
70
|
+
schemaFields.push(' VITE_CLERK_PUBLISHABLE_KEY: z.string().min(1),');
|
|
71
|
+
envFields.push(' VITE_CLERK_PUBLISHABLE_KEY: import.meta.env.VITE_CLERK_PUBLISHABLE_KEY,');
|
|
72
|
+
}
|
|
66
73
|
// Vite built-in env vars (always included)
|
|
67
74
|
schemaFields.push(" MODE: z.enum(['development', 'production', 'test']).default('development'),");
|
|
68
75
|
schemaFields.push(' DEV: z.boolean().default(false),');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generators.js","sourceRoot":"","sources":["../../../src/utils/scaffold/generators.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generators.js","sourceRoot":"","sources":["../../../src/utils/scaffold/generators.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/templates/.env.example
CHANGED
|
@@ -19,3 +19,9 @@ VITE_APP_URL=http://localhost:5173
|
|
|
19
19
|
# - SENTRY_AUTH_TOKEN: API token for uploading source maps
|
|
20
20
|
# - SENTRY_ORG: Sentry organization slug
|
|
21
21
|
# - SENTRY_PROJECT: Sentry project slug
|
|
22
|
+
|
|
23
|
+
# ─────────────────────────────────────────────────────────────
|
|
24
|
+
# Clerk Authentication
|
|
25
|
+
# ─────────────────────────────────────────────────────────────
|
|
26
|
+
# Get your Publishable Key from: https://dashboard.clerk.com/~/api-keys
|
|
27
|
+
VITE_CLERK_PUBLISHABLE_KEY=YOUR_PUBLISHABLE_KEY
|
|
@@ -84,11 +84,16 @@ jobs:
|
|
|
84
84
|
fail-fast: false
|
|
85
85
|
matrix:
|
|
86
86
|
include:
|
|
87
|
-
- type:
|
|
88
|
-
project:
|
|
89
|
-
command: npx playwright test --project=
|
|
87
|
+
- type: desktop
|
|
88
|
+
project: desktop
|
|
89
|
+
command: npx playwright test --project=desktop
|
|
90
90
|
report-name: playwright-report
|
|
91
91
|
upload-on: failure
|
|
92
|
+
- type: mobile
|
|
93
|
+
project: mobile
|
|
94
|
+
command: npx playwright test --project=mobile
|
|
95
|
+
report-name: playwright-report-mobile
|
|
96
|
+
upload-on: failure
|
|
92
97
|
- type: performance
|
|
93
98
|
project: performance
|
|
94
99
|
command: PERF_TEST=true npx playwright test --project=performance
|
package/templates/CLAUDE.md
CHANGED
|
@@ -14,7 +14,9 @@ npm run format # Prettier format
|
|
|
14
14
|
npm run test # Vitest once
|
|
15
15
|
npm run test:watch # Vitest watch mode
|
|
16
16
|
npm run test:coverage # Coverage (80% threshold)
|
|
17
|
-
npm run e2e # Playwright
|
|
17
|
+
npm run e2e # Playwright E2E (desktop)
|
|
18
|
+
npm run e2e:mobile # Playwright E2E (mobile)
|
|
19
|
+
npm run e2e:all # Playwright E2E (all viewports)
|
|
18
20
|
npm run e2e:perf # Performance regression tests
|
|
19
21
|
npm run i18n:extract # Extract translations to .po
|
|
20
22
|
```
|
|
@@ -50,6 +52,76 @@ e2e/ # Playwright tests
|
|
|
50
52
|
|
|
51
53
|
See [docs/CODING_STANDARDS.md](docs/CODING_STANDARDS.md) and [docs/COMPONENT_GUIDELINES.md](docs/COMPONENT_GUIDELINES.md).
|
|
52
54
|
|
|
55
|
+
## Custom Hooks
|
|
56
|
+
|
|
57
|
+
### State & Storage
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { useLocalStorage } from '@/hooks';
|
|
61
|
+
|
|
62
|
+
// localStorage with tab sync and updater functions
|
|
63
|
+
const [value, setValue] = useLocalStorage('key', defaultValue);
|
|
64
|
+
setValue((prev) => newValue);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Form State Sync
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
import { useSyncedFormData, useSyncedState } from '@/hooks';
|
|
71
|
+
|
|
72
|
+
// Sync form data when trigger changes (dialog open, ID changes)
|
|
73
|
+
const [formData, setFormData] = useSyncedFormData(sourceData, syncTrigger);
|
|
74
|
+
|
|
75
|
+
// Sync state but block when actively editing
|
|
76
|
+
const [localValue, setLocalValue] = useSyncedState(externalValue, isEditing);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Utilities
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import { useCopyFeedback, useDebouncedCallback, useKeyboardShortcut, useDocumentTitle } from '@/hooks';
|
|
83
|
+
|
|
84
|
+
// Copy feedback with auto-reset
|
|
85
|
+
const { isCopied, triggerCopied } = useCopyFeedback(2000);
|
|
86
|
+
|
|
87
|
+
// Debounced callbacks
|
|
88
|
+
const debouncedSearch = useDebouncedCallback(handleSearch, 300);
|
|
89
|
+
|
|
90
|
+
// Keyboard shortcuts
|
|
91
|
+
useKeyboardShortcut('mod+s', handleSave, { preventDefault: true });
|
|
92
|
+
|
|
93
|
+
// Dynamic page titles
|
|
94
|
+
useDocumentTitle('Dashboard');
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Mobile & iOS
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
import { useIOSViewportReset, useMobileContext, useTouchSizes } from '@/hooks';
|
|
101
|
+
|
|
102
|
+
// iOS Safari keyboard viewport fix
|
|
103
|
+
const handleBlur = useIOSViewportReset();
|
|
104
|
+
<input onBlur={handleBlur} />;
|
|
105
|
+
|
|
106
|
+
// Responsive breakpoints
|
|
107
|
+
const { isMobile, isTablet, isDesktop } = useMobileContext();
|
|
108
|
+
|
|
109
|
+
// Touch-aware sizes (44px on mobile)
|
|
110
|
+
const sizes = useTouchSizes();
|
|
111
|
+
<Button size={sizes.button}>Click</Button>;
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## TIMING Constants
|
|
115
|
+
|
|
116
|
+
Use centralized timing constants for consistent UX:
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
import { TIMING } from '@/lib/constants';
|
|
120
|
+
|
|
121
|
+
// TIMING.DEBOUNCE_DELAY = 300ms
|
|
122
|
+
// TIMING.COPY_FEEDBACK_DURATION = 2000ms
|
|
123
|
+
```
|
|
124
|
+
|
|
53
125
|
## UI Components (Shadcn/UI)
|
|
54
126
|
|
|
55
127
|
This project uses **Shadcn/UI** with radix-nova style. Components live in `src/components/ui/`.
|
|
@@ -104,6 +176,7 @@ resolve-library-id → get-library-docs
|
|
|
104
176
|
- `zod` - Schema validation
|
|
105
177
|
- `date-fns` - Date formatting
|
|
106
178
|
- `msw` - Mock service worker setup
|
|
179
|
+
- `@clerk/react-router` - Authentication patterns
|
|
107
180
|
|
|
108
181
|
### Decision Flow
|
|
109
182
|
|