@regardio/dev 1.24.0 → 2.0.2

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 (128) hide show
  1. package/README.md +2 -2
  2. package/dist/bin/ship/hotfix.bin.mjs +140 -0
  3. package/dist/bin/ship/production.bin.mjs +120 -0
  4. package/dist/bin/ship/staging.bin.mjs +70 -0
  5. package/dist/bin/ship/utils-BQ-JZ2D5.mjs +45 -0
  6. package/dist/playwright/index.d.mts +24 -0
  7. package/dist/playwright/index.mjs +61 -0
  8. package/dist/vitest/node.d.mts +22 -0
  9. package/dist/vitest/node.mjs +28 -0
  10. package/dist/vitest/react.d.mts +22 -0
  11. package/dist/vitest/react.mjs +28 -0
  12. package/docs/en/README.md +95 -0
  13. package/docs/en/agents.md +57 -0
  14. package/docs/en/standards/api.md +324 -0
  15. package/docs/en/standards/coding.md +144 -0
  16. package/docs/en/standards/commits.md +111 -0
  17. package/docs/en/standards/documentation.md +173 -0
  18. package/docs/en/standards/naming.md +180 -0
  19. package/docs/en/standards/principles.md +84 -0
  20. package/docs/en/standards/react.md +246 -0
  21. package/docs/en/standards/sql.md +258 -0
  22. package/docs/en/standards/testing.md +139 -0
  23. package/docs/en/standards/writing.md +119 -0
  24. package/docs/en/tools/biome.md +89 -0
  25. package/docs/en/tools/commitlint.md +92 -0
  26. package/docs/en/tools/dependencies.md +116 -0
  27. package/docs/en/tools/husky.md +90 -0
  28. package/docs/en/tools/markdownlint.md +84 -0
  29. package/docs/en/tools/playwright.md +117 -0
  30. package/docs/en/tools/releases.md +242 -0
  31. package/docs/en/tools/typescript.md +89 -0
  32. package/docs/en/tools/vitest.md +146 -0
  33. package/package.json +57 -70
  34. package/src/biome/preset.json +3 -0
  35. package/templates/changeset/README.md +14 -0
  36. package/templates/changeset/config.json +11 -0
  37. package/templates/github/release.yml +77 -0
  38. package/dist/bin/exec/clean.d.ts +0 -3
  39. package/dist/bin/exec/clean.d.ts.map +0 -1
  40. package/dist/bin/exec/clean.js +0 -25
  41. package/dist/bin/exec/clean.test.d.ts +0 -2
  42. package/dist/bin/exec/clean.test.d.ts.map +0 -1
  43. package/dist/bin/exec/clean.test.js +0 -45
  44. package/dist/bin/exec/husky.d.ts +0 -3
  45. package/dist/bin/exec/husky.d.ts.map +0 -1
  46. package/dist/bin/exec/husky.js +0 -9
  47. package/dist/bin/exec/p.d.ts +0 -3
  48. package/dist/bin/exec/p.d.ts.map +0 -1
  49. package/dist/bin/exec/p.js +0 -8
  50. package/dist/bin/exec/s.d.ts +0 -3
  51. package/dist/bin/exec/s.d.ts.map +0 -1
  52. package/dist/bin/exec/s.js +0 -8
  53. package/dist/bin/exec/tsc.d.ts +0 -3
  54. package/dist/bin/exec/tsc.d.ts.map +0 -1
  55. package/dist/bin/exec/tsc.js +0 -8
  56. package/dist/bin/lint/biome.d.ts +0 -3
  57. package/dist/bin/lint/biome.d.ts.map +0 -1
  58. package/dist/bin/lint/biome.js +0 -8
  59. package/dist/bin/lint/commit.d.ts +0 -3
  60. package/dist/bin/lint/commit.d.ts.map +0 -1
  61. package/dist/bin/lint/commit.js +0 -8
  62. package/dist/bin/lint/md.d.ts +0 -3
  63. package/dist/bin/lint/md.d.ts.map +0 -1
  64. package/dist/bin/lint/md.js +0 -16
  65. package/dist/bin/lint/package.d.ts +0 -4
  66. package/dist/bin/lint/package.d.ts.map +0 -1
  67. package/dist/bin/lint/package.js +0 -81
  68. package/dist/bin/lint/package.test.d.ts +0 -2
  69. package/dist/bin/lint/package.test.d.ts.map +0 -1
  70. package/dist/bin/lint/package.test.js +0 -65
  71. package/dist/bin/ship/hotfix.d.ts +0 -3
  72. package/dist/bin/ship/hotfix.d.ts.map +0 -1
  73. package/dist/bin/ship/hotfix.js +0 -141
  74. package/dist/bin/ship/production.d.ts +0 -3
  75. package/dist/bin/ship/production.d.ts.map +0 -1
  76. package/dist/bin/ship/production.js +0 -124
  77. package/dist/bin/ship/staging.d.ts +0 -3
  78. package/dist/bin/ship/staging.d.ts.map +0 -1
  79. package/dist/bin/ship/staging.js +0 -51
  80. package/dist/bin/ship/utils.d.ts +0 -9
  81. package/dist/bin/ship/utils.d.ts.map +0 -1
  82. package/dist/bin/ship/utils.js +0 -63
  83. package/dist/bin/ship/utils.test.d.ts +0 -2
  84. package/dist/bin/ship/utils.test.d.ts.map +0 -1
  85. package/dist/bin/ship/utils.test.js +0 -127
  86. package/dist/config.test.d.ts +0 -2
  87. package/dist/config.test.d.ts.map +0 -1
  88. package/dist/config.test.js +0 -101
  89. package/dist/playwright/index.d.ts +0 -10
  90. package/dist/playwright/index.d.ts.map +0 -1
  91. package/dist/playwright/index.js +0 -42
  92. package/dist/playwright/index.test.d.ts +0 -2
  93. package/dist/playwright/index.test.d.ts.map +0 -1
  94. package/dist/playwright/index.test.js +0 -55
  95. package/dist/testing/setup-react.d.ts +0 -2
  96. package/dist/testing/setup-react.d.ts.map +0 -1
  97. package/dist/testing/setup-react.js +0 -1
  98. package/dist/vitest/node.d.ts +0 -22
  99. package/dist/vitest/node.d.ts.map +0 -1
  100. package/dist/vitest/node.js +0 -16
  101. package/dist/vitest/react.d.ts +0 -17
  102. package/dist/vitest/react.d.ts.map +0 -1
  103. package/dist/vitest/react.js +0 -12
  104. package/src/bin/exec/clean.test.ts +0 -63
  105. package/src/bin/exec/clean.ts +0 -36
  106. package/src/bin/exec/husky.ts +0 -14
  107. package/src/bin/exec/p.ts +0 -13
  108. package/src/bin/exec/s.ts +0 -13
  109. package/src/bin/exec/tsc.ts +0 -13
  110. package/src/bin/lint/biome.ts +0 -13
  111. package/src/bin/lint/commit.ts +0 -13
  112. package/src/bin/lint/md.ts +0 -28
  113. package/src/bin/lint/package.test.ts +0 -83
  114. package/src/bin/lint/package.ts +0 -108
  115. package/src/bin/ship/hotfix.ts +0 -241
  116. package/src/bin/ship/production.ts +0 -240
  117. package/src/bin/ship/staging.ts +0 -108
  118. package/src/bin/ship/utils.test.ts +0 -178
  119. package/src/bin/ship/utils.ts +0 -109
  120. package/src/config.test.ts +0 -129
  121. package/src/markdownlint/markdownlint-cli2.jsonc +0 -9
  122. package/src/playwright/index.test.ts +0 -73
  123. package/src/playwright/index.ts +0 -63
  124. package/src/templates/release.yml +0 -128
  125. package/src/testing/setup-react.ts +0 -8
  126. package/src/vitest/node.ts +0 -25
  127. package/src/vitest/react.ts +0 -19
  128. /package/{src → templates}/sqlfluff/setup.cfg +0 -0
