template-git-repo 0.1.23 → 0.1.25
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/README.md +9 -0
- package/bin/template-git-repo.js +2 -0
- package/docs/BADGES.md +72 -0
- package/package.json +1 -1
- package/src/badges.js +171 -4
- package/src/context.js +141 -0
- package/src/index.js +2 -0
- package/template/{scripts → .github/scripts}/list-test-packages.mjs +1 -1
- package/template/{scripts → .github/scripts}/next-free-version.mjs +2 -2
- package/template/{scripts → .github/scripts}/pin-workspace-deps.mjs +1 -1
- package/template/{scripts → .github/scripts}/restore-pinned-deps.mjs +1 -1
- package/template/{scripts → .github/scripts}/workspace-build-order.mjs +1 -1
- package/template/.github/workflows/npm-publish.yml +5 -5
- package/template/.github/workflows/tests.yml +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,15 @@
|
|
|
9
9
|
<a href="https://www.npmjs.com/package/template-git-repo"><img src="https://img.shields.io/npm/types/template-git-repo" alt="TypeScript types" /></a>
|
|
10
10
|
<a href="https://packagephobia.com/result?p=template-git-repo"><img src="https://packagephobia.com/badge?p=template-git-repo" alt="Install size" /></a>
|
|
11
11
|
<a href="https://app.codecov.io/gh/OpenSourceAGI/dev-tools-starter-agent/flags"><img src="https://img.shields.io/codecov/c/github/OpenSourceAGI/dev-tools-starter-agent?flag=template-git-repo&label=template-git-repo%20coverage&logo=codecov&logoColor=white" alt="Coverage" /></a>
|
|
12
|
+
<br />
|
|
13
|
+
<a href="https://github.com/OpenSourceAGI/dev-tools-starter-agent/stargazers"><img src="https://img.shields.io/github/stars/OpenSourceAGI/dev-tools-starter-agent" alt="GitHub Stars" /></a>
|
|
14
|
+
<a href="https://github.com/OpenSourceAGI/dev-tools-starter-agent/issues"><img src="https://img.shields.io/github/issues/OpenSourceAGI/dev-tools-starter-agent?logo=github" alt="GitHub Issues" /></a>
|
|
15
|
+
<a href="https://github.com/OpenSourceAGI/dev-tools-starter-agent/pulls"><img src="https://img.shields.io/github/issues-pr/OpenSourceAGI/dev-tools-starter-agent?logo=github&label=PRs" alt="Open Pull Requests" /></a>
|
|
16
|
+
<a href="https://github.com/OpenSourceAGI/dev-tools-starter-agent/pulls?q=is%3Apr+is%3Aclosed"><img src="https://img.shields.io/github/issues-pr-closed/OpenSourceAGI/dev-tools-starter-agent?logo=github&label=PRs%20merged&color=8957e5" alt="Merged Pull Requests" /></a>
|
|
17
|
+
<a href="https://github.com/OpenSourceAGI/dev-tools-starter-agent/discussions"><img src="https://img.shields.io/github/discussions/OpenSourceAGI/dev-tools-starter-agent" alt="GitHub Discussions" /></a>
|
|
18
|
+
<a href="https://github.com/OpenSourceAGI/dev-tools-starter-agent/commits/master/"><img src="https://img.shields.io/github/last-commit/OpenSourceAGI/dev-tools-starter-agent.svg" alt="GitHub last commit" /></a>
|
|
19
|
+
<br />
|
|
20
|
+
<img src="https://img.shields.io/badge/Bun-14151A?logo=bun&logoColor=white" alt="Bun" /> <img src="https://img.shields.io/badge/Vitest-6E9F18?logo=vitest&logoColor=white" alt="Vitest" />
|
|
12
21
|
</p>
|
|
13
22
|
<!-- template-git-repo:badges:end -->
|
|
14
23
|
|
package/bin/template-git-repo.js
CHANGED
|
@@ -53,6 +53,7 @@ Context (all optional — detected where possible)
|
|
|
53
53
|
|
|
54
54
|
Badge inputs (each enables the badge that needs it)
|
|
55
55
|
--doi <10.5281/...> --docs <url> --api <url>
|
|
56
|
+
--website <url>
|
|
56
57
|
--youtube <url> --uptime <url> --test-report <url>
|
|
57
58
|
--discord-id <id> --discord-invite <url>
|
|
58
59
|
--stack <A,B,C> --cloudflare-deploy
|
|
@@ -108,6 +109,7 @@ function overridesFrom(flags) {
|
|
|
108
109
|
npmPackage: text('npm-package'),
|
|
109
110
|
workflowFile: text('workflow'),
|
|
110
111
|
doi: text('doi'),
|
|
112
|
+
websiteUrl: text('website'),
|
|
111
113
|
docsUrl: text('docs'),
|
|
112
114
|
apiUrl: text('api'),
|
|
113
115
|
youtubeUrl: text('youtube'),
|
package/docs/BADGES.md
CHANGED
|
@@ -23,12 +23,20 @@ package or finish setting up Codecov.
|
|
|
23
23
|
| --- | --- | --- |
|
|
24
24
|
| [Zenodo DOI](#doi) `doi` | doi | `--doi <10.5281/zenodo.NNNNNNN>` |
|
|
25
25
|
| [Ask DeepWiki](#deepwiki) `deepwiki` | — | on by default |
|
|
26
|
+
| [Live app](#website) `website` | websiteUrl | `--website <url>` |
|
|
26
27
|
| [Documentation](#docs) `docs` | docsUrl | `--docs <url>` |
|
|
27
28
|
| [API reference](#api) `api` | apiUrl | `--api <url>` |
|
|
28
29
|
| [YouTube demo](#youtube) `youtube` | youtubeUrl | `--youtube <url>` |
|
|
29
30
|
| [Deploy to Cloudflare Workers](#deploy-cloudflare) `deploy-cloudflare` | cloudflareDeploy | `--cloudflare-deploy` |
|
|
30
31
|
| [Open in StackBlitz](#stackblitz) `stackblitz` | stackblitzUrl | `--stackblitz <url>` |
|
|
32
|
+
| [Open in GitHub Codespaces](#codespaces) `codespaces` | — | on by default |
|
|
31
33
|
| [GitHub stars](#stars) `stars` | — | on by default |
|
|
34
|
+
| [GitHub forks](#forks) `forks` | — | on by default |
|
|
35
|
+
| [Contributors](#contributors) `contributors` | — | on by default |
|
|
36
|
+
| [Open issues](#issues) `issues` | — | on by default |
|
|
37
|
+
| [Open pull requests](#pull-requests) `pull-requests` | — | on by default |
|
|
38
|
+
| [Merged pull requests](#prs-merged) `prs-merged` | — | on by default |
|
|
39
|
+
| [GitHub Discussions](#discussions) `discussions` | — | on by default |
|
|
32
40
|
| [npm monthly downloads](#npm-downloads) `npm-downloads` | npmPackage | `--npm-package <name>` |
|
|
33
41
|
| [npm version](#npm-version) `npm-version` | npmPackage | `--npm-package <name>` |
|
|
34
42
|
| [npm total downloads](#npm-total-downloads) `npm-total-downloads` | npmPackage | `--npm-package <name>` |
|
|
@@ -64,6 +72,14 @@ Nothing to configure for a public repo — visit deepwiki.com/<owner>/<repo> onc
|
|
|
64
72
|
|
|
65
73
|
Included by default — no configuration needed.
|
|
66
74
|
|
|
75
|
+
### website
|
|
76
|
+
|
|
77
|
+
**Live app**
|
|
78
|
+
|
|
79
|
+
The deployed thing, not the repo. It is first in the row on purpose: a visitor who can click through to a running app decides in seconds whether to read the rest. Static badge — nothing checks that the URL is up, which is what the uptime badge is for.
|
|
80
|
+
|
|
81
|
+
Enable with: `--website <url>`
|
|
82
|
+
|
|
67
83
|
### docs
|
|
68
84
|
|
|
69
85
|
**Documentation**
|
|
@@ -104,6 +120,14 @@ Nothing to configure — StackBlitz imports a public repo straight from a URL: `
|
|
|
104
120
|
|
|
105
121
|
Enable with: `--stackblitz <url>`
|
|
106
122
|
|
|
123
|
+
### codespaces
|
|
124
|
+
|
|
125
|
+
**Open in GitHub Codespaces**
|
|
126
|
+
|
|
127
|
+
Nothing to configure — the link boots the repo in a default container. Add a `.devcontainer/devcontainer.json` if the default image is missing something your install needs, because the visitor sees the failure, not you. Codespaces bills the visitor's own free hours, so the button costs you nothing.
|
|
128
|
+
|
|
129
|
+
Included by default — no configuration needed.
|
|
130
|
+
|
|
107
131
|
## Quality — is it working, is it tested, is it shipped
|
|
108
132
|
|
|
109
133
|
### npm-downloads
|
|
@@ -196,6 +220,54 @@ Nothing to configure. Public repos only — shields.io cannot read a private rep
|
|
|
196
220
|
|
|
197
221
|
Included by default — no configuration needed.
|
|
198
222
|
|
|
223
|
+
### forks
|
|
224
|
+
|
|
225
|
+
**GitHub forks**
|
|
226
|
+
|
|
227
|
+
Nothing to configure. Counts direct forks only, not forks of forks, so it undercounts a repo that has been forked along a chain. Public repos only.
|
|
228
|
+
|
|
229
|
+
Included by default — no configuration needed.
|
|
230
|
+
|
|
231
|
+
### contributors
|
|
232
|
+
|
|
233
|
+
**Contributors**
|
|
234
|
+
|
|
235
|
+
Nothing to configure, but it counts commit authors GitHub could match to an account — commits made with an unregistered email are attributed to nobody and do not appear here. Use `contributors-anon` instead if your history has many of those.
|
|
236
|
+
|
|
237
|
+
Included by default — no configuration needed.
|
|
238
|
+
|
|
239
|
+
### issues
|
|
240
|
+
|
|
241
|
+
**Open issues**
|
|
242
|
+
|
|
243
|
+
Nothing to configure beyond having Issues enabled (Settings → Features). Read it as a work-in-flight number, not a defect count: shields.io asks GitHub Search, which counts pull requests as issues unless the badge path excludes them — this one uses the `/issues/` path, which already does.
|
|
244
|
+
|
|
245
|
+
Included by default — no configuration needed.
|
|
246
|
+
|
|
247
|
+
### pull-requests
|
|
248
|
+
|
|
249
|
+
**Open pull requests**
|
|
250
|
+
|
|
251
|
+
Nothing to configure. Counts open PRs including drafts. Pair it with the merged count below — an open count alone reads the same whether the queue moves in a day or has been stuck for a year.
|
|
252
|
+
|
|
253
|
+
Included by default — no configuration needed.
|
|
254
|
+
|
|
255
|
+
### prs-merged
|
|
256
|
+
|
|
257
|
+
**Merged pull requests**
|
|
258
|
+
|
|
259
|
+
Nothing to configure. shields.io has no "merged" endpoint — `issues-pr-closed` counts every PR that is no longer open, so PRs closed without merging are in this number too. On a repo that closes a lot of stale PRs, label it "PRs closed" instead of overstating what landed.
|
|
260
|
+
|
|
261
|
+
Included by default — no configuration needed.
|
|
262
|
+
|
|
263
|
+
### discussions
|
|
264
|
+
|
|
265
|
+
**GitHub Discussions**
|
|
266
|
+
|
|
267
|
+
Discussions has to be turned on (Settings → Features → Discussions) or the badge reads "repo not found" — which looks identical to a private repo. Turn it on before adding the badge, not after.
|
|
268
|
+
|
|
269
|
+
Included by default — no configuration needed.
|
|
270
|
+
|
|
199
271
|
### commit-activity
|
|
200
272
|
|
|
201
273
|
**Commit activity**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "template-git-repo",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.25",
|
|
4
4
|
"description": "One command to set up a repo with GitHub Actions, README badges, Turborepo and Codecov — the CI setup from qwksearch-research-agent, as a template",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/badges.js
CHANGED
|
@@ -63,6 +63,19 @@ export const BADGES = [
|
|
|
63
63
|
setup:
|
|
64
64
|
'Nothing to configure for a public repo — visit deepwiki.com/<owner>/<repo> once to trigger the first index. Private repos need the DeepWiki GitHub App installed.',
|
|
65
65
|
},
|
|
66
|
+
{
|
|
67
|
+
id: 'website',
|
|
68
|
+
title: 'Live app',
|
|
69
|
+
group: 'identity',
|
|
70
|
+
needs: ['websiteUrl'],
|
|
71
|
+
alt: 'Website',
|
|
72
|
+
href: (c) => c.websiteUrl,
|
|
73
|
+
img: () =>
|
|
74
|
+
shieldsBadge('App', 'blueviolet', { style: 'for-the-badge', logo: 'googlechrome', logoColor: 'white' }),
|
|
75
|
+
setup:
|
|
76
|
+
'The deployed thing, not the repo. It is first in the row on purpose: a visitor who can click through to a running app decides in seconds whether to read the rest. Static badge — nothing checks that the URL is up, which is what the uptime badge is for.',
|
|
77
|
+
height: '20px',
|
|
78
|
+
},
|
|
66
79
|
{
|
|
67
80
|
id: 'docs',
|
|
68
81
|
title: 'Documentation',
|
|
@@ -119,6 +132,18 @@ export const BADGES = [
|
|
|
119
132
|
'Nothing to configure — StackBlitz imports a public repo straight from a URL: `https://stackblitz.com/github/<owner>/<repo>/tree/<branch>/<path>`. Point it at a directory that boots on its own (a package with its own package.json, or an `examples/` folder), because StackBlitz installs from the manifest at that path and a bare monorepo root will not run. Node APIs need the WebContainer runtime, which means the directory must be ESM and its deps must be installable from npm.',
|
|
120
133
|
height: '20px',
|
|
121
134
|
},
|
|
135
|
+
{
|
|
136
|
+
id: 'codespaces',
|
|
137
|
+
title: 'Open in GitHub Codespaces',
|
|
138
|
+
group: 'identity',
|
|
139
|
+
needs: [],
|
|
140
|
+
alt: 'Open in GitHub Codespaces',
|
|
141
|
+
href: (c) => `https://codespaces.new/${c.repoSlug}`,
|
|
142
|
+
img: () => 'https://github.com/codespaces/badge.svg',
|
|
143
|
+
setup:
|
|
144
|
+
'Nothing to configure — the link boots the repo in a default container. Add a `.devcontainer/devcontainer.json` if the default image is missing something your install needs, because the visitor sees the failure, not you. Codespaces bills the visitor\'s own free hours, so the button costs you nothing.',
|
|
145
|
+
height: '20px',
|
|
146
|
+
},
|
|
122
147
|
{
|
|
123
148
|
id: 'stars',
|
|
124
149
|
title: 'GitHub stars',
|
|
@@ -129,6 +154,73 @@ export const BADGES = [
|
|
|
129
154
|
img: (c) => `https://img.shields.io/github/stars/${c.repoSlug}`,
|
|
130
155
|
setup: 'Nothing to configure. Public repos only — shields.io cannot read a private repo.',
|
|
131
156
|
},
|
|
157
|
+
{
|
|
158
|
+
id: 'forks',
|
|
159
|
+
title: 'GitHub forks',
|
|
160
|
+
group: 'community',
|
|
161
|
+
needs: [],
|
|
162
|
+
alt: 'GitHub Forks',
|
|
163
|
+
href: (c) => `https://github.com/${c.repoSlug}/forks`,
|
|
164
|
+
img: (c) => `https://img.shields.io/github/forks/${c.repoSlug}`,
|
|
165
|
+
setup:
|
|
166
|
+
'Nothing to configure. Counts direct forks only, not forks of forks, so it undercounts a repo that has been forked along a chain. Public repos only.',
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: 'contributors',
|
|
170
|
+
title: 'Contributors',
|
|
171
|
+
group: 'community',
|
|
172
|
+
needs: [],
|
|
173
|
+
alt: 'Contributors',
|
|
174
|
+
href: (c) => `https://github.com/${c.repoSlug}/graphs/contributors`,
|
|
175
|
+
img: (c) => `https://img.shields.io/github/contributors/${c.repoSlug}`,
|
|
176
|
+
setup:
|
|
177
|
+
'Nothing to configure, but it counts commit authors GitHub could match to an account — commits made with an unregistered email are attributed to nobody and do not appear here. Use `contributors-anon` instead if your history has many of those.',
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
id: 'issues',
|
|
181
|
+
title: 'Open issues',
|
|
182
|
+
group: 'community',
|
|
183
|
+
needs: [],
|
|
184
|
+
alt: 'GitHub Issues',
|
|
185
|
+
href: (c) => `https://github.com/${c.repoSlug}/issues`,
|
|
186
|
+
img: (c) => `https://img.shields.io/github/issues/${c.repoSlug}?logo=github`,
|
|
187
|
+
setup:
|
|
188
|
+
'Nothing to configure beyond having Issues enabled (Settings → Features). Read it as a work-in-flight number, not a defect count: shields.io asks GitHub Search, which counts pull requests as issues unless the badge path excludes them — this one uses the `/issues/` path, which already does.',
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
id: 'pull-requests',
|
|
192
|
+
title: 'Open pull requests',
|
|
193
|
+
group: 'community',
|
|
194
|
+
needs: [],
|
|
195
|
+
alt: 'Open Pull Requests',
|
|
196
|
+
href: (c) => `https://github.com/${c.repoSlug}/pulls`,
|
|
197
|
+
img: (c) => `https://img.shields.io/github/issues-pr/${c.repoSlug}?logo=github&label=PRs`,
|
|
198
|
+
setup:
|
|
199
|
+
'Nothing to configure. Counts open PRs including drafts. Pair it with the merged count below — an open count alone reads the same whether the queue moves in a day or has been stuck for a year.',
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
id: 'prs-merged',
|
|
203
|
+
title: 'Merged pull requests',
|
|
204
|
+
group: 'community',
|
|
205
|
+
needs: [],
|
|
206
|
+
alt: 'Merged Pull Requests',
|
|
207
|
+
href: (c) => `https://github.com/${c.repoSlug}/pulls?q=is%3Apr+is%3Aclosed`,
|
|
208
|
+
img: (c) =>
|
|
209
|
+
`https://img.shields.io/github/issues-pr-closed/${c.repoSlug}?logo=github&label=PRs%20merged&color=8957e5`,
|
|
210
|
+
setup:
|
|
211
|
+
'Nothing to configure. shields.io has no "merged" endpoint — `issues-pr-closed` counts every PR that is no longer open, so PRs closed without merging are in this number too. On a repo that closes a lot of stale PRs, label it "PRs closed" instead of overstating what landed.',
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
id: 'discussions',
|
|
215
|
+
title: 'GitHub Discussions',
|
|
216
|
+
group: 'community',
|
|
217
|
+
needs: [],
|
|
218
|
+
alt: 'GitHub Discussions',
|
|
219
|
+
href: (c) => `https://github.com/${c.repoSlug}/discussions`,
|
|
220
|
+
img: (c) => `https://img.shields.io/github/discussions/${c.repoSlug}`,
|
|
221
|
+
setup:
|
|
222
|
+
'Discussions has to be turned on (Settings → Features → Discussions) or the badge reads "repo not found" — which looks identical to a private repo. Turn it on before adding the badge, not after.',
|
|
223
|
+
},
|
|
132
224
|
{
|
|
133
225
|
id: 'npm-downloads',
|
|
134
226
|
title: 'npm monthly downloads',
|
|
@@ -309,18 +401,90 @@ export const BADGES = [
|
|
|
309
401
|
},
|
|
310
402
|
];
|
|
311
403
|
|
|
312
|
-
/**
|
|
404
|
+
/**
|
|
405
|
+
* Brand colors for the stack chips, so the common ones look right by default.
|
|
406
|
+
*
|
|
407
|
+
* Keyed by the lowercased chip name. Anything not listed falls back to a
|
|
408
|
+
* neutral grey, which is a perfectly good chip — this map is a nicety, not a
|
|
409
|
+
* gate on what you can name.
|
|
410
|
+
*/
|
|
313
411
|
const STACK_COLORS = {
|
|
314
412
|
claude: 'D97757',
|
|
315
413
|
cloudflare: 'F38020',
|
|
414
|
+
'cloudflare workers': 'F38020',
|
|
415
|
+
d1: 'F38020',
|
|
416
|
+
r2: 'F38020',
|
|
417
|
+
wrangler: 'F38020',
|
|
316
418
|
'next.js': 'black',
|
|
317
419
|
react: '20232A',
|
|
420
|
+
svelte: 'FF3E00',
|
|
421
|
+
'vue.js': '4FC08D',
|
|
318
422
|
typescript: '3178C6',
|
|
423
|
+
javascript: 'F7DF1E',
|
|
424
|
+
'node.js': '5FA04E',
|
|
319
425
|
bun: '14151A',
|
|
426
|
+
npm: 'CB3837',
|
|
427
|
+
pnpm: 'F69220',
|
|
428
|
+
turborepo: 'EF4444',
|
|
320
429
|
vite: '646CFF',
|
|
430
|
+
vitest: '6E9F18',
|
|
431
|
+
jest: 'C21325',
|
|
432
|
+
playwright: '2EAD33',
|
|
433
|
+
biome: '60A5FA',
|
|
321
434
|
vercel: 'black',
|
|
322
435
|
postgresql: '4169E1',
|
|
436
|
+
sqlite: '003B57',
|
|
437
|
+
'drizzle orm': 'C5F74F',
|
|
323
438
|
tailwindcss: '06B6D4',
|
|
439
|
+
'tailwind css': '06B6D4',
|
|
440
|
+
'shadcn/ui': '000000',
|
|
441
|
+
'radix ui': '161618',
|
|
442
|
+
'better-auth': '000000',
|
|
443
|
+
hono: 'E36002',
|
|
444
|
+
stripe: '635BFF',
|
|
445
|
+
zod: '3E67B1',
|
|
446
|
+
tauri: '24C8D8',
|
|
447
|
+
electron: '47848F',
|
|
448
|
+
prosemirror: '000000',
|
|
449
|
+
tiptap: '000000',
|
|
450
|
+
fumadocs: '000000',
|
|
451
|
+
mcp: '000000',
|
|
452
|
+
'vercel ai sdk': 'black',
|
|
453
|
+
openai: '412991',
|
|
454
|
+
python: '3776AB',
|
|
455
|
+
docker: '2496ED',
|
|
456
|
+
'github actions': '2088FF',
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* simple-icons slugs for chips whose name does not reduce to one.
|
|
461
|
+
*
|
|
462
|
+
* `?logo=` takes a simpleicons.org slug, and the derivation below (lowercase,
|
|
463
|
+
* drop dots, spaces and slashes) gets most of them right — `Next.js` really is
|
|
464
|
+
* `nextjs`. It gets a handful wrong, and a wrong slug renders a chip with a
|
|
465
|
+
* blank square where the logo should be, so those are written out.
|
|
466
|
+
*
|
|
467
|
+
* A name with no icon at all (`better-auth`, `MCP`) maps to the empty string:
|
|
468
|
+
* the chip renders as plain text rather than carrying someone else's logo.
|
|
469
|
+
*/
|
|
470
|
+
const STACK_LOGOS = {
|
|
471
|
+
'cloudflare workers': 'cloudflareworkers',
|
|
472
|
+
d1: 'cloudflare',
|
|
473
|
+
r2: 'cloudflare',
|
|
474
|
+
'drizzle orm': 'drizzle',
|
|
475
|
+
'tailwind css': 'tailwindcss',
|
|
476
|
+
'vue.js': 'vuedotjs',
|
|
477
|
+
'node.js': 'nodedotjs',
|
|
478
|
+
'next.js': 'nextdotjs',
|
|
479
|
+
'radix ui': 'radixui',
|
|
480
|
+
'github actions': 'githubactions',
|
|
481
|
+
'vercel ai sdk': 'vercel',
|
|
482
|
+
claude: 'claude',
|
|
483
|
+
'better-auth': '',
|
|
484
|
+
mcp: '',
|
|
485
|
+
prosemirror: '',
|
|
486
|
+
fumadocs: '',
|
|
487
|
+
zod: 'zod',
|
|
324
488
|
};
|
|
325
489
|
|
|
326
490
|
/**
|
|
@@ -328,10 +492,13 @@ const STACK_COLORS = {
|
|
|
328
492
|
* @returns {string} an `<img>` chip for one stack entry
|
|
329
493
|
*/
|
|
330
494
|
export function stackChip(name) {
|
|
331
|
-
const
|
|
495
|
+
const label = name.trim();
|
|
496
|
+
const key = label.toLowerCase();
|
|
332
497
|
const color = STACK_COLORS[key] ?? '555555';
|
|
333
|
-
const logo = key.replace(/[.\s]/g, '');
|
|
334
|
-
|
|
498
|
+
const logo = STACK_LOGOS[key] ?? key.replace(/[.\s/]/g, '');
|
|
499
|
+
|
|
500
|
+
const params = logo ? { logo, logoColor: 'white' } : {};
|
|
501
|
+
return `<img src="${shieldsBadge(label, color, params)}" alt="${label}" />`;
|
|
335
502
|
}
|
|
336
503
|
|
|
337
504
|
/**
|
package/src/context.js
CHANGED
|
@@ -160,6 +160,146 @@ export function detectNpmPackage(root, packagesDir) {
|
|
|
160
160
|
return undefined;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Dependency name -> the stack chip it implies, in the order the chips should
|
|
165
|
+
* read: language and runtime first, then framework, then the things bolted onto
|
|
166
|
+
* it, then the test runner.
|
|
167
|
+
*
|
|
168
|
+
* Keyed on the dependency rather than on a guess about the project, because the
|
|
169
|
+
* manifest is the one place that cannot lie about what a package is built with.
|
|
170
|
+
* A hand-written stack row goes stale the week someone swaps a framework out and
|
|
171
|
+
* nobody remembers the README says otherwise.
|
|
172
|
+
*
|
|
173
|
+
* Several entries collapse many packages into one chip — a ProseMirror app
|
|
174
|
+
* depends on eight `prosemirror-*` modules and is built with ProseMirror once.
|
|
175
|
+
* Duplicates are removed by `detectStack`, so listing every alias is safe.
|
|
176
|
+
*/
|
|
177
|
+
const STACK_BY_DEPENDENCY = [
|
|
178
|
+
['typescript', 'TypeScript'],
|
|
179
|
+
['next', 'Next.js'],
|
|
180
|
+
['react', 'React'],
|
|
181
|
+
['svelte', 'Svelte'],
|
|
182
|
+
['vue', 'Vue.js'],
|
|
183
|
+
['@tauri-apps/api', 'Tauri'],
|
|
184
|
+
['@tauri-apps/cli', 'Tauri'],
|
|
185
|
+
['electron', 'Electron'],
|
|
186
|
+
['wrangler', 'Cloudflare Workers'],
|
|
187
|
+
['hono', 'Hono'],
|
|
188
|
+
['tailwindcss', 'Tailwind CSS'],
|
|
189
|
+
['@radix-ui/react-dialog', 'shadcn/ui'],
|
|
190
|
+
['drizzle-orm', 'Drizzle ORM'],
|
|
191
|
+
['better-auth', 'better-auth'],
|
|
192
|
+
['stripe', 'Stripe'],
|
|
193
|
+
['ai', 'Vercel AI SDK'],
|
|
194
|
+
['@modelcontextprotocol/sdk', 'MCP'],
|
|
195
|
+
['@tiptap/core', 'TipTap'],
|
|
196
|
+
['prosemirror-state', 'ProseMirror'],
|
|
197
|
+
['prosemirror-view', 'ProseMirror'],
|
|
198
|
+
['zod', 'Zod'],
|
|
199
|
+
['fumadocs-ui', 'Fumadocs'],
|
|
200
|
+
['vite', 'Vite'],
|
|
201
|
+
['turbo', 'Turborepo'],
|
|
202
|
+
['vitest', 'Vitest'],
|
|
203
|
+
['jest', 'Jest'],
|
|
204
|
+
['@playwright/test', 'Playwright'],
|
|
205
|
+
];
|
|
206
|
+
|
|
207
|
+
/** The chip for each package manager, so the runtime shows up even with no deps. */
|
|
208
|
+
const STACK_BY_PACKAGE_MANAGER = { bun: 'Bun', pnpm: 'pnpm', yarn: 'Yarn', npm: 'npm' };
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* De-duplicate chips and put them back in catalog order.
|
|
212
|
+
*
|
|
213
|
+
* Needed because the workspace union collects chips manifest by manifest, and
|
|
214
|
+
* alphabetical directory order is not a sensible reading order for a stack row —
|
|
215
|
+
* it lands on "Drizzle ORM, Vitest, TypeScript, React". Anything not in the
|
|
216
|
+
* catalog (a `prepend` like Claude) keeps its position at the front.
|
|
217
|
+
*
|
|
218
|
+
* @param {string[]} chips
|
|
219
|
+
* @returns {string[]}
|
|
220
|
+
*/
|
|
221
|
+
function orderChips(chips) {
|
|
222
|
+
const order = STACK_BY_DEPENDENCY.map(([, chip]) => chip);
|
|
223
|
+
const rank = (chip) => {
|
|
224
|
+
const index = order.indexOf(chip);
|
|
225
|
+
return index === -1 ? -1 : index;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const unique = [...new Set(chips)];
|
|
229
|
+
const leading = unique.filter((chip) => rank(chip) === -1);
|
|
230
|
+
const known = unique.filter((chip) => rank(chip) !== -1).sort((a, b) => rank(a) - rank(b));
|
|
231
|
+
|
|
232
|
+
return [...leading, ...known];
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* The stack chips for one manifest, read off its dependencies.
|
|
237
|
+
*
|
|
238
|
+
* Returns a comma-separated string because that is what the `stack` badge takes
|
|
239
|
+
* and what `--stack` passes on the command line. An empty result means the
|
|
240
|
+
* manifest declared nothing recognizable, and the badge is skipped — better
|
|
241
|
+
* than a row asserting a framework the package does not use.
|
|
242
|
+
*
|
|
243
|
+
* @param {Record<string, any> | null} manifest
|
|
244
|
+
* @param {{ prepend?: string[], packageManager?: string }} [options]
|
|
245
|
+
* @returns {string | undefined}
|
|
246
|
+
*/
|
|
247
|
+
export function detectStack(manifest, options = {}) {
|
|
248
|
+
const { prepend = [], packageManager } = options;
|
|
249
|
+
|
|
250
|
+
const declared = new Set([
|
|
251
|
+
...Object.keys(manifest?.dependencies ?? {}),
|
|
252
|
+
...Object.keys(manifest?.devDependencies ?? {}),
|
|
253
|
+
...Object.keys(manifest?.peerDependencies ?? {}),
|
|
254
|
+
]);
|
|
255
|
+
|
|
256
|
+
const chips = [...prepend];
|
|
257
|
+
|
|
258
|
+
const runtime = packageManager ? STACK_BY_PACKAGE_MANAGER[packageManager] : undefined;
|
|
259
|
+
if (runtime) chips.push(runtime);
|
|
260
|
+
|
|
261
|
+
for (const [dependency, chip] of STACK_BY_DEPENDENCY) {
|
|
262
|
+
if (declared.has(dependency)) chips.push(chip);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const ordered = orderChips(chips);
|
|
266
|
+
return ordered.length > 0 ? ordered.join(',') : undefined;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* The stack for a whole workspace: the union of every member's chips.
|
|
271
|
+
*
|
|
272
|
+
* A monorepo root manifest lists turbo and little else, so reading it alone
|
|
273
|
+
* describes the build tooling and none of the product. This walks the workspace
|
|
274
|
+
* directory instead, which is what the root README's stack row should say.
|
|
275
|
+
*
|
|
276
|
+
* @param {string} root
|
|
277
|
+
* @param {{ packagesDirs?: string[], prepend?: string[], packageManager?: string }} [options]
|
|
278
|
+
* @returns {string | undefined}
|
|
279
|
+
*/
|
|
280
|
+
export function detectWorkspaceStack(root, options = {}) {
|
|
281
|
+
const { packagesDirs = ['packages', 'apps'], prepend = [], packageManager } = options;
|
|
282
|
+
|
|
283
|
+
const manifests = [readJson(path.join(root, 'package.json'))];
|
|
284
|
+
|
|
285
|
+
for (const dir of packagesDirs) {
|
|
286
|
+
const parent = path.join(root, dir);
|
|
287
|
+
if (!fs.existsSync(parent)) continue;
|
|
288
|
+
|
|
289
|
+
for (const entry of fs.readdirSync(parent, { withFileTypes: true })) {
|
|
290
|
+
if (!entry.isDirectory()) continue;
|
|
291
|
+
manifests.push(readJson(path.join(parent, entry.name, 'package.json')));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const merged = manifests.filter(Boolean).flatMap((manifest) =>
|
|
296
|
+
(detectStack(manifest, { packageManager }) ?? '').split(',').filter(Boolean),
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
const ordered = orderChips([...prepend, ...merged]);
|
|
300
|
+
return ordered.length > 0 ? ordered.join(',') : undefined;
|
|
301
|
+
}
|
|
302
|
+
|
|
163
303
|
/**
|
|
164
304
|
* Everything the templates and badges need, detected then overridden by flags.
|
|
165
305
|
*
|
|
@@ -194,6 +334,7 @@ export function buildContext(options = {}) {
|
|
|
194
334
|
// Everything below has no sensible default — a badge that needs one of
|
|
195
335
|
// these is skipped until it is passed in.
|
|
196
336
|
doi: overrides.doi,
|
|
337
|
+
websiteUrl: overrides.websiteUrl,
|
|
197
338
|
docsUrl: overrides.docsUrl,
|
|
198
339
|
apiUrl: overrides.apiUrl,
|
|
199
340
|
youtubeUrl: overrides.youtubeUrl,
|
package/src/index.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* `empty` exists because GitHub fails a job whose matrix has no entries, which
|
|
23
23
|
* would make a repo with no test suites look broken rather than untested.
|
|
24
24
|
*
|
|
25
|
-
* Usage: node scripts/list-test-packages.mjs [rootDir]
|
|
25
|
+
* Usage: node .github/scripts/list-test-packages.mjs [rootDir]
|
|
26
26
|
*/
|
|
27
27
|
import fs from 'node:fs';
|
|
28
28
|
import path from 'node:path';
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* ones — the exact numbers `latest` cannot see. The union of the two is the
|
|
24
24
|
* taken set.
|
|
25
25
|
*
|
|
26
|
-
* Usage: node scripts/next-free-version.mjs <package-name> <local-version>
|
|
26
|
+
* Usage: node .github/scripts/next-free-version.mjs <package-name> <local-version>
|
|
27
27
|
* Prints the next free version, always strictly above <local-version>. If
|
|
28
28
|
* the registry says nothing about the package (a first publish, or an
|
|
29
29
|
* unreachable registry) that is just <local-version> plus a patch.
|
|
@@ -161,7 +161,7 @@ if (import.meta.url === pathToFileURL(process.argv[1] || '').href) {
|
|
|
161
161
|
const [name, local] = process.argv.slice(2);
|
|
162
162
|
|
|
163
163
|
if (!name || !local) {
|
|
164
|
-
console.error('Usage: node scripts/next-free-version.mjs <package-name> <local-version>');
|
|
164
|
+
console.error('Usage: node .github/scripts/next-free-version.mjs <package-name> <local-version>');
|
|
165
165
|
process.exit(2);
|
|
166
166
|
}
|
|
167
167
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* The edit is deliberately left in the working tree — `restore-pinned-deps.mjs`
|
|
16
16
|
* takes it back out after the publish, keeping only any version bump.
|
|
17
17
|
*
|
|
18
|
-
* Usage: node scripts/pin-workspace-deps.mjs [packageDir] [workspaceRoot]
|
|
18
|
+
* Usage: node .github/scripts/pin-workspace-deps.mjs [packageDir] [workspaceRoot]
|
|
19
19
|
* Both default to what the publish loop needs: the current directory, and its
|
|
20
20
|
* parent as the directory holding sibling packages.
|
|
21
21
|
*/
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* string back in keeps the committed diff to one line per bumped package, and
|
|
14
14
|
* keeps each file's original formatting.
|
|
15
15
|
*
|
|
16
|
-
* Usage: node scripts/restore-pinned-deps.mjs [packagesRoot...]
|
|
16
|
+
* Usage: node .github/scripts/restore-pinned-deps.mjs [packagesRoot...]
|
|
17
17
|
* Defaults to `packages`.
|
|
18
18
|
*/
|
|
19
19
|
import fs from 'node:fs';
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Cannot find module '<sibling>' or its corresponding type declarations.
|
|
15
15
|
*
|
|
16
|
-
* Usage: node scripts/workspace-build-order.mjs [rootDir]
|
|
16
|
+
* Usage: node .github/scripts/workspace-build-order.mjs [rootDir]
|
|
17
17
|
* rootDir defaults to `packages`. Prints one directory per line, with a
|
|
18
18
|
* trailing slash, e.g. `packages/my-lib/`.
|
|
19
19
|
*/
|
|
@@ -150,7 +150,7 @@ jobs:
|
|
|
150
150
|
unattempted_packages=""
|
|
151
151
|
auth_broken=""
|
|
152
152
|
|
|
153
|
-
build_order=$(node scripts/workspace-build-order.mjs)
|
|
153
|
+
build_order=$(node .github/scripts/workspace-build-order.mjs)
|
|
154
154
|
echo "📋 Build order:"
|
|
155
155
|
echo "$build_order" | sed 's/^/ /'
|
|
156
156
|
|
|
@@ -189,7 +189,7 @@ jobs:
|
|
|
189
189
|
# from the referenced local package; drop deps on local packages
|
|
190
190
|
# that are not published. Only committed back if the version is
|
|
191
191
|
# bumped.
|
|
192
|
-
node "$repo_root/scripts/pin-workspace-deps.mjs"
|
|
192
|
+
node "$repo_root/.github/scripts/pin-workspace-deps.mjs"
|
|
193
193
|
|
|
194
194
|
# Build before deciding anything: the tarball comparison below
|
|
195
195
|
# needs real dist output, and a package whose build fails is never
|
|
@@ -238,7 +238,7 @@ jobs:
|
|
|
238
238
|
# any version staged by an interrupted publish, and npm answers
|
|
239
239
|
# a PUT for one of those with E409 "Cannot publish over
|
|
240
240
|
# previously staged version".
|
|
241
|
-
next=$(node "$repo_root/scripts/next-free-version.mjs" "$name" "$version")
|
|
241
|
+
next=$(node "$repo_root/.github/scripts/next-free-version.mjs" "$name" "$version")
|
|
242
242
|
echo "🔼 $name content changed since $version — bumping to $next"
|
|
243
243
|
# --no-workspaces stops npm from doing workspace-aware
|
|
244
244
|
# processing over bun's symlinks, which trips
|
|
@@ -275,7 +275,7 @@ jobs:
|
|
|
275
275
|
exit 1
|
|
276
276
|
fi
|
|
277
277
|
|
|
278
|
-
next=$(node "$repo_root/scripts/next-free-version.mjs" "$name" "$version")
|
|
278
|
+
next=$(node "$repo_root/.github/scripts/next-free-version.mjs" "$name" "$version")
|
|
279
279
|
echo "↩ npm has $name@$version reserved — retrying as $next"
|
|
280
280
|
npm version "$next" --no-git-tag-version --no-workspaces
|
|
281
281
|
version="$next"
|
|
@@ -313,7 +313,7 @@ jobs:
|
|
|
313
313
|
# Bumps made during publish must land back in the repo so the next run
|
|
314
314
|
# sees them. The workspace:* pinning done for the tarballs must not —
|
|
315
315
|
# restore everything except the "version" field.
|
|
316
|
-
node scripts/restore-pinned-deps.mjs
|
|
316
|
+
node .github/scripts/restore-pinned-deps.mjs
|
|
317
317
|
git add '{{PACKAGES_GLOB}}/package.json'
|
|
318
318
|
git diff --staged --quiet && echo "No version changes to commit" && exit 0
|
|
319
319
|
git commit -m "chore: bump published package versions [skip ci]"
|