@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.
- package/.claude/settings.template.json +41 -0
- package/LICENSE +21 -0
- package/README.md +120 -0
- package/biome/base.json +75 -0
- package/commitlint.config.cjs +26 -0
- package/dist/checks/deps.d.ts +22 -0
- package/dist/checks/deps.d.ts.map +1 -0
- package/dist/checks/deps.js +45 -0
- package/dist/checks/deps.js.map +1 -0
- package/dist/checks/files.d.ts +30 -0
- package/dist/checks/files.d.ts.map +1 -0
- package/dist/checks/files.js +70 -0
- package/dist/checks/files.js.map +1 -0
- package/dist/checks/hooks.d.ts +15 -0
- package/dist/checks/hooks.d.ts.map +1 -0
- package/dist/checks/hooks.js +62 -0
- package/dist/checks/hooks.js.map +1 -0
- package/dist/checks/i18n.d.ts +43 -0
- package/dist/checks/i18n.d.ts.map +1 -0
- package/dist/checks/i18n.js +168 -0
- package/dist/checks/i18n.js.map +1 -0
- package/dist/checks/text.d.ts +30 -0
- package/dist/checks/text.d.ts.map +1 -0
- package/dist/checks/text.js +86 -0
- package/dist/checks/text.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +129 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/init/claudeSettings.d.ts +19 -0
- package/dist/init/claudeSettings.d.ts.map +1 -0
- package/dist/init/claudeSettings.js +23 -0
- package/dist/init/claudeSettings.js.map +1 -0
- package/dist/init/init.d.ts +35 -0
- package/dist/init/init.d.ts.map +1 -0
- package/dist/init/init.js +286 -0
- package/dist/init/init.js.map +1 -0
- package/dist/init/packageJson.d.ts +39 -0
- package/dist/init/packageJson.d.ts.map +1 -0
- package/dist/init/packageJson.js +97 -0
- package/dist/init/packageJson.js.map +1 -0
- package/dist/kitConfig.d.ts +69 -0
- package/dist/kitConfig.d.ts.map +1 -0
- package/dist/kitConfig.js +84 -0
- package/dist/kitConfig.js.map +1 -0
- package/dist/kitConfig.schema.json +163 -0
- package/github/ISSUE_TEMPLATE/config.yml +1 -0
- package/github/ISSUE_TEMPLATE/feature.yml +63 -0
- package/github/pr-checks.yml +153 -0
- package/jest/package.json +3 -0
- package/jest/preset.js +18 -0
- package/lefthook.yml +30 -0
- package/package.json +73 -0
- package/templates/dependency-cruiser.template.mjs +13 -0
- package/templates/eslint.config.template.mjs +11 -0
- package/tsconfig/expo.json +14 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { createJiti } from 'jiti';
|
|
4
|
+
import { display, sourceFiles, sourceRoots } from './files.js';
|
|
5
|
+
const CATALOG_EXTENSIONS = ['.ts', '.tsx', '.js', '.mjs', '.cjs', '.json'];
|
|
6
|
+
/** The file that holds `language` inside `catalogPath`: `<catalogPath>/<language>.ts`, or `.js` or `.json`. */
|
|
7
|
+
export function catalogFile(rootDir, catalogPath, language) {
|
|
8
|
+
return CATALOG_EXTENSIONS.map(ext => resolve(rootDir, catalogPath, `${language}${ext}`)).find(file => existsSync(file));
|
|
9
|
+
}
|
|
10
|
+
/** Every string leaf of a nested catalog object, keyed by its dotted path. */
|
|
11
|
+
export function flattenCatalog(value, prefix = '') {
|
|
12
|
+
if (value === null || typeof value !== 'object')
|
|
13
|
+
return [];
|
|
14
|
+
return Object.entries(value).flatMap(([key, child]) => {
|
|
15
|
+
if (typeof child === 'string')
|
|
16
|
+
return [[`${prefix}${key}`, child]];
|
|
17
|
+
return flattenCatalog(child, `${prefix}${key}.`);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Loads one language's catalog through jiti, so TypeScript catalogs are read as the real objects
|
|
22
|
+
* rather than parsed as text. The catalog is the export named after the language (`export const en`),
|
|
23
|
+
* or the default export.
|
|
24
|
+
*/
|
|
25
|
+
export async function loadCatalog(file, language) {
|
|
26
|
+
const jiti = createJiti(file, { moduleCache: false, fsCache: false });
|
|
27
|
+
const mod = await jiti.import(file);
|
|
28
|
+
const catalog = mod[language] ?? mod.default;
|
|
29
|
+
if (catalog === null || typeof catalog !== 'object') {
|
|
30
|
+
throw new Error(`${file} exports no catalog: export it as \`${language}\` or as the default export`);
|
|
31
|
+
}
|
|
32
|
+
return flattenCatalog(catalog);
|
|
33
|
+
}
|
|
34
|
+
async function loadCatalogs(rootDir, i18n) {
|
|
35
|
+
const catalogs = new Map();
|
|
36
|
+
const files = [];
|
|
37
|
+
for (const language of i18n.languages) {
|
|
38
|
+
const file = catalogFile(rootDir, i18n.catalogPath, language);
|
|
39
|
+
if (!file)
|
|
40
|
+
throw new Error(`no catalog for "${language}" in ${i18n.catalogPath} (expected ${language}.ts)`);
|
|
41
|
+
files.push(file);
|
|
42
|
+
catalogs.set(language, await loadCatalog(file, language));
|
|
43
|
+
}
|
|
44
|
+
return { languages: i18n.languages, catalogs, files };
|
|
45
|
+
}
|
|
46
|
+
const skipped = (what) => ({
|
|
47
|
+
ok: true,
|
|
48
|
+
summary: `SKIP: no i18n section in kit.config.json, so no ${what}`,
|
|
49
|
+
problems: [],
|
|
50
|
+
});
|
|
51
|
+
const PLURAL = /_(one|other)$/;
|
|
52
|
+
function placeholders(text) {
|
|
53
|
+
return [...text.matchAll(/\{(\w+)\}/g)]
|
|
54
|
+
.map(match => match[1])
|
|
55
|
+
.sort()
|
|
56
|
+
.join(',');
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Copy that never reached the catalog: a line of plain words inside a JSX element, with no braces
|
|
60
|
+
* or quotes on it. Deliberately narrow: it cannot see a one-word label or a template literal, so
|
|
61
|
+
* it is a net under the change most likely made by hand (a paragraph typed into a component).
|
|
62
|
+
*/
|
|
63
|
+
function proseOutsideCatalog(rootDir, files) {
|
|
64
|
+
const problems = [];
|
|
65
|
+
for (const file of files) {
|
|
66
|
+
const lines = readFileSync(file, 'utf8').split('\n');
|
|
67
|
+
lines.forEach((line, i) => {
|
|
68
|
+
if (!/^\s*[A-Za-z][A-Za-z0-9 ,.'’:;()%/-]{14,}$/.test(line))
|
|
69
|
+
return;
|
|
70
|
+
if (/[{}<>="]/.test(line))
|
|
71
|
+
return;
|
|
72
|
+
if (/\w\(|\w\.\w/.test(line))
|
|
73
|
+
return;
|
|
74
|
+
let j = i - 1;
|
|
75
|
+
while (j >= 0 && (lines[j] ?? '').trim() === '')
|
|
76
|
+
j -= 1;
|
|
77
|
+
const prev = (lines[j] ?? '').trimEnd();
|
|
78
|
+
const prevTrimmed = prev.trimStart();
|
|
79
|
+
if (!prev.endsWith('>'))
|
|
80
|
+
return;
|
|
81
|
+
if (prevTrimmed.startsWith('*') || prevTrimmed.startsWith('//'))
|
|
82
|
+
return;
|
|
83
|
+
problems.push(`${display(rootDir, file)}:${i + 1}: copy outside the catalog: "${line.trim().slice(0, 60)}"`);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return problems;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Catalog parity, driven by `kit.config.json` `i18n`. The first language is the reference.
|
|
90
|
+
*
|
|
91
|
+
* - every key of every language exists in every other one;
|
|
92
|
+
* - a plural key (`_one`) has its partner (`_other`) in the same language, and the reverse;
|
|
93
|
+
* - `{placeholder}` slots match the reference, so no language renders a literal brace;
|
|
94
|
+
* - no line of plain prose sits inside JSX under the source roots.
|
|
95
|
+
*/
|
|
96
|
+
export async function checkI18n({ rootDir, config }) {
|
|
97
|
+
if (!config.i18n)
|
|
98
|
+
return skipped('catalog parity check');
|
|
99
|
+
const { languages, catalogs } = await loadCatalogs(rootDir, config.i18n);
|
|
100
|
+
const [reference, ...others] = languages;
|
|
101
|
+
const maps = new Map([...catalogs].map(([language, flat]) => [language, new Map(flat)]));
|
|
102
|
+
const refMap = maps.get(reference ?? '') ?? new Map();
|
|
103
|
+
const problems = [];
|
|
104
|
+
for (const other of others) {
|
|
105
|
+
const otherMap = maps.get(other) ?? new Map();
|
|
106
|
+
for (const key of refMap.keys())
|
|
107
|
+
if (!otherMap.has(key))
|
|
108
|
+
problems.push(`missing in ${other}: ${key}`);
|
|
109
|
+
for (const key of otherMap.keys())
|
|
110
|
+
if (!refMap.has(key))
|
|
111
|
+
problems.push(`missing in ${reference}: ${key}`);
|
|
112
|
+
for (const [key, value] of refMap) {
|
|
113
|
+
const translated = otherMap.get(key);
|
|
114
|
+
if (translated === undefined || placeholders(value) === placeholders(translated))
|
|
115
|
+
continue;
|
|
116
|
+
problems.push(`${key}: placeholders differ (${reference} "${placeholders(value)}" against ${other} "${placeholders(translated)}")`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
for (const [language, map] of maps) {
|
|
120
|
+
for (const key of map.keys()) {
|
|
121
|
+
if (key.endsWith('_one') && !map.has(key.replace(PLURAL, '_other'))) {
|
|
122
|
+
problems.push(`${language}: ${key} has no _other form`);
|
|
123
|
+
}
|
|
124
|
+
if (key.endsWith('_other') && !map.has(key.replace(PLURAL, '_one'))) {
|
|
125
|
+
problems.push(`${language}: ${key} has no _one form`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
problems.push(...proseOutsideCatalog(rootDir, sourceFiles(sourceRoots(rootDir, config), true)));
|
|
130
|
+
if (problems.length > 0)
|
|
131
|
+
return { ok: false, summary: `FAIL: ${problems.length} i18n problem(s)`, problems };
|
|
132
|
+
return {
|
|
133
|
+
ok: true,
|
|
134
|
+
summary: `PASS: ${refMap.size} keys, ${languages.join(' and ')} agree, and no copy outside the catalog`,
|
|
135
|
+
problems,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Every key of the reference catalog is read somewhere under the source roots, as a quoted
|
|
140
|
+
* string: `t('home.title')`, `tr('home.title')` or a module-level table of keys. A plural key
|
|
141
|
+
* counts as used when its base is, because `t()` picks the form from `count`. A key built at
|
|
142
|
+
* runtime from pieces reads as unused, on purpose: a key nobody can search for is a key nobody
|
|
143
|
+
* can safely rename.
|
|
144
|
+
*/
|
|
145
|
+
export async function checkUnusedKeys({ rootDir, config }) {
|
|
146
|
+
if (!config.i18n)
|
|
147
|
+
return skipped('unused key check');
|
|
148
|
+
const { languages, catalogs, files } = await loadCatalogs(rootDir, config.i18n);
|
|
149
|
+
const keys = (catalogs.get(languages[0] ?? '') ?? []).map(([key]) => key);
|
|
150
|
+
const catalogFiles = new Set(files);
|
|
151
|
+
const text = sourceFiles(sourceRoots(rootDir, config))
|
|
152
|
+
.filter(file => !catalogFiles.has(file))
|
|
153
|
+
.map(file => readFileSync(file, 'utf8'))
|
|
154
|
+
.join('\n');
|
|
155
|
+
const unused = keys.filter(key => {
|
|
156
|
+
const base = key.replace(PLURAL, '');
|
|
157
|
+
return !text.includes(`'${base}'`) && !text.includes(`"${base}"`) && !text.includes(`\`${base}\``);
|
|
158
|
+
});
|
|
159
|
+
if (unused.length > 0) {
|
|
160
|
+
return {
|
|
161
|
+
ok: false,
|
|
162
|
+
summary: `FAIL: ${unused.length} catalog key(s) are never read. Delete them from every language in ${config.i18n.catalogPath}.`,
|
|
163
|
+
problems: unused,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
return { ok: true, summary: `PASS: all ${keys.length} catalog keys are read`, problems: [] };
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=i18n.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/checks/i18n.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type CheckResult } from './files.js';
|
|
2
|
+
export interface TextCheckOptions {
|
|
3
|
+
readonly rootDir: string;
|
|
4
|
+
readonly config: {
|
|
5
|
+
readonly lint?: {
|
|
6
|
+
readonly dashes?: 'forbid' | 'allow';
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
/** Files to check, relative to `rootDir`. Defaults to every tracked and untracked, not ignored, file. */
|
|
10
|
+
readonly files?: readonly string[];
|
|
11
|
+
/** A commit message to check instead of files. */
|
|
12
|
+
readonly message?: string;
|
|
13
|
+
/** Rewrite the dashes with `replaceDashes` instead of reporting them. Ignored for a message. */
|
|
14
|
+
readonly fix?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The mechanical fix: a numeric range (`8`, en dash, `12`) becomes `8-12`, and every other em or
|
|
18
|
+
* en dash becomes a spaced hyphen. A colon, comma or parentheses often reads better; this only
|
|
19
|
+
* guarantees the text passes.
|
|
20
|
+
*/
|
|
21
|
+
export declare function replaceDashes(text: string): string;
|
|
22
|
+
/** Dash hits in `text`, one line per hit, prefixed with `label`. */
|
|
23
|
+
export declare function dashHits(label: string, text: string): string[];
|
|
24
|
+
/**
|
|
25
|
+
* No em dash or en dash in any file of the app, whatever its type (code, Markdown, JSON, YAML,
|
|
26
|
+
* native sources), or in a commit message. Runs when `lint.dashes` is `forbid`, the default;
|
|
27
|
+
* ESLint's `no-dashes` covers only JavaScript and TypeScript.
|
|
28
|
+
*/
|
|
29
|
+
export declare function checkText({ rootDir, config, files, message, fix }: TextCheckOptions): CheckResult;
|
|
30
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/checks/text.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,YAAY,CAAC;AAmB5D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE;YAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAA;SAAE,CAAA;KAAE,CAAC;IAC9E,yGAAyG;IACzG,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,kDAAkD;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,gGAAgG;IAChG,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED,oEAAoE;AACpE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAS9D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAW,EAAE,EAAE,gBAAgB,GAAG,WAAW,CAmCzG"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { projectFiles } from './files.js';
|
|
4
|
+
/**
|
|
5
|
+
* NOTE: built from code points, so this file does not fail its own check and a repo-wide text
|
|
6
|
+
* replace cannot rewrite the characters it looks for.
|
|
7
|
+
*/
|
|
8
|
+
const EM = String.fromCharCode(0x2014);
|
|
9
|
+
const EN = String.fromCharCode(0x2013);
|
|
10
|
+
const DASHES = [
|
|
11
|
+
[EM, 'em dash'],
|
|
12
|
+
[EN, 'en dash'],
|
|
13
|
+
];
|
|
14
|
+
const BINARY = /\.(png|jpe?g|gif|webp|avif|heic|ico|icns|pdf|zip|gz|tgz|jar|keystore|mp3|mp4|mov|wav|ttf|otf|woff2?|lottie)$/i;
|
|
15
|
+
/** Generated files nobody edits by hand. */
|
|
16
|
+
const GENERATED = /(^|\/)(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lockb?)$/;
|
|
17
|
+
/**
|
|
18
|
+
* The mechanical fix: a numeric range (`8`, en dash, `12`) becomes `8-12`, and every other em or
|
|
19
|
+
* en dash becomes a spaced hyphen. A colon, comma or parentheses often reads better; this only
|
|
20
|
+
* guarantees the text passes.
|
|
21
|
+
*/
|
|
22
|
+
export function replaceDashes(text) {
|
|
23
|
+
return text
|
|
24
|
+
.replace(new RegExp(`(\\d)[ \\t]*${EN}[ \\t]*(\\d)`, 'g'), '$1-$2')
|
|
25
|
+
.replace(new RegExp(`[ \\t]*[${EM}${EN}][ \\t]*`, 'g'), ' - ');
|
|
26
|
+
}
|
|
27
|
+
/** Dash hits in `text`, one line per hit, prefixed with `label`. */
|
|
28
|
+
export function dashHits(label, text) {
|
|
29
|
+
if (!DASHES.some(([dash]) => text.includes(dash)))
|
|
30
|
+
return [];
|
|
31
|
+
const hits = [];
|
|
32
|
+
text.split('\n').forEach((line, i) => {
|
|
33
|
+
for (const [dash, name] of DASHES) {
|
|
34
|
+
if (line.includes(dash))
|
|
35
|
+
hits.push(`${label}:${i + 1} ${name} ${line.trim().slice(0, 96)}`);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
return hits;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* No em dash or en dash in any file of the app, whatever its type (code, Markdown, JSON, YAML,
|
|
42
|
+
* native sources), or in a commit message. Runs when `lint.dashes` is `forbid`, the default;
|
|
43
|
+
* ESLint's `no-dashes` covers only JavaScript and TypeScript.
|
|
44
|
+
*/
|
|
45
|
+
export function checkText({ rootDir, config, files, message, fix = false }) {
|
|
46
|
+
if (config.lint?.dashes === 'allow') {
|
|
47
|
+
return { ok: true, summary: 'SKIP: lint.dashes is "allow" in kit.config.json', problems: [] };
|
|
48
|
+
}
|
|
49
|
+
const problems = [];
|
|
50
|
+
const fixed = [];
|
|
51
|
+
let checked = 0;
|
|
52
|
+
if (message !== undefined) {
|
|
53
|
+
problems.push(...dashHits('commit message', message));
|
|
54
|
+
checked = 1;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
for (const file of files ?? projectFiles(rootDir)) {
|
|
58
|
+
const full = resolve(rootDir, file);
|
|
59
|
+
if (BINARY.test(file) || GENERATED.test(file) || !existsSync(full) || !statSync(full).isFile())
|
|
60
|
+
continue;
|
|
61
|
+
const text = readFileSync(full, 'utf8');
|
|
62
|
+
checked += 1;
|
|
63
|
+
const hits = dashHits(file, text);
|
|
64
|
+
if (hits.length === 0)
|
|
65
|
+
continue;
|
|
66
|
+
if (fix) {
|
|
67
|
+
writeFileSync(full, replaceDashes(text));
|
|
68
|
+
fixed.push(file);
|
|
69
|
+
}
|
|
70
|
+
else
|
|
71
|
+
problems.push(...hits);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (fixed.length > 0) {
|
|
75
|
+
return { ok: true, summary: `FIXED: replaced the dashes in ${fixed.length} file(s)`, problems: fixed };
|
|
76
|
+
}
|
|
77
|
+
if (problems.length > 0) {
|
|
78
|
+
return {
|
|
79
|
+
ok: false,
|
|
80
|
+
summary: `FAIL: ${problems.length} dash(es). Use a colon, comma, parentheses or a hyphen (or run with --fix).`,
|
|
81
|
+
problems,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return { ok: true, summary: `PASS: no em or en dashes in ${checked} file(s)`, problems };
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/checks/text.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
import { createInterface } from 'node:readline/promises';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { parseArgs } from 'node:util';
|
|
7
|
+
import { runDepsCheck } from './checks/deps.js';
|
|
8
|
+
import { checkHooks } from './checks/hooks.js';
|
|
9
|
+
import { checkI18n, checkUnusedKeys } from './checks/i18n.js';
|
|
10
|
+
import { checkText } from './checks/text.js';
|
|
11
|
+
import { init } from './init/init.js';
|
|
12
|
+
import { findKitConfig, KitConfigError, loadKitConfig } from './kitConfig.js';
|
|
13
|
+
const USAGE = `Usage: config-presets <command> [options]
|
|
14
|
+
|
|
15
|
+
init write kit.config.json and the kit's configs into the app, add the scripts
|
|
16
|
+
--yes, -y accept the defaults for every question no flag answers
|
|
17
|
+
--force overwrite files, kit.config.json and scripts the app already has
|
|
18
|
+
--no-install only write files: skip npm install, expo install, Biome and lefthook
|
|
19
|
+
--project-name <name> --features-root <features|src/features> --app-root <dir>
|
|
20
|
+
--i18n <catalog folder|none> --languages <en,it> --dashes <forbid|allow>
|
|
21
|
+
check-text [files] no em or en dash in any file (--message <file> for a commit message,
|
|
22
|
+
--fix to replace them with hyphens)
|
|
23
|
+
check-i18n catalog parity: keys, plural pairs, placeholders, copy outside the catalog
|
|
24
|
+
check-unused-keys every catalog key is read somewhere
|
|
25
|
+
check-hooks no hook or memoised component holding a stale language
|
|
26
|
+
check-deps dependency-cruiser architecture rules (--config <file>)
|
|
27
|
+
`;
|
|
28
|
+
const out = (line) => process.stdout.write(`${line}\n`);
|
|
29
|
+
const err = (line) => process.stderr.write(`${line}\n`);
|
|
30
|
+
/** The package folder: `dist/cli.js` sits one level below it. */
|
|
31
|
+
const packageRoot = () => dirname(dirname(fileURLToPath(import.meta.url)));
|
|
32
|
+
function context() {
|
|
33
|
+
const file = findKitConfig();
|
|
34
|
+
if (!file)
|
|
35
|
+
throw new KitConfigError(`No kit.config.json in ${process.cwd()} or above it. Run config-presets init.`);
|
|
36
|
+
return { rootDir: dirname(file), config: loadKitConfig({ path: file }) };
|
|
37
|
+
}
|
|
38
|
+
function print(result) {
|
|
39
|
+
const lines = result.problems.slice(0, 50).map(problem => ` ${problem}`);
|
|
40
|
+
if (result.problems.length > 50)
|
|
41
|
+
lines.push(` ... and ${result.problems.length - 50} more`);
|
|
42
|
+
(result.ok ? out : err)([result.summary, ...lines].join('\n'));
|
|
43
|
+
return result.ok ? 0 : 1;
|
|
44
|
+
}
|
|
45
|
+
async function ask(question, fallback) {
|
|
46
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
47
|
+
try {
|
|
48
|
+
return await rl.question(`${question} [${fallback}]: `);
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
rl.close();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async function main(argv) {
|
|
55
|
+
const [command, ...rest] = argv;
|
|
56
|
+
switch (command) {
|
|
57
|
+
case 'init': {
|
|
58
|
+
const { values } = parseArgs({
|
|
59
|
+
args: [...rest],
|
|
60
|
+
options: {
|
|
61
|
+
yes: { type: 'boolean', short: 'y', default: false },
|
|
62
|
+
force: { type: 'boolean', default: false },
|
|
63
|
+
install: { type: 'boolean', default: true },
|
|
64
|
+
'project-name': { type: 'string' },
|
|
65
|
+
'features-root': { type: 'string' },
|
|
66
|
+
'app-root': { type: 'string' },
|
|
67
|
+
i18n: { type: 'string' },
|
|
68
|
+
languages: { type: 'string' },
|
|
69
|
+
dashes: { type: 'string' },
|
|
70
|
+
},
|
|
71
|
+
allowNegative: true,
|
|
72
|
+
});
|
|
73
|
+
return init({
|
|
74
|
+
cwd: process.cwd(),
|
|
75
|
+
packageRoot: packageRoot(),
|
|
76
|
+
yes: values.yes,
|
|
77
|
+
force: values.force,
|
|
78
|
+
install: values.install,
|
|
79
|
+
flags: {
|
|
80
|
+
...(values['project-name'] !== undefined ? { projectName: values['project-name'] } : {}),
|
|
81
|
+
...(values['features-root'] !== undefined ? { featuresRoot: values['features-root'] } : {}),
|
|
82
|
+
...(values['app-root'] !== undefined ? { appRoot: values['app-root'] } : {}),
|
|
83
|
+
...(values.i18n !== undefined ? { i18n: values.i18n } : {}),
|
|
84
|
+
...(values.languages !== undefined ? { languages: values.languages.split(',') } : {}),
|
|
85
|
+
...(values.dashes !== undefined ? { dashes: values.dashes } : {}),
|
|
86
|
+
},
|
|
87
|
+
...(process.stdin.isTTY ? { ask } : {}),
|
|
88
|
+
write: out,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
case 'check-text': {
|
|
92
|
+
const { values, positionals } = parseArgs({
|
|
93
|
+
args: [...rest],
|
|
94
|
+
options: { message: { type: 'string' }, fix: { type: 'boolean', default: false } },
|
|
95
|
+
allowPositionals: true,
|
|
96
|
+
});
|
|
97
|
+
const { rootDir, config } = context();
|
|
98
|
+
if (values.message !== undefined) {
|
|
99
|
+
return print(checkText({ rootDir, config, message: readFileSync(values.message, 'utf8') }));
|
|
100
|
+
}
|
|
101
|
+
return print(checkText({ rootDir, config, fix: values.fix, ...(positionals.length > 0 ? { files: positionals } : {}) }));
|
|
102
|
+
}
|
|
103
|
+
case 'check-i18n':
|
|
104
|
+
return print(await checkI18n(context()));
|
|
105
|
+
case 'check-unused-keys':
|
|
106
|
+
return print(await checkUnusedKeys(context()));
|
|
107
|
+
case 'check-hooks':
|
|
108
|
+
return print(checkHooks(context()));
|
|
109
|
+
case 'check-deps': {
|
|
110
|
+
const { values } = parseArgs({ args: [...rest], options: { config: { type: 'string' } } });
|
|
111
|
+
return runDepsCheck({ ...context(), ...(values.config !== undefined ? { configFile: values.config } : {}) }, out);
|
|
112
|
+
}
|
|
113
|
+
case undefined:
|
|
114
|
+
case '--help':
|
|
115
|
+
case '-h':
|
|
116
|
+
out(USAGE);
|
|
117
|
+
return command === undefined ? 1 : 0;
|
|
118
|
+
default:
|
|
119
|
+
err(`Unknown command "${command}".\n\n${USAGE}`);
|
|
120
|
+
return 1;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
main(process.argv.slice(2)).then(code => {
|
|
124
|
+
process.exitCode = code;
|
|
125
|
+
}, (error) => {
|
|
126
|
+
err(error instanceof Error ? error.message : String(error));
|
|
127
|
+
process.exitCode = 1;
|
|
128
|
+
});
|
|
129
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE9E,MAAM,KAAK,GAAG;;;;;;;;;;;;;;CAcb,CAAC;AAEF,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;AAChE,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;AAEhE,iEAAiE;AACjE,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAE3E,SAAS,OAAO;IACd,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,cAAc,CAAC,yBAAyB,OAAO,CAAC,GAAG,EAAE,wCAAwC,CAAC,CAAC;IACpH,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAC3E,CAAC;AAED,SAAS,KAAK,CAAC,MAAmB;IAChC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;IAC1E,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,EAAE,OAAO,CAAC,CAAC;IAC7F,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/D,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED,KAAK,UAAU,GAAG,CAAC,QAAgB,EAAE,QAAgB;IACnD,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7E,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,KAAK,QAAQ,KAAK,CAAC,CAAC;IAC1D,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI,CAAC,IAAuB;IACzC,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAChC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;gBAC3B,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;gBACf,OAAO,EAAE;oBACP,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE;oBACpD,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;oBAC1C,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE;oBAC3C,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBAClC,eAAe,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACnC,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBAC9B,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACxB,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBAC7B,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;iBAC3B;gBACD,aAAa,EAAE,IAAI;aACpB,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;gBACV,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;gBAClB,WAAW,EAAE,WAAW,EAAE;gBAC1B,GAAG,EAAE,MAAM,CAAC,GAAG;gBACf,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,KAAK,EAAE;oBACL,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACxF,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC3F,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC5E,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC3D,GAAG,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACrF,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAClE;gBACD,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvC,KAAK,EAAE,GAAG;aACX,CAAC,CAAC;QACL,CAAC;QACD,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC;gBACxC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;gBACf,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;gBAClF,gBAAgB,EAAE,IAAI;aACvB,CAAC,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC;YACtC,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBACjC,OAAO,KAAK,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;YAC9F,CAAC;YACD,OAAO,KAAK,CACV,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAC3G,CAAC;QACJ,CAAC;QACD,KAAK,YAAY;YACf,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC3C,KAAK,mBAAmB;YACtB,OAAO,KAAK,CAAC,MAAM,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACjD,KAAK,aAAa;YAChB,OAAO,KAAK,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACtC,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;YAC3F,OAAO,YAAY,CAAC,EAAE,GAAG,OAAO,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACpH,CAAC;QACD,KAAK,SAAS,CAAC;QACf,KAAK,QAAQ,CAAC;QACd,KAAK,IAAI;YACP,GAAG,CAAC,KAAK,CAAC,CAAC;YACX,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC;YACE,GAAG,CAAC,oBAAoB,OAAO,SAAS,KAAK,EAAE,CAAC,CAAC;YACjD,OAAO,CAAC,CAAC;IACb,CAAC;AACH,CAAC;AAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC9B,IAAI,CAAC,EAAE;IACL,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC1B,CAAC,EACD,CAAC,KAAc,EAAE,EAAE;IACjB,GAAG,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CACF,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { type DepsCheckOptions, planDepsCheck, runDepsCheck } from './checks/deps.js';
|
|
2
|
+
export type { CheckResult } from './checks/files.js';
|
|
3
|
+
export { checkHooks } from './checks/hooks.js';
|
|
4
|
+
export { type CatalogCheckOptions, checkI18n, checkUnusedKeys, type I18nKitConfig } from './checks/i18n.js';
|
|
5
|
+
export { checkText, type TextCheckOptions } from './checks/text.js';
|
|
6
|
+
export { type InitFlags, type InitOptions, init } from './init/init.js';
|
|
7
|
+
export { findKitConfig, KIT_CONFIG_FILE, type KitConfig, KitConfigError, type LoadKitConfigOptions, loadKitConfig, parseKitConfig, type QaTarget, } from './kitConfig.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACtF,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,KAAK,mBAAmB,EAAE,SAAS,EAAE,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC5G,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EACL,aAAa,EACb,eAAe,EACf,KAAK,SAAS,EACd,cAAc,EACd,KAAK,oBAAoB,EACzB,aAAa,EACb,cAAc,EACd,KAAK,QAAQ,GACd,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { planDepsCheck, runDepsCheck } from './checks/deps.js';
|
|
2
|
+
export { checkHooks } from './checks/hooks.js';
|
|
3
|
+
export { checkI18n, checkUnusedKeys } from './checks/i18n.js';
|
|
4
|
+
export { checkText } from './checks/text.js';
|
|
5
|
+
export { init } from './init/init.js';
|
|
6
|
+
export { findKitConfig, KIT_CONFIG_FILE, KitConfigError, loadKitConfig, parseKitConfig, } from './kitConfig.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEtF,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAA4B,SAAS,EAAE,eAAe,EAAsB,MAAM,kBAAkB,CAAC;AAC5G,OAAO,EAAE,SAAS,EAAyB,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAoC,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EACL,aAAa,EACb,eAAe,EAEf,cAAc,EAEd,aAAa,EACb,cAAc,GAEf,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** The slice of `.claude/settings.json` that `init` merges. Other fields are kept as they are. */
|
|
2
|
+
export interface ClaudeSettings {
|
|
3
|
+
permissions?: {
|
|
4
|
+
allow?: string[];
|
|
5
|
+
deny?: string[];
|
|
6
|
+
ask?: string[];
|
|
7
|
+
[field: string]: unknown;
|
|
8
|
+
};
|
|
9
|
+
extraKnownMarketplaces?: Record<string, unknown>;
|
|
10
|
+
enabledPlugins?: Record<string, boolean>;
|
|
11
|
+
[field: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Adds the template's permissions, marketplace and plugin to an app's existing settings. Nothing
|
|
15
|
+
* the app already has is removed or overridden: permission lists are unions, and a marketplace or
|
|
16
|
+
* plugin entry the app already names is kept as it is.
|
|
17
|
+
*/
|
|
18
|
+
export declare function mergeClaudeSettings(current: ClaudeSettings, template: ClaudeSettings): ClaudeSettings;
|
|
19
|
+
//# sourceMappingURL=claudeSettings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudeSettings.d.ts","sourceRoot":"","sources":["../../src/init/claudeSettings.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAC9F,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAMD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,cAAc,GAAG,cAAc,CAYrG"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const union = (current, extra) => [
|
|
2
|
+
...new Set([...(current ?? []), ...(extra ?? [])]),
|
|
3
|
+
];
|
|
4
|
+
/**
|
|
5
|
+
* Adds the template's permissions, marketplace and plugin to an app's existing settings. Nothing
|
|
6
|
+
* the app already has is removed or overridden: permission lists are unions, and a marketplace or
|
|
7
|
+
* plugin entry the app already names is kept as it is.
|
|
8
|
+
*/
|
|
9
|
+
export function mergeClaudeSettings(current, template) {
|
|
10
|
+
const permissions = { ...(current.permissions ?? {}) };
|
|
11
|
+
for (const list of ['allow', 'deny']) {
|
|
12
|
+
const merged = union(current.permissions?.[list], template.permissions?.[list]);
|
|
13
|
+
if (merged.length > 0)
|
|
14
|
+
permissions[list] = merged;
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
...current,
|
|
18
|
+
extraKnownMarketplaces: { ...(template.extraKnownMarketplaces ?? {}), ...(current.extraKnownMarketplaces ?? {}) },
|
|
19
|
+
enabledPlugins: { ...(template.enabledPlugins ?? {}), ...(current.enabledPlugins ?? {}) },
|
|
20
|
+
permissions,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=claudeSettings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudeSettings.js","sourceRoot":"","sources":["../../src/init/claudeSettings.ts"],"names":[],"mappings":"AAQA,MAAM,KAAK,GAAG,CAAC,OAAsC,EAAE,KAAoC,EAAE,EAAE,CAAC;IAC9F,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;CACnD,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAuB,EAAE,QAAwB;IACnF,MAAM,WAAW,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,CAAC;IACvD,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,MAAM,CAAU,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QAChF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;IACpD,CAAC;IACD,OAAO;QACL,GAAG,OAAO;QACV,sBAAsB,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,sBAAsB,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,sBAAsB,IAAI,EAAE,CAAC,EAAE;QACjH,cAAc,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,cAAc,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC,EAAE;QACzF,WAAW;KACZ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** Answers `init` can take as flags instead of prompts. */
|
|
2
|
+
export interface InitFlags {
|
|
3
|
+
readonly projectName?: string;
|
|
4
|
+
readonly featuresRoot?: string;
|
|
5
|
+
readonly appRoot?: string;
|
|
6
|
+
/** Catalog folder; an empty string means no catalog. */
|
|
7
|
+
readonly i18n?: string;
|
|
8
|
+
readonly languages?: readonly string[];
|
|
9
|
+
readonly dashes?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface InitOptions {
|
|
12
|
+
/** The app root, where `package.json` lives. */
|
|
13
|
+
readonly cwd: string;
|
|
14
|
+
/** This package's folder, which holds the templates. */
|
|
15
|
+
readonly packageRoot: string;
|
|
16
|
+
/** Accept the default for every question that no flag answers. */
|
|
17
|
+
readonly yes: boolean;
|
|
18
|
+
/** Overwrite files and scripts the app already has. */
|
|
19
|
+
readonly force: boolean;
|
|
20
|
+
/** Run `npm install`, `npx expo install` for the test packages, Biome and `lefthook install`. */
|
|
21
|
+
readonly install: boolean;
|
|
22
|
+
readonly flags: InitFlags;
|
|
23
|
+
/** Asks one question. Absent when stdin is not a terminal: the defaults are used. */
|
|
24
|
+
readonly ask?: (question: string, fallback: string) => Promise<string>;
|
|
25
|
+
/** Runs a command in `cwd` and returns its exit code. Defaults to `spawnSync` with inherited output. */
|
|
26
|
+
readonly run?: (command: string, args: readonly string[]) => number;
|
|
27
|
+
readonly write: (line: string) => void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Writes the kit's config files into an app, merges its `package.json`, `tsconfig.json` and
|
|
31
|
+
* `.claude/settings.json`, and (unless `install` is false) installs the tools and hooks. Returns
|
|
32
|
+
* the process exit code.
|
|
33
|
+
*/
|
|
34
|
+
export declare function init(options: InitOptions): Promise<number>;
|
|
35
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/init/init.ts"],"names":[],"mappings":"AAUA,2DAA2D;AAC3D,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,gDAAgD;IAChD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,uDAAuD;IACvD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,iGAAiG;IACjG,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,qFAAqF;IACrF,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACvE,wGAAwG;IACxG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,CAAC;IACpE,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAkHD;;;;GAIG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAqLhE"}
|