@icebreakers/monorepo-templates 1.3.2 → 1.3.4

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.
@@ -0,0 +1,90 @@
1
+ import { Buffer } from 'node:buffer'
2
+
3
+ function repositoryParts(repository) {
4
+ const [owner, name] = repository.split('/')
5
+ if (!owner || !name) {
6
+ throw new Error(`Invalid GitHub repository: ${repository}`)
7
+ }
8
+ return { owner, name }
9
+ }
10
+
11
+ function encodePath(path) {
12
+ return path.split('/').map(segment => encodeURIComponent(segment)).join('/')
13
+ }
14
+
15
+ export function createGitHubClient({ token, repository, fetchImpl = fetch }) {
16
+ const { owner, name } = repositoryParts(repository)
17
+ const apiBase = `https://api.github.com/repos/${owner}/${name}`
18
+ async function request(path, options = {}) {
19
+ const response = await fetchImpl(`${apiBase}${path}`, {
20
+ ...options,
21
+ headers: {
22
+ 'accept': 'application/vnd.github+json',
23
+ 'authorization': `Bearer ${token}`,
24
+ 'content-type': 'application/json',
25
+ 'x-github-api-version': '2022-11-28',
26
+ ...(options.headers ?? {}),
27
+ },
28
+ })
29
+ const text = await response.text()
30
+ let body
31
+ try {
32
+ body = text ? JSON.parse(text) : undefined
33
+ }
34
+ catch {
35
+ body = text
36
+ }
37
+ if (!response.ok) {
38
+ throw new Error(`GitHub API ${response.status} ${options.method ?? 'GET'} ${path}: ${typeof body === 'string' ? body : body?.message ?? 'request failed'}`)
39
+ }
40
+ return body
41
+ }
42
+ return {
43
+ repository,
44
+ getPullRequest: number => request(`/pulls/${number}`),
45
+ getPullRequestFiles: async (number) => {
46
+ const files = []
47
+ for (let page = 1; ; page++) {
48
+ const pageFiles = await request(`/pulls/${number}/files?per_page=100&page=${page}`)
49
+ files.push(...pageFiles)
50
+ if (pageFiles.length < 100) {
51
+ return files
52
+ }
53
+ }
54
+ },
55
+ getContent: async (path, ref) => {
56
+ try {
57
+ const content = await request(`/contents/${encodePath(path)}?ref=${encodeURIComponent(ref)}`)
58
+ if (Array.isArray(content) || content.encoding !== 'base64') {
59
+ return undefined
60
+ }
61
+ return Buffer.from(content.content.replace(/\n/g, ''), 'base64').toString('utf8')
62
+ }
63
+ catch (error) {
64
+ if (String(error.message).startsWith('GitHub API 404')) {
65
+ return undefined
66
+ }
67
+ throw error
68
+ }
69
+ },
70
+ getRef: ref => request(`/git/ref/${encodePath(ref)}`),
71
+ getCommit: sha => request(`/git/commits/${sha}`),
72
+ createBlob: content => request('/git/blobs', { method: 'POST', body: JSON.stringify({ content, encoding: 'utf-8' }) }),
73
+ createTree: (baseTree, tree) => request('/git/trees', { method: 'POST', body: JSON.stringify({ base_tree: baseTree, tree }) }),
74
+ createCommit: (message, tree, parents) => request('/git/commits', { method: 'POST', body: JSON.stringify({ message, tree, parents }) }),
75
+ updateRef: (ref, sha) => request(`/git/refs/heads/${encodePath(ref)}`, { method: 'PATCH', body: JSON.stringify({ sha, force: false }) }),
76
+ createComment: (number, body) => request(`/issues/${number}/comments`, { method: 'POST', body: JSON.stringify({ body }) }),
77
+ listComments: async (number) => {
78
+ const comments = []
79
+ for (let page = 1; ; page++) {
80
+ const pageComments = await request(`/issues/${number}/comments?per_page=100&page=${page}`)
81
+ comments.push(...pageComments)
82
+ if (pageComments.length < 100) {
83
+ return comments
84
+ }
85
+ }
86
+ },
87
+ createBranch: async (branch, sha) => request('/git/refs', { method: 'POST', body: JSON.stringify({ ref: `refs/heads/${branch}`, sha }) }),
88
+ createPullRequest: input => request('/pulls', { method: 'POST', body: JSON.stringify(input) }),
89
+ }
90
+ }
@@ -0,0 +1,218 @@
1
+ import fs from 'node:fs/promises'
2
+ import process from 'node:process'
3
+ import { createGitHubClient } from './github.mjs'
4
+
5
+ const CHANGESET_MARKER = '<!-- repoctl-auto-changeset -->'
6
+ const PACKAGE_PATH = /^packages\/([^/]+)\//
7
+ const CHANGESET_PATH = /^\.changeset\/[^/]+\.md$/
8
+ const RELEASE_BRANCH = /^(?:pnpm-release\/|release\/pnpm-version)/
9
+
10
+ export function packageDirectories(files) {
11
+ return [...new Set(files
12
+ .map(file => file.filename ?? file)
13
+ .filter(filename => !/^packages\/[^/]+\/dist(?:\/|$)/.test(filename))
14
+ .map(filename => filename.match(PACKAGE_PATH)?.[1])
15
+ .filter(Boolean))]
16
+ }
17
+
18
+ export function releaseLevel(labels = []) {
19
+ const names = labels.map(label => typeof label === 'string' ? label : label.name)
20
+ if (names.includes('release:major')) {
21
+ return 'major'
22
+ }
23
+ if (names.includes('release:minor')) {
24
+ return 'minor'
25
+ }
26
+ return 'patch'
27
+ }
28
+
29
+ export function renderChangeset({ packages, level = 'patch', number, title }) {
30
+ const frontmatter = packages
31
+ .slice()
32
+ .sort((a, b) => a.localeCompare(b))
33
+ .map(name => `${/^[\w.-]+$/.test(name) ? name : JSON.stringify(name)}: ${level}`)
34
+ .join('\n')
35
+ const summary = title.replace(/\r?\n/g, ' ').replace(/\s+/g, ' ').trim()
36
+ return `---\n${frontmatter}\n---\n\n${summary} (#${number})\n`
37
+ }
38
+
39
+ export function changesetPath(number) {
40
+ return `.changeset/auto-pr-${number}.md`
41
+ }
42
+
43
+ export function isReleaseBranch(ref) {
44
+ return RELEASE_BRANCH.test(ref)
45
+ }
46
+
47
+ export function hasChangeset(files) {
48
+ return files.some(file => CHANGESET_PATH.test(file.filename ?? file))
49
+ }
50
+
51
+ function hasManualChangeset(files, generatedPath) {
52
+ return files.some((file) => {
53
+ const filename = file.filename ?? file
54
+ return CHANGESET_PATH.test(filename) && filename !== generatedPath
55
+ })
56
+ }
57
+
58
+ export function isPublishableManifest(manifest) {
59
+ return Boolean(manifest && typeof manifest.name === 'string' && manifest.private !== true)
60
+ }
61
+
62
+ async function manifestsForFiles(client, files, ref) {
63
+ const names = []
64
+ for (const directory of packageDirectories(files)) {
65
+ const content = await client.getContent(`packages/${directory}/package.json`, ref)
66
+ if (!content) {
67
+ continue
68
+ }
69
+ try {
70
+ const manifest = JSON.parse(content)
71
+ if (isPublishableManifest(manifest)) {
72
+ names.push(manifest.name)
73
+ }
74
+ }
75
+ catch {
76
+ // Ignore a malformed manifest; the normal CI checks will report it.
77
+ }
78
+ }
79
+ return [...new Set(names)]
80
+ }
81
+
82
+ async function commitChangesets(client, branch, baseSha, entries) {
83
+ const commit = await client.getCommit(baseSha)
84
+ const tree = []
85
+ for (const entry of entries) {
86
+ const blob = await client.createBlob(entry.content)
87
+ tree.push({ path: entry.path, mode: '100644', type: 'blob', sha: blob.sha })
88
+ }
89
+ const nextTree = await client.createTree(commit.tree.sha, tree)
90
+ const nextCommit = await client.createCommit('chore(release): add automated changesets', nextTree.sha, [baseSha])
91
+ await client.updateRef(branch, nextCommit.sha)
92
+ return nextCommit.sha
93
+ }
94
+
95
+ async function commentFork(client, number) {
96
+ const comments = await client.listComments(number)
97
+ if (comments.some(comment => comment.body?.includes(CHANGESET_MARKER))) {
98
+ return false
99
+ }
100
+ await client.createComment(number, `${CHANGESET_MARKER}\nThis PR changes a publishable package. Please add a .changeset/*.md release intent before merging. You can run pnpm change locally.`)
101
+ return true
102
+ }
103
+
104
+ async function prepareEntry(client, pullRequest, files) {
105
+ const path = changesetPath(pullRequest.number)
106
+ if (pullRequest.draft || isReleaseBranch(pullRequest.head.ref) || hasManualChangeset(files, path)) {
107
+ return undefined
108
+ }
109
+ const packages = await manifestsForFiles(client, files, pullRequest.head.sha)
110
+ if (!packages.length) {
111
+ return undefined
112
+ }
113
+ const level = releaseLevel(pullRequest.labels)
114
+ const content = renderChangeset({ packages, level, number: pullRequest.number, title: pullRequest.title })
115
+ const existing = await client.getContent(path, pullRequest.head.sha)
116
+ if (existing && !['patch', 'minor', 'major'].some(candidate => existing === renderChangeset({ packages, level: candidate, number: pullRequest.number, title: pullRequest.title }))) {
117
+ return undefined
118
+ }
119
+ if (existing === content) {
120
+ return undefined
121
+ }
122
+ return {
123
+ path,
124
+ content,
125
+ }
126
+ }
127
+
128
+ export async function processPullRequest(client, number) {
129
+ const pullRequest = await client.getPullRequest(number)
130
+ const files = await client.getPullRequestFiles(number)
131
+ const entry = await prepareEntry(client, pullRequest, files)
132
+ if (!entry) {
133
+ return { action: 'skipped', number }
134
+ }
135
+ const repository = pullRequest.base.repo.full_name
136
+ if (pullRequest.head.repo.full_name !== repository) {
137
+ await commentFork(client, number)
138
+ return { action: 'commented', number }
139
+ }
140
+ const ref = await client.getRef(`heads/${pullRequest.head.ref}`)
141
+ await commitChangesets(client, pullRequest.head.ref, ref.object.sha, [entry])
142
+ return { action: 'committed', number, path: entry.path }
143
+ }
144
+
145
+ export async function backfillPullRequests(client, numbers, { runId = `${Date.now()}` } = {}) {
146
+ const baseRef = await client.getRef('heads/main')
147
+ const entries = []
148
+ const seen = new Set()
149
+ const results = []
150
+ for (const number of numbers) {
151
+ const pullRequest = await client.getPullRequest(number)
152
+ if (!pullRequest.merged_at || pullRequest.base.ref !== 'main') {
153
+ results.push({ action: 'skipped', number })
154
+ continue
155
+ }
156
+ const files = await client.getPullRequestFiles(number)
157
+ const path = changesetPath(number)
158
+ if (hasChangeset(files) || seen.has(path) || await client.getContent(path, baseRef.object.sha)) {
159
+ results.push({ action: 'skipped', number })
160
+ continue
161
+ }
162
+ const packages = await manifestsForFiles(client, files, pullRequest.merge_commit_sha)
163
+ if (!packages.length) {
164
+ results.push({ action: 'skipped', number })
165
+ continue
166
+ }
167
+ seen.add(path)
168
+ entries.push({
169
+ path,
170
+ content: renderChangeset({ packages, level: releaseLevel(pullRequest.labels), number, title: pullRequest.title }),
171
+ })
172
+ results.push({ action: 'planned', number, path })
173
+ }
174
+ if (!entries.length) {
175
+ return { results, pullRequest: undefined }
176
+ }
177
+ const branch = `automation/changeset-backfill-${runId}`
178
+ await client.createBranch(branch, baseRef.object.sha)
179
+ await commitChangesets(client, branch, baseRef.object.sha, entries)
180
+ const created = await client.createPullRequest({
181
+ base: 'main',
182
+ head: branch,
183
+ title: `chore(release): backfill changesets (${numbers.map(number => `#${number}`).join(', ')})`,
184
+ body: `This PR backfills automated release intents for merged PRs.\n\n${entries.map(entry => `- ${entry.path}`).join('\n')}`,
185
+ })
186
+ return { results, pullRequest: created }
187
+ }
188
+
189
+ async function main() {
190
+ const eventPath = process.env.GITHUB_EVENT_PATH
191
+ const event = eventPath ? JSON.parse(await fs.readFile(eventPath, 'utf8')) : undefined
192
+ const repository = process.env.GITHUB_REPOSITORY ?? event?.repository?.full_name
193
+ const token = process.env.GITHUB_TOKEN
194
+ if (!repository || !token) {
195
+ throw new Error('GITHUB_REPOSITORY and GITHUB_TOKEN are required')
196
+ }
197
+ const client = createGitHubClient({ token, repository })
198
+ if (process.env.GITHUB_EVENT_NAME === 'workflow_dispatch') {
199
+ const numbers = (process.env.PR_NUMBERS ?? '').split(',').map(value => Number(value.trim())).filter(value => Number.isInteger(value) && value > 0)
200
+ if (!numbers.length) {
201
+ throw new Error('PR_NUMBERS must contain at least one PR number')
202
+ }
203
+ console.log(JSON.stringify(await backfillPullRequests(client, numbers, { runId: process.env.GITHUB_RUN_ID })))
204
+ return
205
+ }
206
+ const number = event?.pull_request?.number
207
+ if (!number) {
208
+ throw new Error('pull_request event payload is required')
209
+ }
210
+ console.log(JSON.stringify(await processPullRequest(client, number)))
211
+ }
212
+
213
+ if (import.meta.url === `file://${process.argv[1]}`) {
214
+ main().catch((error) => {
215
+ console.error(error.stack ?? error)
216
+ process.exitCode = 1
217
+ })
218
+ }
@@ -36,7 +36,7 @@ jobs:
36
36
  with:
