@timothyrusso/config-presets 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.
Files changed (60) hide show
  1. package/.claude/settings.template.json +41 -0
  2. package/LICENSE +21 -0
  3. package/README.md +120 -0
  4. package/biome/base.json +75 -0
  5. package/commitlint.config.cjs +26 -0
  6. package/dist/checks/deps.d.ts +22 -0
  7. package/dist/checks/deps.d.ts.map +1 -0
  8. package/dist/checks/deps.js +45 -0
  9. package/dist/checks/deps.js.map +1 -0
  10. package/dist/checks/files.d.ts +30 -0
  11. package/dist/checks/files.d.ts.map +1 -0
  12. package/dist/checks/files.js +70 -0
  13. package/dist/checks/files.js.map +1 -0
  14. package/dist/checks/hooks.d.ts +15 -0
  15. package/dist/checks/hooks.d.ts.map +1 -0
  16. package/dist/checks/hooks.js +62 -0
  17. package/dist/checks/hooks.js.map +1 -0
  18. package/dist/checks/i18n.d.ts +43 -0
  19. package/dist/checks/i18n.d.ts.map +1 -0
  20. package/dist/checks/i18n.js +168 -0
  21. package/dist/checks/i18n.js.map +1 -0
  22. package/dist/checks/text.d.ts +30 -0
  23. package/dist/checks/text.d.ts.map +1 -0
  24. package/dist/checks/text.js +86 -0
  25. package/dist/checks/text.js.map +1 -0
  26. package/dist/cli.d.ts +3 -0
  27. package/dist/cli.d.ts.map +1 -0
  28. package/dist/cli.js +129 -0
  29. package/dist/cli.js.map +1 -0
  30. package/dist/index.d.ts +8 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +7 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/init/claudeSettings.d.ts +19 -0
  35. package/dist/init/claudeSettings.d.ts.map +1 -0
  36. package/dist/init/claudeSettings.js +23 -0
  37. package/dist/init/claudeSettings.js.map +1 -0
  38. package/dist/init/init.d.ts +35 -0
  39. package/dist/init/init.d.ts.map +1 -0
  40. package/dist/init/init.js +286 -0
  41. package/dist/init/init.js.map +1 -0
  42. package/dist/init/packageJson.d.ts +39 -0
  43. package/dist/init/packageJson.d.ts.map +1 -0
  44. package/dist/init/packageJson.js +97 -0
  45. package/dist/init/packageJson.js.map +1 -0
  46. package/dist/kitConfig.d.ts +69 -0
  47. package/dist/kitConfig.d.ts.map +1 -0
  48. package/dist/kitConfig.js +84 -0
  49. package/dist/kitConfig.js.map +1 -0
  50. package/dist/kitConfig.schema.json +163 -0
  51. package/github/ISSUE_TEMPLATE/config.yml +1 -0
  52. package/github/ISSUE_TEMPLATE/feature.yml +63 -0
  53. package/github/pr-checks.yml +153 -0
  54. package/jest/package.json +3 -0
  55. package/jest/preset.js +18 -0
  56. package/lefthook.yml +30 -0
  57. package/package.json +73 -0
  58. package/templates/dependency-cruiser.template.mjs +13 -0
  59. package/templates/eslint.config.template.mjs +11 -0
  60. package/tsconfig/expo.json +14 -0
