spine-framework 0.1.50 → 0.1.51
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.
|
@@ -5,42 +5,27 @@
|
|
|
5
5
|
* @layer cli
|
|
6
6
|
* @stability stable
|
|
7
7
|
*
|
|
8
|
-
* `spine dev` command —
|
|
9
|
-
* Handles assembly, integrity verification, and Vite dev server startup.
|
|
10
|
-
*
|
|
11
|
-
* **Commands:**
|
|
12
|
-
* | Subcommand | Description |
|
|
13
|
-
* |-------------------|-------------------------------------------------------|
|
|
14
|
-
* | `dev` | Start dev server with assembly and integrity check |
|
|
15
|
-
* | `dev --no-verify` | Skip integrity verification (faster) |
|
|
16
|
-
* | `dev --port 3002` | Use custom port (default: 3001) |
|
|
17
|
-
* | `dev --watch` | Watch v2-custom for changes and auto-reassemble |
|
|
18
|
-
* | `dev --no-watch` | Disable file watching (manual rebuild only) |
|
|
8
|
+
* `spine-framework dev` command — assemble and start the Netlify dev server.
|
|
19
9
|
*
|
|
20
10
|
* **What happens:**
|
|
21
|
-
* 1. Runs `assemble
|
|
22
|
-
* 2.
|
|
23
|
-
* 3. Starts Vite dev server on port 3001 (or --port)
|
|
24
|
-
* 4. Watches v2-custom/ for changes (--watch by default)
|
|
25
|
-
* 5. Fast incremental reassembly on custom code changes
|
|
11
|
+
* 1. Runs `npm run assemble` to merge framework + custom apps
|
|
12
|
+
* 2. Starts `netlify dev` (which runs Vite + Netlify Functions)
|
|
26
13
|
*
|
|
27
14
|
* **Usage:**
|
|
28
15
|
* ```bash
|
|
29
|
-
* spine dev
|
|
30
|
-
* spine dev --
|
|
31
|
-
* spine dev --no-verify
|
|
16
|
+
* spine-framework dev
|
|
17
|
+
* spine-framework dev --no-assemble # skip assembly step
|
|
32
18
|
* ```
|
|
33
19
|
*
|
|
34
|
-
* @seeAlso scripts/assemble
|
|
35
|
-
* @seeAlso
|
|
36
|
-
* @seeAlso vite.config.ts (Vite configuration)
|
|
20
|
+
* @seeAlso scripts/assemble.sh (assembly script)
|
|
21
|
+
* @seeAlso netlify.toml (Netlify dev configuration)
|
|
37
22
|
*/
|
|
38
23
|
|
|
39
24
|
import type { Command } from 'commander'
|
|
40
|
-
import { spawn
|
|
25
|
+
import { spawn } from 'child_process'
|
|
41
26
|
import { resolve, dirname } from 'path'
|
|
42
27
|
import { fileURLToPath } from 'url'
|
|
43
|
-
import {
|
|
28
|
+
import { existsSync } from 'fs'
|
|
44
29
|
|
|
45
30
|
const __filename = fileURLToPath(import.meta.url)
|
|
46
31
|
const __dirname = dirname(__filename)
|
|
@@ -51,131 +36,50 @@ const PROJECT_ROOT = process.cwd()
|
|
|
51
36
|
export function registerDevCommands(program: Command) {
|
|
52
37
|
program
|
|
53
38
|
.command('dev')
|
|
54
|
-
.description('
|
|
55
|
-
.option('--no-
|
|
56
|
-
.option('--port <port>', 'Dev server port', '3001')
|
|
57
|
-
.option('--host', 'Expose to network', false)
|
|
58
|
-
.option('--no-watch', 'Disable file watching')
|
|
59
|
-
.option('--watch-delay <ms>', 'Debounce delay for reassembly', '500')
|
|
39
|
+
.description('Assemble and start the Netlify dev server')
|
|
40
|
+
.option('--no-assemble', 'Skip the assembly step')
|
|
60
41
|
.action(async (opts) => {
|
|
61
42
|
console.log('\n🚀 Starting Spine dev server...\n')
|
|
62
43
|
|
|
63
44
|
try {
|
|
64
45
|
// Step 1: Assembly
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
'
|
|
68
|
-
[resolve(PROJECT_ROOT, 'scripts/assemble-v2.sh')],
|
|
69
|
-
PROJECT_ROOT
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
if (assemblyExitCode !== 0) {
|
|
73
|
-
console.error('\n❌ Assembly failed. Please check the errors above.')
|
|
74
|
-
process.exit(1)
|
|
75
|
-
}
|
|
76
|
-
console.log('✓ Assembly complete\n')
|
|
46
|
+
if (opts.assemble !== false) {
|
|
47
|
+
console.log('📦 Step 1: Assembling...')
|
|
48
|
+
const assemblyExitCode = await runCommand('npm', ['run', 'assemble'], PROJECT_ROOT)
|
|
77
49
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const verifyExitCode = await runCommand(
|
|
82
|
-
'bash',
|
|
83
|
-
[resolve(PROJECT_ROOT, 'scripts/verify-integrity.sh')],
|
|
84
|
-
PROJECT_ROOT
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
if (verifyExitCode !== 0) {
|
|
88
|
-
console.warn('\n⚠️ Integrity check failed. Continuing anyway (--no-verify to skip)\n')
|
|
89
|
-
} else {
|
|
90
|
-
console.log('✓ Integrity verified\n')
|
|
50
|
+
if (assemblyExitCode !== 0) {
|
|
51
|
+
console.error('\n❌ Assembly failed. Please check the errors above.')
|
|
52
|
+
process.exit(1)
|
|
91
53
|
}
|
|
54
|
+
console.log('✓ Assembly complete\n')
|
|
92
55
|
} else {
|
|
93
|
-
console.log('⏭️ Step
|
|
56
|
+
console.log('⏭️ Step 1: Skipping assembly (--no-assemble)\n')
|
|
94
57
|
}
|
|
95
58
|
|
|
96
|
-
// Step
|
|
97
|
-
console.log(
|
|
59
|
+
// Step 2: Start netlify dev
|
|
60
|
+
console.log('🌐 Step 2: Starting netlify dev...')
|
|
98
61
|
console.log(' (Press Ctrl+C to stop)\n')
|
|
99
62
|
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
[
|
|
103
|
-
'--config', resolve(PROJECT_ROOT, 'vite.config.ts'),
|
|
104
|
-
'--port', opts.port,
|
|
105
|
-
...(opts.host ? ['--host'] : [])
|
|
106
|
-
],
|
|
107
|
-
{
|
|
108
|
-
cwd: PROJECT_ROOT,
|
|
109
|
-
stdio: 'inherit',
|
|
110
|
-
env: { ...process.env, SPINE_DEV: 'true' }
|
|
111
|
-
}
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
// Step 4: Watch v2-custom for changes (unless disabled)
|
|
115
|
-
let watcher: ReturnType<typeof watch> | null = null
|
|
116
|
-
if (opts.watch !== false) {
|
|
117
|
-
const watchDelay = parseInt(opts.watchDelay) || 500
|
|
118
|
-
const customDir = resolve(PROJECT_ROOT, 'v2-custom')
|
|
119
|
-
|
|
120
|
-
if (existsSync(customDir)) {
|
|
121
|
-
console.log(`👁️ Step 4: Watching v2-custom/ for changes...`)
|
|
122
|
-
console.log(` (Changes trigger fast reassembly after ${watchDelay}ms debounce)\n`)
|
|
123
|
-
|
|
124
|
-
let reassemblyTimeout: NodeJS.Timeout | null = null
|
|
125
|
-
|
|
126
|
-
watcher = watch(customDir, { recursive: true }, (eventType, filename) => {
|
|
127
|
-
// Ignore node_modules, .git, and temp files
|
|
128
|
-
if (!filename || filename.includes('node_modules') || filename.startsWith('.')) {
|
|
129
|
-
return
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
console.log(`\n📝 Change detected in v2-custom/${filename}`)
|
|
63
|
+
const netlifyBin = resolve(PROJECT_ROOT, 'node_modules/.bin/netlify')
|
|
64
|
+
const cmd = existsSync(netlifyBin) ? netlifyBin : 'netlify'
|
|
133
65
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
reassemblyTimeout = setTimeout(async () => {
|
|
140
|
-
console.log('🔧 Running fast reassembly...')
|
|
141
|
-
try {
|
|
142
|
-
const start = Date.now()
|
|
143
|
-
await fastReassemble(PROJECT_ROOT)
|
|
144
|
-
const duration = Date.now() - start
|
|
145
|
-
console.log(`✓ Reassembly complete (${duration}ms)\n`)
|
|
146
|
-
} catch (err: any) {
|
|
147
|
-
console.error(`✗ Reassembly failed: ${err.message}\n`)
|
|
148
|
-
}
|
|
149
|
-
}, watchDelay)
|
|
150
|
-
})
|
|
151
|
-
} else {
|
|
152
|
-
console.log('⏭️ Step 4: v2-custom/ not found, skipping watch mode\n')
|
|
153
|
-
}
|
|
154
|
-
} else {
|
|
155
|
-
console.log('⏭️ Step 4: File watching disabled (--no-watch)\n')
|
|
156
|
-
}
|
|
66
|
+
const netlify = spawn(cmd, ['dev'], {
|
|
67
|
+
cwd: PROJECT_ROOT,
|
|
68
|
+
stdio: 'inherit',
|
|
69
|
+
env: { ...process.env }
|
|
70
|
+
})
|
|
157
71
|
|
|
158
|
-
|
|
159
|
-
if (watcher) {
|
|
160
|
-
watcher.close()
|
|
161
|
-
}
|
|
72
|
+
netlify.on('exit', (code) => {
|
|
162
73
|
process.exit(code || 0)
|
|
163
74
|
})
|
|
164
75
|
|
|
165
|
-
// Handle Ctrl+C gracefully
|
|
166
76
|
process.on('SIGINT', () => {
|
|
167
|
-
console.log('\n\n🛑 Shutting down
|
|
168
|
-
|
|
169
|
-
watcher.close()
|
|
170
|
-
}
|
|
171
|
-
vite.kill('SIGTERM')
|
|
77
|
+
console.log('\n\n🛑 Shutting down...')
|
|
78
|
+
netlify.kill('SIGTERM')
|
|
172
79
|
})
|
|
173
80
|
|
|
174
81
|
process.on('SIGTERM', () => {
|
|
175
|
-
|
|
176
|
-
watcher.close()
|
|
177
|
-
}
|
|
178
|
-
vite.kill('SIGTERM')
|
|
82
|
+
netlify.kill('SIGTERM')
|
|
179
83
|
})
|
|
180
84
|
|
|
181
85
|
} catch (err: any) {
|
|
@@ -207,89 +111,3 @@ function runCommand(command: string, args: string[], cwd: string): Promise<numbe
|
|
|
207
111
|
})
|
|
208
112
|
})
|
|
209
113
|
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Fast incremental reassembly of v2-custom files only.
|
|
213
|
-
* Uses rsync if available, falls back to selective copy.
|
|
214
|
-
*/
|
|
215
|
-
async function fastReassemble(projectRoot: string): Promise<void> {
|
|
216
|
-
const customDir = resolve(projectRoot, 'v2-custom')
|
|
217
|
-
const srcDest = resolve(projectRoot, 'src/v2-assembled')
|
|
218
|
-
const funcsDest = resolve(projectRoot, 'functions')
|
|
219
|
-
|
|
220
|
-
// Check if rsync is available
|
|
221
|
-
let hasRsync = false
|
|
222
|
-
try {
|
|
223
|
-
execSync('which rsync', { stdio: 'pipe' })
|
|
224
|
-
hasRsync = true
|
|
225
|
-
} catch {
|
|
226
|
-
hasRsync = false
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// Reassemble custom frontend files
|
|
230
|
-
const customSrcDir = resolve(customDir, 'src')
|
|
231
|
-
if (existsSync(customSrcDir)) {
|
|
232
|
-
const destDir = srcDest
|
|
233
|
-
|
|
234
|
-
if (hasRsync) {
|
|
235
|
-
// Use rsync for efficient incremental sync
|
|
236
|
-
execSync(
|
|
237
|
-
`rsync -av --delete "${customSrcDir}/" "${destDir}/"`,
|
|
238
|
-
{ stdio: 'pipe', cwd: projectRoot }
|
|
239
|
-
)
|
|
240
|
-
} else {
|
|
241
|
-
// Fallback: copy files that have changed
|
|
242
|
-
copyChangedFiles(customSrcDir, destDir)
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Reassemble custom function files
|
|
247
|
-
const customFuncsDir = resolve(customDir, 'functions')
|
|
248
|
-
if (existsSync(customFuncsDir)) {
|
|
249
|
-
if (hasRsync) {
|
|
250
|
-
execSync(
|
|
251
|
-
`rsync -av --delete "${customFuncsDir}/" "${funcsDest}/"`,
|
|
252
|
-
{ stdio: 'pipe', cwd: projectRoot }
|
|
253
|
-
)
|
|
254
|
-
} else {
|
|
255
|
-
copyChangedFiles(customFuncsDir, funcsDest)
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Copy only files that have changed (mtime comparison).
|
|
262
|
-
* Fallback when rsync is not available.
|
|
263
|
-
*/
|
|
264
|
-
function copyChangedFiles(src: string, dest: string): void {
|
|
265
|
-
const files = readdirSync(src, { withFileTypes: true })
|
|
266
|
-
|
|
267
|
-
for (const entry of files) {
|
|
268
|
-
const srcPath = resolve(src, entry.name)
|
|
269
|
-
const destPath = resolve(dest, entry.name)
|
|
270
|
-
|
|
271
|
-
if (entry.isDirectory()) {
|
|
272
|
-
if (!existsSync(destPath)) {
|
|
273
|
-
// Create directory
|
|
274
|
-
const { mkdirSync } = require('fs')
|
|
275
|
-
mkdirSync(destPath, { recursive: true })
|
|
276
|
-
}
|
|
277
|
-
// Recurse
|
|
278
|
-
copyChangedFiles(srcPath, destPath)
|
|
279
|
-
} else {
|
|
280
|
-
// Check if file needs copying
|
|
281
|
-
const srcStat = statSync(srcPath)
|
|
282
|
-
let needsCopy = true
|
|
283
|
-
|
|
284
|
-
if (existsSync(destPath)) {
|
|
285
|
-
const destStat = statSync(destPath)
|
|
286
|
-
needsCopy = srcStat.mtime > destStat.mtime
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (needsCopy) {
|
|
290
|
-
const { copyFileSync } = require('fs')
|
|
291
|
-
copyFileSync(srcPath, destPath)
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
@@ -4,35 +4,20 @@
|
|
|
4
4
|
* @layer cli
|
|
5
5
|
* @stability stable
|
|
6
6
|
*
|
|
7
|
-
* `spine dev` command —
|
|
8
|
-
* Handles assembly, integrity verification, and Vite dev server startup.
|
|
9
|
-
*
|
|
10
|
-
* **Commands:**
|
|
11
|
-
* | Subcommand | Description |
|
|
12
|
-
* |-------------------|-------------------------------------------------------|
|
|
13
|
-
* | `dev` | Start dev server with assembly and integrity check |
|
|
14
|
-
* | `dev --no-verify` | Skip integrity verification (faster) |
|
|
15
|
-
* | `dev --port 3002` | Use custom port (default: 3001) |
|
|
16
|
-
* | `dev --watch` | Watch v2-custom for changes and auto-reassemble |
|
|
17
|
-
* | `dev --no-watch` | Disable file watching (manual rebuild only) |
|
|
7
|
+
* `spine-framework dev` command — assemble and start the Netlify dev server.
|
|
18
8
|
*
|
|
19
9
|
* **What happens:**
|
|
20
|
-
* 1. Runs `assemble
|
|
21
|
-
* 2.
|
|
22
|
-
* 3. Starts Vite dev server on port 3001 (or --port)
|
|
23
|
-
* 4. Watches v2-custom/ for changes (--watch by default)
|
|
24
|
-
* 5. Fast incremental reassembly on custom code changes
|
|
10
|
+
* 1. Runs `npm run assemble` to merge framework + custom apps
|
|
11
|
+
* 2. Starts `netlify dev` (which runs Vite + Netlify Functions)
|
|
25
12
|
*
|
|
26
13
|
* **Usage:**
|
|
27
14
|
* ```bash
|
|
28
|
-
* spine dev
|
|
29
|
-
* spine dev --
|
|
30
|
-
* spine dev --no-verify
|
|
15
|
+
* spine-framework dev
|
|
16
|
+
* spine-framework dev --no-assemble # skip assembly step
|
|
31
17
|
* ```
|
|
32
18
|
*
|
|
33
|
-
* @seeAlso scripts/assemble
|
|
34
|
-
* @seeAlso
|
|
35
|
-
* @seeAlso vite.config.ts (Vite configuration)
|
|
19
|
+
* @seeAlso scripts/assemble.sh (assembly script)
|
|
20
|
+
* @seeAlso netlify.toml (Netlify dev configuration)
|
|
36
21
|
*/
|
|
37
22
|
import type { Command } from 'commander';
|
|
38
23
|
export declare function registerDevCommands(program: Command): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../.framework/cli/commands/dev.ts"],"names":[],"mappings":"AACA
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../.framework/cli/commands/dev.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAYxC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,QAyDnD"}
|