37
37
  fetch-depth: 2
38
38
 
39
- - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
39
+ - uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
40
40
 
41
41
  - name: Setup Node.js environment
42
42
  uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
@@ -0,0 +1,40 @@
1
+ name: Automatic Release Intent
2
+
3
+ on:
4
+ pull_request_target:
5
+ types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]
6
+ workflow_dispatch:
7
+ inputs:
8
+ pr_numbers:
9
+ description: Comma-separated merged PR numbers to backfill
10
+ required: true
11
+ type: string
12
+
13
+ permissions:
14
+ contents: write
15
+ pull-requests: write
16
+
17
+ concurrency:
18
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
19
+ cancel-in-progress: false
20
+
21
+ jobs:
22
+ generate:
23
+ name: Generate release intent
24
+ runs-on: ubuntu-latest
25
+ steps:
26
+ - name: Check out workflow source
27
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
28
+ with:
29
+ fetch-depth: 1
30
+
31
+ - name: Setup Node.js environment
32
+ uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
33
+ with:
34
+ node-version: 24
35
+
36
+ - name: Generate or backfill changesets
37
+ env:
38
+ GITHUB_TOKEN: ${{ github.token }}
39
+ PR_NUMBERS: ${{ inputs.pr_numbers }}
40
+ run: node .github/auto-changeset/index.mjs
@@ -54,7 +54,7 @@ jobs:
54
54
  with:
