Skip to content

Commit b967087

Browse files
authored
Merge pull request #111 from TrueNine/dev
Merge dev into main
2 parents f34da7d + 932223c commit b967087

File tree

18 files changed

+463
-515
lines changed

18 files changed

+463
-515
lines changed

.github/actions/setup-node-pnpm/action.yml

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ inputs:
55
node-version:
66
description: Node.js version
77
required: false
8-
default: '25'
8+
default: "25"
99
install:
1010
description: Whether to run pnpm install
1111
required: false
12-
default: 'true'
12+
default: "true"
1313

1414
runs:
1515
using: composite
@@ -18,22 +18,11 @@ runs:
1818
uses: pnpm/action-setup@v4
1919

2020
- name: Setup Node
21-
uses: actions/setup-node@v4
21+
uses: actions/setup-node@v6
2222
with:
2323
node-version: ${{ inputs.node-version }}
24-
25-
- name: Get pnpm store directory
26-
id: pnpm-cache
27-
shell: bash
28-
run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
29-
30-
- name: Cache pnpm store
31-
uses: actions/cache@v4
32-
with:
33-
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
34-
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
35-
restore-keys: |
36-
${{ runner.os }}-pnpm-store-
24+
cache: pnpm
25+
cache-dependency-path: pnpm-lock.yaml
3726

3827
- name: Install workspace dependencies
3928
if: inputs.install == 'true'

.github/actions/setup-rust/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ runs:
2424
targets: ${{ inputs.targets }}
2525

2626
- name: Cache cargo
27-
uses: actions/cache@v4
27+
uses: actions/cache@v5
2828
with:
2929
path: |
3030
~/.cargo/registry

.github/actions/setup-tauri/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ runs:
2323
steps:
2424
- name: Cache Linux package archives
2525
if: runner.os == 'Linux'
26-
uses: actions/cache@v4
26+
uses: actions/cache@v5
2727
with:
2828
path: /var/cache/apt/archives
2929
key: ${{ runner.os }}-tauri-apt-${{ hashFiles('.github/actions/setup-tauri/action.yml') }}
@@ -80,7 +80,7 @@ runs:
8080
echo "hash=$HASH" >> $GITHUB_OUTPUT
8181
8282
- name: Cache cargo + tauri target
83-
uses: actions/cache@v4
83+
uses: actions/cache@v5
8484
with:
8585
path: |
8686
~/.cargo/registry

Cargo.lock

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/env.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,7 @@ declare const __CLI_PACKAGE_NAME__: string
1616
* Kiro global powers registry JSON string injected at build time
1717
*/
1818
declare const __KIRO_GLOBAL_POWERS_REGISTRY__: string
19+
20+
interface GlobalThis {
21+
__TNMSC_TEST_NATIVE_BINDING__?: object
22+
}

cli/eslint.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const config = await eslint10({
1111
strictTypescriptEslint: true,
1212
tsconfigPath: resolve(configDir, 'tsconfig.eslint.json'),
1313
parserOptions: {
14-
allowDefaultProject: ['*.config.ts']
14+
allowDefaultProject: ['*.config.ts', 'test/**/*.ts']
1515
}
1616
},
1717
ignores: [

cli/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@
4949
},
5050
"scripts": {
5151
"build": "run-s build:deps build:napi bundle finalize:bundle generate:schema",
52-
"build:napi": "tsx ../scripts/copy-napi.ts",
52+
"build:napi": "run-s build:native build:napi:copy",
53+
"build:napi:copy": "tsx ../scripts/copy-napi.ts",
54+
"build:native": "napi build --platform --release --output-dir dist -- --features napi",
5355
"build:deps": "pnpm -F @truenine/logger -F @truenine/md-compiler -F @truenine/script-runtime run build",
5456
"build:deps:ts": "pnpm -F @truenine/logger -F @truenine/md-compiler -F @truenine/script-runtime run build:ts",
5557
"bundle": "tsx ../scripts/build-quiet.ts",

cli/src/core/native-binding.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,16 @@
11
import {createRequire} from 'node:module'
22
import process from 'node:process'
33

4-
declare global {
5-
interface GlobalThis {
6-
__TNMSC_TEST_NATIVE_BINDING__?: object
7-
}
8-
}
9-
104
function shouldSkipNativeBinding(): boolean {
115
if (process.env['TNMSC_FORCE_NATIVE_BINDING'] === '1') return false
126
if (process.env['TNMSC_DISABLE_NATIVE_BINDING'] === '1') return true
137

14-
return process.env['NODE_ENV'] === 'test'
15-
|| process.env['VITEST'] != null
16-
|| process.env['VITEST_WORKER_ID'] != null
8+
return process.env['NODE_ENV'] === 'test' || process.env['VITEST'] != null || process.env['VITEST_WORKER_ID'] != null
179
}
1810

1911
export function tryLoadNativeBinding<T extends object>(): T | undefined {
20-
const testBinding: unknown = globalThis.__TNMSC_TEST_NATIVE_BINDING__
12+
const testGlobals = globalThis as typeof globalThis & {__TNMSC_TEST_NATIVE_BINDING__?: object}
13+
const testBinding: unknown = testGlobals.__TNMSC_TEST_NATIVE_BINDING__
2114
if (testBinding != null && typeof testBinding === 'object') return testBinding as T
2215
if (shouldSkipNativeBinding()) return void 0
2316

@@ -58,12 +51,9 @@ export function tryLoadNativeBinding<T extends object>(): T | undefined {
5851
for (const candidate of possibleBindings) {
5952
if (candidate != null && typeof candidate === 'object') return candidate as T
6053
}
61-
}
62-
catch {}
54+
} catch {}
6355
}
64-
}
65-
catch {
66-
}
56+
} catch {}
6757