package/README.md CHANGED
@@ -27,7 +27,7 @@ The goal is code that's correct, consistent, and a pleasure to work with.
27
27
  | **Testing** | Vitest, Playwright, Testing Library |
28
28
  | **Build** | TypeScript, tsx, Vite |
29
29
  | **Workflow** | Husky, GitLab Flow |
30
- | **CLI utilities** | exec-clean, exec-p, exec-s, exec-tsc, ship-staging, ship-production, ship-hotfix, lint-biome, lint-md, lint-package |
30
+ | **CLI utilities** | `ship-staging`, `ship-production`, `ship-hotfix` |
31
31
 
32
32
  ## Quick Start
33
33
 
@@ -42,7 +42,7 @@ Extend the shared configs in your project:
42
42
  { "extends": ["@regardio/dev/biome"] }
43
43
 
44
44
  // tsconfig.json
45
- { "extends": "@regardio/dev/typescript/base.json" }
45
+ { "extends": "@regardio/dev/typescript/base" }
46
46
  ```
47
47
 
48
48
  ## Documentation
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env node
2
+ import { a as runQualityChecks, i as gitRead, o as runScript, r as git, t as branchExists } from "./utils-BQ-JZ2D5.mjs";
3
+ import { execFileSync, execSync } from "node:child_process";
4
+ import { existsSync, readFileSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ //#region src/bin/ship/hotfix.ts
7
+ /**
8
+ * ship-hotfix: Manage hotfix branches based on production code.
9
+ *
10
+ * Usage:
11
+ * ship-hotfix start <name> - Create hotfix/<name> from production
12
+ * ship-hotfix finish - Finish and propagate the hotfix
13
+ *
14
+ * GitLab workflow:
15
+ * production → hotfix/<name> → production → staging → main
16
+ *
17
+ * During a hotfix, add a changeset (`pnpm changeset`) describing the fix.
18
+ * `ship-hotfix finish` consumes all pending changesets, commits the version
19
+ * bumps, and propagates the hotfix through production → staging → main.
20
+ * CI on `production` handles the `changeset publish` to npm.
21
+ */
22
+ function runShipHotfix(subcommand, subArgs, cwd = process.cwd()) {
23
+ if (subcommand === "start") {
24
+ const name = subArgs[0];
25
+ if (!name) {
26
+ console.error("Usage: ship-hotfix start <name>");
27
+ process.exit(1);
28
+ }
29
+ const hotfixBranch = `hotfix/${name}`;
30
+ if (gitRead("status", "--porcelain")) {
31
+ console.error("Working directory has uncommitted changes. Commit or stash them first.");
32
+ process.exit(1);
33
+ }
34
+ console.log("\nFetching latest state from origin...");
35
+ git("fetch", "origin");
36
+ if (!branchExists("production")) {
37
+ console.error("Branch \"production\" does not exist. Create it first:\n git checkout -b production && git push -u origin production");
38
+ process.exit(1);
39
+ }
40
+ git("checkout", "production");
41
+ git("pull", "--ff-only", "origin", "production");
42
+ git("checkout", "-b", hotfixBranch);
43
+ console.log(`\n✅ Hotfix branch "${hotfixBranch}" created from production.`);
44
+ console.log("Apply your fix, add a changeset (`pnpm changeset`), commit, then run:");
45
+ console.log(" ship-hotfix finish");
46
+ process.exit(0);
47
+ }
48
+ if (subcommand === "finish") {
49
+ const currentBranch = gitRead("branch", "--show-current");
50
+ if (!currentBranch.startsWith("hotfix/")) {
51
+ console.error(`Must be on a hotfix/* branch. Currently on: ${currentBranch}`);
52
+ process.exit(1);
53
+ }
54
+ if (gitRead("status", "--porcelain")) {
55
+ console.error("Working directory has uncommitted changes. Commit or stash them first.");
56
+ process.exit(1);
57
+ }
58
+ if (!existsSync(join(cwd, ".changeset"))) {
59
+ console.error("\nNo .changeset/ directory found. This tooling requires Changesets.\nCopy the template from @regardio/dev/templates/changeset and run:\n pnpm changeset init");
60
+ process.exit(1);
61
+ }
62
+ if (execFileSync("sh", ["-c", `ls .changeset/*.md 2>/dev/null | grep -v README.md | wc -l | tr -d ' '`], { encoding: "utf-8" }).trim() === "0") {
63
+ console.error("\nNo pending changesets. Run `pnpm changeset` before finishing the hotfix.");
64
+ process.exit(1);
65
+ }
66
+ console.log("\nRunning quality checks...");
67
+ try {
68
+ runQualityChecks();
69
+ } catch {
70
+ console.error("\nQuality checks failed. Fix all issues before finishing the hotfix.");
71
+ process.exit(1);
72
+ }
73
+ console.log("✅ Quality checks passed");
74
+ const packageJsonPath = join(cwd, "package.json");
75
+ if (!existsSync(packageJsonPath)) {
76
+ console.error("No package.json found in current directory.");
77
+ process.exit(1);
78
+ }
79
+ const { name: packageName } = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
80
+ console.log("\nApplying changesets (bumping versions and updating CHANGELOGs)...");
81
+ runScript("changeset version");
82
+ try {
83
+ runScript("fix:pkg");
84
+ } catch {}
85
+ try {
86
+ git("add", "-A");
87
+ const changedFiles = gitRead("diff", "--cached", "--name-only").split("\n").filter(Boolean);
88
+ for (const file of changedFiles) {
89
+ if (file.endsWith(".json")) try {
90
+ execSync(`npx biome check --write ${file}`, {
91
+ cwd,
92
+ stdio: "inherit"
93
+ });
94
+ } catch {}
95
+ if (file.endsWith(".md")) try {
96
+ execSync(`npx markdownlint-cli2 --fix ${file}`, {
97
+ cwd,
98
+ stdio: "inherit"
99
+ });
100
+ } catch {}
101
+ }
102
+ } catch {}
103
+ git("add", "-A");
104
+ git("commit", "-m", "chore(hotfix): version packages");
105
+ console.log("\nFetching latest state from origin...");
106
+ git("fetch", "origin");
107
+ console.log("\nMerging hotfix into production...");
108
+ git("checkout", "production");
109
+ git("pull", "--ff-only", "origin", "production");
110
+ git("merge", "--no-ff", currentBranch, "-m", `chore(hotfix): merge ${currentBranch} into production`);
111
+ git("push", "origin", "production");
112
+ console.log("\nPropagating hotfix to staging...");
113
+ git("checkout", "staging");
114
+ git("pull", "--ff-only", "origin", "staging");
115
+ git("merge", "--no-ff", "production", "-m", "chore(hotfix): merge production into staging");
116
+ git("push", "origin", "staging");
117
+ console.log("\nPropagating hotfix to main...");
118
+ git("checkout", "main");
119
+ git("pull", "--ff-only", "origin", "main");
120
+ git("merge", "--no-ff", "staging", "-m", "chore(hotfix): merge staging into main");
121
+ git("push", "origin", "main");
122
+ git("branch", "-d", currentBranch);
123
+ try {
124
+ git("push", "origin", "--delete", currentBranch);
125
+ } catch {}
126
+ console.log(`\n✅ Hotfix ${packageName} shipped to production → staging → main`);
127
+ console.log("CI will publish changed packages to npm.");
128
+ console.log("You are on main and ready to keep working.");
129
+ process.exit(0);
130
+ }
131
+ console.error("Usage:");
132
+ console.error(" ship-hotfix start <name>");
133
+ console.error(" ship-hotfix finish");
134
+ process.exit(1);
135
+ }
136
+ //#endregion
137
+ //#region src/bin/ship/hotfix.bin.ts
138
+ runShipHotfix(process.argv[2], process.argv.slice(3));
139
+ //#endregion
140
+ export {};
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env node
2
+ import { a as runQualityChecks, i as gitRead, n as confirm, o as runScript, r as git, t as branchExists } from "./utils-BQ-JZ2D5.mjs";
3
+ import { execFileSync, execSync } from "node:child_process";
4
+ import { existsSync, readFileSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ //#region src/bin/ship/production.ts
7
+ /**
8
+ * ship-production: Promote main to production following the GitLab workflow.
9
+ *
10
+ * Usage: ship-production
11
+ *
12
+ * GitLab workflow:
13
+ * main → (changeset version + commit) → production → staging → main
14
+ *
15
+ * Versioning is driven by Changesets. Authors add a changeset (`pnpm changeset`)
16
+ * alongside their change on main. This script consumes all pending changesets
17
+ * at ship time, commits the version bumps, then merges main → production.
18
+ * CI on `production` handles the actual `changeset publish` to npm.
19
+ */
20
+ function runShipProduction(cwd = process.cwd()) {
21
+ const currentBranch = gitRead("branch", "--show-current");
22
+ if (currentBranch !== "main") {
23
+ console.error(`Must be on the main branch to ship. Currently on: ${currentBranch}`);
24
+ process.exit(1);
25
+ }
26
+ if (gitRead("status", "--porcelain")) {
27
+ console.error("Working directory has uncommitted changes. Commit or stash them first.");
28
+ process.exit(1);
29
+ }
30
+ console.log("\nFetching latest state from origin...");
31
+ git("fetch", "origin");
32
+ if (!branchExists("staging")) {
33
+ console.error("Branch \"staging\" does not exist. Create it first:\n git checkout -b staging && git push -u origin staging");
34
+ process.exit(1);
35
+ }
36
+ if (!branchExists("production")) {
37
+ console.error("Branch \"production\" does not exist. Create it first:\n git checkout -b production && git push -u origin production");
38
+ process.exit(1);
39
+ }
40
+ git("pull", "--ff-only", "origin", "main");
41
+ const ahead = gitRead("log", "origin/production..HEAD", "--oneline");
42
+ if (!ahead) {
43
+ console.error("main is already in sync with production. Nothing to ship.");
44
+ process.exit(1);
45
+ }
46
+ console.log("\nCommits to be shipped to production:");
47
+ console.log(ahead);
48
+ if (!existsSync(join(cwd, ".changeset"))) {
49
+ console.error("\nNo .changeset/ directory found. This tooling requires Changesets.\nCopy the template from @regardio/dev/templates/changeset and run:\n pnpm changeset init");
50
+ process.exit(1);
51
+ }
52
+ const pendingChangesets = execFileSync("sh", ["-c", `ls .changeset/*.md 2>/dev/null | grep -v README.md | wc -l | tr -d ' '`], { encoding: "utf-8" }).trim();
53
+ if (pendingChangesets === "0") {
54
+ console.error("\nNo pending changesets. Run `pnpm changeset` before shipping to production.");
55
+ process.exit(1);
56
+ }
57
+ const packageJsonPath = join(cwd, "package.json");
58
+ if (!existsSync(packageJsonPath)) {
59
+ console.error("No package.json found in current directory.");
60
+ process.exit(1);
61
+ }
62
+ const { name: packageName } = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
63
+ console.log(`\n${pendingChangesets} pending changeset(s) will be consumed.`);
64
+ if (!confirm(`Ship ${packageName} to production?`)) {
65
+ console.log("Aborted.");
66
+ process.exit(0);
67
+ }
68
+ console.log("\nRunning quality checks on main...");
69
+ try {
70
+ runQualityChecks();
71
+ } catch {
72
+ console.error("\nQuality checks failed on main. Fix issues before shipping.");
73
+ process.exit(1);
74
+ }
75
+ console.log("✅ Quality checks passed");
76
+ console.log("\nApplying changesets (bumping versions and updating CHANGELOGs)...");
77
+ runScript("changeset version");
78
+ try {
79
+ runScript("fix:pkg");
80
+ } catch {}
81
+ try {
82
+ git("add", "-A");
83
+ const changedFiles = gitRead("diff", "--cached", "--name-only").split("\n").filter(Boolean);
84
+ for (const file of changedFiles) {
85
+ if (file.endsWith(".json")) try {
86
+ execSync(`npx biome check --write ${file}`, {
87
+ cwd,
88
+ stdio: "inherit"
89
+ });
90
+ } catch {}
91
+ if (file.endsWith(".md")) try {
92
+ execSync(`npx markdownlint-cli2 --fix ${file}`, {
93
+ cwd,
94
+ stdio: "inherit"
95
+ });
96
+ } catch {}
97
+ }
98
+ } catch {}
99
+ git("add", "-A");
100
+ git("commit", "-m", "chore(release): version packages");
101
+ console.log("\nMerging main into production...");
102
+ git("checkout", "production");
103
+ git("pull", "--ff-only", "origin", "production");
104
+ git("merge", "--ff-only", "main");
105
+ git("push", "origin", "production");
106
+ console.log("\nSyncing staging with production...");
107
+ git("checkout", "staging");
108
+ git("pull", "--ff-only", "origin", "staging");
109
+ git("merge", "--ff-only", "production");
110
+ git("push", "origin", "staging");
111
+ git("checkout", "main");
112
+ git("push", "origin", "main");
113
+ console.log(`\n✅ Shipped ${packageName} to production. CI will publish changed packages to npm.`);
114
+ console.log("You are on main and ready to keep working.");
115
+ }
116
+ //#endregion
117
+ //#region src/bin/ship/production.bin.ts
118
+ runShipProduction();
119
+ //#endregion
120
+ export {};
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env node
2
+ import { a as runQualityChecks, i as gitRead, r as git, t as branchExists } from "./utils-BQ-JZ2D5.mjs";
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ //#region src/bin/ship/staging.ts
6
+ /**
7
+ * ship-staging: Deploy changes to staging following the GitLab workflow.
8
+ *
9
+ * Usage: ship-staging
10
+ *
11
+ * GitLab workflow:
12
+ * main → staging (staging deploy, no version bump yet)
13
+ *
14
+ * Optional step: you can ship directly to production via ship-production,
15
+ * which automatically syncs staging afterward. Use ship-staging when you
16
+ * want to validate changes in a staging environment first.
17
+ *
18
+ * Versioning is deferred to ship-production so version numbers only ever
19
+ * correspond to production-verified code.
20
+ */
21
+ function runShipStaging(cwd = process.cwd()) {
22
+ const currentBranch = gitRead("branch", "--show-current");
23
+ if (currentBranch !== "main") {
24
+ console.error(`Must be on the main branch to release. Currently on: ${currentBranch}`);
25
+ process.exit(1);
26
+ }
27
+ if (gitRead("status", "--porcelain")) {
28
+ console.error("Working directory has uncommitted changes. Commit or stash them first.");
29
+ process.exit(1);
30
+ }
31
+ console.log("\nFetching latest state from origin...");
32
+ git("fetch", "origin");
33
+ git("pull", "--ff-only", "origin", "main");
34
+ const packageJsonPath = join(cwd, "package.json");
35
+ if (!existsSync(packageJsonPath)) {
36
+ console.error("No package.json found in current directory.");
37
+ process.exit(1);
38
+ }
39
+ const packageName = JSON.parse(readFileSync(packageJsonPath, "utf-8")).name;
40
+ if (!packageName) {
41
+ console.error("No \"name\" field found in package.json.");
42
+ process.exit(1);
43
+ }
44
+ if (!branchExists("staging")) {
45
+ console.error("Branch \"staging\" does not exist locally or on origin. Create it first:\n git checkout -b staging && git push -u origin staging");
46
+ process.exit(1);
47
+ }
48
+ console.log("\nRunning quality checks...");
49
+ try {
50
+ runQualityChecks();
51
+ } catch {
52
+ console.error("\nQuality checks failed. Fix all issues before releasing.");
53
+ process.exit(1);
54
+ }
55
+ console.log("✅ Quality checks passed");
56
+ console.log("\nMerging main into staging...");
57
+ git("checkout", "staging");
58
+ git("merge", "--ff-only", "main");
59
+ git("push", "origin", "staging");
60
+ git("checkout", "main");
61
+ git("push", "origin", "main");
62
+ console.log(`\n✅ ${packageName} deployed to staging`);
63
+ console.log("Run ship-production when ready to ship to production.");
64
+ console.log("(Or ship directly from main to production without using ship-staging first.)");
65
+ }
66
+ //#endregion
67
+ //#region src/bin/ship/staging.bin.ts
68
+ runShipStaging();
69
+ //#endregion
70
+ export {};
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+ import { execFileSync, execSync } from "node:child_process";
3
+ import { closeSync, openSync, readSync } from "node:fs";
4
+ //#region src/bin/ship/utils.ts
5
+ /**
6
+ * Shared utilities for ship-staging, ship-production, and ship-hotfix.
7
+ *
8
+ * Git commands use execFileSync (not a shell string) so user-provided
9
+ * strings such as commit messages are never interpolated by the shell.
10
+ * pnpm script invocations use execSync via shell since script names are
11
+ * developer-controlled and pnpm itself is resolved through PATH.
12
+ */
13
+ const git = (...args) => {
14
+ console.log(`$ git ${args.join(" ")}`);
15
+ execFileSync("git", args, { stdio: "inherit" });
16
+ };
17
+ const gitRead = (...args) => execFileSync("git", args, { encoding: "utf-8" }).trim();
18
+ const runScript = (script) => {
19
+ console.log(`$ pnpm ${script}`);
20
+ execSync(`pnpm ${script}`, { stdio: "inherit" });
21
+ };
22
+ const runQualityChecks = () => {
23
+ runScript("build");
24
+ runScript("typecheck");
25
+ runScript("test");
26
+ };
27
+ const branchExists = (name) => gitRead("branch", "--list", name) !== "" || gitRead("branch", "--list", "--remotes", `origin/${name}`) !== "";
28
+ const confirm = (prompt, ttyPath = "/dev/tty") => {
29
+ process.stdout.write(`${prompt} (y/N) `);
30
+ const buf = Buffer.alloc(1024);
31
+ let fd;
32
+ let shouldClose = false;
33
+ try {
34
+ fd = openSync(ttyPath, "r");
35
+ shouldClose = true;
36
+ } catch {
37
+ fd = process.stdin.fd;
38
+ }
39
+ const bytesRead = readSync(fd, buf, 0, buf.length, null);
40
+ if (shouldClose) closeSync(fd);
41
+ const answer = buf.slice(0, bytesRead).toString().trim();
42
+ return answer === "y" || answer === "Y";
43
+ };
44
+ //#endregion
45
+ export { runQualityChecks as a, gitRead as i, confirm as n, runScript as o, git as r, branchExists as t };
@@ -0,0 +1,24 @@
1
+ import * as _$_playwright_test0 from "@playwright/test";
2
+ import { PlaywrightTestConfig } from "@playwright/test";
3
+
4
+ //#region src/playwright/index.d.ts
5
+ interface BuildPlaywrightBaseConfigParams {
6
+ appPort: number;
7
+ appUrl: string;
8
+ ci?: boolean;
9
+ devices: typeof _$_playwright_test0.devices;
10
+ webServerCommand: string;
11
+ }
12
+ /**
13
+ * Build a base Playwright config object with Regardio defaults.
14
+ * Consumers should wrap with defineConfig() in their local playwright.config.ts
15
+ */
16
+ declare function buildPlaywrightBaseConfig({
17
+ appUrl,
18
+ appPort,
19
+ devices,
20
+ ci,
21
+ webServerCommand
22
+ }: BuildPlaywrightBaseConfigParams): PlaywrightTestConfig;
23
+ //#endregion
24
+ export { BuildPlaywrightBaseConfigParams, buildPlaywrightBaseConfig };
@@ -0,0 +1,61 @@
1
+ //#region src/playwright/index.ts
2
+ /**
3
+ * Build a base Playwright config object with Regardio defaults.
4
+ * Consumers should wrap with defineConfig() in their local playwright.config.ts
5
+ */
6
+ function buildPlaywrightBaseConfig({ appUrl, appPort, devices, ci = !!process.env.CI, webServerCommand }) {
7
+ if (!appUrl || typeof appUrl !== "string") throw new Error("[playwright] appUrl must be a non-empty string");
8
+ if (!appPort || typeof appPort !== "number") throw new Error("[playwright] appPort must be a number");
9
+ if (!devices) throw new Error("[playwright] devices must be provided from \"@playwright/test\"");
10
+ return {
11
+ forbidOnly: ci,
12
+ fullyParallel: true,
13
+ outputDir: "./tests/test-results",
14
+ projects: [
15
+ {
16
+ name: "chromium",
17
+ use: { ...devices["Desktop Chrome"] }
18
+ },
19
+ {
20
+ name: "firefox",
21
+ use: { ...devices["Desktop Firefox"] }
22
+ },
23
+ {
24
+ name: "webkit",
25
+ use: { ...devices["Desktop Safari"] }
26
+ },
27
+ {
28
+ name: "iPad Pro 11 landscape",
29
+ use: { ...devices["iPad Pro 11 landscape"] }
30
+ },
31
+ {
32
+ name: "iPhone 14 portrait",
33
+ use: { ...devices["iPhone 14"] }
34
+ },
35
+ {
36
+ name: "Pixel 7 portrait",
37
+ use: { ...devices["Pixel 7"] }
38
+ }
39
+ ],
40
+ reporter: [["html", {
41
+ open: "never",
42
+ outputFolder: "./tests/playwright-report"
43
+ }]],
44
+ retries: ci ? 2 : 0,
45
+ testDir: "./tests",
46
+ testMatch: "**/*.e2e.ts",
47
+ use: {
48
+ baseURL: appUrl,
49
+ trace: "on-first-retry"
50
+ },
51
+ webServer: {
52
+ command: webServerCommand,
53
+ ignoreHTTPSErrors: true,
54
+ reuseExistingServer: !ci,
55
+ url: appUrl
56
+ },
57
+ ...ci ? { workers: 1 } : {}
58
+ };
59
+ }
60
+ //#endregion
61
+ export { buildPlaywrightBaseConfig };
@@ -0,0 +1,22 @@
1
+ //#region src/vitest/node.d.ts
2
+ /**
3
+ * Base Vitest configuration for Node.js packages.
4
+ * Use with defineConfig() in your vitest.config.ts
5
+ */
6
+ declare const vitestNodeConfig: {
7
+ coverage: {
8
+ provider: "v8";
9
+ thresholds: {
10
+ branches: number;
11
+ functions: number;
12
+ lines: number;
13
+ statements: number;
14
+ };
15
+ };
16
+ environment: string;
17
+ exclude: string[];
18
+ globals: boolean;
19
+ include: string[];
20
+ };
21
+ //#endregion
22
+ export { vitestNodeConfig };
@@ -0,0 +1,28 @@
1
+ //#region src/vitest/node.ts
2
+ /**
3
+ * Base Vitest configuration for Node.js packages.
4
+ * Use with defineConfig() in your vitest.config.ts
5
+ */
6
+ const vitestNodeConfig = {
7
+ coverage: {
8
+ provider: "v8",
9
+ thresholds: {
10
+ branches: 80,
11
+ functions: 80,
12
+ lines: 80,
13
+ statements: 80
14
+ }
15
+ },
16
+ environment: "node",
17
+ exclude: [
18
+ "node_modules",
19
+ "dist",
20
+ "build",
21
+ ".turbo",
22
+ ".react-router"
23
+ ],
24
+ globals: true,
25
+ include: ["**/*.test.ts", "**/*.test.tsx"]
26
+ };
27
+ //#endregion
28
+ export { vitestNodeConfig };
@@ -0,0 +1,22 @@
1
+ //#region src/vitest/react.d.ts
2
+ /**
3
+ * Vitest configuration for React packages with jsdom environment.
4
+ * Use with defineConfig() in your vitest.config.ts
5
+ */
6
+ declare const vitestReactConfig: {
7
+ coverage: {
8
+ provider: "v8";
9
+ thresholds: {
10
+ branches: number;
11
+ functions: number;
12
+ lines: number;
13
+ statements: number;
14
+ };
15
+ };
16
+ environment: string;
17
+ exclude: string[];
18
+ globals: boolean;
19
+ include: string[];
20
+ };
21
+ //#endregion
22
+ export { vitestReactConfig };
@@ -0,0 +1,28 @@
1
+ //#region src/vitest/react.ts
2
+ /**
3
+ * Vitest configuration for React packages with jsdom environment.
4
+ * Use with defineConfig() in your vitest.config.ts
5
+ */
6
+ const vitestReactConfig = {
7
+ coverage: {
8
+ provider: "v8",
9
+ thresholds: {
10
+ branches: 80,
11
+ functions: 80,
12
+ lines: 80,
13
+ statements: 80
14
+ }
15
+ },
16
+ environment: "jsdom",
17
+ exclude: [
18
+ "node_modules",
19
+ "dist",
20
+ "build",
21
+ ".turbo",
22
+ ".react-router"
23
+ ],
24
+ globals: true,
25
+ include: ["**/*.test.ts", "**/*.test.tsx"]
26
+ };
27
+ //#endregion
28
+ export { vitestReactConfig };
@@ -0,0 +1,95 @@
1
+ ---
2
+
3
+ title: @regardio/dev Documentation
4
+ type: guide
5
+ status: published
6
+ summary: Complete documentation for the @regardio/dev toolchain
7
+ related: [coding-standards, development-principles]
8
+ locale: en-US
9
+ ---
10
+
11
+ # Documentation
12
+
13
+ Documentation index and quick reference for the `@regardio/dev` toolchain.
14
+
15
+ ## Concepts
16
+
17
+ Foundational principles and standards that guide development:
18
+
19
+ | Document | Description |
20
+ |----------|-------------|
21
+ | [AI Agents](./agents.md) | Instructions for AI coding assistants |
22
+ | [API](./standards/api.md) | API design and implementation guidelines |
23
+ | [Coding](./standards/coding.md) | TypeScript, React, and general patterns |
24
+ | [Commits](./standards/commits.md) | Conventional commits and changelog generation |
25
+ | [Documentation](./standards/documentation.md) | Documentation structure and conventions |
26
+ | [Naming](./standards/naming.md) | Consistent naming across languages |
27
+ | [Principles](./standards/principles.md) | Code quality, architecture, maintainability |
28
+ | [React](./standards/react.md) | React and TypeScript development patterns |
29
+ | [SQL](./standards/sql.md) | PostgreSQL schema styling, structure, and access control |
30
+ | [Testing](./standards/testing.md) | Testing philosophy and patterns |
31
+ | [Writing](./standards/writing.md) | Voice, tone, and language |
32
+
33
+ ## Toolchain
34
+
35
+ Configuration and usage for each tool in the stack:
36
+
37
+ | Document | Description |
38
+ |----------|-------------|
39
+ | [Biome](./tools/biome.md) | Linting and formatting |
40
+ | [Commitlint](./tools/commitlint.md) | Commit message validation |
41
+ | [Dependencies](./tools/dependencies.md) | Safe dependency updates and supply-chain controls |
42
+ | [Husky](./tools/husky.md) | Git hooks |
43
+ | [Markdownlint](./tools/markdownlint.md) | Markdown quality |
44
+ | [Playwright](./tools/playwright.md) | End-to-end testing |
45
+ | [Releases](./tools/releases.md) | GitLab-flow-based versioning and releases |
46
+ | [TypeScript](./tools/typescript.md) | Strict TypeScript configuration |
47
+ | [Vitest](./tools/vitest.md) | Unit and integration testing |
48
+
49
+ ## Quick Reference
50
+
51
+ ### Commands
52
+
53
+ ```bash
54
+ pnpm build # Build all packages
55
+ pnpm dev # Start development
56
+ pnpm fix # Run all fixes and linting
57
+ pnpm lint # Run linting only
58
+ pnpm report # Run tests with coverage
59
+ pnpm changeset # Declare a version bump alongside your change
60
+ pnpm ship:staging # Deploy main to staging for validation (optional)
61
+ pnpm ship:production # Consume changesets, merge main → production, trigger publish
62
+ pnpm ship:hotfix start <name> # Start an urgent fix from production
63
+ pnpm ship:hotfix finish # Propagate the hotfix back through production → staging → main
64
+ pnpm test # Run tests
65
+ pnpm typecheck # TypeScript type checking
66
+ ```
67
+
68
+ ### Config Files
69
+
70
+ | File | Purpose |
71
+ |------|---------|
72
+ | `.commitlintrc.json` | Commit message rules |
73
+ | `.markdownlint.json` | Markdown rules |
74
+ | `biome.jsonc` | Linting and formatting |
75
+ | `playwright.config.ts` | E2E test configuration |
76
+ | `pnpm-workspace.yaml` | Workspace dependency and supply-chain policy |
77
+ | `tsconfig.json` | TypeScript configuration |
78
+ | `vitest.config.ts` | Unit test configuration |
79
+ | `.sqlfluff` | SQL linting (copy from `@regardio/dev/sqlfluff/setup.cfg`) |
80
+
81
+ ### Extending Presets
82
+
83
+ ```jsonc
84
+ // biome.jsonc
85
+ { "extends": ["@regardio/dev/biome"] }
86
+
87
+ // tsconfig.json
88
+ { "extends": "@regardio/dev/typescript/base" }
89
+
90
+ // .commitlintrc.json
91
+ { "extends": ["@regardio/dev/commitlint"] }
92
+
93
+ // .markdownlint.json
94
+ { "extends": "@regardio/dev/markdownlint" }
95
+ ```