55
55
  fetch-depth: 0
56
56
 
57
- - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
57
+ - uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
58
58
 
59
59
  - name: Setup Node.js environment
60
60
  uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
@@ -23,6 +23,10 @@ pnpm test
23
23
 
24
24
  Changes to publishable packages require a pnpm change intent created with `pnpm change`. Commits must use Conventional Commit syntax.
25
25
 
26
+ Pull requests that change a publishable package receive an automatic `.changeset/auto-pr-<number>.md` intent when they come from a branch in this repository. The default bump is `patch`; add the `release:minor` or `release:major` label to override it. Fork pull requests cannot be written to by the workflow, so add the intent manually. Existing hand-written intents are always preserved.
27
+
28
+ To backfill merged pull requests that predate this automation, run the `Automatic Release Intent` workflow manually with a comma-separated list of PR numbers. The workflow opens one backfill pull request, and the next `repo release ci` run consumes its changesets normally.
29
+
26
30
  The repository includes repoctl's CLI and monorepo engine, template assets, shared lint/config packages, and the `apps/mock` fixture demo. Keep package APIs and independent version lines intact when working across these areas.
27
31
 
28
32
  When changing templates or managed root assets, update their source first and refresh packaged copies with `pnpm --filter @icebreakers/monorepo-templates sync:assets`.