6858
return void 0
6959
}

cli/src/plugins/plugin-core/filters.ts

Lines changed: 36 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,51 @@
1-
import type {
2-
ProjectConfig,
3-
RulePrompt,
4-
SeriName
5-
} from './types'
1+
import type {ProjectConfig, RulePrompt, SeriName} from './types'
62
import * as fs from 'node:fs'
73
import * as path from 'node:path'
84
import {getNativeBinding} from '@/core/native-binding'
95

106
interface SeriesFilterFns {
11-
readonly resolveEffectiveIncludeSeries: (
12-
topLevel?: readonly string[],
13-
typeSpecific?: readonly string[]
14-
) => string[]
15-
readonly matchesSeries: (
16-
seriName: string | readonly string[] | null | undefined,
17-
effectiveIncludeSeries: readonly string[]
18-
) => boolean
7+
readonly resolveEffectiveIncludeSeries: (topLevel?: readonly string[], typeSpecific?: readonly string[]) => string[]
8+
readonly matchesSeries: (seriName: string | readonly string[] | null | undefined, effectiveIncludeSeries: readonly string[]) => boolean
199
readonly resolveSubSeries: (
2010
topLevel?: Readonly<Record<string, readonly string[]>>,
2111
typeSpecific?: Readonly<Record<string, readonly string[]>>
2212
) => Record<string, string[]>
2313
}
2414

