@reddoorla/maintenance 0.3.0 → 0.5.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/dist/cli/bin.js +143 -6
- package/dist/cli/bin.js.map +1 -1
- package/dist/configs/svelte.d.ts +39 -0
- package/dist/configs/svelte.js +30 -0
- package/dist/configs/svelte.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +143 -6
- package/dist/index.js.map +1 -1
- package/dist/recipes/sync-configs.d.ts +1 -1
- package/dist/recipes/sync-configs.js +143 -6
- package/dist/recipes/sync-configs.js.map +1 -1
- package/dist/{sync-configs-D_Dm-68_.d.ts → sync-configs-CW3nKS_N.d.ts} +1 -1
- package/dist/util/git.d.ts +3 -1
- package/dist/util/git.js +10 -0
- package/dist/util/git.js.map +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal shape we touch — the full type lives in @sveltejs/kit's `Config`.
|
|
3
|
+
* We don't import it directly to avoid a peer dependency for what amounts
|
|
4
|
+
* to a small config helper. Sites get full type-checking from their own
|
|
5
|
+
* `@sveltejs/kit` install when they invoke createSvelteConfig.
|
|
6
|
+
*/
|
|
7
|
+
type WarningFilter = (warning: {
|
|
8
|
+
code?: string;
|
|
9
|
+
message?: string;
|
|
10
|
+
}) => boolean;
|
|
11
|
+
type SvelteConfigLike = {
|
|
12
|
+
kit?: unknown;
|
|
13
|
+
preprocess?: unknown;
|
|
14
|
+
compilerOptions?: {
|
|
15
|
+
warningFilter?: WarningFilter;
|
|
16
|
+
[k: string]: unknown;
|
|
17
|
+
};
|
|
18
|
+
[k: string]: unknown;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Compose a Svelte/Kit config with reddoor's canonical compilerOptions
|
|
22
|
+
* layered in. Sites pass their site-specific bits (`kit.adapter`,
|
|
23
|
+
* `preprocess`, etc.) and get back a complete config with the canonical
|
|
24
|
+
* warning filter applied.
|
|
25
|
+
*
|
|
26
|
+
* If the site supplies its own `compilerOptions.warningFilter`, the filters
|
|
27
|
+
* compose: a warning is shown only when both filters allow it.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* import { createSvelteConfig } from "@reddoorla/maintenance/configs/svelte";
|
|
31
|
+
* import adapter from "@sveltejs/adapter-auto";
|
|
32
|
+
*
|
|
33
|
+
* export default createSvelteConfig({ kit: { adapter: adapter() } });
|
|
34
|
+
*/
|
|
35
|
+
declare function createSvelteConfig(siteConfig?: SvelteConfigLike): SvelteConfigLike & {
|
|
36
|
+
compilerOptions: NonNullable<SvelteConfigLike["compilerOptions"]>;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export { type SvelteConfigLike, createSvelteConfig, createSvelteConfig as default };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/configs/svelte.ts
|
|
2
|
+
var SILENCED_WARNING_CODES = /* @__PURE__ */ new Set([
|
|
3
|
+
// `<div ... />` shorthand is widely used across reddoor codebases; the
|
|
4
|
+
// Svelte 5 strictness change for non-void self-closing tags would flood
|
|
5
|
+
// dev logs with no actionable signal.
|
|
6
|
+
"element_invalid_self_closing_tag"
|
|
7
|
+
]);
|
|
8
|
+
function isSilenced(warning) {
|
|
9
|
+
return warning.code !== void 0 && SILENCED_WARNING_CODES.has(warning.code);
|
|
10
|
+
}
|
|
11
|
+
function createSvelteConfig(siteConfig = {}) {
|
|
12
|
+
const siteCompiler = siteConfig.compilerOptions ?? {};
|
|
13
|
+
const siteFilter = siteCompiler.warningFilter;
|
|
14
|
+
return {
|
|
15
|
+
...siteConfig,
|
|
16
|
+
compilerOptions: {
|
|
17
|
+
...siteCompiler,
|
|
18
|
+
warningFilter: (warning) => {
|
|
19
|
+
if (isSilenced(warning)) return false;
|
|
20
|
+
return siteFilter ? siteFilter(warning) : true;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
var svelte_default = createSvelteConfig;
|
|
26
|
+
export {
|
|
27
|
+
createSvelteConfig,
|
|
28
|
+
svelte_default as default
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=svelte.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/configs/svelte.ts"],"sourcesContent":["/**\n * Minimal shape we touch — the full type lives in @sveltejs/kit's `Config`.\n * We don't import it directly to avoid a peer dependency for what amounts\n * to a small config helper. Sites get full type-checking from their own\n * `@sveltejs/kit` install when they invoke createSvelteConfig.\n */\ntype WarningFilter = (warning: { code?: string; message?: string }) => boolean;\n\nexport type SvelteConfigLike = {\n kit?: unknown;\n preprocess?: unknown;\n compilerOptions?: {\n warningFilter?: WarningFilter;\n [k: string]: unknown;\n };\n [k: string]: unknown;\n};\n\n/** Compiler-level warnings the canonical reddoor stack treats as noise. */\nconst SILENCED_WARNING_CODES = new Set<string>([\n // `<div ... />` shorthand is widely used across reddoor codebases; the\n // Svelte 5 strictness change for non-void self-closing tags would flood\n // dev logs with no actionable signal.\n \"element_invalid_self_closing_tag\",\n]);\n\nfunction isSilenced(warning: { code?: string }): boolean {\n return warning.code !== undefined && SILENCED_WARNING_CODES.has(warning.code);\n}\n\n/**\n * Compose a Svelte/Kit config with reddoor's canonical compilerOptions\n * layered in. Sites pass their site-specific bits (`kit.adapter`,\n * `preprocess`, etc.) and get back a complete config with the canonical\n * warning filter applied.\n *\n * If the site supplies its own `compilerOptions.warningFilter`, the filters\n * compose: a warning is shown only when both filters allow it.\n *\n * @example\n * import { createSvelteConfig } from \"@reddoorla/maintenance/configs/svelte\";\n * import adapter from \"@sveltejs/adapter-auto\";\n *\n * export default createSvelteConfig({ kit: { adapter: adapter() } });\n */\nexport function createSvelteConfig(siteConfig: SvelteConfigLike = {}): SvelteConfigLike & {\n compilerOptions: NonNullable<SvelteConfigLike[\"compilerOptions\"]>;\n} {\n const siteCompiler = siteConfig.compilerOptions ?? {};\n const siteFilter = siteCompiler.warningFilter;\n\n return {\n ...siteConfig,\n compilerOptions: {\n ...siteCompiler,\n warningFilter: (warning) => {\n if (isSilenced(warning)) return false;\n return siteFilter ? siteFilter(warning) : true;\n },\n },\n };\n}\n\nexport default createSvelteConfig;\n"],"mappings":";AAmBA,IAAM,yBAAyB,oBAAI,IAAY;AAAA;AAAA;AAAA;AAAA,EAI7C;AACF,CAAC;AAED,SAAS,WAAW,SAAqC;AACvD,SAAO,QAAQ,SAAS,UAAa,uBAAuB,IAAI,QAAQ,IAAI;AAC9E;AAiBO,SAAS,mBAAmB,aAA+B,CAAC,GAEjE;AACA,QAAM,eAAe,WAAW,mBAAmB,CAAC;AACpD,QAAM,aAAa,aAAa;AAEhC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,iBAAiB;AAAA,MACf,GAAG;AAAA,MACH,eAAe,CAAC,YAAY;AAC1B,YAAI,WAAW,OAAO,EAAG,QAAO;AAChC,eAAO,aAAa,WAAW,OAAO,IAAI;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,iBAAQ;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as Site, a as AuditResult, A as AuditName, b as RecipeResult, R as RecipeName, I as InventoryProvider } from './sync-configs-
|
|
2
|
-
export { C as ConfigName, c as SyncConfigsOptions, s as syncConfigs } from './sync-configs-
|
|
1
|
+
import { S as Site, a as AuditResult, A as AuditName, b as RecipeResult, R as RecipeName, I as InventoryProvider } from './sync-configs-CW3nKS_N.js';
|
|
2
|
+
export { C as ConfigName, c as SyncConfigsOptions, s as syncConfigs } from './sync-configs-CW3nKS_N.js';
|
|
3
3
|
|
|
4
4
|
type SpawnResult = {
|
|
5
5
|
code: number;
|
package/dist/index.js
CHANGED
|
@@ -702,11 +702,116 @@ var playwrightA11y = {
|
|
|
702
702
|
contents: `export { default } from "@reddoorla/maintenance/configs/playwright-a11y";
|
|
703
703
|
`
|
|
704
704
|
};
|
|
705
|
-
var
|
|
705
|
+
var svelte = {
|
|
706
|
+
config: "svelte",
|
|
707
|
+
path: "svelte.config.js",
|
|
708
|
+
contents: `import { createSvelteConfig } from "@reddoorla/maintenance/configs/svelte";
|
|
709
|
+
import adapter from "@sveltejs/adapter-auto";
|
|
710
|
+
|
|
711
|
+
/** @type {import('@sveltejs/kit').Config} */
|
|
712
|
+
export default createSvelteConfig({
|
|
713
|
+
kit: { adapter: adapter() },
|
|
714
|
+
});
|
|
715
|
+
`
|
|
716
|
+
};
|
|
717
|
+
var ALL_TEMPLATES = [
|
|
718
|
+
eslint,
|
|
719
|
+
prettier,
|
|
720
|
+
lighthouse,
|
|
721
|
+
playwrightA11y,
|
|
722
|
+
svelte
|
|
723
|
+
];
|
|
706
724
|
function templatesByName(which) {
|
|
707
725
|
return ALL_TEMPLATES.filter((t) => which.includes(t.config));
|
|
708
726
|
}
|
|
709
727
|
|
|
728
|
+
// src/recipes/sync-configs/gitignore.ts
|
|
729
|
+
var MANAGED_MARKER = "# canonical entries from @reddoorla/maintenance sync-configs";
|
|
730
|
+
var CANONICAL_GITIGNORE_ENTRIES = [
|
|
731
|
+
"node_modules/",
|
|
732
|
+
"build/",
|
|
733
|
+
"dist/",
|
|
734
|
+
".svelte-kit/",
|
|
735
|
+
"coverage/",
|
|
736
|
+
".vitest-cache/",
|
|
737
|
+
"playwright-report/",
|
|
738
|
+
"test-results/",
|
|
739
|
+
".lighthouseci/",
|
|
740
|
+
".tsbuildinfo",
|
|
741
|
+
".env",
|
|
742
|
+
".env.*",
|
|
743
|
+
"!.env.example",
|
|
744
|
+
".DS_Store",
|
|
745
|
+
"*.log",
|
|
746
|
+
".vercel/",
|
|
747
|
+
".netlify/"
|
|
748
|
+
];
|
|
749
|
+
function stripLeadingSlash(s) {
|
|
750
|
+
return s.startsWith("/") ? s.slice(1) : s;
|
|
751
|
+
}
|
|
752
|
+
function stripTrailingSlash(s) {
|
|
753
|
+
return s.endsWith("/") ? s.slice(0, -1) : s;
|
|
754
|
+
}
|
|
755
|
+
function normalizePresence(line) {
|
|
756
|
+
return stripTrailingSlash(stripLeadingSlash(line.trim()));
|
|
757
|
+
}
|
|
758
|
+
function presentSet(existing) {
|
|
759
|
+
const set = /* @__PURE__ */ new Set();
|
|
760
|
+
for (const raw of existing.split(/\r?\n/)) {
|
|
761
|
+
const trimmed = raw.trim();
|
|
762
|
+
if (!trimmed) continue;
|
|
763
|
+
if (trimmed.startsWith("#")) continue;
|
|
764
|
+
set.add(normalizePresence(trimmed));
|
|
765
|
+
}
|
|
766
|
+
return set;
|
|
767
|
+
}
|
|
768
|
+
function mergeGitignore(existing, canonical) {
|
|
769
|
+
if (existing === null) {
|
|
770
|
+
const body = [MANAGED_MARKER, ...canonical].join("\n") + "\n";
|
|
771
|
+
return { content: body, added: [...canonical] };
|
|
772
|
+
}
|
|
773
|
+
const present = presentSet(existing);
|
|
774
|
+
const added = [];
|
|
775
|
+
for (const entry of canonical) {
|
|
776
|
+
const norm = normalizePresence(entry);
|
|
777
|
+
if (!present.has(norm)) {
|
|
778
|
+
added.push(entry);
|
|
779
|
+
present.add(norm);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
if (added.length === 0) {
|
|
783
|
+
return { content: existing, added: [] };
|
|
784
|
+
}
|
|
785
|
+
let base = existing;
|
|
786
|
+
if (!base.endsWith("\n")) base += "\n";
|
|
787
|
+
const block = ["", MANAGED_MARKER, ...added].join("\n") + "\n";
|
|
788
|
+
return { content: base + block, added };
|
|
789
|
+
}
|
|
790
|
+
function findTrackedArtifacts(tracked, canonical) {
|
|
791
|
+
const dirEntries = [];
|
|
792
|
+
for (const raw of canonical) {
|
|
793
|
+
const t = raw.trim();
|
|
794
|
+
if (!t) continue;
|
|
795
|
+
if (t.startsWith("!")) continue;
|
|
796
|
+
if (/[*?[]/.test(t)) continue;
|
|
797
|
+
const noLead = stripLeadingSlash(t);
|
|
798
|
+
if (!noLead.endsWith("/")) continue;
|
|
799
|
+
const name = stripTrailingSlash(noLead);
|
|
800
|
+
if (!name) continue;
|
|
801
|
+
dirEntries.push(name);
|
|
802
|
+
}
|
|
803
|
+
const matched = [];
|
|
804
|
+
for (const path of tracked) {
|
|
805
|
+
for (const dir of dirEntries) {
|
|
806
|
+
if (path === dir || path.startsWith(dir + "/")) {
|
|
807
|
+
matched.push(path);
|
|
808
|
+
break;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
return matched;
|
|
813
|
+
}
|
|
814
|
+
|
|
710
815
|
// src/util/git.ts
|
|
711
816
|
import { execFile } from "child_process";
|
|
712
817
|
import { promisify } from "util";
|
|
@@ -729,6 +834,14 @@ async function createBranch(cwd, name) {
|
|
|
729
834
|
async function stageAll(cwd) {
|
|
730
835
|
await git(cwd, ["add", "-A"]);
|
|
731
836
|
}
|
|
837
|
+
async function listTrackedFiles(cwd) {
|
|
838
|
+
const { stdout } = await git(cwd, ["ls-files"]);
|
|
839
|
+
return stdout.split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
|
|
840
|
+
}
|
|
841
|
+
async function removeFromIndex(cwd, paths) {
|
|
842
|
+
if (paths.length === 0) return;
|
|
843
|
+
await git(cwd, ["rm", "-r", "--cached", "--", ...paths]);
|
|
844
|
+
}
|
|
732
845
|
async function commit(cwd, message) {
|
|
733
846
|
await stageAll(cwd);
|
|
734
847
|
const { stdout: status } = await git(cwd, ["status", "--porcelain"]);
|
|
@@ -739,6 +852,7 @@ async function commit(cwd, message) {
|
|
|
739
852
|
}
|
|
740
853
|
|
|
741
854
|
// src/recipes/sync-configs.ts
|
|
855
|
+
var GITIGNORE_CONFIG = "gitignore";
|
|
742
856
|
function siteLabel6(site) {
|
|
743
857
|
return site.name ?? site.path;
|
|
744
858
|
}
|
|
@@ -749,7 +863,7 @@ async function readMaybe(path) {
|
|
|
749
863
|
return null;
|
|
750
864
|
}
|
|
751
865
|
}
|
|
752
|
-
async function
|
|
866
|
+
async function planTemplateDiffs(cwd, templates) {
|
|
753
867
|
const diffs = [];
|
|
754
868
|
for (const t of templates) {
|
|
755
869
|
const existing = await readMaybe(join5(cwd, t.path));
|
|
@@ -757,11 +871,29 @@ async function planDiffs(cwd, templates) {
|
|
|
757
871
|
}
|
|
758
872
|
return diffs;
|
|
759
873
|
}
|
|
874
|
+
async function planGitignore(cwd) {
|
|
875
|
+
const existing = await readMaybe(join5(cwd, ".gitignore"));
|
|
876
|
+
const merge = mergeGitignore(existing, CANONICAL_GITIGNORE_ENTRIES);
|
|
877
|
+
const tracked = await listTrackedFiles(cwd);
|
|
878
|
+
const toUntrack = findTrackedArtifacts(tracked, CANONICAL_GITIGNORE_ENTRIES);
|
|
879
|
+
if (merge.added.length === 0 && toUntrack.length === 0) return { kind: "noop" };
|
|
880
|
+
return { kind: "apply", content: merge.content, toUntrack, added: merge.added };
|
|
881
|
+
}
|
|
882
|
+
async function applyGitignore(cwd, plan) {
|
|
883
|
+
await writeFile3(join5(cwd, ".gitignore"), plan.content, "utf-8");
|
|
884
|
+
if (plan.toUntrack.length > 0) {
|
|
885
|
+
await removeFromIndex(cwd, plan.toUntrack);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
760
888
|
async function syncConfigs(site, opts = {}) {
|
|
761
889
|
const label = siteLabel6(site);
|
|
762
|
-
const
|
|
763
|
-
const
|
|
764
|
-
|
|
890
|
+
const requested = opts.which ?? ALL_TEMPLATES.map((t) => t.config).concat(GITIGNORE_CONFIG);
|
|
891
|
+
const templateNames = requested.filter((c) => c !== GITIGNORE_CONFIG);
|
|
892
|
+
const templates = templatesByName(templateNames);
|
|
893
|
+
const includeGitignore = requested.includes(GITIGNORE_CONFIG);
|
|
894
|
+
const templateDiffs = await planTemplateDiffs(site.path, templates);
|
|
895
|
+
const gitignorePlan = includeGitignore ? await planGitignore(site.path) : { kind: "noop" };
|
|
896
|
+
if (templateDiffs.length === 0 && gitignorePlan.kind === "noop") {
|
|
765
897
|
return {
|
|
766
898
|
recipe: "sync-configs",
|
|
767
899
|
site: label,
|
|
@@ -776,7 +908,7 @@ async function syncConfigs(site, opts = {}) {
|
|
|
776
908
|
const branch = branchName("sync-configs");
|
|
777
909
|
await createBranch(site.path, branch);
|
|
778
910
|
const shas = [];
|
|
779
|
-
for (const t of
|
|
911
|
+
for (const t of templateDiffs) {
|
|
780
912
|
await writeFile3(join5(site.path, t.path), t.contents, "utf-8");
|
|
781
913
|
const sha = await commit(
|
|
782
914
|
site.path,
|
|
@@ -784,6 +916,11 @@ async function syncConfigs(site, opts = {}) {
|
|
|
784
916
|
);
|
|
785
917
|
if (sha) shas.push(sha);
|
|
786
918
|
}
|
|
919
|
+
if (gitignorePlan.kind === "apply") {
|
|
920
|
+
await applyGitignore(site.path, gitignorePlan);
|
|
921
|
+
const sha = await commit(site.path, `chore: sync gitignore from @reddoorla/maintenance`);
|
|
922
|
+
if (sha) shas.push(sha);
|
|
923
|
+
}
|
|
787
924
|
return {
|
|
788
925
|
recipe: "sync-configs",
|
|
789
926
|
site: label,
|