@@ -3,7 +3,7 @@
3
3
  "type": "module",
4
4
  "version": "0.0.0",
5
5
  "private": true,
6
- "packageManager": "pnpm@11.25.0",
6
+ "packageManager": "pnpm@12.3.4",
7
7
  "description": "Source workspace for repoctl and Icebreaker's shared development packages",
8
8
  "author": "ice breaker <hi@sonofmagic.top>",
9
9
  "homepage": "https://repoctl.icebreaker.top",
@@ -85,18 +85,18 @@
85
85
  "@types/lodash-es": "^4.17.12",
86
86
  "@types/micromatch": "^4.0.10",
87
87
  "@icebreakers/monorepo": "workspace:*",
88
- "@types/node": "^26.4.1",
88
+ "@types/node": "^26.5.0",
89
89
  "@types/semver": "^7.8.0",
90
90
  "@types/set-value": "^4.0.3",
91
- "@typescript-eslint/types": "^8.69.0",
92
- "@unocss/eslint-plugin": "66.9.2",
93
- "@vitest/coverage-v8": "~4.1.11",
91
+ "@typescript-eslint/types": "^8.70.0",
92
+ "@unocss/eslint-plugin": "66.10.0",
93
+ "@vitest/coverage-v8": "~5.0.0",
94
94
  "astro-eslint-parser": "^3.1.0",
