@react-vault/create-app 0.1.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/LICENSE +12 -0
- package/README.md +16 -0
- package/bin/create-app.js +8 -0
- package/claude-toolkit/README.md +131 -0
- package/claude-toolkit/agents/bfsi-accessibility-auditor.md +132 -0
- package/claude-toolkit/agents/bfsi-architect.md +156 -0
- package/claude-toolkit/agents/bfsi-code-reviewer.md +137 -0
- package/claude-toolkit/agents/bfsi-compliance-auditor.md +161 -0
- package/claude-toolkit/agents/bfsi-pii-scanner.md +142 -0
- package/claude-toolkit/agents/bfsi-pr-reviewer.md +114 -0
- package/claude-toolkit/agents/bfsi-security-reviewer.md +136 -0
- package/claude-toolkit/commands/bfsi-audit.md +46 -0
- package/claude-toolkit/commands/bfsi-doctor.md +97 -0
- package/claude-toolkit/commands/bfsi-review.md +46 -0
- package/claude-toolkit/commands/bfsi-scaffold.md +47 -0
- package/claude-toolkit/hooks/hooks.json +181 -0
- package/claude-toolkit/hooks/scripts/a11y-check.sh +63 -0
- package/claude-toolkit/hooks/scripts/audit-prompt.sh +36 -0
- package/claude-toolkit/hooks/scripts/block-destructive.sh +41 -0
- package/claude-toolkit/hooks/scripts/block-force-push.sh +30 -0
- package/claude-toolkit/hooks/scripts/format.sh +42 -0
- package/claude-toolkit/hooks/scripts/inject-context.sh +44 -0
- package/claude-toolkit/hooks/scripts/lint.sh +45 -0
- package/claude-toolkit/hooks/scripts/protect-files.sh +53 -0
- package/claude-toolkit/hooks/scripts/save-compliance-context.sh +35 -0
- package/claude-toolkit/hooks/scripts/scan-pii.sh +87 -0
- package/claude-toolkit/hooks/scripts/scan-secrets.sh +67 -0
- package/claude-toolkit/hooks/scripts/verify-clean.sh +50 -0
- package/claude-toolkit/package.json +22 -0
- package/claude-toolkit/plugin.json +31 -0
- package/claude-toolkit/skills/bfsi-api-endpoint/SKILL.md +105 -0
- package/claude-toolkit/skills/bfsi-commit/SKILL.md +102 -0
- package/claude-toolkit/skills/bfsi-compliance-check/SKILL.md +107 -0
- package/claude-toolkit/skills/bfsi-encrypt-helper/SKILL.md +127 -0
- package/claude-toolkit/skills/bfsi-error-message/SKILL.md +162 -0
- package/claude-toolkit/skills/bfsi-feature/SKILL.md +120 -0
- package/claude-toolkit/skills/bfsi-feature/references/architecture.md +69 -0
- package/claude-toolkit/skills/bfsi-feature/references/audit-events.md +70 -0
- package/claude-toolkit/skills/bfsi-feature/scripts/scaffold.mjs +136 -0
- package/claude-toolkit/skills/bfsi-form/SKILL.md +73 -0
- package/claude-toolkit/skills/bfsi-form/references/validation-regex.md +50 -0
- package/claude-toolkit/skills/bfsi-onboarding/SKILL.md +110 -0
- package/claude-toolkit/skills/bfsi-pii-field/SKILL.md +90 -0
- package/claude-toolkit/skills/bfsi-test-pattern/SKILL.md +179 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +339 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -0
- package/templates/_shared/.claude/settings.json +31 -0
- package/templates/_shared/.env.local.sample +25 -0
- package/templates/_shared/.github/workflows/ci.yml +49 -0
- package/templates/_shared/CLAUDE.md +89 -0
- package/templates/_shared/README.md +50 -0
- package/templates/_shared/index.html +16 -0
- package/templates/_shared/package.json +73 -0
- package/templates/_shared/postcss.config.cjs +6 -0
- package/templates/_shared/src/app/App.tsx +13 -0
- package/templates/_shared/src/app/globals.css +64 -0
- package/templates/_shared/src/env.ts +33 -0
- package/templates/_shared/src/i18n/i18n.ts +18 -0
- package/templates/_shared/src/i18n/translations/en.json +54 -0
- package/templates/_shared/src/i18n/translations/hi.json +30 -0
- package/templates/_shared/src/main.tsx +16 -0
- package/templates/_shared/src/routes/ProtectedRoute.tsx +28 -0
- package/templates/_shared/src/routes/index.tsx +67 -0
- package/templates/_shared/src/shared/ErrorBoundary.tsx +60 -0
- package/templates/_shared/tailwind.config.ts +68 -0
- package/templates/_shared/tests/setup.ts +7 -0
- package/templates/_shared/tsconfig.json +33 -0
- package/templates/_shared/tsconfig.node.json +13 -0
- package/templates/_shared/vite.config.ts +47 -0
- package/templates/rtk-query/.claude/skills/axios-auth/SKILL.md +103 -0
- package/templates/rtk-query/.claude/skills/axios-auth/references/error-shape.md +84 -0
- package/templates/rtk-query/.claude/skills/axios-auth/references/full-code-walkthrough.md +146 -0
- package/templates/rtk-query/.claude/skills/axios-auth/references/notification-wiring.md +141 -0
- package/templates/rtk-query/.claude/skills/constants-organization/SKILL.md +112 -0
- package/templates/rtk-query/.claude/skills/constants-organization/references/example-files.md +134 -0
- package/templates/rtk-query/.claude/skills/constants-organization/references/tag-types-catalog.md +53 -0
- package/templates/rtk-query/.claude/skills/redux-store-integration/SKILL.md +159 -0
- package/templates/rtk-query/.claude/skills/redux-store-integration/references/localStorage-persistence.md +70 -0
- package/templates/rtk-query/.claude/skills/redux-store-integration/references/middleware-patterns.md +82 -0
- package/templates/rtk-query/.claude/skills/rtk-query-api/SKILL.md +148 -0
- package/templates/rtk-query/.claude/skills/rtk-query-api/references/cache-strategies.md +96 -0
- package/templates/rtk-query/.claude/skills/rtk-query-api/references/endpoint-cookbook.md +145 -0
- package/templates/rtk-query/.claude/skills/rtk-query-api/references/optimistic-update.md +53 -0
- package/templates/rtk-query/README.md +84 -0
- package/templates/rtk-query/package.partial.json +7 -0
- package/templates/rtk-query/src/app/App.tsx +23 -0
- package/templates/rtk-query/src/axiosconfig/axiosInstance.ts +26 -0
- package/templates/rtk-query/src/axiosconfig/baseQuery.ts +72 -0
- package/templates/rtk-query/src/axiosconfig/interceptor.ts +42 -0
- package/templates/rtk-query/src/redux/invalidateCacheMiddleware.ts +20 -0
- package/templates/rtk-query/src/redux/reduxHooks.ts +10 -0
- package/templates/rtk-query/src/redux/rootReducer.ts +18 -0
- package/templates/rtk-query/src/redux/store.ts +36 -0
- package/templates/tanstack-query/.claude/skills/axios-auth/SKILL.md +109 -0
- package/templates/tanstack-query/.claude/skills/axios-auth/references/error-shape.md +89 -0
- package/templates/tanstack-query/.claude/skills/axios-auth/references/full-code-walkthrough.md +121 -0
- package/templates/tanstack-query/.claude/skills/axios-auth/references/notification-pattern.md +109 -0
- package/templates/tanstack-query/.claude/skills/constants-organization/SKILL.md +144 -0
- package/templates/tanstack-query/.claude/skills/constants-organization/references/example-files.md +111 -0
- package/templates/tanstack-query/.claude/skills/constants-organization/references/query-key-factories.md +129 -0
- package/templates/tanstack-query/.claude/skills/query-client-setup/SKILL.md +165 -0
- package/templates/tanstack-query/.claude/skills/query-client-setup/references/devtools.md +67 -0
- package/templates/tanstack-query/.claude/skills/query-client-setup/references/global-handlers.md +94 -0
- package/templates/tanstack-query/.claude/skills/tanstack-services/SKILL.md +142 -0
- package/templates/tanstack-query/.claude/skills/tanstack-services/references/audited-mutation.md +144 -0
- package/templates/tanstack-query/.claude/skills/tanstack-services/references/optimistic-update.md +102 -0
- package/templates/tanstack-query/.claude/skills/tanstack-services/references/service-cookbook.md +151 -0
- package/templates/tanstack-query/README.md +63 -0
- package/templates/tanstack-query/package.partial.json +8 -0
- package/templates/tanstack-query/src/api/axiosInstance.ts +20 -0
- package/templates/tanstack-query/src/api/http.ts +62 -0
- package/templates/tanstack-query/src/api/queryClient.ts +28 -0
- package/templates/tanstack-query/src/app/App.tsx +20 -0
- package/templates/tanstack-query/src/services/example.ts +32 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `create-app` entry point.
|
|
3
|
+
*
|
|
4
|
+
* Scaffolds a new BFSI React project from `templates/_shared/` + a variant overlay
|
|
5
|
+
* (RTK Query or TanStack Query), inlines the Claude toolkit into the project's
|
|
6
|
+
* `.claude/` directory, and optionally rewrites `@react-vault/*` deps to local `link:`
|
|
7
|
+
* paths so the project installs without the packages being published yet.
|
|
8
|
+
*/
|
|
9
|
+
import { intro, outro, text, select, confirm, isCancel, cancel, spinner, note, } from '@clack/prompts';
|
|
10
|
+
import pc from 'picocolors';
|
|
11
|
+
import fs from 'fs-extra';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
import { execa } from 'execa';
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
+
const __dirname = path.dirname(__filename);
|
|
17
|
+
// The CLI runs in two modes:
|
|
18
|
+
// - Dev: inside the monorepo at <starter>/packages/cli/dist/index.js.
|
|
19
|
+
// Templates are at <starter>/templates/ and the toolkit lives at
|
|
20
|
+
// <starter>/packages/claude-toolkit/.
|
|
21
|
+
// - Published: installed at <somewhere>/node_modules/@react-vault/create-app/.
|
|
22
|
+
// The prepublishOnly script bundles templates/ and claude-toolkit/ INTO
|
|
23
|
+
// the package itself, so they sit alongside dist/.
|
|
24
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
25
|
+
const BUNDLED_TEMPLATES = path.join(PACKAGE_ROOT, 'templates');
|
|
26
|
+
const IS_PUBLISHED_MODE = fs.existsSync(BUNDLED_TEMPLATES);
|
|
27
|
+
const TEMPLATES_ROOT = IS_PUBLISHED_MODE
|
|
28
|
+
? BUNDLED_TEMPLATES
|
|
29
|
+
: path.resolve(PACKAGE_ROOT, '..', '..', 'templates');
|
|
30
|
+
const TOOLKIT_ROOT = IS_PUBLISHED_MODE
|
|
31
|
+
? path.join(PACKAGE_ROOT, 'claude-toolkit')
|
|
32
|
+
: path.resolve(PACKAGE_ROOT, '..', 'claude-toolkit');
|
|
33
|
+
// The npm scope used in templates' package.json references. The CLI's `link:`
|
|
34
|
+
// rewrite swaps these to absolute paths for local-dev mode.
|
|
35
|
+
const PACKAGE_SCOPE = '@react-vault';
|
|
36
|
+
export async function main() {
|
|
37
|
+
console.log();
|
|
38
|
+
intro(pc.bold(pc.bgCyan(pc.black(' @react-vault/create-app '))));
|
|
39
|
+
const projectName = await text({
|
|
40
|
+
message: 'Project name?',
|
|
41
|
+
placeholder: 'my-bank-app',
|
|
42
|
+
validate(value) {
|
|
43
|
+
if (!value) {
|
|
44
|
+
return 'Project name is required';
|
|
45
|
+
}
|
|
46
|
+
if (!/^[a-z0-9][a-z0-9-]*$/.test(value)) {
|
|
47
|
+
return 'Lowercase letters, digits, and hyphens only';
|
|
48
|
+
}
|
|
49
|
+
const target = path.resolve(process.cwd(), value);
|
|
50
|
+
if (fs.existsSync(target)) {
|
|
51
|
+
return `Directory ${value} already exists`;
|
|
52
|
+
}
|
|
53
|
+
return undefined;
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
if (isCancel(projectName)) {
|
|
57
|
+
return cancelled();
|
|
58
|
+
}
|
|
59
|
+
const variant = (await select({
|
|
60
|
+
message: 'State management?',
|
|
61
|
+
options: [
|
|
62
|
+
{
|
|
63
|
+
value: 'rtk',
|
|
64
|
+
label: 'RTK Query (Redux Toolkit)',
|
|
65
|
+
hint: 'Recommended for complex client state',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
value: 'tanstack',
|
|
69
|
+
label: 'TanStack Query + Zustand',
|
|
70
|
+
hint: 'Lighter; great for server-state-heavy apps',
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
}));
|
|
74
|
+
if (isCancel(variant)) {
|
|
75
|
+
return cancelled();
|
|
76
|
+
}
|
|
77
|
+
const inlineToolkit = (await confirm({
|
|
78
|
+
message: 'Inline the Claude toolkit (skills/agents/hooks/commands) into .claude/?',
|
|
79
|
+
initialValue: true,
|
|
80
|
+
}));
|
|
81
|
+
if (isCancel(inlineToolkit)) {
|
|
82
|
+
return cancelled();
|
|
83
|
+
}
|
|
84
|
+
// In published mode (npx-installed CLI), `link:` paths to a local workspace
|
|
85
|
+
// don't exist on the user's machine — skip the prompt. In dev mode (running
|
|
86
|
+
// from the monorepo), offer to point at the local workspace.
|
|
87
|
+
let localLink = false;
|
|
88
|
+
if (!IS_PUBLISHED_MODE) {
|
|
89
|
+
const answer = (await confirm({
|
|
90
|
+
message: 'Use link: refs for @react-vault/core and @react-vault/ui? (points the project at this local workspace instead of fetching from npm)',
|
|
91
|
+
initialValue: true,
|
|
92
|
+
}));
|
|
93
|
+
if (isCancel(answer)) {
|
|
94
|
+
return cancelled();
|
|
95
|
+
}
|
|
96
|
+
localLink = answer;
|
|
97
|
+
}
|
|
98
|
+
const installDeps = (await confirm({
|
|
99
|
+
message: 'Install dependencies after scaffolding (pnpm install)?',
|
|
100
|
+
initialValue: true,
|
|
101
|
+
}));
|
|
102
|
+
if (isCancel(installDeps)) {
|
|
103
|
+
return cancelled();
|
|
104
|
+
}
|
|
105
|
+
const initGit = (await confirm({
|
|
106
|
+
message: 'Initialise git repository?',
|
|
107
|
+
initialValue: true,
|
|
108
|
+
}));
|
|
109
|
+
if (isCancel(initGit)) {
|
|
110
|
+
return cancelled();
|
|
111
|
+
}
|
|
112
|
+
const opts = {
|
|
113
|
+
projectName: projectName,
|
|
114
|
+
variant,
|
|
115
|
+
inlineToolkit,
|
|
116
|
+
localLink,
|
|
117
|
+
installDeps,
|
|
118
|
+
initGit,
|
|
119
|
+
};
|
|
120
|
+
await scaffold(opts);
|
|
121
|
+
const lines = [
|
|
122
|
+
`${pc.bold('cd ' + opts.projectName)}`,
|
|
123
|
+
'',
|
|
124
|
+
` ${pc.cyan('pnpm dev')} — start dev server`,
|
|
125
|
+
` ${pc.cyan('claude')} — Claude Code (BFSI toolkit auto-available)`,
|
|
126
|
+
` ${pc.cyan('/bfsi-doctor')} — verify wiring inside Claude`,
|
|
127
|
+
` ${pc.cyan('/bfsi-onboarding')} — orient yourself to the project`,
|
|
128
|
+
];
|
|
129
|
+
note(lines.join('\n'), 'Next steps');
|
|
130
|
+
outro(pc.green('Done.'));
|
|
131
|
+
}
|
|
132
|
+
async function scaffold(opts) {
|
|
133
|
+
const s = spinner();
|
|
134
|
+
const target = path.resolve(process.cwd(), opts.projectName);
|
|
135
|
+
const sharedDir = path.join(TEMPLATES_ROOT, '_shared');
|
|
136
|
+
const variantDir = path.join(TEMPLATES_ROOT, opts.variant === 'rtk' ? 'rtk-query' : 'tanstack-query');
|
|
137
|
+
// 1. Copy shared template
|
|
138
|
+
s.start('Copying template files');
|
|
139
|
+
await fs.copy(sharedDir, target, {
|
|
140
|
+
filter: (src) => !/(\bnode_modules\b|\.turbo\b|\bdist\b)/.test(src),
|
|
141
|
+
});
|
|
142
|
+
// 2. Apply variant overlay
|
|
143
|
+
if (await fs.pathExists(variantDir)) {
|
|
144
|
+
await fs.copy(variantDir, target, { overwrite: true });
|
|
145
|
+
}
|
|
146
|
+
s.stop('Template files copied');
|
|
147
|
+
// 3. Merge package.partial.json from variant into package.json, then delete it
|
|
148
|
+
await mergeVariantPackage(target);
|
|
149
|
+
// 4. Substitute {{projectName}} in package.json, README.md, index.html, i18n
|
|
150
|
+
await substituteVars(target, opts.projectName);
|
|
151
|
+
// 5. In dev mode, optionally swap @react-vault/{core,ui} dep versions to
|
|
152
|
+
// `link:` paths pointing at the workspace. No-op in published mode.
|
|
153
|
+
await maybeRewriteToLinkDeps(target, opts.localLink);
|
|
154
|
+
// 6. Inline the toolkit (skills, agents, commands, hooks) into .claude/.
|
|
155
|
+
// Variant-specific RTK skills are shipped in templates/rtk-query/.claude/
|
|
156
|
+
// so they're already in place from step 2 — nothing extra to copy here.
|
|
157
|
+
if (opts.inlineToolkit) {
|
|
158
|
+
s.start('Inlining Claude toolkit into .claude/');
|
|
159
|
+
await inlineToolkitInto(target);
|
|
160
|
+
s.stop('Claude toolkit inlined into .claude/');
|
|
161
|
+
}
|
|
162
|
+
// 7. pnpm install
|
|
163
|
+
if (opts.installDeps) {
|
|
164
|
+
s.start('Installing dependencies (pnpm install)');
|
|
165
|
+
try {
|
|
166
|
+
await execa('pnpm', ['install'], { cwd: target, stdio: 'pipe' });
|
|
167
|
+
s.stop('Dependencies installed');
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
s.stop(pc.yellow('pnpm install failed — see error above. Re-run manually with: pnpm install'));
|
|
171
|
+
console.warn(pc.dim(err.message));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// 8. git init + rename to main + first commit
|
|
175
|
+
if (opts.initGit) {
|
|
176
|
+
s.start('Initialising git');
|
|
177
|
+
try {
|
|
178
|
+
await execa('git', ['init', '-q'], { cwd: target });
|
|
179
|
+
await execa('git', ['branch', '-m', 'main'], { cwd: target }).catch(() => {
|
|
180
|
+
// Older git versions: master is created by init; rename may fail if no commits yet
|
|
181
|
+
});
|
|
182
|
+
await execa('git', ['add', '.'], { cwd: target });
|
|
183
|
+
await execa('git', ['commit', '-q', '-m', `chore: scaffold ${opts.projectName} from create-app`], {
|
|
184
|
+
cwd: target,
|
|
185
|
+
});
|
|
186
|
+
// Ensure final branch is main even if rename pre-commit failed
|
|
187
|
+
await execa('git', ['branch', '-M', 'main'], { cwd: target }).catch(() => {
|
|
188
|
+
/* ignore */
|
|
189
|
+
});
|
|
190
|
+
s.stop('Git repo initialised (branch: main)');
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
s.stop(pc.yellow('git init failed (continuing anyway)'));
|
|
194
|
+
console.warn(pc.dim(err.message));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
async function mergeVariantPackage(target) {
|
|
199
|
+
const partialPath = path.join(target, 'package.partial.json');
|
|
200
|
+
const pkgPath = path.join(target, 'package.json');
|
|
201
|
+
if (!(await fs.pathExists(partialPath)) || !(await fs.pathExists(pkgPath))) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const partial = (await fs.readJSON(partialPath));
|
|
205
|
+
const pkg = (await fs.readJSON(pkgPath));
|
|
206
|
+
if (partial.dependencies) {
|
|
207
|
+
pkg.dependencies = { ...(pkg.dependencies ?? {}), ...partial.dependencies };
|
|
208
|
+
}
|
|
209
|
+
if (partial.devDependencies) {
|
|
210
|
+
pkg.devDependencies = { ...(pkg.devDependencies ?? {}), ...partial.devDependencies };
|
|
211
|
+
}
|
|
212
|
+
await fs.writeJSON(pkgPath, pkg, { spaces: 2 });
|
|
213
|
+
await fs.remove(partialPath);
|
|
214
|
+
}
|
|
215
|
+
async function substituteVars(target, projectName) {
|
|
216
|
+
const filesToTouch = [
|
|
217
|
+
path.join(target, 'package.json'),
|
|
218
|
+
path.join(target, 'README.md'),
|
|
219
|
+
path.join(target, 'CLAUDE.md'),
|
|
220
|
+
path.join(target, 'index.html'),
|
|
221
|
+
path.join(target, 'src', 'i18n', 'translations', 'en.json'),
|
|
222
|
+
path.join(target, 'src', 'i18n', 'translations', 'hi.json'),
|
|
223
|
+
];
|
|
224
|
+
for (const f of filesToTouch) {
|
|
225
|
+
if (!(await fs.pathExists(f))) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
const content = await fs.readFile(f, 'utf8');
|
|
229
|
+
const replaced = content.replaceAll('{{projectName}}', projectName);
|
|
230
|
+
if (replaced !== content) {
|
|
231
|
+
await fs.writeFile(f, replaced, 'utf8');
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* In local-dev (running from the monorepo) the user can opt-in to rewriting
|
|
237
|
+
* @react-vault/core and @react-vault/ui dependency versions to `link:` paths
|
|
238
|
+
* that point at the workspace packages. Lets you `pnpm install` before the
|
|
239
|
+
* packages are published to npm.
|
|
240
|
+
*
|
|
241
|
+
* In published mode (npx-installed CLI), `link:` paths would dangle, so this
|
|
242
|
+
* step is a no-op — the templates' versions stay as published npm versions.
|
|
243
|
+
*/
|
|
244
|
+
async function maybeRewriteToLinkDeps(target, localLink) {
|
|
245
|
+
if (!localLink || IS_PUBLISHED_MODE) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const pkgPath = path.join(target, 'package.json');
|
|
249
|
+
if (!(await fs.pathExists(pkgPath))) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const pkg = (await fs.readJSON(pkgPath));
|
|
253
|
+
// Resolve workspace paths relative to the monorepo root (only valid in dev mode)
|
|
254
|
+
const starterRoot = path.resolve(PACKAGE_ROOT, '..', '..');
|
|
255
|
+
const linkTargets = {
|
|
256
|
+
[`${PACKAGE_SCOPE}/core`]: `link:${path.join(starterRoot, 'packages', 'core')}`,
|
|
257
|
+
[`${PACKAGE_SCOPE}/ui`]: `link:${path.join(starterRoot, 'packages', 'ui')}`,
|
|
258
|
+
};
|
|
259
|
+
for (const key of ['dependencies', 'devDependencies']) {
|
|
260
|
+
const block = pkg[key];
|
|
261
|
+
if (!block) {
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
for (const depName of Object.keys(block)) {
|
|
265
|
+
const target = linkTargets[depName];
|
|
266
|
+
if (target) {
|
|
267
|
+
block[depName] = target;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
await fs.writeJSON(pkgPath, pkg, { spaces: 2 });
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Inline the Claude toolkit into <project>/.claude/.
|
|
275
|
+
*
|
|
276
|
+
* - Copies the toolkit's skills/, agents/, commands/ into the project (these
|
|
277
|
+
* are the shared bfsi-* skills that ship in every project)
|
|
278
|
+
* - Copies hooks/scripts/ and rewrites paths in hooks.json from `${CLAUDE_PLUGIN_ROOT}/...`
|
|
279
|
+
* to `${CLAUDE_PROJECT_DIR}/.claude/...` since we're now project-local, not a plugin
|
|
280
|
+
* - Merges hooks into existing `.claude/settings.json` (which already has permissions)
|
|
281
|
+
* - Removes `enabledPlugins` from settings since the plugin is now inlined
|
|
282
|
+
*
|
|
283
|
+
* Variant-specific skills (e.g. RTK pattern skills under templates/rtk-query/
|
|
284
|
+
* .claude/skills/) are NOT handled here — they ship inside their variant
|
|
285
|
+
* overlay and land in the project as part of the standard overlay copy.
|
|
286
|
+
*/
|
|
287
|
+
async function inlineToolkitInto(target) {
|
|
288
|
+
const claudeDir = path.join(target, '.claude');
|
|
289
|
+
await fs.ensureDir(claudeDir);
|
|
290
|
+
// Copy the toolkit's skills, agents, commands. Existing files at the same
|
|
291
|
+
// path (e.g. variant-shipped RTK skills already placed by the overlay) are
|
|
292
|
+
// preserved because we don't write over names we don't have.
|
|
293
|
+
for (const sub of ['skills', 'agents', 'commands']) {
|
|
294
|
+
const src = path.join(TOOLKIT_ROOT, sub);
|
|
295
|
+
const dst = path.join(claudeDir, sub);
|
|
296
|
+
if (await fs.pathExists(src)) {
|
|
297
|
+
await fs.copy(src, dst, { overwrite: true });
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
// Copy hook scripts + chmod +x
|
|
301
|
+
const scriptsSrc = path.join(TOOLKIT_ROOT, 'hooks', 'scripts');
|
|
302
|
+
const scriptsDst = path.join(claudeDir, 'hooks', 'scripts');
|
|
303
|
+
if (await fs.pathExists(scriptsSrc)) {
|
|
304
|
+
await fs.copy(scriptsSrc, scriptsDst, { overwrite: true });
|
|
305
|
+
const entries = await fs.readdir(scriptsDst);
|
|
306
|
+
for (const e of entries) {
|
|
307
|
+
const p = path.join(scriptsDst, e);
|
|
308
|
+
if ((await fs.stat(p)).isFile()) {
|
|
309
|
+
await fs.chmod(p, 0o755);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// Read toolkit hooks.json, rewrite ${CLAUDE_PLUGIN_ROOT} → ${CLAUDE_PROJECT_DIR}/.claude
|
|
314
|
+
const toolkitHooksPath = path.join(TOOLKIT_ROOT, 'hooks', 'hooks.json');
|
|
315
|
+
let toolkitHooks = {};
|
|
316
|
+
if (await fs.pathExists(toolkitHooksPath)) {
|
|
317
|
+
const raw = await fs.readFile(toolkitHooksPath, 'utf8');
|
|
318
|
+
const rewritten = raw.replaceAll('${CLAUDE_PLUGIN_ROOT}', '${CLAUDE_PROJECT_DIR}/.claude');
|
|
319
|
+
toolkitHooks = JSON.parse(rewritten);
|
|
320
|
+
}
|
|
321
|
+
// Merge into existing settings.json
|
|
322
|
+
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
323
|
+
const existing = (await fs.pathExists(settingsPath))
|
|
324
|
+
? (await fs.readJSON(settingsPath))
|
|
325
|
+
: {};
|
|
326
|
+
// Remove plugin reference — the toolkit is now project-local
|
|
327
|
+
delete existing.enabledPlugins;
|
|
328
|
+
// Set hooks from the rewritten toolkit
|
|
329
|
+
const hookSection = toolkitHooks.hooks;
|
|
330
|
+
if (hookSection !== undefined) {
|
|
331
|
+
existing.hooks = hookSection;
|
|
332
|
+
}
|
|
333
|
+
await fs.writeJSON(settingsPath, existing, { spaces: 2 });
|
|
334
|
+
}
|
|
335
|
+
function cancelled() {
|
|
336
|
+
cancel('Cancelled. No files written.');
|
|
337
|
+
process.exit(0);
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@react-vault/create-app",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Scaffold a new BFSI React project with security, audit, encryption, Tailwind, shadcn/ui, and a Claude Code companion baked in. Pick RTK Query or TanStack Query at scaffold time.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"create-app": "./bin/create-app.js"
|
|
9
|
+
},
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"files": [
|
|
12
|
+
"bin",
|
|
13
|
+
"dist",
|
|
14
|
+
"templates",
|
|
15
|
+
"claude-toolkit",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@clack/prompts": "0.7.0",
|
|
20
|
+
"picocolors": "1.0.0",
|
|
21
|
+
"fs-extra": "11.2.0",
|
|
22
|
+
"execa": "9.0.2"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "20.11.30",
|
|
26
|
+
"@types/fs-extra": "11.0.4",
|
|
27
|
+
"typescript": "5.4.5",
|
|
28
|
+
"vitest": "1.6.0"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=20.11.0"
|
|
32
|
+
},
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/amar-josh/react-vault.git",
|
|
36
|
+
"directory": "packages/cli"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/amar-josh/react-vault#readme",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/amar-josh/react-vault/issues"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"create-app",
|
|
44
|
+
"react",
|
|
45
|
+
"vite",
|
|
46
|
+
"bfsi",
|
|
47
|
+
"fintech",
|
|
48
|
+
"tailwind",
|
|
49
|
+
"shadcn",
|
|
50
|
+
"rtk-query",
|
|
51
|
+
"tanstack-query",
|
|
52
|
+
"claude-code",
|
|
53
|
+
"scaffolder",
|
|
54
|
+
"starter"
|
|
55
|
+
],
|
|
56
|
+
"publishConfig": {
|
|
57
|
+
"access": "public"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"build": "tsc -p tsconfig.json",
|
|
61
|
+
"dev": "tsc -p tsconfig.json --watch",
|
|
62
|
+
"lint": "eslint src --ext .ts",
|
|
63
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
64
|
+
"test": "vitest run",
|
|
65
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
66
|
+
"clean": "rm -rf dist .tsbuildinfo templates claude-toolkit",
|
|
67
|
+
"bundle": "node ./scripts/bundle-for-publish.mjs"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
|
3
|
+
"enabledPlugins": [
|
|
4
|
+
"toolkit@react-vault"
|
|
5
|
+
],
|
|
6
|
+
"permissions": {
|
|
7
|
+
"deny": [
|
|
8
|
+
"Bash(rm -rf /*)",
|
|
9
|
+
"Bash(git push --force *main*)",
|
|
10
|
+
"Bash(git push --force *master*)",
|
|
11
|
+
"Bash(git push --force *production*)",
|
|
12
|
+
"Bash(git push --force *staging*)"
|
|
13
|
+
],
|
|
14
|
+
"allow": [
|
|
15
|
+
"Bash(pnpm:*)",
|
|
16
|
+
"Bash(npx:*)",
|
|
17
|
+
"Bash(node:*)",
|
|
18
|
+
"Bash(git status:*)",
|
|
19
|
+
"Bash(git diff:*)",
|
|
20
|
+
"Bash(git log:*)",
|
|
21
|
+
"Bash(git branch:*)",
|
|
22
|
+
"Bash(git show:*)",
|
|
23
|
+
"Bash(git add:*)",
|
|
24
|
+
"Bash(git commit:*)",
|
|
25
|
+
"Bash(git pull:*)",
|
|
26
|
+
"Bash(git fetch:*)",
|
|
27
|
+
"Bash(gh pr:*)",
|
|
28
|
+
"Bash(gh repo:*)"
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Copy this file to .env.local and fill in real values for your environment.
|
|
2
|
+
# .env.local is gitignored — never commit real secrets.
|
|
3
|
+
|
|
4
|
+
# --- API ---
|
|
5
|
+
VITE_API_BASE_URL=https://api.example.com
|
|
6
|
+
VITE_API_TIMEOUT_MS=30000
|
|
7
|
+
|
|
8
|
+
# --- Auth ---
|
|
9
|
+
VITE_AUTH_HEADER_NAME=Authorization
|
|
10
|
+
|
|
11
|
+
# --- Audit ---
|
|
12
|
+
VITE_AUDIT_ENDPOINT=/api/audit
|
|
13
|
+
VITE_AUDIT_BATCH_SIZE=20
|
|
14
|
+
VITE_AUDIT_FLUSH_INTERVAL_MS=5000
|
|
15
|
+
|
|
16
|
+
# --- Observability (optional) ---
|
|
17
|
+
# Sentry DSN — leave empty to disable
|
|
18
|
+
VITE_SENTRY_DSN=
|
|
19
|
+
|
|
20
|
+
# --- Session ---
|
|
21
|
+
VITE_IDLE_TIMEOUT_MS=900000 # 15 minutes
|
|
22
|
+
VITE_SENSITIVE_IDLE_TIMEOUT_MS=300000 # 5 minutes for transaction routes
|
|
23
|
+
|
|
24
|
+
# --- Feature flags ---
|
|
25
|
+
VITE_FEATURE_FLAGS_PROVIDER=local
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, staging]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, staging]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
timeout-minutes: 15
|
|
16
|
+
strategy:
|
|
17
|
+
matrix:
|
|
18
|
+
node: [20]
|
|
19
|
+
steps:
|
|
20
|
+
- name: Checkout
|
|
21
|
+
uses: actions/checkout@v4
|
|
22
|
+
with:
|
|
23
|
+
fetch-depth: 0
|
|
24
|
+
- name: Setup pnpm
|
|
25
|
+
uses: pnpm/action-setup@v3
|
|
26
|
+
with:
|
|
27
|
+
version: 9
|
|
28
|
+
- name: Setup Node
|
|
29
|
+
uses: actions/setup-node@v4
|
|
30
|
+
with:
|
|
31
|
+
node-version: ${{ matrix.node }}
|
|
32
|
+
cache: pnpm
|
|
33
|
+
- name: Install
|
|
34
|
+
run: pnpm install --frozen-lockfile
|
|
35
|
+
- name: Typecheck
|
|
36
|
+
run: pnpm typecheck
|
|
37
|
+
- name: Lint
|
|
38
|
+
run: pnpm lint
|
|
39
|
+
- name: Test
|
|
40
|
+
run: pnpm test
|
|
41
|
+
- name: Build
|
|
42
|
+
run: pnpm build
|
|
43
|
+
- name: npm audit (high+)
|
|
44
|
+
run: pnpm audit --audit-level=high
|
|
45
|
+
continue-on-error: true
|
|
46
|
+
- name: Gitleaks
|
|
47
|
+
uses: gitleaks/gitleaks-action@v2
|
|
48
|
+
env:
|
|
49
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# CLAUDE.md — `{{projectName}}`
|
|
2
|
+
|
|
3
|
+
BFSI React project scaffolded from `create-app`. This file is what Claude reads at session start, per the [Claude Code spec](https://code.claude.com/docs/best-practices).
|
|
4
|
+
|
|
5
|
+
## Stack (so you don't have to read configs)
|
|
6
|
+
|
|
7
|
+
- **React 18** + **Vite 5** + **TypeScript strict**
|
|
8
|
+
- **Tailwind CSS** + **shadcn/ui** (components owned in `src/components/ui/`)
|
|
9
|
+
- **React Hook Form** + **Zod** for forms
|
|
10
|
+
- **react-router-dom v6** with `<ProtectedRoute permission="...">` guards
|
|
11
|
+
- **react-i18next** (`en`, `hi` defaults)
|
|
12
|
+
- Data layer: **RTK Query** OR **TanStack Query** — check `package.json` to confirm which
|
|
13
|
+
- Tests: **Vitest** + **Testing Library**; E2E **Playwright**
|
|
14
|
+
|
|
15
|
+
## Bash commands
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm dev # vite dev server on :5173
|
|
19
|
+
pnpm build # tsc -b && vite build
|
|
20
|
+
pnpm test # vitest run
|
|
21
|
+
pnpm test:watch # vitest watch
|
|
22
|
+
pnpm test:e2e # playwright
|
|
23
|
+
pnpm typecheck # tsc -b --noEmit
|
|
24
|
+
pnpm lint # eslint, --max-warnings 0
|
|
25
|
+
pnpm format # prettier write
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Critical conventions (DO NOT violate)
|
|
29
|
+
|
|
30
|
+
1. **Tokens never in `localStorage`.** Use `setAuthToken(axios, token)` from `@<scope>/core/http` at login — it lives in memory.
|
|
31
|
+
2. **All API responses go through Zod `.parse()`.** No raw types. See the `rtk-query-api` or `tanstack-services` skill.
|
|
32
|
+
3. **PII fields display via `<PIIMaskedDisplay>`.** Never render PAN/Aadhaar/account-number directly.
|
|
33
|
+
4. **No card data in HTML inputs.** Use `<PCITokenizedCardInput>` (v0.2 — for now, flag any plain card input).
|
|
34
|
+
5. **All routes are `<ProtectedRoute permission="...">`** with explicit permission strings (route to feature-permission mapping in `src/routes/`).
|
|
35
|
+
6. **No `dangerouslySetInnerHTML`** unless explicitly sanitised. Pre-write hook will block it.
|
|
36
|
+
7. **No `console.log` of PII variables** (PAN, Aadhaar, account, password, OTP). Post-write hook scans for this.
|
|
37
|
+
8. **Conventional Commits with BFSI types**: `feat`, `fix`, `security`, `compliance`, `audit`, `perf`, `refactor`, `docs`, `style`, `test`, `build`, `ci`, `chore`. NO `Co-Authored-By` trailer.
|
|
38
|
+
|
|
39
|
+
## Where things live
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
src/
|
|
43
|
+
├── app/ App.tsx, providers, globals.css
|
|
44
|
+
├── routes/ ProtectedRoute, route config
|
|
45
|
+
├── features/<Feature>/ ALL feature code: api/schema/types/containers/components/tests
|
|
46
|
+
├── shared/ Cross-feature components (ErrorBoundary, NotFound)
|
|
47
|
+
├── i18n/ react-i18next setup + translations/en.json + hi.json
|
|
48
|
+
├── utils/constants/ urls / routes / regex / tag-types / app constants
|
|
49
|
+
├── env.ts Zod-validated env (throws at boot on bad config)
|
|
50
|
+
└── main.tsx Entry point
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Variant-specific:
|
|
54
|
+
|
|
55
|
+
- **RTK Query**: `src/axiosconfig/` (instance + interceptor + baseQuery), `src/redux/` (store + rootReducer + reduxHooks + invalidateCacheMiddleware)
|
|
56
|
+
- **TanStack Query**: `src/api/` (axiosInstance + http + queryClient), `src/services/` (typed service methods)
|
|
57
|
+
|
|
58
|
+
## Claude skills available
|
|
59
|
+
|
|
60
|
+
Run `/skills` or open `.claude/skills/<name>/SKILL.md` directly. Reference skills auto-load when relevant; action skills are invoked with `/<name>`.
|
|
61
|
+
|
|
62
|
+
**Always available** (from the toolkit): `/bfsi-feature`, `/bfsi-form`, `/bfsi-pii-field`, `/bfsi-api-endpoint`, `/bfsi-compliance-check`, `/bfsi-commit`, `/bfsi-doctor`, `/bfsi-onboarding`, `/bfsi-review`, `/bfsi-audit`.
|
|
63
|
+
|
|
64
|
+
**Variant-specific** (in `.claude/skills/`):
|
|
65
|
+
- RTK: `axios-auth`, `constants-organization`, `redux-store-integration`, `rtk-query-api`
|
|
66
|
+
- TanStack: `axios-auth`, `constants-organization`, `tanstack-services`, `query-client-setup`
|
|
67
|
+
|
|
68
|
+
## Auto-review on Stop
|
|
69
|
+
|
|
70
|
+
A Stop hook runs a review sub-agent after every coding turn. If it finds P0 (security/PII/secrets) or P1 (convention violations) issues in the uncommitted diff, it'll show you the list and ask:
|
|
71
|
+
|
|
72
|
+
1. **Fix all now** — Claude resolves every P0/P1 finding before stopping
|
|
73
|
+
2. **Fix selected ones** — checkbox list, you pick which
|
|
74
|
+
3. **Skip** — Claude stops; the findings list is yours to act on
|
|
75
|
+
|
|
76
|
+
No prompt fires when the diff is clean, doc-only, or contains only P2 (style/naming) findings. To turn it off entirely, delete the second entry under `Stop` in `.claude/settings.json`.
|
|
77
|
+
|
|
78
|
+
## Gotchas
|
|
79
|
+
|
|
80
|
+
- `.env.local` is gitignored. If app fails at boot with a Zod error, copy `.env.local.sample` → `.env.local` and fill in real values.
|
|
81
|
+
- `src/components/ui/` is shadcn-managed. Add components via `pnpm dlx shadcn-ui@latest add <component>` — don't hand-author there.
|
|
82
|
+
- The dev server enforces tight security headers (X-Frame-Options: DENY, etc.). If iframe embedding fails in dev, that's why.
|
|
83
|
+
- ESLint runs with `--max-warnings 0`. Warnings fail CI; fix them as they appear.
|
|
84
|
+
|
|
85
|
+
## When something fails
|
|
86
|
+
|
|
87
|
+
- Type error after `pnpm install` → `pnpm typecheck` to see all errors; the `@<scope>/core` and `@<scope>/ui` paths resolve via `link:` to the local workspace.
|
|
88
|
+
- 401 in dev → check `setAuthToken(axiosInstance, token)` is called in the login mutation's `onQueryStarted` (RTK) or `onSuccess` (TanStack).
|
|
89
|
+
- `/bfsi-doctor` fails on `.claude/settings.json $schema` → the correct URL is `https://json.schemastore.org/claude-code-settings.json`.
|