@@ -0,0 +1,286 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { dirname, join } from 'node:path';
4
+ import { checkText } from '../checks/text.js';
5
+ import { KIT_CONFIG_FILE, parseKitConfig } from '../kitConfig.js';
6
+ import { mergeClaudeSettings } from './claudeSettings.js';
7
+ import { planPackageJson } from './packageJson.js';
8
+ const TSCONFIG_PRESET = '@timothyrusso/config-presets/tsconfig/expo.json';
9
+ const SCHEMA_PATH = './node_modules/@timothyrusso/config-presets/dist/kitConfig.schema.json';
10
+ function readJson(file) {
11
+ return JSON.parse(readFileSync(file, 'utf8'));
12
+ }
13
+ const json = (value) => `${JSON.stringify(value, null, 2)}\n`;
14
+ function defaults(cwd, pkg, existing) {
15
+ const srcLayout = existsSync(join(cwd, 'src', 'app'));
16
+ const i18n = existing?.i18n;
17
+ const lint = existing?.lint;
18
+ return {
19
+ projectName: existing?.projectName ?? pkg.name ?? 'app',
20
+ featuresRoot: existing?.featuresRoot ?? (srcLayout ? 'src/features' : 'features'),
21
+ appRoot: existing?.appRoot ?? (srcLayout ? 'src/app' : 'app'),
22
+ ...(i18n ? { i18n } : {}),
23
+ dashes: lint?.dashes ?? 'forbid',
24
+ };
25
+ }
26
+ const splitList = (value) => value
27
+ .split(',')
28
+ .map(part => part.trim())
29
+ .filter(Boolean);
30
+ async function resolveAnswers(options, base) {
31
+ const { flags, yes } = options;
32
+ const ask = yes ? undefined : options.ask;
33
+ const answer = async (question, flag, fallback) => flag ?? (ask ? (await ask(question, fallback)).trim() || fallback : fallback);
34
+ const projectName = await answer('Project name', flags.projectName, base.projectName);
35
+ const featuresRoot = await answer('Features folder (features or src/features)', flags.featuresRoot, base.featuresRoot);
36
+ const appRoot = await answer('expo-router app folder', flags.appRoot, base.appRoot);
37
+ const catalogPath = await answer('Translation catalog folder (none for no catalog)', flags.i18n, base.i18n?.catalogPath ?? 'none');
38
+ const hasCatalog = catalogPath !== '' && catalogPath !== 'none';
39
+ const languages = hasCatalog
40
+ ? splitList(await answer('Catalog languages, reference first (comma separated)', flags.languages?.join(','), base.i18n?.languages.join(',') ?? 'en'))
41
+ : [];
42
+ const dashes = await answer('Em and en dashes (forbid or allow)', flags.dashes, base.dashes);
43
+ return {
44
+ projectName,
45
+ featuresRoot: featuresRoot,
46
+ appRoot,
47
+ ...(hasCatalog ? { i18n: { catalogPath, languages } } : {}),
48
+ dashes: dashes,
49
+ };
50
+ }
51
+ function kitConfigJson(answers) {
52
+ const config = {
53
+ $schema: SCHEMA_PATH,
54
+ projectName: answers.projectName,
55
+ featuresRoot: answers.featuresRoot,
56
+ appRoot: answers.appRoot,
57
+ lint: { dashes: answers.dashes },
58
+ ...(answers.i18n ? { i18n: answers.i18n } : {}),
59
+ };
60
+ parseKitConfig(config);
61
+ return config;
62
+ }
63
+ /** Where the `@/` alias points: `src` for a `src/features` layout, the app root otherwise. */
64
+ function aliasRoot(featuresRoot) {
65
+ return featuresRoot === 'src/features' ? 'src/' : '';
66
+ }
67
+ function jestConfig(featuresRoot) {
68
+ const root = aliasRoot(featuresRoot);
69
+ if (root === '')
70
+ return "module.exports = require('@timothyrusso/config-presets/jest');\n";
71
+ return [
72
+ "const preset = require('@timothyrusso/config-presets/jest');",
73
+ '',
74
+ `module.exports = { ...preset, moduleNameMapper: { '^@/(.*)$': '<rootDir>/${root}$1' } };`,
75
+ '',
76
+ ].join('\n');
77
+ }
78
+ /**
79
+ * Writes the kit's config files into an app, merges its `package.json`, `tsconfig.json` and
80
+ * `.claude/settings.json`, and (unless `install` is false) installs the tools and hooks. Returns
81
+ * the process exit code.
82
+ */
83
+ export async function init(options) {
84
+ const { cwd, packageRoot, force, write } = options;
85
+ const run = options.run ??
86
+ ((command, args) => spawnSync(command, args, { cwd, stdio: 'inherit' }).status ?? 1);
87
+ const pkgFile = join(cwd, 'package.json');
88
+ if (!existsSync(pkgFile)) {
89
+ write(`FAIL: no package.json in ${cwd}. Run init at the app root.`);
90
+ return 1;
91
+ }
92
+ const pkg = readJson(pkgFile);
93
+ const kitVersion = readJson(join(packageRoot, 'package.json')).version;
94
+ const kitConfigFile = join(cwd, KIT_CONFIG_FILE);
95
+ const existingConfig = existsSync(kitConfigFile) ? readJson(kitConfigFile) : undefined;
96
+ const keepConfig = existingConfig !== undefined && !force;
97
+ const answers = keepConfig
98
+ ? defaults(cwd, pkg, existingConfig)
99
+ : await resolveAnswers(options, defaults(cwd, pkg, existingConfig));
100
+ const config = keepConfig ? parseKitConfig(existingConfig) : undefined;
101
+ const featuresRoot = (config?.featuresRoot ?? answers.featuresRoot);
102
+ const touched = [];
103
+ const report = (action, file) => write(` ${action.padEnd(8)}${file}`);
104
+ const template = (path) => () => readFileSync(join(packageRoot, path), 'utf8');
105
+ write('config-presets init');
106
+ if (keepConfig)
107
+ report('kept', KIT_CONFIG_FILE);
108
+ else {
109
+ writeFileSync(kitConfigFile, json(kitConfigJson(answers)));
110
+ touched.push(KIT_CONFIG_FILE);
111
+ report('wrote', KIT_CONFIG_FILE);
112
+ }
113
+ const steps = [
114
+ {
115
+ to: 'biome.json',
116
+ rivals: ['biome.jsonc'],
117
+ content: () => json({
118
+ $schema: './node_modules/@biomejs/biome/configuration_schema.json',
119
+ extends: ['@timothyrusso/config-presets/biome'],
120
+ }),
121
+ },
122
+ {
123
+ to: 'commitlint.config.cjs',
124
+ rivals: [
125
+ 'commitlint.config.js',
126
+ 'commitlint.config.mjs',
127
+ 'commitlint.config.ts',
128
+ '.commitlintrc.json',
129
+ '.commitlint.cjs',
130
+ '.commitlintrc.js',
131
+ ],
132
+ content: () => "module.exports = { extends: ['@timothyrusso/config-presets/commitlint'] };\n",
133
+ },
134
+ { to: 'lefthook.yml', rivals: ['lefthook.yaml', '.lefthook.yml'], content: template('lefthook.yml') },
135
+ {
136
+ to: 'eslint.config.mjs',
137
+ rivals: ['eslint.config.js', 'eslint.config.cjs', 'eslint.config.ts', '.eslintrc.js', '.eslintrc.json'],
138
+ content: template('templates/eslint.config.template.mjs'),
139
+ },
140
+ {
141
+ to: '.dependency-cruiser.mjs',
142
+ rivals: ['.dependency-cruiser.js', '.dependency-cruiser.cjs', '.dependency-cruiser.json'],
143
+ content: template('templates/dependency-cruiser.template.mjs'),
144
+ },
145
+ {
146
+ to: 'jest.config.cjs',
147
+ rivals: ['jest.config.js', 'jest.config.mjs', 'jest.config.ts', 'jest.config.json'],
148
+ content: () => jestConfig(featuresRoot),
149
+ },
150
+ { to: '.github/workflows/pr-checks.yml', content: template('github/pr-checks.yml') },
151
+ { to: '.github/ISSUE_TEMPLATE/feature.yml', content: template('github/ISSUE_TEMPLATE/feature.yml') },
152
+ { to: '.github/ISSUE_TEMPLATE/config.yml', content: template('github/ISSUE_TEMPLATE/config.yml') },
153
+ { to: '.nvmrc', content: () => '22\n' },
154
+ ];
155
+ for (const step of steps) {
156
+ const target = join(cwd, step.to);
157
+ const rival = step.rivals?.find(name => existsSync(join(cwd, name)));
158
+ if (rival) {
159
+ report('kept', `${rival} (merge the kit's ${step.to} into it by hand)`);
160
+ continue;
161
+ }
162
+ if (existsSync(target) && !force) {
163
+ report('kept', step.to);
164
+ continue;
165
+ }
166
+ mkdirSync(dirname(target), { recursive: true });
167
+ writeFileSync(target, step.content());
168
+ touched.push(step.to);
169
+ report('wrote', step.to);
170
+ }
171
+ const settingsFile = join(cwd, '.claude', 'settings.json');
172
+ const settingsTemplate = readJson(join(packageRoot, '.claude', 'settings.template.json'));
173
+ mkdirSync(dirname(settingsFile), { recursive: true });
174
+ if (existsSync(settingsFile)) {
175
+ writeFileSync(settingsFile, json(mergeClaudeSettings(readJson(settingsFile), settingsTemplate)));
176
+ report('merged', '.claude/settings.json');
177
+ }
178
+ else {
179
+ copyFileSync(join(packageRoot, '.claude', 'settings.template.json'), settingsFile);
180
+ report('wrote', '.claude/settings.json');
181
+ }
182
+ touched.push('.claude/settings.json');
183
+ const warnings = [];
184
+ const tsconfigFile = join(cwd, 'tsconfig.json');
185
+ const alias = { '@/*': [`./${aliasRoot(featuresRoot)}*`] };
186
+ if (!existsSync(tsconfigFile)) {
187
+ writeFileSync(tsconfigFile, json({ extends: TSCONFIG_PRESET, compilerOptions: { paths: alias } }));
188
+ touched.push('tsconfig.json');
189
+ report('wrote', 'tsconfig.json');
190
+ }
191
+ else {
192
+ let tsconfig;
193
+ try {
194
+ tsconfig = readJson(tsconfigFile);
195
+ }
196
+ catch {
197
+ warnings.push(`tsconfig.json is not plain JSON: set "extends": "${TSCONFIG_PRESET}" by hand`);
198
+ }
199
+ if (tsconfig) {
200
+ const replaceable = tsconfig.extends === undefined || tsconfig.extends === 'expo/tsconfig.base';
201
+ if (replaceable || force)
202
+ tsconfig.extends = TSCONFIG_PRESET;
203
+ else if (tsconfig.extends !== TSCONFIG_PRESET) {
204
+ warnings.push(`tsconfig.json extends ${JSON.stringify(tsconfig.extends)}: add "${TSCONFIG_PRESET}" by hand`);
205
+ }
206
+ tsconfig.compilerOptions = { ...(tsconfig.compilerOptions ?? {}) };
207
+ tsconfig.compilerOptions.paths ??= alias;
208
+ writeFileSync(tsconfigFile, json(tsconfig));
209
+ touched.push('tsconfig.json');
210
+ report('merged', 'tsconfig.json');
211
+ }
212
+ }
213
+ if (aliasRoot(featuresRoot) === '' && adoptStockEntry(join(cwd, 'index.ts'))) {
214
+ touched.push('index.ts');
215
+ report('updated', "index.ts (create-expo-app's entry: App through the @/ alias, comments dropped)");
216
+ }
217
+ const answeredDashes = config?.lint?.dashes ?? answers.dashes;
218
+ if (answeredDashes === 'forbid') {
219
+ const docs = readdirSync(cwd).filter(name => name.endsWith('.md'));
220
+ const fixed = checkText({ rootDir: cwd, config: { lint: { dashes: 'forbid' } }, files: docs, fix: true });
221
+ for (const file of fixed.problems)
222
+ report('updated', `${file} (em and en dashes replaced with hyphens)`);
223
+ }
224
+ const plan = planPackageJson(pkg, kitVersion, force);
225
+ writeFileSync(pkgFile, json(plan.packageJson));
226
+ report('merged', `package.json (scripts: ${plan.scriptsAdded.join(', ') || 'none added'})`);
227
+ for (const name of plan.scriptsKept)
228
+ warnings.push(`script "${name}" already exists and was kept: use --force to replace it`);
229
+ warnings.push(...plan.warnings);
230
+ const next = [];
231
+ if (options.install) {
232
+ if (plan.devDependenciesAdded.length > 0 || !existsSync(join(cwd, 'node_modules'))) {
233
+ if (run('npm', ['install']) !== 0)
234
+ return fail(write, 'npm install failed');
235
+ }
236
+ if (plan.expoTestPackagesMissing.length > 0 && plan.packageJson.dependencies?.expo !== undefined) {
237
+ if (run('npx', ['expo', 'install', '--dev', ...plan.expoTestPackagesMissing]) !== 0) {
238
+ return fail(write, 'npx expo install failed');
239
+ }
240
+ }
241
+ const formattable = [...touched, 'package.json'].filter(file => /\.(json|jsonc|js|cjs|mjs)$/.test(file));
242
+ if (run('npx', ['--no-install', 'biome', 'format', '--write', ...formattable]) !== 0) {
243
+ warnings.push('biome format failed on the written files: run npm run format');
244
+ }
245
+ if (run('npx', ['--no-install', 'lefthook', 'install']) !== 0)
246
+ warnings.push('lefthook install failed');
247
+ }
248
+ else {
249
+ next.push('npm install');
250
+ if (plan.expoTestPackagesMissing.length > 0) {
251
+ next.push(`npx expo install --dev ${plan.expoTestPackagesMissing.join(' ')}`);
252
+ }
253
+ next.push('npm run format');
254
+ }
255
+ next.push('npm run check');
256
+ for (const warning of warnings)
257
+ write(` warning ${warning}`);
258
+ write(`Next: ${next.join(', then ')}`);
259
+ return 0;
260
+ }
261
+ /** The code of create-expo-app's `index.ts` (blank templates), without its comment lines. */
262
+ const STOCK_ENTRY = "import { registerRootComponent } from 'expo';\nimport App from './App';\nregisterRootComponent(App);";
263
+ /** The same entry written to the kit's rules: no relative import, no plain comments. */
264
+ const KIT_ENTRY = "import { registerRootComponent } from 'expo';\n\nimport App from '@/App';\n\nregisterRootComponent(App);\n";
265
+ /**
266
+ * Rewrites `index.ts` to `KIT_ENTRY` when it is still create-expo-app's untouched entry, which
267
+ * imports `./App` relatively and carries plain comments. Any other `index.ts` is left alone.
268
+ */
269
+ function adoptStockEntry(file) {
270
+ if (!existsSync(file))
271
+ return false;
272
+ const code = readFileSync(file, 'utf8')
273
+ .split('\n')
274
+ .map(line => line.trim())
275
+ .filter(line => line !== '' && !line.startsWith('//'))
276
+ .join('\n');
277
+ if (code !== STOCK_ENTRY)
278
+ return false;
279
+ writeFileSync(file, KIT_ENTRY);
280
+ return true;
281
+ }
282
+ function fail(write, message) {
283
+ write(`FAIL: ${message}`);
284
+ return 1;
285
+ }
286
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/init/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /** The slice of an app's `package.json` that `init` reads and writes. */
2
+ export interface PackageJson {
3
+ name?: string;
4
+ type?: string;
5
+ scripts?: Record<string, string>;
6
+ dependencies?: Record<string, string>;
7
+ devDependencies?: Record<string, string>;
8
+ [field: string]: unknown;
9
+ }
10
+ /**
11
+ * The scripts `init` adds. `check` runs every gate; the catalog checks pass with a SKIP note until
12
+ * `kit.config.json` gains an `i18n` section, and `check:arch` until `featuresRoot` or `appRoot`
13
+ * exists, so the script never needs editing as the app grows.
14
+ */
15
+ export declare const APP_SCRIPTS: Readonly<Record<string, string>>;
16
+ /** The `prepare` step that installs the git hooks. */
17
+ export declare const PREPARE = "lefthook install";
18
+ /**
19
+ * Tool versions `init` adds when the app has none. `typescript` is held at 5.9 because
20
+ * dependency-cruiser 18 does not support TypeScript 7; an app already on 5.x or 6.x keeps its own.
21
+ */
22
+ export declare const TOOL_VERSIONS: Readonly<Record<string, string>>;
23
+ /** The kit's own packages, installed at the same (lockstep) version as this one. */
24
+ export declare const KIT_PACKAGES: readonly ["@timothyrusso/config-presets", "@timothyrusso/eslint-plugin-arch", "@timothyrusso/arch-rules"];
25
+ /** Installed with `npx expo install`, so their versions match the app's Expo SDK. */
26
+ export declare const EXPO_TEST_PACKAGES: readonly ["jest-expo", "jest", "@types/jest"];
27
+ export interface PackageJsonPlan {
28
+ readonly packageJson: PackageJson;
29
+ readonly scriptsAdded: readonly string[];
30
+ /** Scripts the app already had with a different command, left alone (without `force`). */
31
+ readonly scriptsKept: readonly string[];
32
+ readonly devDependenciesAdded: readonly string[];
33
+ /** Expo test packages the app is missing. */
34
+ readonly expoTestPackagesMissing: readonly string[];
35
+ readonly warnings: readonly string[];
36
+ }
37
+ /** Merges the kit's scripts and devDependencies into `pkg`, without mutating it. */
38
+ export declare function planPackageJson(pkg: PackageJson, kitVersion: string, force: boolean): PackageJsonPlan;
39
+ //# sourceMappingURL=packageJson.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packageJson.d.ts","sourceRoot":"","sources":["../../src/init/packageJson.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYxD,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,OAAO,qBAAqB,CAAC;AAE1C;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQ1D,CAAC;AAEF,oFAAoF;AACpF,eAAO,MAAM,YAAY,2GAIf,CAAC;AAEX,qFAAqF;AACrF,eAAO,MAAM,kBAAkB,+CAAgD,CAAC;AAEhF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,0FAA0F;IAC1F,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,oBAAoB,EAAE,SAAS,MAAM,EAAE,CAAC;IACjD,6CAA6C;IAC7C,QAAQ,CAAC,uBAAuB,EAAE,SAAS,MAAM,EAAE,CAAC;IACpD,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAKD,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,eAAe,CAuDrG"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * The scripts `init` adds. `check` runs every gate; the catalog checks pass with a SKIP note until
3
+ * `kit.config.json` gains an `i18n` section, and `check:arch` until `featuresRoot` or `appRoot`
4
+ * exists, so the script never needs editing as the app grows.
5
+ */
6
+ export const APP_SCRIPTS = {
7
+ lint: 'biome check . && eslint .',
8
+ format: 'biome check --write .',
9
+ typecheck: 'tsc --noEmit',
10
+ 'check:text': 'config-presets check-text',
11
+ 'check:arch': 'config-presets check-deps',
12
+ 'check:i18n': 'config-presets check-i18n',
13
+ 'check:unused-keys': 'config-presets check-unused-keys',
14
+ 'check:hooks': 'config-presets check-hooks',
15
+ test: 'jest --passWithNoTests',
16
+ check: 'npm run lint && npm run typecheck && npm run check:text && npm run check:arch && npm run check:i18n && npm run check:unused-keys && npm run check:hooks && npm run test',
17
+ };
18
+ /** The `prepare` step that installs the git hooks. */
19
+ export const PREPARE = 'lefthook install';
20
+ /**
21
+ * Tool versions `init` adds when the app has none. `typescript` is held at 5.9 because
22
+ * dependency-cruiser 18 does not support TypeScript 7; an app already on 5.x or 6.x keeps its own.
23
+ */
24
+ export const TOOL_VERSIONS = {
25
+ '@biomejs/biome': '^2.5.14',
26
+ '@commitlint/cli': '^21.2.3',
27
+ '@commitlint/config-conventional': '^21.2.3',
28
+ 'dependency-cruiser': '^18.4.0',
29
+ eslint: '^10.11.0',
30
+ lefthook: '^2.1.14',
31
+ typescript: '~5.9.3',
32
+ };
33
+ /** The kit's own packages, installed at the same (lockstep) version as this one. */
34
+ export const KIT_PACKAGES = [
35
+ '@timothyrusso/config-presets',
36
+ '@timothyrusso/eslint-plugin-arch',
37
+ '@timothyrusso/arch-rules',
38
+ ];
39
+ /** Installed with `npx expo install`, so their versions match the app's Expo SDK. */
40
+ export const EXPO_TEST_PACKAGES = ['jest-expo', 'jest', '@types/jest'];
41
+ const has = (pkg, name) => pkg.dependencies?.[name] !== undefined || pkg.devDependencies?.[name] !== undefined;
42
+ /** Merges the kit's scripts and devDependencies into `pkg`, without mutating it. */
43
+ export function planPackageJson(pkg, kitVersion, force) {
44
+ const scripts = { ...(pkg.scripts ?? {}) };
45
+ const scriptsAdded = [];
46
+ const scriptsKept = [];
47
+ const warnings = [];
48
+ for (const [name, command] of Object.entries(APP_SCRIPTS)) {
49
+ const current = scripts[name];
50
+ if (current === command)
51
+ continue;
52
+ if (current !== undefined && !force) {
53
+ scriptsKept.push(name);
54
+ continue;
55
+ }
56
+ scripts[name] = command;
57
+ scriptsAdded.push(name);
58
+ }
59
+ const prepare = scripts.prepare;
60
+ if (prepare === undefined) {
61
+ scripts.prepare = PREPARE;
62
+ scriptsAdded.push('prepare');
63
+ }
64
+ else if (!prepare.includes('lefthook install')) {
65
+ scripts.prepare = `${prepare} && ${PREPARE}`;
66
+ scriptsAdded.push('prepare');
67
+ }
68
+ const devDependencies = { ...(pkg.devDependencies ?? {}) };
69
+ const devDependenciesAdded = [];
70
+ const wanted = {
71
+ ...Object.fromEntries(KIT_PACKAGES.map(name => [name, `^${kitVersion}`])),
72
+ ...TOOL_VERSIONS,
73
+ };
74
+ for (const [name, range] of Object.entries(wanted)) {
75
+ if (has(pkg, name))
76
+ continue;
77
+ devDependencies[name] = range;
78
+ devDependenciesAdded.push(name);
79
+ }
80
+ const ts = pkg.devDependencies?.typescript ?? pkg.dependencies?.typescript;
81
+ if (ts !== undefined && /^\D*([7-9]|\d{2,})\./.test(ts)) {
82
+ warnings.push(`typescript ${ts}: dependency-cruiser 18 does not support TypeScript 7, use ~5.9.3 or 6.x`);
83
+ }
84
+ if (!has(pkg, 'expo')) {
85
+ warnings.push('expo is not a dependency: the Jest preset extends jest-expo, install it before running tests');
86
+ }
87
+ const sortedDevDependencies = Object.fromEntries(Object.entries(devDependencies).sort(([a], [b]) => (a < b ? -1 : 1)));
88
+ return {
89
+ packageJson: { ...pkg, scripts, devDependencies: sortedDevDependencies },
90
+ scriptsAdded,
91
+ scriptsKept,
92
+ devDependenciesAdded,
93
+ expoTestPackagesMissing: EXPO_TEST_PACKAGES.filter(name => !has(pkg, name)),
94
+ warnings,
95
+ };
96
+ }
97
+ //# sourceMappingURL=packageJson.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packageJson.js","sourceRoot":"","sources":["../../src/init/packageJson.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAqC;IAC3D,IAAI,EAAE,2BAA2B;IACjC,MAAM,EAAE,uBAAuB;IAC/B,SAAS,EAAE,cAAc;IACzB,YAAY,EAAE,2BAA2B;IACzC,YAAY,EAAE,2BAA2B;IACzC,YAAY,EAAE,2BAA2B;IACzC,mBAAmB,EAAE,kCAAkC;IACvD,aAAa,EAAE,4BAA4B;IAC3C,IAAI,EAAE,wBAAwB;IAC9B,KAAK,EACH,yKAAyK;CAC5K,CAAC;AAEF,sDAAsD;AACtD,MAAM,CAAC,MAAM,OAAO,GAAG,kBAAkB,CAAC;AAE1C;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAqC;IAC7D,gBAAgB,EAAE,SAAS;IAC3B,iBAAiB,EAAE,SAAS;IAC5B,iCAAiC,EAAE,SAAS;IAC5C,oBAAoB,EAAE,SAAS;IAC/B,MAAM,EAAE,UAAU;IAClB,QAAQ,EAAE,SAAS;IACnB,UAAU,EAAE,QAAQ;CACrB,CAAC;AAEF,oFAAoF;AACpF,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,8BAA8B;IAC9B,kCAAkC;IAClC,0BAA0B;CAClB,CAAC;AAEX,qFAAqF;AACrF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,CAAU,CAAC;AAahF,MAAM,GAAG,GAAG,CAAC,GAAgB,EAAE,IAAY,EAAE,EAAE,CAC7C,GAAG,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,KAAK,SAAS,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC;AAEtF,oFAAoF;AACpF,MAAM,UAAU,eAAe,CAAC,GAAgB,EAAE,UAAkB,EAAE,KAAc;IAClF,MAAM,OAAO,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC;IAC3C,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,OAAO,KAAK,OAAO;YAAE,SAAS;QAClC,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC;YACpC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvB,SAAS;QACX,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;QACxB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAChC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC;QAC1B,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;SAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACjD,OAAO,CAAC,OAAO,GAAG,GAAG,OAAO,OAAO,OAAO,EAAE,CAAC;QAC7C,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM,eAAe,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC,EAAE,CAAC;IAC3D,MAAM,oBAAoB,GAAa,EAAE,CAAC;IAC1C,MAAM,MAAM,GAA2B;QACrC,GAAG,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC;QACzE,GAAG,aAAa;KACjB,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,IAAI,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC;YAAE,SAAS;QAC7B,eAAe,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QAC9B,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IACD,MAAM,EAAE,GAAG,GAAG,CAAC,eAAe,EAAE,UAAU,IAAI,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC;IAC3E,IAAI,EAAE,KAAK,SAAS,IAAI,sBAAsB,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACxD,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,0EAA0E,CAAC,CAAC;IAC5G,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC;QACtB,QAAQ,CAAC,IAAI,CAAC,8FAA8F,CAAC,CAAC;IAChH,CAAC;IAED,MAAM,qBAAqB,GAAG,MAAM,CAAC,WAAW,CAC9C,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACrE,CAAC;IACF,OAAO;QACL,WAAW,EAAE,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE;QACxE,YAAY;QACZ,WAAW;QACX,oBAAoB;QACpB,uBAAuB,EAAE,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC3E,QAAQ;KACT,CAAC;AACJ,CAAC"}
@@ -0,0 +1,69 @@
1
+ /** File name every consuming app keeps at its root. */
2
+ export declare const KIT_CONFIG_FILE = "kit.config.json";
3
+ export type QaTarget = 'mobile' | 'web';
4
+ /**
5
+ * A validated `kit.config.json` with the schema defaults applied (`featuresRoot`, `appRoot` and
6
+ * the defaults inside any section that is present).
7
+ */
8
+ export interface KitConfig {
9
+ projectName: string;
10
+ featuresRoot: 'features' | 'src/features';
11
+ appRoot: string;
12
+ github?: {
13
+ projectNumber: number;
14
+ projectId: string;
15
+ statusFieldId: string;
16
+ statusOptions: {
17
+ todo: string;
18
+ inProgress: string;
19
+ done: string;
20
+ };
21
+ labels: string[];
22
+ };
23
+ qa?: {
24
+ targets: QaTarget[];
25
+ simulator?: string;
26
+ metroPort?: number;
27
+ baseline?: {
28
+ setup?: string;
29
+ launch?: string;
30
+ firstScreens?: string[];
31
+ navigation?: string[];
32
+ };
33
+ };
34
+ lint?: {
35
+ allowedHooksInViews: string[];
36
+ dashes: 'forbid' | 'allow';
37
+ layoutTokens?: {
38
+ gutterToken: string;
39
+ spacingImport: string;
40
+ allowlistFile: string;
41
+ };
42
+ singleSpinner: boolean;
43
+ };
44
+ i18n?: {
45
+ catalogPath: string;
46
+ languages: string[];
47
+ };
48
+ }
49
+ /** Thrown when `kit.config.json` is missing, unreadable or fails the schema. */
50
+ export declare class KitConfigError extends Error {
51
+ readonly name = "KitConfigError";
52
+ readonly issues: readonly string[];
53
+ constructor(message: string, issues?: readonly string[]);
54
+ }
55
+ /**
56
+ * Validates an already parsed config against `kit.config.schema.json` and applies its defaults.
57
+ * `source` names the file in the error message.
58
+ */
59
+ export declare function parseKitConfig(value: unknown, source?: string): KitConfig;
60
+ /** Walks up from `cwd` to the nearest `kit.config.json`, or returns `undefined`. */
61
+ export declare function findKitConfig(cwd?: string): string | undefined;
62
+ export interface LoadKitConfigOptions {
63
+ /** Explicit file to read. When absent the nearest `kit.config.json` above `cwd` is used. */
64
+ path?: string;
65
+ cwd?: string;
66
+ }
67
+ /** Reads, parses and validates `kit.config.json`. Throws `KitConfigError` with every problem. */
68
+ export declare function loadKitConfig(options?: LoadKitConfigOptions): KitConfig;
69
+ //# sourceMappingURL=kitConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kitConfig.d.ts","sourceRoot":"","sources":["../src/kitConfig.ts"],"names":[],"mappings":"AAKA,uDAAuD;AACvD,eAAO,MAAM,eAAe,oBAAoB,CAAC;AAEjD,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAC;AAExC;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,UAAU,GAAG,cAAc,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE;QACP,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QAClE,MAAM,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;IACF,EAAE,CAAC,EAAE;QACH,OAAO,EAAE,QAAQ,EAAE,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE;YACT,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,MAAM,CAAC,EAAE,MAAM,CAAC;YAChB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;YACxB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;SACvB,CAAC;KACH,CAAC;IACF,IAAI,CAAC,EAAE;QACL,mBAAmB,EAAE,MAAM,EAAE,CAAC;QAC9B,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC;QAC3B,YAAY,CAAC,EAAE;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,aAAa,EAAE,MAAM,CAAC;YAAC,aAAa,EAAE,MAAM,CAAA;SAAE,CAAC;QACrF,aAAa,EAAE,OAAO,CAAC;KACxB,CAAC;IACF,IAAI,CAAC,EAAE;QACL,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAED,gFAAgF;AAChF,qBAAa,cAAe,SAAQ,KAAK;IACvC,SAAkB,IAAI,oBAAoB;IAC1C,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;gBAEvB,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,SAAS,MAAM,EAAO;CAI5D;AA2BD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,GAAE,MAAwB,GAAG,SAAS,CAK1F;AAED,oFAAoF;AACpF,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,GAAG,SAAS,CAS7E;AAED,MAAM,WAAW,oBAAoB;IACnC,4FAA4F;IAC5F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,SAAS,CAgB3E"}
@@ -0,0 +1,84 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { dirname, join, resolve } from 'node:path';
3
+ import { Ajv } from 'ajv';
4
+ import schema from './kitConfig.schema.json' with { type: 'json' };
5
+ /** File name every consuming app keeps at its root. */
6
+ export const KIT_CONFIG_FILE = 'kit.config.json';
7
+ /** Thrown when `kit.config.json` is missing, unreadable or fails the schema. */
8
+ export class KitConfigError extends Error {
9
+ name = 'KitConfigError';
10
+ issues;
11
+ constructor(message, issues = []) {
12
+ super(issues.length > 0 ? `${message}\n${issues.map(issue => ` - ${issue}`).join('\n')}` : message);
13
+ this.issues = issues;
14
+ }
15
+ }
16
+ const ajv = new Ajv({ allErrors: true, useDefaults: true, strict: true });
17
+ const validate = ajv.compile(schema);
18
+ function fieldPath(instancePath, child) {
19
+ const parts = instancePath.split('/').filter(Boolean);
20
+ if (child !== undefined)
21
+ parts.push(child);
22
+ return parts.join('.');
23
+ }
24
+ function describe(error) {
25
+ const field = fieldPath(error.instancePath);
26
+ switch (error.keyword) {
27
+ case 'required':
28
+ return `missing required field "${fieldPath(error.instancePath, String(error.params.missingProperty))}"`;
29
+ case 'additionalProperties':
30
+ return `unknown field "${fieldPath(error.instancePath, String(error.params.additionalProperty))}"`;
31
+ case 'enum':
32
+ return `"${field}" must be one of: ${error.params.allowedValues.join(', ')}`;
33
+ case 'type':
34
+ return field ? `"${field}" must be ${error.params.type}` : `the config must be ${error.params.type}`;
35
+ default:
36
+ return `"${field}" ${error.message ?? 'is invalid'}`;
37
+ }
38
+ }
39
+ /**
40
+ * Validates an already parsed config against `kit.config.schema.json` and applies its defaults.
41
+ * `source` names the file in the error message.
42
+ */
43
+ export function parseKitConfig(value, source = KIT_CONFIG_FILE) {
44
+ const copy = structuredClone(value);
45
+ if (validate(copy))
46
+ return copy;
47
+ const issues = [...new Set((validate.errors ?? []).map(describe))];
48
+ throw new KitConfigError(`Invalid ${source}:`, issues);
49
+ }
50
+ /** Walks up from `cwd` to the nearest `kit.config.json`, or returns `undefined`. */
51
+ export function findKitConfig(cwd = process.cwd()) {
52
+ let dir = resolve(cwd);
53
+ for (;;) {
54
+ const candidate = join(dir, KIT_CONFIG_FILE);
55
+ if (existsSync(candidate))
56
+ return candidate;
57
+ const parent = dirname(dir);
58
+ if (parent === dir)
59
+ return undefined;
60
+ dir = parent;
61
+ }
62
+ }
63
+ /** Reads, parses and validates `kit.config.json`. Throws `KitConfigError` with every problem. */
64
+ export function loadKitConfig(options = {}) {
65
+ const file = options.path ? resolve(options.cwd ?? process.cwd(), options.path) : findKitConfig(options.cwd);
66
+ if (!file)
67
+ throw new KitConfigError(`No ${KIT_CONFIG_FILE} found in ${options.cwd ?? process.cwd()} or above it.`);
68
+ let text;
69
+ try {
70
+ text = readFileSync(file, 'utf8');
71
+ }
72
+ catch (cause) {
73
+ throw new KitConfigError(`Cannot read ${file}: ${cause instanceof Error ? cause.message : String(cause)}`);
74
+ }
75
+ let json;
76
+ try {
77
+ json = JSON.parse(text);
78
+ }
79
+ catch (cause) {
80
+ throw new KitConfigError(`${file} is not valid JSON: ${cause instanceof Error ? cause.message : String(cause)}`);
81
+ }
82
+ return parseKitConfig(json, file);
83
+ }
84
+ //# sourceMappingURL=kitConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kitConfig.js","sourceRoot":"","sources":["../src/kitConfig.ts"],"names":[],"mappings":"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"}