95
95
  "ci-info": "^4.4.0",
96
96
  "cross-env": "^10.1.0",
97
97
  "defu": "^6.1.7",
98
98
  "es-toolkit": "^1.52.0",
99
- "eslint": "^10.9.1",
99
+ "eslint": "^10.10.0",
100
100
  "eslint-plugin-astro": "^3.1.0",
101
101
  "eslint-plugin-mdx": "3.8.1",
102
102
  "eslint-plugin-svelte": "^3.23.0",
@@ -106,24 +106,24 @@
106
106
  "get-value": "^4.1.0",
107
107
  "husky": "^9.1.7",
108
108
  "jiti": "^2.7.0",
109
- "lint-staged": "^17.4.1",
109
+ "lint-staged": "^17.5.0",
110
110
  "lodash": "^4.18.1",
111
111
  "lodash-es": "^4.18.1",
112
112
  "micromatch": "^4.0.8",
113
113
  "only-allow": "^1.2.2",
114
114
  "pathe": "^2.0.3",
115
- "pkg-types": "^2.3.1",
115
+ "pkg-types": "^2.3.3",
116
116
  "prettier": "^3.9.6",
117
117
  "prettier-plugin-astro": "^0.14.1",
118
118
  "repoctl": "workspace:*",
119
119
  "rimraf": "^6.1.3",
120
120
  "set-value": "^4.1.0",
121
- "stylelint": "^17.14.1",
121
+ "stylelint": "^17.15.0",
122
122
  "svelte": "^5.57.0",
123
123
  "svelte-eslint-parser": "^1.8.1",
