@coreframe/scripts 0.1.0 → 0.1.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.
- package/dist/config.d.ts +18 -4
- package/dist/config.js +1 -3
- package/dist/coreframe.d.ts +243 -241
- package/dist/coreframe.js +1 -239
- package/dist/db/client.d.ts +26 -18
- package/dist/db/client.js +1 -29
- package/dist/db/config.d.ts +22 -19
- package/dist/db/config.js +1 -32
- package/dist/db/drizzle-kit.d.ts +6 -5
- package/dist/db/drizzle-kit.js +1 -21
- package/dist/db/ensure.d.ts +20 -2
- package/dist/db/ensure.js +1 -39
- package/dist/db/migrate-held.d.ts +16 -10
- package/dist/db/migrate-held.js +3 -112
- package/dist/db/migrate.d.ts +4 -2
- package/dist/db/migrate.js +1 -24
- package/dist/db/project.d.ts +19 -7
- package/dist/db/project.js +1 -9
- package/dist/db/reset.d.ts +4 -2
- package/dist/db/reset.js +1 -18
- package/dist/db/schema-push.d.ts +22 -0
- package/dist/db/schema-push.js +1 -0
- package/dist/db/seed.d.ts +6 -3
- package/dist/db/seed.js +1 -22
- package/dist/db/setup.d.ts +6 -3
- package/dist/db/setup.js +1 -14
- package/dist/deploy/check-migrations.d.ts +4 -2
- package/dist/deploy/check-migrations.js +1 -17
- package/dist/deploy/checks.d.ts +6 -2
- package/dist/deploy/checks.js +1 -27
- package/dist/deploy/config.d.ts +47 -44
- package/dist/deploy/config.js +1 -9
- package/dist/deploy/migrations.d.ts +21 -18
- package/dist/deploy/migrations.js +4 -203
- package/dist/deploy/pending-migrations.d.ts +9 -5
- package/dist/deploy/pending-migrations.js +1 -30
- package/dist/deploy/tauri-release.d.ts +93 -73
- package/dist/deploy/tauri-release.js +1 -512
- package/dist/deploy/version.d.ts +15 -13
- package/dist/deploy/version.js +1 -41
- package/dist/deploy.d.ts +16 -15
- package/dist/deploy.js +1 -246
- package/dist/dev.d.ts +23 -12
- package/dist/dev.js +1 -95
- package/dist/image-generator.d.ts +18 -2
- package/dist/image-generator.js +1 -59
- package/dist/project.d.ts +4 -1
- package/dist/project.js +1 -13
- package/dist/typecheck.d.ts +4 -2
- package/dist/typecheck.js +1 -44
- package/dist/upgrade/check-skill-current.d.ts +10 -5
- package/dist/upgrade/check-skill-current.js +1 -87
- package/dist/upgrade/ensure-template-remote.d.ts +10 -5
- package/dist/upgrade/ensure-template-remote.js +1 -56
- package/dist/upgrade/fast-forward-template-files.d.ts +8 -6
- package/dist/upgrade/fast-forward-template-files.js +1 -279
- package/package.json +7 -2
- package/config.test.ts +0 -15
- package/config.ts +0 -9
- package/coreframe.ts +0 -272
- package/db/client.ts +0 -72
- package/db/config.ts +0 -41
- package/db/drizzle-kit.test.ts +0 -27
- package/db/drizzle-kit.ts +0 -39
- package/db/ensure.ts +0 -67
- package/db/migrate-held.test.ts +0 -81
- package/db/migrate-held.ts +0 -166
- package/db/migrate.ts +0 -39
- package/db/project.ts +0 -28
- package/db/reset.ts +0 -24
- package/db/seed.ts +0 -38
- package/db/setup.ts +0 -18
- package/deploy/check-migrations.ts +0 -31
- package/deploy/checks.ts +0 -38
- package/deploy/config.test.ts +0 -24
- package/deploy/config.ts +0 -68
- package/deploy/migrations.test.ts +0 -110
- package/deploy/migrations.ts +0 -317
- package/deploy/pending-migrations.test.ts +0 -93
- package/deploy/pending-migrations.ts +0 -45
- package/deploy/tauri-release.test.ts +0 -196
- package/deploy/tauri-release.ts +0 -816
- package/deploy/version.test.ts +0 -29
- package/deploy/version.ts +0 -65
- package/deploy.test.ts +0 -101
- package/deploy.ts +0 -346
- package/dev.test.ts +0 -153
- package/dev.ts +0 -155
- package/image-generator.ts +0 -84
- package/project.ts +0 -6
- package/tsconfig.build.json +0 -12
- package/tsconfig.json +0 -20
- package/typecheck.ts +0 -55
- package/upgrade/check-skill-current.ts +0 -112
- package/upgrade/ensure-template-remote.ts +0 -79
- package/upgrade/fast-forward-template-files.ts +0 -408
package/dev.ts
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawn as nodeSpawn } from "node:child_process"
|
|
3
|
-
import { createWriteStream } from "node:fs"
|
|
4
|
-
import { mkdir } from "node:fs/promises"
|
|
5
|
-
import path from "node:path"
|
|
6
|
-
import process from "node:process"
|
|
7
|
-
import type { Readable } from "node:stream"
|
|
8
|
-
|
|
9
|
-
type Spawn = typeof nodeSpawn
|
|
10
|
-
type TeeProcess = {
|
|
11
|
-
on(event: "close", listener: (code: number | null, signal: NodeJS.Signals | null) => void): void
|
|
12
|
-
on(event: "error", listener: (error: Error) => void): void
|
|
13
|
-
stderr: Readable | null
|
|
14
|
-
stdout: Readable | null
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export type DevServerOptions = {
|
|
18
|
-
cwd?: string
|
|
19
|
-
env?: NodeJS.ProcessEnv
|
|
20
|
-
logPath?: string
|
|
21
|
-
platform?: DevPlatform
|
|
22
|
-
spawn?: Spawn
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type DevPlatform = "android" | "desktop" | "ios" | "web"
|
|
26
|
-
|
|
27
|
-
const defaultLogPath = ".agents/logs/dev-server.log"
|
|
28
|
-
const nodeModulesBinPath = path.resolve("node_modules", ".bin")
|
|
29
|
-
const pnpmCommand = process.platform === "win32" ? "pnpm.cmd" : "pnpm"
|
|
30
|
-
const reactRouterCommand =
|
|
31
|
-
process.platform === "win32" ? "react-router.cmd" : "react-router"
|
|
32
|
-
|
|
33
|
-
export async function runDevServer({
|
|
34
|
-
cwd = process.cwd(),
|
|
35
|
-
env = process.env,
|
|
36
|
-
logPath = defaultLogPath,
|
|
37
|
-
platform = "web",
|
|
38
|
-
spawn = nodeSpawn,
|
|
39
|
-
}: DevServerOptions = {}) {
|
|
40
|
-
const pathEnvValue = env.PATH ?? env.Path ?? ""
|
|
41
|
-
const shouldTee = !("TAURI_ENV_PLATFORM" in env)
|
|
42
|
-
const log = shouldTee ? await createDevLog(logPath) : undefined
|
|
43
|
-
|
|
44
|
-
try {
|
|
45
|
-
if (platform === "web") {
|
|
46
|
-
await runDevProcess(spawn, pnpmCommand, ["db", "ensure"], {
|
|
47
|
-
cwd,
|
|
48
|
-
env,
|
|
49
|
-
log,
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
await runDevProcess(spawn, reactRouterCommand, ["dev"], {
|
|
53
|
-
cwd,
|
|
54
|
-
env: {
|
|
55
|
-
...env,
|
|
56
|
-
CLOUDFLARE_ENV: "development",
|
|
57
|
-
PATH: nodeModulesBinPath + path.delimiter + pathEnvValue,
|
|
58
|
-
},
|
|
59
|
-
log,
|
|
60
|
-
})
|
|
61
|
-
return
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
await runDevProcess(spawn, pnpmCommand, tauriDevArgs(platform), {
|
|
65
|
-
cwd,
|
|
66
|
-
env,
|
|
67
|
-
log,
|
|
68
|
-
})
|
|
69
|
-
} finally {
|
|
70
|
-
await closeLog(log)
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async function createDevLog(logPath: string) {
|
|
75
|
-
await mkdir(path.dirname(logPath), { recursive: true })
|
|
76
|
-
return createWriteStream(logPath, { flags: "w" })
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function closeLog(log: NodeJS.WritableStream | undefined) {
|
|
80
|
-
if (!log) {
|
|
81
|
-
return Promise.resolve()
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return new Promise<void>((resolve, reject) => {
|
|
85
|
-
log.once("error", reject)
|
|
86
|
-
log.end(resolve)
|
|
87
|
-
})
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function tauriDevArgs(platform: Exclude<DevPlatform, "web">) {
|
|
91
|
-
return ["--dir=tauri", "tauri", ...(platform === "desktop" ? [] : [platform]), "dev"]
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function runDevProcess(
|
|
95
|
-
spawn: Spawn,
|
|
96
|
-
command: string,
|
|
97
|
-
args: string[],
|
|
98
|
-
{
|
|
99
|
-
cwd,
|
|
100
|
-
env,
|
|
101
|
-
log,
|
|
102
|
-
}: {
|
|
103
|
-
cwd: string
|
|
104
|
-
env: NodeJS.ProcessEnv
|
|
105
|
-
log: NodeJS.WritableStream | undefined
|
|
106
|
-
},
|
|
107
|
-
) {
|
|
108
|
-
return new Promise<void>((resolve, reject) => {
|
|
109
|
-
const child = spawn(command, args, {
|
|
110
|
-
cwd,
|
|
111
|
-
env,
|
|
112
|
-
stdio: log ? ["inherit", "pipe", "pipe"] : "inherit",
|
|
113
|
-
}) as unknown as TeeProcess
|
|
114
|
-
|
|
115
|
-
if (log) {
|
|
116
|
-
if (!child.stdout || !child.stderr) {
|
|
117
|
-
reject(new Error(`${[command, ...args].join(" ")} did not provide output streams`))
|
|
118
|
-
return
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
child.stdout.on("data", (chunk) => {
|
|
122
|
-
process.stdout.write(chunk)
|
|
123
|
-
log.write(chunk)
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
child.stderr.on("data", (chunk) => {
|
|
127
|
-
process.stderr.write(chunk)
|
|
128
|
-
log.write(chunk)
|
|
129
|
-
})
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
child.on("error", reject)
|
|
133
|
-
|
|
134
|
-
child.on("close", (code, signal) => {
|
|
135
|
-
if (code === 0) {
|
|
136
|
-
resolve()
|
|
137
|
-
return
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const commandText = [command, ...args].join(" ")
|
|
141
|
-
reject(
|
|
142
|
-
new Error(
|
|
143
|
-
`${commandText} failed${signal ? ` with signal ${signal}` : ` with exit code ${code ?? 1}`}`,
|
|
144
|
-
),
|
|
145
|
-
)
|
|
146
|
-
})
|
|
147
|
-
})
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (import.meta.main) {
|
|
151
|
-
runDevServer().catch((error) => {
|
|
152
|
-
console.error(error)
|
|
153
|
-
process.exit(1)
|
|
154
|
-
})
|
|
155
|
-
}
|
package/image-generator.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs"
|
|
2
|
-
import path from "node:path"
|
|
3
|
-
|
|
4
|
-
import type sharp from "sharp"
|
|
5
|
-
import { glob } from "tinyglobby"
|
|
6
|
-
import type { Plugin } from "vite"
|
|
7
|
-
|
|
8
|
-
type SharpFactory = typeof sharp
|
|
9
|
-
|
|
10
|
-
export function imageGenerator(): Plugin {
|
|
11
|
-
return {
|
|
12
|
-
name: "image-generator",
|
|
13
|
-
async buildStart() {
|
|
14
|
-
const files = await glob(["src/**/*@3x.{png,webp}", "public/**/*@3x.{png,webp}"])
|
|
15
|
-
|
|
16
|
-
console.log(`[image-generator] Found ${files.length} @3x images.`)
|
|
17
|
-
|
|
18
|
-
await Promise.all(files.map((file) => generateDensityImages(file)))
|
|
19
|
-
},
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async function generateDensityImages(file: string) {
|
|
24
|
-
const dir = path.dirname(file)
|
|
25
|
-
const ext = path.extname(file)
|
|
26
|
-
const base = path.basename(file, `@3x${ext}`)
|
|
27
|
-
const outputImages = [
|
|
28
|
-
{
|
|
29
|
-
outputPath: path.join(dir, `${base}@2x${ext}`),
|
|
30
|
-
scale: 2 / 3,
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
outputPath: path.join(dir, `${base}@1x${ext}`),
|
|
34
|
-
scale: 1 / 3,
|
|
35
|
-
},
|
|
36
|
-
].filter((image) => !fs.existsSync(image.outputPath))
|
|
37
|
-
|
|
38
|
-
if (outputImages.length === 0) {
|
|
39
|
-
return
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const { default: sharp } = await import("sharp")
|
|
43
|
-
let width: number | undefined
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
width = (await sharp(file).metadata()).width
|
|
47
|
-
} catch (error) {
|
|
48
|
-
console.error(`[image-generator] Failed to read metadata for ${file}`, error)
|
|
49
|
-
return
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (!width) {
|
|
53
|
-
console.error(`[image-generator] Skipping ${file}; image width could not be read.`)
|
|
54
|
-
return
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
await Promise.all(
|
|
58
|
-
outputImages.map((image) =>
|
|
59
|
-
generateDensityImage({
|
|
60
|
-
file,
|
|
61
|
-
outputPath: image.outputPath,
|
|
62
|
-
sharp,
|
|
63
|
-
width: Math.round(width * image.scale),
|
|
64
|
-
}),
|
|
65
|
-
),
|
|
66
|
-
)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async function generateDensityImage(options: {
|
|
70
|
-
file: string
|
|
71
|
-
outputPath: string
|
|
72
|
-
sharp: SharpFactory
|
|
73
|
-
width: number
|
|
74
|
-
}) {
|
|
75
|
-
try {
|
|
76
|
-
console.log(`[image-generator] Generating ${options.outputPath} (${options.width}w)`)
|
|
77
|
-
await options.sharp(options.file).resize({ width: options.width }).toFile(options.outputPath)
|
|
78
|
-
} catch (error) {
|
|
79
|
-
console.error(
|
|
80
|
-
`[image-generator] Failed to process ${options.file} for ${options.outputPath}`,
|
|
81
|
-
error,
|
|
82
|
-
)
|
|
83
|
-
}
|
|
84
|
-
}
|
package/project.ts
DELETED
package/tsconfig.build.json
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "./tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"allowImportingTsExtensions": false,
|
|
5
|
-
"declaration": true,
|
|
6
|
-
"emitDeclarationOnly": false,
|
|
7
|
-
"noEmit": false,
|
|
8
|
-
"outDir": "dist",
|
|
9
|
-
"rewriteRelativeImportExtensions": true
|
|
10
|
-
},
|
|
11
|
-
"exclude": ["**/*.test.ts", "**/*.test.tsx", "dist"]
|
|
12
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"allowImportingTsExtensions": true,
|
|
4
|
-
"allowSyntheticDefaultImports": true,
|
|
5
|
-
"esModuleInterop": true,
|
|
6
|
-
"forceConsistentCasingInFileNames": true,
|
|
7
|
-
"isolatedModules": true,
|
|
8
|
-
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
9
|
-
"module": "ESNext",
|
|
10
|
-
"moduleResolution": "Bundler",
|
|
11
|
-
"noEmit": true,
|
|
12
|
-
"resolveJsonModule": true,
|
|
13
|
-
"rootDir": ".",
|
|
14
|
-
"skipLibCheck": true,
|
|
15
|
-
"strict": true,
|
|
16
|
-
"target": "ES2022",
|
|
17
|
-
"types": ["node"]
|
|
18
|
-
},
|
|
19
|
-
"include": ["**/*.ts"]
|
|
20
|
-
}
|
package/typecheck.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { access } from "node:fs/promises"
|
|
3
|
-
import path from "node:path"
|
|
4
|
-
import process from "node:process"
|
|
5
|
-
|
|
6
|
-
import { supervise } from "procband"
|
|
7
|
-
|
|
8
|
-
const nodeModulesBinPath = path.resolve("node_modules", ".bin")
|
|
9
|
-
process.env.PATH = nodeModulesBinPath + path.delimiter + process.env.PATH
|
|
10
|
-
|
|
11
|
-
const tscCommand = process.platform === "win32" ? "tsc.cmd" : "tsc"
|
|
12
|
-
const projects = [
|
|
13
|
-
{ name: "scripts", path: "scripts/tsconfig.json" },
|
|
14
|
-
{ name: "shared", path: "src/shared/tsconfig.json" },
|
|
15
|
-
{ name: "api", path: "src/api/tsconfig.json" },
|
|
16
|
-
{ name: "worker", path: "src/api/worker/tsconfig.json" },
|
|
17
|
-
{ name: "web", path: "src/web/tsconfig.json" },
|
|
18
|
-
] as const
|
|
19
|
-
|
|
20
|
-
export async function typecheckProject() {
|
|
21
|
-
const existingProjects = []
|
|
22
|
-
|
|
23
|
-
for (const project of projects) {
|
|
24
|
-
try {
|
|
25
|
-
await access(project.path)
|
|
26
|
-
existingProjects.push(project)
|
|
27
|
-
} catch (error) {
|
|
28
|
-
if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) {
|
|
29
|
-
throw error
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const checks = existingProjects.map((project) =>
|
|
35
|
-
supervise({
|
|
36
|
-
name: project.name,
|
|
37
|
-
command: tscCommand,
|
|
38
|
-
args: ["-p", project.path],
|
|
39
|
-
}),
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
const results = await Promise.all(checks.map((check) => check.wait()))
|
|
43
|
-
const failed = results.filter((result) => result.exitCode !== 0)
|
|
44
|
-
|
|
45
|
-
if (failed.length > 0) {
|
|
46
|
-
process.exitCode = failed[0].exitCode
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (import.meta.main) {
|
|
51
|
-
typecheckProject().catch((error) => {
|
|
52
|
-
console.error(error)
|
|
53
|
-
process.exit(1)
|
|
54
|
-
})
|
|
55
|
-
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawnSync } from "node:child_process"
|
|
3
|
-
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"
|
|
4
|
-
import { tmpdir } from "node:os"
|
|
5
|
-
import { join } from "node:path"
|
|
6
|
-
|
|
7
|
-
const skillPath = ".agents/skills/coreframe-upgrade/SKILL.md"
|
|
8
|
-
|
|
9
|
-
export type CheckUpgradeSkillOptions = {
|
|
10
|
-
apply: boolean
|
|
11
|
-
target: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function git(args: string[], options: { encoding?: BufferEncoding } = {}) {
|
|
15
|
-
return spawnSync("git", args, options)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function errorDetail(result: ReturnType<typeof spawnSync>) {
|
|
19
|
-
return result.stderr.toString("utf8").trim() || result.stdout.toString("utf8").trim()
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function readGitFile(ref: string, path: string) {
|
|
23
|
-
const result = git(["show", `${ref}:${path}`], { encoding: "utf8" })
|
|
24
|
-
|
|
25
|
-
if (result.status !== 0) {
|
|
26
|
-
const detail = errorDetail(result)
|
|
27
|
-
throw new Error(`Could not read ${path} at ${ref}.${detail ? ` ${detail}` : ""}`)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return result.stdout.toString()
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function getRepoRoot() {
|
|
34
|
-
const result = git(["rev-parse", "--show-toplevel"], { encoding: "utf8" })
|
|
35
|
-
|
|
36
|
-
if (result.status !== 0) {
|
|
37
|
-
const detail = errorDetail(result)
|
|
38
|
-
throw new Error(`Could not find git repository root.${detail ? ` ${detail}` : ""}`)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return result.stdout.toString().trim()
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function printDiff(localPath: string, targetText: string) {
|
|
45
|
-
const dir = mkdtempSync(join(tmpdir(), "coreframe-upgrade-skill-"))
|
|
46
|
-
const targetPath = join(dir, "SKILL.md")
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
writeFileSync(targetPath, targetText)
|
|
50
|
-
const diff = git([
|
|
51
|
-
"--no-pager",
|
|
52
|
-
"diff",
|
|
53
|
-
"--no-index",
|
|
54
|
-
"--color=never",
|
|
55
|
-
"--",
|
|
56
|
-
localPath,
|
|
57
|
-
targetPath,
|
|
58
|
-
])
|
|
59
|
-
const output = errorDetail(diff)
|
|
60
|
-
|
|
61
|
-
if (output) {
|
|
62
|
-
console.log(output)
|
|
63
|
-
}
|
|
64
|
-
} finally {
|
|
65
|
-
rmSync(dir, { force: true, recursive: true })
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function checkUpgradeSkillCurrent({ apply, target }: CheckUpgradeSkillOptions) {
|
|
70
|
-
const repoRoot = getRepoRoot()
|
|
71
|
-
const localPath = join(repoRoot, skillPath)
|
|
72
|
-
|
|
73
|
-
if (!existsSync(localPath)) {
|
|
74
|
-
throw new Error(`Local ${skillPath} does not exist.`)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const localText = readFileSync(localPath, "utf8")
|
|
78
|
-
const targetText = readGitFile(target, skillPath)
|
|
79
|
-
|
|
80
|
-
if (localText === targetText) {
|
|
81
|
-
console.log(`Coreframe upgrade skill matches ${target}:${skillPath}.`)
|
|
82
|
-
return 0
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (apply) {
|
|
86
|
-
writeFileSync(localPath, targetText)
|
|
87
|
-
console.error(`Updated ${skillPath} from ${target}. Reread it before continuing the upgrade.`)
|
|
88
|
-
return 20
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
console.error(`Coreframe upgrade skill differs from ${target}:${skillPath}.`)
|
|
92
|
-
console.error(`Run again with --apply to update it, then reread ${skillPath} before continuing.`)
|
|
93
|
-
printDiff(localPath, targetText)
|
|
94
|
-
return 20
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (import.meta.main) {
|
|
98
|
-
const targetIndex = process.argv.indexOf("--target")
|
|
99
|
-
const target = targetIndex === -1 ? null : process.argv[targetIndex + 1]
|
|
100
|
-
|
|
101
|
-
if (!target) {
|
|
102
|
-
console.error("Usage: coreframe upgrade check-skill-current --target <git-ref> [--apply]")
|
|
103
|
-
process.exit(64)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
try {
|
|
107
|
-
process.exit(checkUpgradeSkillCurrent({ apply: process.argv.includes("--apply"), target }))
|
|
108
|
-
} catch (error) {
|
|
109
|
-
console.error(error instanceof Error ? error.message : String(error))
|
|
110
|
-
process.exit(65)
|
|
111
|
-
}
|
|
112
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawnSync } from "node:child_process"
|
|
3
|
-
|
|
4
|
-
const defaultRemote = "template"
|
|
5
|
-
const defaultUrl = "https://github.com/airlock-labs/coreframe.git"
|
|
6
|
-
|
|
7
|
-
export type EnsureTemplateRemoteOptions = {
|
|
8
|
-
fetch: boolean
|
|
9
|
-
remote: string
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function git(args: string[]) {
|
|
13
|
-
return spawnSync("git", args, { encoding: "utf8" })
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function runGit(args: string[]) {
|
|
17
|
-
const result = git(args)
|
|
18
|
-
|
|
19
|
-
if (result.status !== 0) {
|
|
20
|
-
const detail = result.stderr.trim() || result.stdout.trim()
|
|
21
|
-
throw new Error(`Git command failed: git ${args.join(" ")}${detail ? `\n${detail}` : ""}`)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return result.stdout
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function getRemoteUrl(remote: string) {
|
|
28
|
-
const result = git(["remote", "get-url", remote])
|
|
29
|
-
|
|
30
|
-
if (result.status === 2) {
|
|
31
|
-
return null
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (result.status !== 0) {
|
|
35
|
-
const detail = result.stderr.trim() || result.stdout.trim()
|
|
36
|
-
throw new Error(`Could not inspect remote ${remote}.${detail ? `\n${detail}` : ""}`)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return result.stdout.trim()
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function ensureTemplateRemote({
|
|
43
|
-
fetch = true,
|
|
44
|
-
remote = defaultRemote,
|
|
45
|
-
}: Partial<EnsureTemplateRemoteOptions> = {}) {
|
|
46
|
-
if (remote.length === 0) {
|
|
47
|
-
throw new Error("Remote name must not be empty.")
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
runGit(["rev-parse", "--show-toplevel"])
|
|
51
|
-
|
|
52
|
-
const existingUrl = getRemoteUrl(remote)
|
|
53
|
-
|
|
54
|
-
if (existingUrl === null) {
|
|
55
|
-
runGit(["remote", "add", remote, defaultUrl])
|
|
56
|
-
console.log(`Added ${remote} remote: ${defaultUrl}`)
|
|
57
|
-
} else if (existingUrl === defaultUrl) {
|
|
58
|
-
console.log(`${remote} remote already points at ${defaultUrl}`)
|
|
59
|
-
} else {
|
|
60
|
-
throw new Error(
|
|
61
|
-
`${remote} remote points at ${existingUrl}, not ${defaultUrl}.\n` +
|
|
62
|
-
"Choose the intended template source before continuing, then update or rename the remote manually.",
|
|
63
|
-
)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (fetch) {
|
|
67
|
-
runGit(["fetch", remote, "--tags", "--prune"])
|
|
68
|
-
console.log(`Fetched ${remote}.`)
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (import.meta.main) {
|
|
73
|
-
try {
|
|
74
|
-
ensureTemplateRemote({ fetch: !process.argv.includes("--no-fetch") })
|
|
75
|
-
} catch (error) {
|
|
76
|
-
console.error(error instanceof Error ? error.message : String(error))
|
|
77
|
-
process.exit(65)
|
|
78
|
-
}
|
|
79
|
-
}
|