@aamini/config 0.0.1
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/msw.d.mts +3 -0
- package/dist/msw.mjs +3 -0
- package/dist/playwright.shared.config.d.mts +8 -0
- package/dist/playwright.shared.config.mjs +47 -0
- package/dist/playwright.shared.config.mjs.map +1 -0
- package/dist/setup/styles.d.mts +1 -0
- package/dist/setup/styles.mjs +3 -0
- package/dist/test/browser.d.mts +15 -0
- package/dist/test/browser.mjs +26 -0
- package/dist/test/browser.mjs.map +1 -0
- package/dist/test/database.d.mts +22 -0
- package/dist/test/database.mjs +18 -0
- package/dist/test/database.mjs.map +1 -0
- package/dist/test/db.d.mts +21 -0
- package/dist/test/db.mjs +53 -0
- package/dist/test/db.mjs.map +1 -0
- package/dist/test/playwright.d.mts +7 -0
- package/dist/test/playwright.mjs +15 -0
- package/dist/test/playwright.mjs.map +1 -0
- package/dist/test/postgres.d.mts +14 -0
- package/dist/test/postgres.mjs +25 -0
- package/dist/test/postgres.mjs.map +1 -0
- package/dist/test/server.d.mts +15 -0
- package/dist/test/server.mjs +23 -0
- package/dist/test/server.mjs.map +1 -0
- package/dist/test/visual-page.d.mts +36 -0
- package/dist/test/visual-page.mjs +30 -0
- package/dist/test/visual-page.mjs.map +1 -0
- package/dist/vite.shared.d.mts +14 -0
- package/dist/vite.shared.mjs +232 -0
- package/dist/vite.shared.mjs.map +1 -0
- package/dist/vitest.shared.d.mts +12 -0
- package/dist/vitest.shared.mjs +122 -0
- package/dist/vitest.shared.mjs.map +1 -0
- package/msw.ts +5 -0
- package/package.json +99 -0
- package/playwright.shared.config.ts +71 -0
- package/setup/styles.ts +4 -0
- package/test/browser.ts +31 -0
- package/test/database.ts +38 -0
- package/test/db.ts +80 -0
- package/test/playwright.ts +17 -0
- package/test/postgres.ts +43 -0
- package/test/server.ts +31 -0
- package/test/visual-page.ts +57 -0
- package/tsconfig/tsconfig.astro.json +34 -0
- package/tsconfig/tsconfig.lib.json +19 -0
- package/tsconfig/tsconfig.react.json +16 -0
- package/tsconfig/tsconfig.strict.json +16 -0
- package/tsconfig/tsconfig.tanstack.json +17 -0
- package/virtual-modules.d.ts +6 -0
- package/vite.config.ts +53 -0
- package/vite.shared.ts +298 -0
- package/vitest.shared.ts +183 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { nitro } from "nitro/vite";
|
|
2
|
+
import { devtools } from "@tanstack/devtools-vite";
|
|
3
|
+
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
|
|
4
|
+
import viteReact, { reactCompilerPreset } from "@vitejs/plugin-react";
|
|
5
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
6
|
+
import babel from "@rolldown/plugin-babel";
|
|
7
|
+
import svgr from "vite-plugin-svgr";
|
|
8
|
+
import { existsSync } from "node:fs";
|
|
9
|
+
import { dirname, resolve } from "node:path";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
import { defineConfig, mergeConfig } from "vitest/config";
|
|
12
|
+
import { defineConfig as defineConfig$1 } from "vite";
|
|
13
|
+
import { playwright } from "vite-plus/test/browser-playwright";
|
|
14
|
+
//#region vite.shared.ts
|
|
15
|
+
const HANDLER_LOCATIONS = [
|
|
16
|
+
"__mocks__/handlers.ts",
|
|
17
|
+
"__mocks__/handlers.js",
|
|
18
|
+
"src/mocks/handlers.ts",
|
|
19
|
+
"src/mocks/handlers.js"
|
|
20
|
+
];
|
|
21
|
+
const STYLES_LOCATIONS = [
|
|
22
|
+
"src/styles.css",
|
|
23
|
+
"src/index.css",
|
|
24
|
+
"src/app.css"
|
|
25
|
+
];
|
|
26
|
+
function mswHandlersPlugin(root) {
|
|
27
|
+
const virtualModuleId = "@test/handlers";
|
|
28
|
+
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
29
|
+
return {
|
|
30
|
+
name: "msw-handlers-resolver",
|
|
31
|
+
resolveId(id) {
|
|
32
|
+
if (id === virtualModuleId) return resolvedVirtualModuleId;
|
|
33
|
+
},
|
|
34
|
+
load(id) {
|
|
35
|
+
if (id === resolvedVirtualModuleId) {
|
|
36
|
+
for (const location of HANDLER_LOCATIONS) {
|
|
37
|
+
const fullPath = resolve(root, location);
|
|
38
|
+
if (existsSync(fullPath)) return `export { default } from '${fullPath}'`;
|
|
39
|
+
}
|
|
40
|
+
throw new Error(`No MSW handlers found. Expected one of:\n${HANDLER_LOCATIONS.map((l) => ` - ${resolve(root, l)}`).join("\n")}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function stylesPlugin(root) {
|
|
46
|
+
const virtualModuleId = "@test/styles";
|
|
47
|
+
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
48
|
+
return {
|
|
49
|
+
name: "styles-resolver",
|
|
50
|
+
resolveId(id) {
|
|
51
|
+
if (id === virtualModuleId) return resolvedVirtualModuleId;
|
|
52
|
+
},
|
|
53
|
+
load(id) {
|
|
54
|
+
if (id === resolvedVirtualModuleId) {
|
|
55
|
+
for (const location of STYLES_LOCATIONS) {
|
|
56
|
+
const fullPath = resolve(root, location);
|
|
57
|
+
if (existsSync(fullPath)) return `import '${fullPath}'`;
|
|
58
|
+
}
|
|
59
|
+
throw new Error(`No styles file found. Expected one of:\n${STYLES_LOCATIONS.map((l) => ` - ${resolve(root, l)}`).join("\n")}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const stylesSetup = new URL("setup/styles.ts", import.meta.url).pathname;
|
|
65
|
+
function mergeProjectConfig(base, overrides = {}) {
|
|
66
|
+
return mergeConfig(base, overrides);
|
|
67
|
+
}
|
|
68
|
+
function createBaseConfig(root, overrides = {}, projectOverrides = {}) {
|
|
69
|
+
const localSetup = resolve(root, "vitest.setup.ts");
|
|
70
|
+
const hasLocalSetup = existsSync(localSetup);
|
|
71
|
+
return mergeConfig(defineConfig({
|
|
72
|
+
root,
|
|
73
|
+
resolve: {
|
|
74
|
+
tsconfigPaths: true,
|
|
75
|
+
dedupe: ["react", "react-dom"],
|
|
76
|
+
alias: [{
|
|
77
|
+
find: "@/mocks",
|
|
78
|
+
replacement: resolve(root, "__mocks__")
|
|
79
|
+
}, {
|
|
80
|
+
find: "@",
|
|
81
|
+
replacement: resolve(root, "src")
|
|
82
|
+
}]
|
|
83
|
+
},
|
|
84
|
+
plugins: [
|
|
85
|
+
tailwindcss(),
|
|
86
|
+
viteReact(),
|
|
87
|
+
svgr({
|
|
88
|
+
include: "**/*.svg",
|
|
89
|
+
svgrOptions: { exportType: "default" }
|
|
90
|
+
})
|
|
91
|
+
],
|
|
92
|
+
test: {
|
|
93
|
+
passWithNoTests: true,
|
|
94
|
+
exclude: [
|
|
95
|
+
"**/node_modules/**",
|
|
96
|
+
"**/dist/**",
|
|
97
|
+
"**/.output/**",
|
|
98
|
+
"**/.vercel/**",
|
|
99
|
+
"**/cypress/**",
|
|
100
|
+
"**/.{idea,git,cache,output,temp}/**",
|
|
101
|
+
"**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*",
|
|
102
|
+
"**/e2e/**"
|
|
103
|
+
],
|
|
104
|
+
projects: [
|
|
105
|
+
{
|
|
106
|
+
extends: true,
|
|
107
|
+
test: {
|
|
108
|
+
name: "unit",
|
|
109
|
+
include: ["src/**/*.test.unit.ts"]
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
mergeProjectConfig({
|
|
113
|
+
extends: true,
|
|
114
|
+
plugins: [mswHandlersPlugin(root)],
|
|
115
|
+
test: {
|
|
116
|
+
name: "server",
|
|
117
|
+
include: ["src/**/*.test.ts"],
|
|
118
|
+
exclude: ["src/**/*.test.unit.ts", "src/**/*.test.tsx"],
|
|
119
|
+
testTimeout: 3e4,
|
|
120
|
+
fileParallelism: false,
|
|
121
|
+
setupFiles: hasLocalSetup ? [localSetup] : []
|
|
122
|
+
}
|
|
123
|
+
}, projectOverrides.server ?? {}),
|
|
124
|
+
mergeProjectConfig({
|
|
125
|
+
extends: true,
|
|
126
|
+
plugins: [mswHandlersPlugin(root), stylesPlugin(root)],
|
|
127
|
+
test: {
|
|
128
|
+
name: "browser",
|
|
129
|
+
include: ["src/**/*.test.tsx", "tests/**/*.test.tsx"],
|
|
130
|
+
setupFiles: [stylesSetup],
|
|
131
|
+
browser: {
|
|
132
|
+
instances: [{ browser: "chromium" }],
|
|
133
|
+
provider: playwright(),
|
|
134
|
+
enabled: true,
|
|
135
|
+
headless: true
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}, projectOverrides.browser ?? {})
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
}), overrides);
|
|
142
|
+
}
|
|
143
|
+
const isVitest = process.env.VITEST === "true";
|
|
144
|
+
function createFrameworkConfig(root) {
|
|
145
|
+
return defineConfig$1({
|
|
146
|
+
root,
|
|
147
|
+
resolve: {
|
|
148
|
+
tsconfigPaths: true,
|
|
149
|
+
dedupe: ["react", "react-dom"],
|
|
150
|
+
alias: [{
|
|
151
|
+
find: "@/mocks",
|
|
152
|
+
replacement: resolve(root, "__mocks__")
|
|
153
|
+
}, {
|
|
154
|
+
find: "@",
|
|
155
|
+
replacement: resolve(root, "src")
|
|
156
|
+
}]
|
|
157
|
+
},
|
|
158
|
+
ssr: { noExternal: ["recharts"] },
|
|
159
|
+
plugins: [
|
|
160
|
+
...isVitest ? [] : [
|
|
161
|
+
devtools(),
|
|
162
|
+
nitro(),
|
|
163
|
+
tanstackStart()
|
|
164
|
+
],
|
|
165
|
+
tailwindcss(),
|
|
166
|
+
viteReact(),
|
|
167
|
+
babel({ presets: [reactCompilerPreset()] }),
|
|
168
|
+
svgr({
|
|
169
|
+
include: "**/*.svg",
|
|
170
|
+
svgrOptions: { exportType: "default" }
|
|
171
|
+
})
|
|
172
|
+
]
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
function createAppConfig(root, projectOverrides = {}, overrides = {}) {
|
|
176
|
+
return mergeConfig(createFrameworkConfig(root), createBaseConfig(root, overrides, projectOverrides));
|
|
177
|
+
}
|
|
178
|
+
function baseConfigFor(configUrl) {
|
|
179
|
+
return createAppConfig(dirname(fileURLToPath(configUrl)));
|
|
180
|
+
}
|
|
181
|
+
const workspaceConfig = defineConfig$1({
|
|
182
|
+
fmt: {
|
|
183
|
+
singleQuote: true,
|
|
184
|
+
semi: false,
|
|
185
|
+
useTabs: true,
|
|
186
|
+
printWidth: 80,
|
|
187
|
+
proseWrap: "always",
|
|
188
|
+
ignorePatterns: [
|
|
189
|
+
"**/.vercel",
|
|
190
|
+
"**/.output",
|
|
191
|
+
"**/env.d.ts",
|
|
192
|
+
"pnpm-lock.yaml",
|
|
193
|
+
"routeTree.gen.ts",
|
|
194
|
+
"**/charts/**",
|
|
195
|
+
"**/*.yaml",
|
|
196
|
+
"**/*.yml"
|
|
197
|
+
]
|
|
198
|
+
},
|
|
199
|
+
lint: {
|
|
200
|
+
plugins: [
|
|
201
|
+
"typescript",
|
|
202
|
+
"react",
|
|
203
|
+
"unicorn"
|
|
204
|
+
],
|
|
205
|
+
options: {
|
|
206
|
+
typeAware: true,
|
|
207
|
+
typeCheck: true
|
|
208
|
+
},
|
|
209
|
+
rules: { "no-console": ["error", { allow: ["warn", "error"] }] },
|
|
210
|
+
overrides: [
|
|
211
|
+
{
|
|
212
|
+
files: ["apps/**"],
|
|
213
|
+
plugins: ["typescript", "react"],
|
|
214
|
+
rules: { "react/self-closing-comp": "error" }
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
files: ["**/*.test.ts", "**/*.test.tsx"],
|
|
218
|
+
plugins: ["typescript", "vitest"],
|
|
219
|
+
rules: { "@typescript-eslint/no-explicit-any": "off" }
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
files: ["**/scripts/**", "**/src/lib/imdb/**"],
|
|
223
|
+
rules: { "no-console": "off" }
|
|
224
|
+
}
|
|
225
|
+
]
|
|
226
|
+
},
|
|
227
|
+
staged: { "*.{js,ts,tsx}": "vp check --fix" }
|
|
228
|
+
});
|
|
229
|
+
//#endregion
|
|
230
|
+
export { baseConfigFor, createAppConfig, workspaceConfig };
|
|
231
|
+
|
|
232
|
+
//# sourceMappingURL=vite.shared.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite.shared.mjs","names":["defineVitestConfig","defineConfig"],"sources":["../vite.shared.ts"],"sourcesContent":["import { nitro } from 'nitro/vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport { tanstackStart } from '@tanstack/react-start/plugin/vite'\nimport viteReact, { reactCompilerPreset } from '@vitejs/plugin-react'\nimport tailwindcss from '@tailwindcss/vite'\nimport babel from '@rolldown/plugin-babel'\nimport svgr from 'vite-plugin-svgr'\nimport { existsSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { Plugin } from 'vite'\nimport {\n\tdefineConfig as defineVitestConfig,\n\tmergeConfig,\n\ttype TestProjectConfiguration,\n\ttype TestProjectInlineConfiguration,\n} from 'vitest/config'\nimport { defineConfig } from 'vite'\nimport { playwright } from 'vite-plus/test/browser-playwright'\n\nconst HANDLER_LOCATIONS = [\n\t'__mocks__/handlers.ts',\n\t'__mocks__/handlers.js',\n\t'src/mocks/handlers.ts',\n\t'src/mocks/handlers.js',\n]\n\nconst STYLES_LOCATIONS = ['src/styles.css', 'src/index.css', 'src/app.css']\n\nfunction mswHandlersPlugin(root: string): Plugin {\n\tconst virtualModuleId = '@test/handlers'\n\tconst resolvedVirtualModuleId = '\\0' + virtualModuleId\n\n\treturn {\n\t\tname: 'msw-handlers-resolver',\n\t\tresolveId(id) {\n\t\t\tif (id === virtualModuleId) {\n\t\t\t\treturn resolvedVirtualModuleId\n\t\t\t}\n\t\t\treturn undefined\n\t\t},\n\t\tload(id) {\n\t\t\tif (id === resolvedVirtualModuleId) {\n\t\t\t\tfor (const location of HANDLER_LOCATIONS) {\n\t\t\t\t\tconst fullPath = resolve(root, location)\n\t\t\t\t\tif (existsSync(fullPath)) {\n\t\t\t\t\t\treturn `export { default } from '${fullPath}'`\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No MSW handlers found. Expected one of:\\n${HANDLER_LOCATIONS.map((l) => ` - ${resolve(root, l)}`).join('\\n')}`,\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn undefined\n\t\t},\n\t}\n}\n\nfunction stylesPlugin(root: string): Plugin {\n\tconst virtualModuleId = '@test/styles'\n\tconst resolvedVirtualModuleId = '\\0' + virtualModuleId\n\n\treturn {\n\t\tname: 'styles-resolver',\n\t\tresolveId(id) {\n\t\t\tif (id === virtualModuleId) {\n\t\t\t\treturn resolvedVirtualModuleId\n\t\t\t}\n\t\t\treturn undefined\n\t\t},\n\t\tload(id) {\n\t\t\tif (id === resolvedVirtualModuleId) {\n\t\t\t\tfor (const location of STYLES_LOCATIONS) {\n\t\t\t\t\tconst fullPath = resolve(root, location)\n\t\t\t\t\tif (existsSync(fullPath)) {\n\t\t\t\t\t\treturn `import '${fullPath}'`\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No styles file found. Expected one of:\\n${STYLES_LOCATIONS.map((l) => ` - ${resolve(root, l)}`).join('\\n')}`,\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn undefined\n\t\t},\n\t}\n}\n\nconst stylesSetup = new URL('setup/styles.ts', import.meta.url).pathname\n\nfunction mergeProjectConfig(\n\tbase: TestProjectConfiguration,\n\toverrides: TestProjectConfiguration = {},\n): TestProjectConfiguration {\n\treturn mergeConfig(\n\t\tbase as Record<string, any>,\n\t\toverrides as Record<string, any>,\n\t) as TestProjectConfiguration\n}\n\ninterface ProjectOverrides {\n\tserver?: TestProjectConfiguration\n\tbrowser?: TestProjectConfiguration\n}\n\nfunction createBaseConfig(\n\troot: string,\n\toverrides: TestProjectInlineConfiguration = {},\n\tprojectOverrides: ProjectOverrides = {},\n) {\n\tconst localSetup = resolve(root, 'vitest.setup.ts')\n\tconst hasLocalSetup = existsSync(localSetup)\n\n\treturn mergeConfig(\n\t\tdefineVitestConfig({\n\t\t\troot,\n\t\t\tresolve: {\n\t\t\t\ttsconfigPaths: true,\n\t\t\t\tdedupe: ['react', 'react-dom'],\n\t\t\t\talias: [\n\t\t\t\t\t{ find: '@/mocks', replacement: resolve(root, '__mocks__') },\n\t\t\t\t\t{ find: '@', replacement: resolve(root, 'src') },\n\t\t\t\t],\n\t\t\t},\n\t\t\tplugins: [\n\t\t\t\ttailwindcss(),\n\t\t\t\tviteReact(),\n\t\t\t\tsvgr({\n\t\t\t\t\tinclude: '**/*.svg',\n\t\t\t\t\tsvgrOptions: { exportType: 'default' },\n\t\t\t\t}),\n\t\t\t],\n\t\t\ttest: {\n\t\t\t\tpassWithNoTests: true,\n\t\t\t\texclude: [\n\t\t\t\t\t'**/node_modules/**',\n\t\t\t\t\t'**/dist/**',\n\t\t\t\t\t'**/.output/**',\n\t\t\t\t\t'**/.vercel/**',\n\t\t\t\t\t'**/cypress/**',\n\t\t\t\t\t'**/.{idea,git,cache,output,temp}/**',\n\t\t\t\t\t'**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*',\n\t\t\t\t\t'**/e2e/**',\n\t\t\t\t],\n\t\t\t\tprojects: [\n\t\t\t\t\t{\n\t\t\t\t\t\textends: true,\n\t\t\t\t\t\ttest: {\n\t\t\t\t\t\t\tname: 'unit',\n\t\t\t\t\t\t\tinclude: ['src/**/*.test.unit.ts'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tmergeProjectConfig(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\textends: true,\n\t\t\t\t\t\t\tplugins: [mswHandlersPlugin(root)],\n\t\t\t\t\t\t\ttest: {\n\t\t\t\t\t\t\t\tname: 'server',\n\t\t\t\t\t\t\t\tinclude: ['src/**/*.test.ts'],\n\t\t\t\t\t\t\t\texclude: ['src/**/*.test.unit.ts', 'src/**/*.test.tsx'],\n\t\t\t\t\t\t\t\ttestTimeout: 30_000,\n\t\t\t\t\t\t\t\tfileParallelism: false,\n\t\t\t\t\t\t\t\tsetupFiles: hasLocalSetup ? [localSetup] : [],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t} satisfies TestProjectConfiguration,\n\t\t\t\t\t\tprojectOverrides.server ?? {},\n\t\t\t\t\t),\n\t\t\t\t\tmergeProjectConfig(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\textends: true,\n\t\t\t\t\t\t\tplugins: [mswHandlersPlugin(root), stylesPlugin(root)],\n\t\t\t\t\t\t\ttest: {\n\t\t\t\t\t\t\t\tname: 'browser',\n\t\t\t\t\t\t\t\tinclude: ['src/**/*.test.tsx', 'tests/**/*.test.tsx'],\n\t\t\t\t\t\t\t\tsetupFiles: [stylesSetup],\n\t\t\t\t\t\t\t\tbrowser: {\n\t\t\t\t\t\t\t\t\tinstances: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tbrowser: 'chromium',\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\tprovider: playwright(),\n\t\t\t\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\t\t\t\theadless: true,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t} satisfies TestProjectConfiguration,\n\t\t\t\t\t\tprojectOverrides.browser ?? {},\n\t\t\t\t\t),\n\t\t\t\t],\n\t\t\t},\n\t\t}),\n\t\toverrides,\n\t)\n}\n\nconst isVitest = process.env.VITEST === 'true'\n\nfunction createFrameworkConfig(root: string) {\n\treturn defineConfig({\n\t\troot,\n\t\tresolve: {\n\t\t\ttsconfigPaths: true,\n\t\t\tdedupe: ['react', 'react-dom'],\n\t\t\talias: [\n\t\t\t\t{ find: '@/mocks', replacement: resolve(root, '__mocks__') },\n\t\t\t\t{ find: '@', replacement: resolve(root, 'src') },\n\t\t\t],\n\t\t},\n\t\tssr: {\n\t\t\tnoExternal: ['recharts'],\n\t\t},\n\t\tplugins: [\n\t\t\t...(isVitest ? [] : [devtools(), nitro(), tanstackStart()]),\n\t\t\ttailwindcss(),\n\t\t\tviteReact(),\n\t\t\tbabel({ presets: [reactCompilerPreset()] }),\n\t\t\tsvgr({\n\t\t\t\tinclude: '**/*.svg',\n\t\t\t\tsvgrOptions: { exportType: 'default' },\n\t\t\t}),\n\t\t],\n\t})\n}\n\n// Creates a full app config with customized test project overrides\nexport function createAppConfig(\n\troot: string,\n\tprojectOverrides: ProjectOverrides = {},\n\toverrides: TestProjectInlineConfiguration = {},\n) {\n\treturn mergeConfig(\n\t\tcreateFrameworkConfig(root),\n\t\tcreateBaseConfig(root, overrides, projectOverrides),\n\t)\n}\n\n// Helper to create config from import.meta.url\nexport function baseConfigFor(configUrl: string | URL) {\n\tconst root = dirname(fileURLToPath(configUrl))\n\treturn createAppConfig(root)\n}\n\n// Workspace-level shared config (lint, fmt, staged)\n// Cast to any because Vite+ extensions (fmt, lint, staged) aren't in standard Vite types\nexport const workspaceConfig = defineConfig({\n\tfmt: {\n\t\tsingleQuote: true,\n\t\tsemi: false,\n\t\tuseTabs: true,\n\t\tprintWidth: 80,\n\t\tproseWrap: 'always',\n\t\tignorePatterns: [\n\t\t\t'**/.vercel',\n\t\t\t'**/.output',\n\t\t\t'**/env.d.ts',\n\t\t\t'pnpm-lock.yaml',\n\t\t\t'routeTree.gen.ts',\n\t\t\t'**/charts/**',\n\t\t\t'**/*.yaml',\n\t\t\t'**/*.yml',\n\t\t],\n\t},\n\tlint: {\n\t\tplugins: ['typescript', 'react', 'unicorn'],\n\t\toptions: {\n\t\t\ttypeAware: true,\n\t\t\ttypeCheck: true,\n\t\t},\n\t\trules: {\n\t\t\t'no-console': ['error', { allow: ['warn', 'error'] }],\n\t\t},\n\t\toverrides: [\n\t\t\t{\n\t\t\t\tfiles: ['apps/**'],\n\t\t\t\tplugins: ['typescript', 'react'],\n\t\t\t\trules: {\n\t\t\t\t\t'react/self-closing-comp': 'error',\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tfiles: ['**/*.test.ts', '**/*.test.tsx'],\n\t\t\t\tplugins: ['typescript', 'vitest'],\n\t\t\t\trules: {\n\t\t\t\t\t'@typescript-eslint/no-explicit-any': 'off',\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tfiles: ['**/scripts/**', '**/src/lib/imdb/**'],\n\t\t\t\trules: {\n\t\t\t\t\t'no-console': 'off',\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t},\n\tstaged: {\n\t\t'*.{js,ts,tsx}': 'vp check --fix',\n\t},\n} as any)\n"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { TestProjectConfiguration, TestProjectInlineConfiguration } from "vitest/config";
|
|
2
|
+
|
|
3
|
+
//#region vitest.shared.d.ts
|
|
4
|
+
interface ProjectOverrides {
|
|
5
|
+
server?: TestProjectConfiguration;
|
|
6
|
+
browser?: TestProjectConfiguration;
|
|
7
|
+
}
|
|
8
|
+
declare const createBaseConfig: (overrides: TestProjectInlineConfiguration, projectOverrides?: ProjectOverrides) => Record<string, any>;
|
|
9
|
+
declare const baseConfig: Record<string, any>;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { baseConfig, createBaseConfig };
|
|
12
|
+
//# sourceMappingURL=vitest.shared.d.mts.map
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import viteReact from "@vitejs/plugin-react";
|
|
2
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
3
|
+
import svgr from "vite-plugin-svgr";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
import { resolve } from "node:path";
|
|
6
|
+
import { defineConfig, mergeConfig } from "vitest/config";
|
|
7
|
+
import { playwright } from "@vitest/browser-playwright";
|
|
8
|
+
//#region vitest.shared.ts
|
|
9
|
+
const HANDLER_LOCATIONS = [
|
|
10
|
+
"__mocks__/handlers.ts",
|
|
11
|
+
"__mocks__/handlers.js",
|
|
12
|
+
"src/mocks/handlers.ts",
|
|
13
|
+
"src/mocks/handlers.js"
|
|
14
|
+
];
|
|
15
|
+
const STYLES_LOCATIONS = [
|
|
16
|
+
"src/styles.css",
|
|
17
|
+
"src/index.css",
|
|
18
|
+
"src/app.css"
|
|
19
|
+
];
|
|
20
|
+
function mswHandlersPlugin() {
|
|
21
|
+
const virtualModuleId = "@test/handlers";
|
|
22
|
+
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
23
|
+
return {
|
|
24
|
+
name: "msw-handlers-resolver",
|
|
25
|
+
resolveId(id) {
|
|
26
|
+
if (id === virtualModuleId) return resolvedVirtualModuleId;
|
|
27
|
+
},
|
|
28
|
+
load(id) {
|
|
29
|
+
if (id === resolvedVirtualModuleId) {
|
|
30
|
+
const cwd = process.cwd();
|
|
31
|
+
for (const location of HANDLER_LOCATIONS) {
|
|
32
|
+
const fullPath = resolve(cwd, location);
|
|
33
|
+
if (existsSync(fullPath)) return `export { default } from '${fullPath}'`;
|
|
34
|
+
}
|
|
35
|
+
throw new Error(`No MSW handlers found. Expected one of:\n${HANDLER_LOCATIONS.map((l) => ` - ${resolve(cwd, l)}`).join("\n")}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function stylesPlugin() {
|
|
41
|
+
const virtualModuleId = "@test/styles";
|
|
42
|
+
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
43
|
+
return {
|
|
44
|
+
name: "styles-resolver",
|
|
45
|
+
resolveId(id) {
|
|
46
|
+
if (id === virtualModuleId) return resolvedVirtualModuleId;
|
|
47
|
+
},
|
|
48
|
+
load(id) {
|
|
49
|
+
if (id === resolvedVirtualModuleId) {
|
|
50
|
+
const cwd = process.cwd();
|
|
51
|
+
for (const location of STYLES_LOCATIONS) {
|
|
52
|
+
const fullPath = resolve(cwd, location);
|
|
53
|
+
if (existsSync(fullPath)) return `import '${fullPath}'`;
|
|
54
|
+
}
|
|
55
|
+
throw new Error(`No styles file found. Expected one of:\n${STYLES_LOCATIONS.map((l) => ` - ${resolve(cwd, l)}`).join("\n")}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const stylesSetup = new URL("setup/styles.ts", import.meta.url).pathname;
|
|
61
|
+
function asPlugins(plugins) {
|
|
62
|
+
return plugins;
|
|
63
|
+
}
|
|
64
|
+
function mergeProjectConfig(base, overrides = {}) {
|
|
65
|
+
return mergeConfig(base, overrides);
|
|
66
|
+
}
|
|
67
|
+
const localSetup = resolve(process.cwd(), "vitest.setup.ts");
|
|
68
|
+
const hasLocalSetup = existsSync(localSetup);
|
|
69
|
+
const createBaseConfig = (overrides, projectOverrides = {}) => mergeConfig(defineConfig({
|
|
70
|
+
resolve: { tsconfigPaths: true },
|
|
71
|
+
plugins: asPlugins([
|
|
72
|
+
tailwindcss(),
|
|
73
|
+
viteReact({ babel: { plugins: ["babel-plugin-react-compiler"] } }),
|
|
74
|
+
svgr({
|
|
75
|
+
include: "**/*.svg",
|
|
76
|
+
svgrOptions: { exportType: "default" }
|
|
77
|
+
})
|
|
78
|
+
]),
|
|
79
|
+
test: {
|
|
80
|
+
passWithNoTests: true,
|
|
81
|
+
projects: [
|
|
82
|
+
{
|
|
83
|
+
extends: true,
|
|
84
|
+
test: {
|
|
85
|
+
name: "unit",
|
|
86
|
+
include: ["src/**/*.test.unit.ts"]
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
mergeProjectConfig({
|
|
90
|
+
extends: true,
|
|
91
|
+
plugins: [mswHandlersPlugin()],
|
|
92
|
+
test: {
|
|
93
|
+
name: "server",
|
|
94
|
+
include: ["src/**/*.test.ts"],
|
|
95
|
+
testTimeout: 3e4,
|
|
96
|
+
fileParallelism: false,
|
|
97
|
+
setupFiles: hasLocalSetup ? [localSetup] : []
|
|
98
|
+
}
|
|
99
|
+
}, projectOverrides.server ?? {}),
|
|
100
|
+
mergeProjectConfig({
|
|
101
|
+
extends: true,
|
|
102
|
+
plugins: [mswHandlersPlugin(), stylesPlugin()],
|
|
103
|
+
test: {
|
|
104
|
+
name: "browser",
|
|
105
|
+
include: ["src/**/*.test.tsx", "tests/**/*.test.tsx"],
|
|
106
|
+
setupFiles: [stylesSetup],
|
|
107
|
+
browser: {
|
|
108
|
+
instances: [{ browser: "chromium" }],
|
|
109
|
+
provider: playwright(),
|
|
110
|
+
enabled: true,
|
|
111
|
+
headless: true
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}, projectOverrides.browser ?? {})
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
}), overrides);
|
|
118
|
+
const baseConfig = createBaseConfig({});
|
|
119
|
+
//#endregion
|
|
120
|
+
export { baseConfig, createBaseConfig };
|
|
121
|
+
|
|
122
|
+
//# sourceMappingURL=vitest.shared.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest.shared.mjs","names":[],"sources":["../vitest.shared.ts"],"sourcesContent":["import tailwindcss from '@tailwindcss/vite'\nimport viteReact from '@vitejs/plugin-react'\nimport { playwright } from '@vitest/browser-playwright'\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport type { Plugin } from 'vite'\nimport svgr from 'vite-plugin-svgr'\nimport {\n\tdefineConfig,\n\tmergeConfig,\n\ttype TestProjectConfiguration,\n\ttype TestProjectInlineConfiguration,\n\ttype ViteUserConfig,\n} from 'vitest/config'\n\nconst HANDLER_LOCATIONS = [\n\t'__mocks__/handlers.ts',\n\t'__mocks__/handlers.js',\n\t'src/mocks/handlers.ts',\n\t'src/mocks/handlers.js',\n]\n\nconst STYLES_LOCATIONS = ['src/styles.css', 'src/index.css', 'src/app.css']\n\nfunction mswHandlersPlugin(): Plugin {\n\tconst virtualModuleId = '@test/handlers'\n\tconst resolvedVirtualModuleId = '\\0' + virtualModuleId\n\n\treturn {\n\t\tname: 'msw-handlers-resolver',\n\t\tresolveId(id) {\n\t\t\tif (id === virtualModuleId) {\n\t\t\t\treturn resolvedVirtualModuleId\n\t\t\t}\n\t\t\treturn undefined\n\t\t},\n\t\tload(id) {\n\t\t\tif (id === resolvedVirtualModuleId) {\n\t\t\t\tconst cwd = process.cwd()\n\t\t\t\tfor (const location of HANDLER_LOCATIONS) {\n\t\t\t\t\tconst fullPath = resolve(cwd, location)\n\t\t\t\t\tif (existsSync(fullPath)) {\n\t\t\t\t\t\treturn `export { default } from '${fullPath}'`\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No MSW handlers found. Expected one of:\\n${HANDLER_LOCATIONS.map((l) => ` - ${resolve(cwd, l)}`).join('\\n')}`,\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn undefined\n\t\t},\n\t}\n}\n\nfunction stylesPlugin(): Plugin {\n\tconst virtualModuleId = '@test/styles'\n\tconst resolvedVirtualModuleId = '\\0' + virtualModuleId\n\n\treturn {\n\t\tname: 'styles-resolver',\n\t\tresolveId(id) {\n\t\t\tif (id === virtualModuleId) {\n\t\t\t\treturn resolvedVirtualModuleId\n\t\t\t}\n\t\t\treturn undefined\n\t\t},\n\t\tload(id) {\n\t\t\tif (id === resolvedVirtualModuleId) {\n\t\t\t\tconst cwd = process.cwd()\n\t\t\t\tfor (const location of STYLES_LOCATIONS) {\n\t\t\t\t\tconst fullPath = resolve(cwd, location)\n\t\t\t\t\tif (existsSync(fullPath)) {\n\t\t\t\t\t\treturn `import '${fullPath}'`\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No styles file found. Expected one of:\\n${STYLES_LOCATIONS.map((l) => ` - ${resolve(cwd, l)}`).join('\\n')}`,\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn undefined\n\t\t},\n\t}\n}\n\nconst stylesSetup = new URL('setup/styles.ts', import.meta.url).pathname\n\nfunction asPlugins(plugins: unknown[]): NonNullable<ViteUserConfig['plugins']> {\n\treturn plugins as NonNullable<ViteUserConfig['plugins']>\n}\n\nfunction mergeProjectConfig(\n\tbase: TestProjectConfiguration,\n\toverrides: TestProjectConfiguration = {},\n): TestProjectConfiguration {\n\treturn mergeConfig(\n\t\tbase as Record<string, any>,\n\t\toverrides as Record<string, any>,\n\t) as TestProjectConfiguration\n}\n\n// Auto-detect app-level vitest.setup.ts for custom setup (e.g., MSW server)\nconst localSetup = resolve(process.cwd(), 'vitest.setup.ts')\nconst hasLocalSetup = existsSync(localSetup)\n\ninterface ProjectOverrides {\n\tserver?: TestProjectConfiguration\n\tbrowser?: TestProjectConfiguration\n}\n\nexport const createBaseConfig = (\n\toverrides: TestProjectInlineConfiguration,\n\tprojectOverrides: ProjectOverrides = {},\n) =>\n\tmergeConfig(\n\t\tdefineConfig({\n\t\t\tresolve: {\n\t\t\t\ttsconfigPaths: true,\n\t\t\t},\n\t\t\tplugins: asPlugins([\n\t\t\t\ttailwindcss(),\n\t\t\t\tviteReact({\n\t\t\t\t\tbabel: {\n\t\t\t\t\t\tplugins: ['babel-plugin-react-compiler'],\n\t\t\t\t\t},\n\t\t\t\t} as Parameters<typeof viteReact>[0]),\n\t\t\t\tsvgr({\n\t\t\t\t\tinclude: '**/*.svg',\n\t\t\t\t\tsvgrOptions: { exportType: 'default' },\n\t\t\t\t}),\n\t\t\t]),\n\t\t\ttest: {\n\t\t\t\tpassWithNoTests: true,\n\t\t\t\tprojects: [\n\t\t\t\t\t{\n\t\t\t\t\t\textends: true,\n\t\t\t\t\t\ttest: {\n\t\t\t\t\t\t\tname: 'unit',\n\t\t\t\t\t\t\tinclude: ['src/**/*.test.unit.ts'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tmergeProjectConfig(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\textends: true,\n\t\t\t\t\t\t\tplugins: [mswHandlersPlugin()],\n\t\t\t\t\t\t\ttest: {\n\t\t\t\t\t\t\t\tname: 'server',\n\t\t\t\t\t\t\t\tinclude: ['src/**/*.test.ts'],\n\t\t\t\t\t\t\t\ttestTimeout: 30_000,\n\t\t\t\t\t\t\t\tfileParallelism: false,\n\t\t\t\t\t\t\t\tsetupFiles: hasLocalSetup ? [localSetup] : [],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t} satisfies TestProjectConfiguration,\n\t\t\t\t\t\tprojectOverrides.server ?? {},\n\t\t\t\t\t),\n\t\t\t\t\tmergeProjectConfig(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\textends: true,\n\t\t\t\t\t\t\tplugins: [mswHandlersPlugin(), stylesPlugin()],\n\t\t\t\t\t\t\ttest: {\n\t\t\t\t\t\t\t\tname: 'browser',\n\t\t\t\t\t\t\t\tinclude: ['src/**/*.test.tsx', 'tests/**/*.test.tsx'],\n\t\t\t\t\t\t\t\tsetupFiles: [stylesSetup],\n\t\t\t\t\t\t\t\tbrowser: {\n\t\t\t\t\t\t\t\t\tinstances: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tbrowser: 'chromium',\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\tprovider: playwright(),\n\t\t\t\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\t\t\t\theadless: true,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t} satisfies TestProjectConfiguration,\n\t\t\t\t\t\tprojectOverrides.browser ?? {},\n\t\t\t\t\t),\n\t\t\t\t],\n\t\t\t},\n\t\t}),\n\t\toverrides,\n\t)\n\nexport const baseConfig = createBaseConfig({})\n"],"mappings":";;;;;;;;AAeA,MAAM,oBAAoB;CACzB;CACA;CACA;CACA;CACA;AAED,MAAM,mBAAmB;CAAC;CAAkB;CAAiB;CAAc;AAE3E,SAAS,oBAA4B;CACpC,MAAM,kBAAkB;CACxB,MAAM,0BAA0B,OAAO;CAEvC,OAAO;EACN,MAAM;EACN,UAAU,IAAI;GACb,IAAI,OAAO,iBACV,OAAO;;EAIT,KAAK,IAAI;GACR,IAAI,OAAO,yBAAyB;IACnC,MAAM,MAAM,QAAQ,KAAK;IACzB,KAAK,MAAM,YAAY,mBAAmB;KACzC,MAAM,WAAW,QAAQ,KAAK,SAAS;KACvC,IAAI,WAAW,SAAS,EACvB,OAAO,4BAA4B,SAAS;;IAG9C,MAAM,IAAI,MACT,4CAA4C,kBAAkB,KAAK,MAAM,OAAO,QAAQ,KAAK,EAAE,GAAG,CAAC,KAAK,KAAK,GAC7G;;;EAIH;;AAGF,SAAS,eAAuB;CAC/B,MAAM,kBAAkB;CACxB,MAAM,0BAA0B,OAAO;CAEvC,OAAO;EACN,MAAM;EACN,UAAU,IAAI;GACb,IAAI,OAAO,iBACV,OAAO;;EAIT,KAAK,IAAI;GACR,IAAI,OAAO,yBAAyB;IACnC,MAAM,MAAM,QAAQ,KAAK;IACzB,KAAK,MAAM,YAAY,kBAAkB;KACxC,MAAM,WAAW,QAAQ,KAAK,SAAS;KACvC,IAAI,WAAW,SAAS,EACvB,OAAO,WAAW,SAAS;;IAG7B,MAAM,IAAI,MACT,2CAA2C,iBAAiB,KAAK,MAAM,OAAO,QAAQ,KAAK,EAAE,GAAG,CAAC,KAAK,KAAK,GAC3G;;;EAIH;;AAGF,MAAM,cAAc,IAAI,IAAI,mBAAmB,OAAO,KAAK,IAAI,CAAC;AAEhE,SAAS,UAAU,SAA4D;CAC9E,OAAO;;AAGR,SAAS,mBACR,MACA,YAAsC,EAAE,EACb;CAC3B,OAAO,YACN,MACA,UACA;;AAIF,MAAM,aAAa,QAAQ,QAAQ,KAAK,EAAE,kBAAkB;AAC5D,MAAM,gBAAgB,WAAW,WAAW;AAO5C,MAAa,oBACZ,WACA,mBAAqC,EAAE,KAEvC,YACC,aAAa;CACZ,SAAS,EACR,eAAe,MACf;CACD,SAAS,UAAU;EAClB,aAAa;EACb,UAAU,EACT,OAAO,EACN,SAAS,CAAC,8BAA8B,EACxC,EACD,CAAoC;EACrC,KAAK;GACJ,SAAS;GACT,aAAa,EAAE,YAAY,WAAW;GACtC,CAAC;EACF,CAAC;CACF,MAAM;EACL,iBAAiB;EACjB,UAAU;GACT;IACC,SAAS;IACT,MAAM;KACL,MAAM;KACN,SAAS,CAAC,wBAAwB;KAClC;IACD;GACD,mBACC;IACC,SAAS;IACT,SAAS,CAAC,mBAAmB,CAAC;IAC9B,MAAM;KACL,MAAM;KACN,SAAS,CAAC,mBAAmB;KAC7B,aAAa;KACb,iBAAiB;KACjB,YAAY,gBAAgB,CAAC,WAAW,GAAG,EAAE;KAC7C;IACD,EACD,iBAAiB,UAAU,EAAE,CAC7B;GACD,mBACC;IACC,SAAS;IACT,SAAS,CAAC,mBAAmB,EAAE,cAAc,CAAC;IAC9C,MAAM;KACL,MAAM;KACN,SAAS,CAAC,qBAAqB,sBAAsB;KACrD,YAAY,CAAC,YAAY;KACzB,SAAS;MACR,WAAW,CACV,EACC,SAAS,YACT,CACD;MACD,UAAU,YAAY;MACtB,SAAS;MACT,UAAU;MACV;KACD;IACD,EACD,iBAAiB,WAAW,EAAE,CAC9B;GACD;EACD;CACD,CAAC,EACF,UACA;AAEF,MAAa,aAAa,iBAAiB,EAAE,CAAC"}
|
package/msw.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aamini/config",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/aamini-stack/projects.git",
|
|
9
|
+
"directory": "packages/config"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/aamini-stack/projects/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/aamini-stack/projects/tree/main/packages/config#readme",
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"setup",
|
|
21
|
+
"test",
|
|
22
|
+
"tsconfig",
|
|
23
|
+
"*.ts",
|
|
24
|
+
"virtual-modules.d.ts"
|
|
25
|
+
],
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/vite.shared.d.mts",
|
|
29
|
+
"import": "./dist/vite.shared.mjs",
|
|
30
|
+
"default": "./dist/vite.shared.mjs"
|
|
31
|
+
},
|
|
32
|
+
"./typescript/*": "./tsconfig/tsconfig.*.json",
|
|
33
|
+
"./playwright": {
|
|
34
|
+
"types": "./dist/playwright.shared.config.d.mts",
|
|
35
|
+
"import": "./dist/playwright.shared.config.mjs",
|
|
36
|
+
"default": "./dist/playwright.shared.config.mjs"
|
|
37
|
+
},
|
|
38
|
+
"./vitest": {
|
|
39
|
+
"types": "./dist/vite.shared.d.mts",
|
|
40
|
+
"import": "./dist/vite.shared.mjs",
|
|
41
|
+
"default": "./dist/vite.shared.mjs"
|
|
42
|
+
},
|
|
43
|
+
"./test/*": {
|
|
44
|
+
"types": "./dist/test/*.d.mts",
|
|
45
|
+
"import": "./dist/test/*.mjs",
|
|
46
|
+
"default": "./dist/test/*.mjs"
|
|
47
|
+
},
|
|
48
|
+
"./setup/*": {
|
|
49
|
+
"types": "./dist/setup/*.d.mts",
|
|
50
|
+
"import": "./dist/setup/*.mjs",
|
|
51
|
+
"default": "./dist/setup/*.mjs"
|
|
52
|
+
},
|
|
53
|
+
"./msw": {
|
|
54
|
+
"types": "./dist/msw.d.mts",
|
|
55
|
+
"import": "./dist/msw.mjs",
|
|
56
|
+
"default": "./dist/msw.mjs"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"pack": "vp pack",
|
|
61
|
+
"prepublishOnly": "vp pack"
|
|
62
|
+
},
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"@playwright/test": "^1.59.1",
|
|
65
|
+
"@tailwindcss/vite": "^4.2.1",
|
|
66
|
+
"@tanstack/devtools-vite": "^0.6.0",
|
|
67
|
+
"@tanstack/react-start": "^1.166.7",
|
|
68
|
+
"@testcontainers/postgresql": "^11.12.0",
|
|
69
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
70
|
+
"@types/node": "^25.4.0",
|
|
71
|
+
"@types/pg": "^8.18.0",
|
|
72
|
+
"@types/react": "^19.2.14",
|
|
73
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
74
|
+
"@vitest/browser-playwright": "4.1.5",
|
|
75
|
+
"babel-plugin-react-compiler": "^1.0.0",
|
|
76
|
+
"drizzle-orm": "^0.45.1",
|
|
77
|
+
"drizzle-seed": "^0.3.1",
|
|
78
|
+
"get-port": "^7.2.0",
|
|
79
|
+
"msw": "^2.13.4",
|
|
80
|
+
"nitro": "latest",
|
|
81
|
+
"pg": "^8.20.0",
|
|
82
|
+
"react": "^19.2.4",
|
|
83
|
+
"testcontainers": "^11.12.0",
|
|
84
|
+
"typescript": "^5.8.3",
|
|
85
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@latest",
|
|
86
|
+
"vite-plugin-svgr": "^5.2.0",
|
|
87
|
+
"vitest": "npm:@voidzero-dev/vite-plus-test@latest",
|
|
88
|
+
"vitest-browser-react": "^2.0.5"
|
|
89
|
+
},
|
|
90
|
+
"devDependencies": {
|
|
91
|
+
"@babel/core": "^7.29.0",
|
|
92
|
+
"@rolldown/plugin-babel": "^0.2.3",
|
|
93
|
+
"@types/babel__core": "^7.20.5",
|
|
94
|
+
"@vitest/ui": "4.1.5",
|
|
95
|
+
"babel-plugin-react-compiler": "^1.0.0",
|
|
96
|
+
"playwright": "*",
|
|
97
|
+
"vite-plus": "latest"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineConfig,
|
|
3
|
+
devices,
|
|
4
|
+
type PlaywrightTestConfig,
|
|
5
|
+
} from '@playwright/test'
|
|
6
|
+
|
|
7
|
+
/** See https://playwright.dev/docs/test-configuration. */
|
|
8
|
+
export const baseConfig = async (overrides?: PlaywrightTestConfig) => {
|
|
9
|
+
return defineConfig(
|
|
10
|
+
{
|
|
11
|
+
testDir: './e2e',
|
|
12
|
+
outputDir: '.playwright/test-results',
|
|
13
|
+
/* Run tests in files in parallel */
|
|
14
|
+
fullyParallel: true,
|
|
15
|
+
// Opt out of parallel tests on CI.
|
|
16
|
+
workers: process.env.CI ? 1 : '50%',
|
|
17
|
+
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
|
18
|
+
forbidOnly: !!process.env.CI,
|
|
19
|
+
retries: process.env.CI ? 3 : 0,
|
|
20
|
+
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
|
21
|
+
reporter: [
|
|
22
|
+
['html', { open: 'never', outputFolder: '.playwright/report' }],
|
|
23
|
+
],
|
|
24
|
+
|
|
25
|
+
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
|
26
|
+
use: {
|
|
27
|
+
colorScheme: 'dark',
|
|
28
|
+
|
|
29
|
+
/* Base URL to use in actions like `await page.goto('/')`. */
|
|
30
|
+
baseURL: process.env.BASE_URL,
|
|
31
|
+
|
|
32
|
+
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
|
33
|
+
trace: 'retain-on-first-failure',
|
|
34
|
+
screenshot: 'on',
|
|
35
|
+
video: 'retain-on-failure',
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
timeout: 15_000,
|
|
39
|
+
expect: {
|
|
40
|
+
timeout: 5_000,
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
/* Configure projects for major browsers */
|
|
44
|
+
projects: [
|
|
45
|
+
{
|
|
46
|
+
name: 'chromium',
|
|
47
|
+
use: {
|
|
48
|
+
...devices['Desktop Chrome'],
|
|
49
|
+
launchOptions: {
|
|
50
|
+
args: ['--disable-lcd-text'],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'mobile',
|
|
56
|
+
use: {
|
|
57
|
+
...devices['Desktop Chrome'],
|
|
58
|
+
viewport: {
|
|
59
|
+
width: 320,
|
|
60
|
+
height: 800,
|
|
61
|
+
},
|
|
62
|
+
launchOptions: {
|
|
63
|
+
args: ['--disable-lcd-text'],
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
overrides ?? {},
|
|
70
|
+
)
|
|
71
|
+
}
|
package/setup/styles.ts
ADDED
package/test/browser.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// oxlint-disable typescript-eslint/triple-slash-reference
|
|
2
|
+
/// <reference path="../virtual-modules.d.ts" />
|
|
3
|
+
// oxlint-disable no-empty-pattern
|
|
4
|
+
import handlers from '@test/handlers'
|
|
5
|
+
import { setupWorker, type SetupWorker } from 'msw/browser'
|
|
6
|
+
import { test as baseTest } from 'vitest'
|
|
7
|
+
|
|
8
|
+
export interface MswBrowserFixture {
|
|
9
|
+
worker: SetupWorker
|
|
10
|
+
_cleanup: void
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const client = setupWorker(...handlers)
|
|
14
|
+
|
|
15
|
+
export const test = baseTest.extend<MswBrowserFixture>({
|
|
16
|
+
worker: [
|
|
17
|
+
async ({}, use) => {
|
|
18
|
+
await client.start({ quiet: true, onUnhandledRequest: 'bypass' })
|
|
19
|
+
await use(client)
|
|
20
|
+
client.stop()
|
|
21
|
+
},
|
|
22
|
+
{ auto: true, scope: 'worker' },
|
|
23
|
+
],
|
|
24
|
+
_cleanup: [
|
|
25
|
+
async ({ worker }, use) => {
|
|
26
|
+
await use()
|
|
27
|
+
worker.resetHandlers()
|
|
28
|
+
},
|
|
29
|
+
{ auto: true },
|
|
30
|
+
],
|
|
31
|
+
})
|
package/test/database.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { NodePgDatabase } from 'drizzle-orm/node-postgres'
|
|
2
|
+
import type { Pool } from 'pg'
|
|
3
|
+
|
|
4
|
+
// Convention: schema at src/db/tables.ts, migrations at src/db/migrations/
|
|
5
|
+
const DEFAULT_EXTENSIONS = ['pg_trgm']
|
|
6
|
+
|
|
7
|
+
export type Database = NodePgDatabase & {
|
|
8
|
+
$client: Pool
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface SeedDatabaseOptions {
|
|
12
|
+
schemaPath: string
|
|
13
|
+
migrationsFolder: string
|
|
14
|
+
seedFunction?: (db: Database) => Promise<void>
|
|
15
|
+
extensions?: string[]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function seedDatabase(
|
|
19
|
+
db: Database,
|
|
20
|
+
{
|
|
21
|
+
schemaPath,
|
|
22
|
+
migrationsFolder,
|
|
23
|
+
seedFunction,
|
|
24
|
+
extensions = DEFAULT_EXTENSIONS,
|
|
25
|
+
}: SeedDatabaseOptions,
|
|
26
|
+
) {
|
|
27
|
+
const { migrate } = await import('drizzle-orm/node-postgres/migrator')
|
|
28
|
+
const { reset } = await import('drizzle-seed')
|
|
29
|
+
|
|
30
|
+
const schema = await import(/* @vite-ignore */ schemaPath)
|
|
31
|
+
|
|
32
|
+
for (const ext of extensions) {
|
|
33
|
+
await db.execute(`CREATE EXTENSION IF NOT EXISTS "${ext}"`)
|
|
34
|
+
}
|
|
35
|
+
await migrate(db, { migrationsFolder })
|
|
36
|
+
await reset(db, schema)
|
|
37
|
+
if (seedFunction) await seedFunction(db)
|
|
38
|
+
}
|