124
124
  "tailwindcss": "^4.3.3",
125
125
  "tsd": "^0.33.0",
126
- "tsdown": "0.22.14",
126
+ "tsdown": "0.23.0",
127
127
  "tslib": "^2.8.1",
128
128
  "tsx": "^4.23.13",
129
129
  "turbo": "^2.10.12",
@@ -131,7 +131,7 @@
131
131
  "tsup": "^8.5.1",
132
132
  "typescript": "^6.0.3",
133
133
  "unbuild": "^3.6.1",
134
- "vitest": "~4.1.11",
134
+ "vitest": "~5.0.0",
135
135
  "yaml": "^2.9.0"
136
136
  },
137
137
  "publishConfig": {
@@ -18,8 +18,8 @@ overrides:
18
18
  prettier: 3.9.6
19
19
  typescript: 6.0.3
20
20
  vite: 8.2.2
21
- postcss: 8.5.26
22
- postcss-selector-parser: 7.1.5
21
+ postcss: 8.5.28
22
+ postcss-selector-parser: 7.1.6
23
23
  js-yaml: 5.4.1
24
24
  nanoid: 6.0.1
25
25
  brace-expansion: 5.0.9
package/dist/index.d.mts CHANGED
@@ -24,20 +24,20 @@ interface SuggestTemplateKeyOptions extends GetTemplateChoicesOptions {
24
24
  }
25
25
  //#endregion
26
26
  //#region src/paths.d.ts
27
- declare const packageDir: string;
28
- declare const templatesDir: string;
29
- declare const assetsDir: string;
30
- declare const skeletonDir: string;
27
+ export declare const packageDir: string;
28
+ export declare const templatesDir: string;
29
+ export declare const assetsDir: string;
30
+ export declare const skeletonDir: string;
31
31
  //#endregion
32
32
  //#region src/prepare.d.ts
33
33
  interface PrepareAssetsOptions {
34
34
  overwriteExisting?: boolean;
35
35
  silent?: boolean;
36
36
  }
37
- declare function prepareAssets(options?: PrepareAssetsOptions): Promise<void>;
37
+ export declare function prepareAssets(options?: PrepareAssetsOptions): Promise<void>;
38
38
  //#endregion
39
39
  //#region src/runtime-assets.d.ts
40
- declare function ensureTemplateAssetsPrepared(): Promise<void>;
40
+ export declare function ensureTemplateAssetsPrepared(): Promise<void>;
41
41
  //#endregion
42
42
  //#region src/scaffold.d.ts
43
43
  type TargetMode = 'prepare' | 'ensure' | 'skip';
@@ -58,48 +58,48 @@ interface ScaffoldWorkspaceOptions {
58
58
  targetMode?: TargetMode;
59
59
  force?: boolean;
60
60
  }
61
- declare function scaffoldTemplate(options: ScaffoldTemplateOptions): Promise<void>;
62
- declare function scaffoldWorkspace(options: ScaffoldWorkspaceOptions): Promise<void>;
61
+ export declare function scaffoldTemplate(options: ScaffoldTemplateOptions): Promise<void>;
62
+ export declare function scaffoldWorkspace(options: ScaffoldWorkspaceOptions): Promise<void>;
63
63
  //#endregion
64
64
  //#region src/utils/command.d.ts
65
65
  interface RunCommandOptions {
66
66
  cwd?: string;
67
67
  stdio?: 'inherit' | 'pipe';
68
68
  }
69
- declare function runCommand(command: string, args: string[], options?: RunCommandOptions): Promise<{
69
+ export declare function runCommand(command: string, args: string[], options?: RunCommandOptions): Promise<{
70
70
  exitCode: number | null;
71
71
  }>;
72
- declare function execaCommand(command: string, options?: RunCommandOptions): Promise<{
72
+ export declare function execaCommand(command: string, options?: RunCommandOptions): Promise<{
73
73
  exitCode: number | null;
74
74
  }>;
75
75
  //#endregion
76
76
  //#region src/utils/gitignore.d.ts
77
- declare function toPublishGitignorePath(input: string): string;
78
- declare function toWorkspaceGitignorePath(input: string): string;
79
- declare function isGitignoreFile(name: string): boolean;
77
+ export declare function toPublishGitignorePath(input: string): string;
78
+ export declare function toWorkspaceGitignorePath(input: string): string;
79
+ export declare function isGitignoreFile(name: string): boolean;
80
80
  //#endregion
81
81
  //#region src/utils/template-filter.d.ts
82
- declare function shouldSkipTemplatePath(rootDir: string, targetPath: string): boolean;
83
- declare function createTemplateCopyFilter(rootDir: string): (src: string) => boolean;
82
+ export declare function shouldSkipTemplatePath(rootDir: string, targetPath: string): boolean;
83
+ export declare function createTemplateCopyFilter(rootDir: string): (src: string) => boolean;
84
84
  //#endregion
85
85
  //#region src/templates.d.ts
86
- declare const templateCategories: readonly ["app", "docs", "library", "service", "tool"];
87
- declare function isTemplateCategory(value: string): value is TemplateCategory;
88
- declare function getTemplateChoices(options?: GetTemplateChoicesOptions): TemplateChoice[];
89
- declare function getTemplateKeys(options?: GetTemplateChoicesOptions): string[];
90
- declare function getTemplateChoice(key: string): TemplateChoice | undefined;
91
- declare function isTemplateKey(key: string): boolean;
92
- declare function getTemplateDefinition(key: string): TemplateDefinition | undefined;
93
- declare function getTemplateSource(key: string): string | undefined;
94
- declare function getTemplateTarget(key: string): string | undefined;
95
- declare function suggestTemplateKey(key: string, options?: SuggestTemplateKeyOptions): string | undefined;
86
+ export declare const templateCategories: readonly ["app", "docs", "library", "service", "tool"];
87
+ export declare function isTemplateCategory(value: string): value is TemplateCategory;
88
+ export declare function getTemplateChoices(options?: GetTemplateChoicesOptions): TemplateChoice[];
89
+ export declare function getTemplateKeys(options?: GetTemplateChoicesOptions): string[];
90
+ export declare function getTemplateChoice(key: string): TemplateChoice | undefined;
91
+ export declare function isTemplateKey(key: string): boolean;
92
+ export declare function getTemplateDefinition(key: string): TemplateDefinition | undefined;
93
+ export declare function getTemplateSource(key: string): string | undefined;
94
+ export declare function getTemplateTarget(key: string): string | undefined;
95
+ export declare function suggestTemplateKey(key: string, options?: SuggestTemplateKeyOptions): string | undefined;
96
96
  //#endregion
97
97
  //#region src/index.d.ts
98
- declare const templateChoices: TemplateChoice[];
99
- declare const assetTargets: string[];
100
- declare const getAssetTargets: (core?: boolean) => string[];
101
- declare const templateSourceMap: Record<string, string>;
102
- declare const templateTargetMap: Record<string, string>;
103
- declare const templateMap: Record<string, string>;
98
+ export declare const templateChoices: TemplateChoice[];
99
+ export declare const assetTargets: string[];
100
+ export declare const getAssetTargets: (core?: boolean) => string[];
101
+ export declare const templateSourceMap: Record<string, string>;
102
+ export declare const templateTargetMap: Record<string, string>;
103
+ export declare const templateMap: Record<string, string>;
104
104
  //#endregion
105
- export { Command, type GetTemplateChoicesOptions, type SuggestTemplateKeyOptions, type TemplateCategory, type TemplateChoice, type TemplateDefinition, assetTargets, assetsDir, checkbox, createTemplateCopyFilter, ensureTemplateAssetsPrepared, execaCommand, getAssetTargets, getTemplateChoice, getTemplateChoices, getTemplateDefinition, getTemplateKeys, getTemplateSource, getTemplateTarget, input, isGitignoreFile, isTemplateCategory, isTemplateKey, packageDir, prepareAssets, program, runCommand, scaffoldTemplate, scaffoldWorkspace, select, shouldSkipTemplatePath, skeletonDir, suggestTemplateKey, templateCategories, templateChoices, templateMap, templateSourceMap, templateTargetMap, templatesDir, toPublishGitignorePath, toWorkspaceGitignorePath };
105
+ export { Command, type GetTemplateChoicesOptions, type SuggestTemplateKeyOptions, type TemplateCategory, type TemplateChoice, type TemplateDefinition, checkbox, input, program, select };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@icebreakers/monorepo-templates",
3
3
  "type": "module",
4
- "version": "1.3.2",
4
+ "version": "1.3.4",
5
5
  "description": "Built-in project templates and managed workspace assets for repoctl",
6
6
  "author": "ice breaker <hi@sonofmagic.top>",
7
7
  "license": "MIT",
@@ -45,9 +45,9 @@
45
45
  "node": ">=18.0.0"
46
46
  },
47
47
  "dependencies": {
48
- "@inquirer/checkbox": "^5.2.3",
49
- "@inquirer/input": "^5.1.4",
50
- "@inquirer/select": "^5.2.3",
48
+ "@inquirer/checkbox": "^5.2.5",
49
+ "@inquirer/input": "^5.1.6",
50
+ "@inquirer/select": "^5.2.5",
51
51
  "commander": "^15.0.0",
52
52
  "nanoexec": "^1.1.0",
53
53
  "yaml": "^2.9.0"
@@ -36,7 +36,7 @@
36
36
  "consola": "^3.4.2"
37
37
  },
38
38
  "devDependencies": {
39
- "tsdown": "0.22.14"
39
+ "tsdown": "0.23.0"
40
40
  },
41
41
  "publishConfig": {
42
42
  "bin": {
@@ -35,7 +35,7 @@
35
35
  "@tanstack/vue-query": "^5.102.8",
36
36
  "@tanstack/vue-query-devtools": "^6.1.48",
37
37
  "@tanstack/vue-table": "^9.2.4",
38
- "@tanstack/vue-virtual": "^3.13.36",
38
+ "@tanstack/vue-virtual": "^3.13.37",
39
39
  "@trpc/client": "^11.18.0",
40
40
  "clsx": "^2.1.1",
41
41
  "pinia": "^4.0.3",
@@ -43,7 +43,7 @@
43
43
  "tailwind-variants": "^3.3.1",
44
44
  "vue": "^3.5.42",
45
45
  "vue-i18n": "^11.4.10",
46
- "vue-router": "^5.3.0"
46
+ "vue-router": "^5.3.1"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@cloudflare/vite-plugin": "^1.54.3",
@@ -55,7 +55,7 @@
55
55
  "@vitejs/plugin-vue-jsx": "^5.1.6",
56
56
  "@vue/tsconfig": "^0.9.1",
57
57
  "consola": "^3.4.2",
58
- "hono": "^4.13.5",
58
+ "hono": "^4.13.7",
59
59
  "tailwindcss": "^4.3.3",
60
60
  "typescript": "~6.0.3",
61
61
  "vite": "^8.2.2",
@@ -63,8 +63,8 @@
63
63
  "devDependencies": {
64
64
  "@hono/node-server": "^2.1.1",
65
65
  "consola": "^3.4.2",
66
- "hono": "^4.13.5",
67
- "tsdown": "0.22.14",
66
+ "hono": "^4.13.7",
67
+ "tsdown": "0.23.0",
68
68
  "wrangler": "^4.128.0",
69
69
  "zod": "^4.5.4"
70
70
  }
@@ -38,7 +38,7 @@
38
38
  "devDependencies": {
39
39
  "@braintree/sanitize-url": "^7.1.2",
40
40
  "@tailwindcss/vite": "^4.3.3",
41
- "cytoscape": "^3.34.2",
41
+ "cytoscape": "^3.34.3",
42
42
  "cytoscape-cose-bilkent": "^4.1.0",
43
43
  "dayjs": "^1.11.23",
44
44
  "debug": "^4.4.3",