25-
function requireSeriesFilterFns(): SeriesFilterFns {
15+
let seriesFilterFnsCache: SeriesFilterFns | undefined
16+
17+
function getSeriesFilterFns(): SeriesFilterFns {
18+
if (seriesFilterFnsCache != null) return seriesFilterFnsCache
19+
2620
const candidate = getNativeBinding<SeriesFilterFns>()
2721
if (candidate == null) {
2822
throw new TypeError('Native series-filter binding is required. Build or install the Rust NAPI package before running tnmsc.')
2923
}
30-
if (typeof candidate.matchesSeries !== 'function'
24+
if (
25+
typeof candidate.matchesSeries !== 'function'
3126
|| typeof candidate.resolveEffectiveIncludeSeries !== 'function'
32-
|| typeof candidate.resolveSubSeries !== 'function') {
27+
|| typeof candidate.resolveSubSeries !== 'function'
28+
) {
3329
throw new TypeError('Native series-filter binding is incomplete. Rebuild the Rust NAPI package before running tnmsc.')
3430
}
31+
seriesFilterFnsCache = candidate
3532
return candidate
3633
}
3734

38-
const {
39-
resolveEffectiveIncludeSeries,
40-
matchesSeries,
41-
resolveSubSeries
42-
}: SeriesFilterFns = requireSeriesFilterFns()
35+
function resolveEffectiveIncludeSeries(topLevel?: readonly string[], typeSpecific?: readonly string[]): string[] {
36+
return getSeriesFilterFns().resolveEffectiveIncludeSeries(topLevel, typeSpecific)
37+
}
38+
39+
function matchesSeries(seriName: string | readonly string[] | null | undefined, effectiveIncludeSeries: readonly string[]): boolean {
40+
return getSeriesFilterFns().matchesSeries(seriName, effectiveIncludeSeries)
41+
}
42+
43+
function resolveSubSeries(
44+
topLevel?: Readonly<Record<string, readonly string[]>>,
45+
typeSpecific?: Readonly<Record<string, readonly string[]>>
46+
): Record<string, string[]> {
47+
return getSeriesFilterFns().resolveSubSeries(topLevel, typeSpecific)
48+
}
4349

4450
/**
4551
* Interface for items that can be filtered by series name
@@ -58,10 +64,7 @@ export function filterByProjectConfig<T extends SeriesFilterable>(
5864
projectConfig: ProjectConfig | undefined,
5965
configPath: FilterConfigPath
6066
): readonly T[] {
61-
const effectiveSeries = resolveEffectiveIncludeSeries(
62-
projectConfig?.includeSeries,
63-
projectConfig?.[configPath]?.includeSeries
64-
)
67+
const effectiveSeries = resolveEffectiveIncludeSeries(projectConfig?.includeSeries, projectConfig?.[configPath]?.includeSeries)
6568
return items.filter(item => matchesSeries(item.seriName, effectiveSeries))
6669
}
6770

@@ -77,10 +80,7 @@ function smartConcatGlob(prefix: string, glob: string): string {
7780
return `${prefix}/${glob}`
7881
}
7982

80-
function extractPrefixAndBaseGlob(
81-
glob: string,
82-
prefixes: readonly string[]
83-
): {prefix: string | null, baseGlob: string} {
83+
function extractPrefixAndBaseGlob(glob: string, prefixes: readonly string[]): {prefix: string | null, baseGlob: string} {
8484
for (const prefix of prefixes) {
8585
const normalizedPrefix = prefix.replaceAll(/\/+$/g, '')
8686
const patterns = [
@@ -95,10 +95,7 @@ function extractPrefixAndBaseGlob(
9595
return {prefix: null, baseGlob: glob}
9696
}
9797

98-
export function applySubSeriesGlobPrefix(
99-
rules: readonly RulePrompt[],
100-
projectConfig: ProjectConfig | undefined
101-
): readonly RulePrompt[] {
98+
export function applySubSeriesGlobPrefix(rules: readonly RulePrompt[], projectConfig: ProjectConfig | undefined): readonly RulePrompt[] {
10299
const subSeries = resolveSubSeries(projectConfig?.subSeries, projectConfig?.rules?.subSeries)
103100
if (Object.keys(subSeries).length === 0) return rules
104101

@@ -115,9 +112,7 @@ export function applySubSeriesGlobPrefix(
115112

116113
const matchedPrefixes: string[] = []
117114
for (const [subdir, seriNames] of Object.entries(normalizedSubSeries)) {
118-
const matched = Array.isArray(rule.seriName)
119-
? rule.seriName.some(name => seriNames.includes(name))
120-
: seriNames.includes(rule.seriName)
115+
const matched = Array.isArray(rule.seriName) ? rule.seriName.some(name => seriNames.includes(name)) : seriNames.includes(rule.seriName)
121116
if (matched) matchedPrefixes.push(subdir)
122117
}
123118

@@ -168,9 +163,7 @@ export function resolveGitInfoDir(projectDir: string): string | null {
168163
const gitdir = path.resolve(projectDir, match[1])
169164
return path.join(gitdir, 'info')
170165
}
171-
}
172-
catch {
173-
} // ignore read errors
166+
} catch {} // ignore read errors
174167
}
175168

176169
return null
@@ -193,8 +186,7 @@ export function findAllGitRepos(rootDir: string, maxDepth = 5): string[] {
193186
const raw = fs.readdirSync(dir, {withFileTypes: true})
194187
if (!Array.isArray(raw)) return
195188
entries = raw
196-
}
197-
catch {
189+
} catch {
198190
return
199191
}
200192

@@ -229,8 +221,7 @@ export function findGitModuleInfoDirs(dotGitDir: string): string[] {
229221
const raw = fs.readdirSync(dir, {withFileTypes: true})
230222
if (!Array.isArray(raw)) return
231223
entries = raw
232-
}
233-
catch {
224+
} catch {
234225
return
235226
}
236227

@@ -245,8 +236,7 @@ export function findGitModuleInfoDirs(dotGitDir: string): string[] {
245236
const raw = fs.readdirSync(path.join(dir, 'modules'), {withFileTypes: true})
246237
if (!Array.isArray(raw)) return
247238
subEntries = raw
248-
}
249-
catch {
239+
} catch {
250240
return
251241
}
252242
for (const sub of subEntries) {
@@ -259,8 +249,7 @@ export function findGitModuleInfoDirs(dotGitDir: string): string[] {
259249
const raw = fs.readdirSync(modulesDir, {withFileTypes: true})
260250
if (!Array.isArray(raw)) return results
261251
topEntries = raw
262-
}
263-
catch {
252+
} catch {
264253
return results
265254
}
266255

0 commit comments

Comments
 (0)