@symbo.ls/cli 2.33.26 → 2.33.28
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/bin/collab.js +92 -3
- package/bin/config.js +85 -0
- package/bin/fetch.js +15 -51
- package/bin/index.js +1 -0
- package/bin/push.js +7 -4
- package/bin/sync.js +8 -6
- package/helpers/changesUtils.js +76 -5
- package/helpers/symbolsConfig.js +32 -1
- package/package.json +5 -5
package/bin/collab.js
CHANGED
|
@@ -5,7 +5,7 @@ import path from 'path'
|
|
|
5
5
|
import chalk from 'chalk'
|
|
6
6
|
import { program } from './program.js'
|
|
7
7
|
import { CredentialManager } from '../helpers/credentialManager.js'
|
|
8
|
-
import { loadSymbolsConfig } from '../helpers/symbolsConfig.js'
|
|
8
|
+
import { loadSymbolsConfig, resolveDistDir } from '../helpers/symbolsConfig.js'
|
|
9
9
|
import { loadCliConfig, readLock, writeLock, getConfigPaths } from '../helpers/config.js'
|
|
10
10
|
import { stringifyFunctionsForTransport } from '../helpers/transportUtils.js'
|
|
11
11
|
import { getCurrentProjectData } from '../helpers/apiUtils.js'
|
|
@@ -48,6 +48,10 @@ export async function startCollab(options) {
|
|
|
48
48
|
const branch = options.branch || cliConfig.branch || symbolsConfig.branch || 'main'
|
|
49
49
|
const appKey = cliConfig.projectKey || symbolsConfig.key
|
|
50
50
|
|
|
51
|
+
const distDir =
|
|
52
|
+
resolveDistDir(symbolsConfig) ||
|
|
53
|
+
path.join(process.cwd(), 'smbls')
|
|
54
|
+
|
|
51
55
|
if (!appKey) {
|
|
52
56
|
console.log(chalk.red('Missing project key. Add it to symbols.json or .symbols/config.json'))
|
|
53
57
|
process.exit(1)
|
|
@@ -148,7 +152,7 @@ export async function startCollab(options) {
|
|
|
148
152
|
sendLocalChanges.cancel()
|
|
149
153
|
}
|
|
150
154
|
try {
|
|
151
|
-
await createFs(fullObj,
|
|
155
|
+
await createFs(fullObj, distDir, { update: true, metadata: false })
|
|
152
156
|
} finally {
|
|
153
157
|
// Extend suppression window to allow file events to settle fully
|
|
154
158
|
suppressUntil = Date.now() + suppressionWindowMs
|
|
@@ -253,7 +257,6 @@ export async function startCollab(options) {
|
|
|
253
257
|
})
|
|
254
258
|
|
|
255
259
|
// Watch local dist output and push coarse per-key changes
|
|
256
|
-
const distDir = path.join(process.cwd(), 'smbls')
|
|
257
260
|
const outputDir = path.join(distDir, 'dist')
|
|
258
261
|
const outputFile = path.join(outputDir, 'index.js')
|
|
259
262
|
|
|
@@ -272,10 +275,77 @@ export async function startCollab(options) {
|
|
|
272
275
|
}
|
|
273
276
|
}
|
|
274
277
|
|
|
278
|
+
/**
|
|
279
|
+
* Augment the loaded project object with any new items that exist as
|
|
280
|
+
* filesystem files (e.g. newly created component/page/method/function/snippet
|
|
281
|
+
* files) but are not yet present in the in‑memory data object.
|
|
282
|
+
*
|
|
283
|
+
* This bridges the gap between the one‑way createFs → files mapping so that
|
|
284
|
+
* adding a new file like components/MainFooter.js is seen as a new
|
|
285
|
+
* `components.MainFooter` data item and can be sent to the server.
|
|
286
|
+
*/
|
|
287
|
+
async function augmentLocalWithNewFsItems(local) {
|
|
288
|
+
if (!local || typeof local !== 'object') return
|
|
289
|
+
|
|
290
|
+
const TYPES = ['components', 'pages', 'snippets', 'methods', 'functions']
|
|
291
|
+
|
|
292
|
+
for (let i = 0; i < TYPES.length; i++) {
|
|
293
|
+
const type = TYPES[i]
|
|
294
|
+
const srcDir = path.join(distDir, type)
|
|
295
|
+
|
|
296
|
+
let entries
|
|
297
|
+
try {
|
|
298
|
+
entries = await fs.promises.readdir(srcDir)
|
|
299
|
+
} catch {
|
|
300
|
+
continue
|
|
301
|
+
}
|
|
302
|
+
if (!Array.isArray(entries) || !entries.length) continue
|
|
303
|
+
|
|
304
|
+
const container = local[type] && typeof local[type] === 'object' && !Array.isArray(local[type])
|
|
305
|
+
? local[type]
|
|
306
|
+
: (local[type] = {})
|
|
307
|
+
const baseSection = currentBase && currentBase[type] && typeof currentBase[type] === 'object'
|
|
308
|
+
? currentBase[type]
|
|
309
|
+
: {}
|
|
310
|
+
|
|
311
|
+
for (let j = 0; j < entries.length; j++) {
|
|
312
|
+
const filename = entries[j]
|
|
313
|
+
if (!filename.endsWith('.js') || filename === 'index.js') continue
|
|
314
|
+
|
|
315
|
+
const key = filename.slice(0, -3)
|
|
316
|
+
if (Object.prototype.hasOwnProperty.call(container, key)) continue
|
|
317
|
+
if (Object.prototype.hasOwnProperty.call(baseSection, key)) continue
|
|
318
|
+
|
|
319
|
+
const compiledPath = path.join(outputDir, type, filename)
|
|
320
|
+
let mod
|
|
321
|
+
try {
|
|
322
|
+
const { loadModule } = await import('./require.js')
|
|
323
|
+
mod = await loadModule(compiledPath, { silent: true })
|
|
324
|
+
} catch {
|
|
325
|
+
if (options.verbose) {
|
|
326
|
+
console.error(`Failed to load new ${type} item from`, compiledPath)
|
|
327
|
+
}
|
|
328
|
+
continue
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (!mod) continue
|
|
332
|
+
|
|
333
|
+
let value = null
|
|
334
|
+
if (mod && typeof mod === 'object') {
|
|
335
|
+
value = mod.default || mod[key] || null
|
|
336
|
+
}
|
|
337
|
+
if (!value || typeof value !== 'object') continue
|
|
338
|
+
|
|
339
|
+
container[key] = value
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
275
344
|
const sendLocalChanges = debounce(async () => {
|
|
276
345
|
if (suppressLocalChanges) return
|
|
277
346
|
const local = await loadLocalProject()
|
|
278
347
|
if (!local) return
|
|
348
|
+
await augmentLocalWithNewFsItems(local)
|
|
279
349
|
// Prepare safe, JSON-serialisable snapshots for diffing & transport
|
|
280
350
|
const base = currentBase || {}
|
|
281
351
|
const safeBase = stringifyFunctionsForTransport(base)
|
|
@@ -291,6 +361,25 @@ export async function startCollab(options) {
|
|
|
291
361
|
const { granularChanges } = preprocessChanges(safeBase, changes)
|
|
292
362
|
const orders = computeOrdersForTuples(safeLocal, granularChanges)
|
|
293
363
|
console.log(chalk.gray(`Emitting local ops: ${JSON.stringify({ changes, granularChanges, orders, branch })}`))
|
|
364
|
+
|
|
365
|
+
// Optimistically apply our own ops to the in-memory base so that
|
|
366
|
+
// subsequent diffs are computed against the latest local state.
|
|
367
|
+
// This avoids repeatedly re-emitting the same changes when the
|
|
368
|
+
// server does not immediately send back a fresh snapshot.
|
|
369
|
+
try {
|
|
370
|
+
const tuplesToApply = Array.isArray(granularChanges) && granularChanges.length
|
|
371
|
+
? granularChanges
|
|
372
|
+
: changes
|
|
373
|
+
applyTuples(currentBase, tuplesToApply)
|
|
374
|
+
if (Array.isArray(orders) && orders.length) {
|
|
375
|
+
applyOrders(currentBase, orders)
|
|
376
|
+
}
|
|
377
|
+
} catch (e) {
|
|
378
|
+
if (options.verbose) {
|
|
379
|
+
console.error('Failed to apply local ops to in-memory base', e)
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
294
383
|
socket.emit('ops', {
|
|
295
384
|
changes,
|
|
296
385
|
granularChanges,
|
package/bin/config.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import inquirer from 'inquirer'
|
|
6
|
+
import chalk from 'chalk'
|
|
7
|
+
import { program } from './program.js'
|
|
8
|
+
import { loadSymbolsConfig } from '../helpers/symbolsConfig.js'
|
|
9
|
+
import { loadCliConfig, saveCliConfig, updateLegacySymbolsJson } from '../helpers/config.js'
|
|
10
|
+
|
|
11
|
+
program
|
|
12
|
+
.command('config')
|
|
13
|
+
.description('Interactively configure Symbols project settings')
|
|
14
|
+
.option('--dist-dir <dir>', 'Set distDir non-interactively')
|
|
15
|
+
.action(async (options) => {
|
|
16
|
+
// Load existing configs (do not fail if missing/malformed)
|
|
17
|
+
const symbolsConfig =
|
|
18
|
+
(await loadSymbolsConfig({ required: false, validateKey: false, silent: true })) || {}
|
|
19
|
+
const cliConfig = loadCliConfig()
|
|
20
|
+
|
|
21
|
+
// Fast path: only update distDir when provided explicitly
|
|
22
|
+
if (options.distDir) {
|
|
23
|
+
const next = { ...symbolsConfig, distDir: options.distDir }
|
|
24
|
+
updateLegacySymbolsJson(next)
|
|
25
|
+
console.log(chalk.green(`Updated symbols.json distDir to "${options.distDir}"`))
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const questions = [
|
|
30
|
+
{
|
|
31
|
+
type: 'input',
|
|
32
|
+
name: 'key',
|
|
33
|
+
message: 'App key (symbols.json.key):',
|
|
34
|
+
default: symbolsConfig.key || '',
|
|
35
|
+
filter: (v) => v.trim()
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: 'input',
|
|
39
|
+
name: 'branch',
|
|
40
|
+
message: 'Default branch:',
|
|
41
|
+
default: cliConfig.branch || symbolsConfig.branch || 'main',
|
|
42
|
+
filter: (v) => v.trim() || 'main'
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
type: 'input',
|
|
46
|
+
name: 'distDir',
|
|
47
|
+
message: 'Directory for generated files (distDir):',
|
|
48
|
+
default: symbolsConfig.distDir || './smbls',
|
|
49
|
+
filter: (v) => v.trim() || './smbls'
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
type: 'input',
|
|
53
|
+
name: 'apiBaseUrl',
|
|
54
|
+
message: 'API base URL:',
|
|
55
|
+
default: cliConfig.apiBaseUrl || 'https://api.symbols.app',
|
|
56
|
+
filter: (v) => v.trim() || 'https://api.symbols.app'
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
const answers = await inquirer.prompt(questions)
|
|
61
|
+
|
|
62
|
+
// Update symbols.json (legacy project config)
|
|
63
|
+
const nextSymbols = updateLegacySymbolsJson({
|
|
64
|
+
...symbolsConfig,
|
|
65
|
+
key: answers.key || undefined,
|
|
66
|
+
branch: answers.branch,
|
|
67
|
+
distDir: answers.distDir
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
// Update .symbols/config.json (runtime CLI config)
|
|
71
|
+
const _nextCli = saveCliConfig({
|
|
72
|
+
apiBaseUrl: answers.apiBaseUrl,
|
|
73
|
+
projectKey: answers.key || cliConfig.projectKey || nextSymbols.key,
|
|
74
|
+
branch: answers.branch
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
console.log(`\n`)
|
|
78
|
+
console.log(chalk.green('Configuration updated successfully.'))
|
|
79
|
+
const symbolsPath = path.join(process.cwd(), 'symbols.json')
|
|
80
|
+
const cliConfigPath = path.join(process.cwd(), '.symbols', 'config.json')
|
|
81
|
+
console.log(chalk.gray(`symbols.json: ${chalk.cyan(symbolsPath)}`))
|
|
82
|
+
console.log(chalk.gray(`.symbols/config.json: ${chalk.cyan(cliConfigPath)}`))
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
|
package/bin/fetch.js
CHANGED
|
@@ -10,15 +10,10 @@ import { createFs } from './fs.js'
|
|
|
10
10
|
import { CredentialManager } from '../helpers/credentialManager.js'
|
|
11
11
|
import { getCurrentProjectData } from '../helpers/apiUtils.js'
|
|
12
12
|
import { showAuthRequiredMessages } from '../helpers/buildMessages.js'
|
|
13
|
-
import { loadSymbolsConfig } from '../helpers/symbolsConfig.js'
|
|
13
|
+
import { loadSymbolsConfig, resolveDistDir } from '../helpers/symbolsConfig.js'
|
|
14
14
|
import { loadCliConfig, readLock, writeLock, updateLegacySymbolsJson, getConfigPaths } from '../helpers/config.js'
|
|
15
15
|
const { isObjectLike } = (utils.default || utils)
|
|
16
16
|
|
|
17
|
-
const RC_PATH = process.cwd() + '/symbols.json'
|
|
18
|
-
const LOCAL_CONFIG_PATH =
|
|
19
|
-
process.cwd() + '/node_modules/@symbo.ls/init/dynamic.json'
|
|
20
|
-
const DEFAULT_REMOTE_REPOSITORY = 'https://github.com/symbo-ls/default-config/'
|
|
21
|
-
|
|
22
17
|
const debugMsg = chalk.dim(
|
|
23
18
|
'Use --verbose to debug the error or open the issue at https://github.com/symbo-ls/smbls'
|
|
24
19
|
)
|
|
@@ -38,7 +33,7 @@ export const fetchFromCli = async (opts) => {
|
|
|
38
33
|
|
|
39
34
|
const projectKey = cliConfig.projectKey || symbolsConfig.key
|
|
40
35
|
const branch = cliConfig.branch || symbolsConfig.branch || 'main'
|
|
41
|
-
const { framework
|
|
36
|
+
const { framework } = symbolsConfig
|
|
42
37
|
|
|
43
38
|
console.log('\nFetching project data...\n')
|
|
44
39
|
|
|
@@ -79,7 +74,7 @@ export const fetchFromCli = async (opts) => {
|
|
|
79
74
|
console.log(chalk.red('Failed to fetch:'), projectKey)
|
|
80
75
|
if (verbose) console.error(e)
|
|
81
76
|
else console.log(debugMsg)
|
|
82
|
-
|
|
77
|
+
process.exit(1)
|
|
83
78
|
}
|
|
84
79
|
|
|
85
80
|
// Persist base snapshot for future rebases
|
|
@@ -87,24 +82,11 @@ export const fetchFromCli = async (opts) => {
|
|
|
87
82
|
const { projectPath } = getConfigPaths()
|
|
88
83
|
await fs.promises.mkdir(path.dirname(projectPath), { recursive: true })
|
|
89
84
|
await fs.promises.writeFile(projectPath, JSON.stringify(payload, null, 2))
|
|
90
|
-
} catch (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
chalk.bold('Symbols'),
|
|
96
|
-
'data fetched for',
|
|
97
|
-
chalk.green(payload.name)
|
|
98
|
-
)
|
|
99
|
-
} else {
|
|
100
|
-
console.log(
|
|
101
|
-
chalk.bold('Symbols'),
|
|
102
|
-
'config fetched from',
|
|
103
|
-
chalk.bold('default-config from:'),
|
|
104
|
-
chalk.dim.underline(DEFAULT_REMOTE_REPOSITORY)
|
|
105
|
-
)
|
|
106
|
-
}
|
|
107
|
-
console.log()
|
|
85
|
+
} catch (e) {
|
|
86
|
+
console.error(chalk.bold.red('\nError writing file'))
|
|
87
|
+
if (verbose) console.error(e)
|
|
88
|
+
else console.log(debugMsg)
|
|
89
|
+
process.exit(1)
|
|
108
90
|
}
|
|
109
91
|
|
|
110
92
|
const { version: fetchedVersion, ...config } = payload
|
|
@@ -123,30 +105,12 @@ export const fetchFromCli = async (opts) => {
|
|
|
123
105
|
} else console.log(chalk.dim(t + ':'), chalk.bold(type))
|
|
124
106
|
}
|
|
125
107
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (verbose) {
|
|
133
|
-
console.log(chalk.dim('\ndynamic.json has been updated:'))
|
|
134
|
-
console.log(chalk.dim.underline(LOCAL_CONFIG_PATH))
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
console.log(chalk.bold.green('\nSuccessfully wrote file'))
|
|
138
|
-
} catch (e) {
|
|
139
|
-
console.log(chalk.bold.red('\nError writing file'))
|
|
140
|
-
if (verbose) console.error(e)
|
|
141
|
-
else console.log(debugMsg)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
console.log()
|
|
145
|
-
console.warn(
|
|
146
|
-
'No --dist-dir option or "distDir" in symbols.json provided. Saving in ./node_modules/@symbo.ls/init/dynamic.json.'
|
|
147
|
-
)
|
|
148
|
-
return {}
|
|
149
|
-
}
|
|
108
|
+
// Resolve effective distDir from CLI flag or symbols.json, with a sane default
|
|
109
|
+
const distDir =
|
|
110
|
+
resolveDistDir(symbolsConfig, {
|
|
111
|
+
distDirOverride: opts.distDir
|
|
112
|
+
}) ||
|
|
113
|
+
path.join(process.cwd(), 'smbls')
|
|
150
114
|
|
|
151
115
|
if (payload.components && convertOpt && framework) {
|
|
152
116
|
convertFromCli(payload.components, { ...opts, framework })
|
|
@@ -169,5 +133,5 @@ program
|
|
|
169
133
|
.option('--force', 'Force overriding changes from platform')
|
|
170
134
|
.option('--update', 'Overriding changes from platform')
|
|
171
135
|
.option('--verbose-code', 'Verbose errors and warnings')
|
|
172
|
-
.option('--dist-dir', 'Directory to import files to.')
|
|
136
|
+
.option('--dist-dir <dir>', 'Directory to import files to.')
|
|
173
137
|
.action(fetchFromCli)
|
package/bin/index.js
CHANGED
package/bin/push.js
CHANGED
|
@@ -12,13 +12,12 @@ import { generateDiffDisplay, showDiffPager } from '../helpers/diffUtils.js'
|
|
|
12
12
|
import { getCurrentProjectData, postProjectChanges } from '../helpers/apiUtils.js'
|
|
13
13
|
import { computeCoarseChanges, computeOrdersForTuples, preprocessChanges } from '../helpers/changesUtils.js'
|
|
14
14
|
import { showAuthRequiredMessages, showProjectNotFoundMessages, showBuildErrorMessages } from '../helpers/buildMessages.js'
|
|
15
|
-
import { loadSymbolsConfig } from '../helpers/symbolsConfig.js'
|
|
15
|
+
import { loadSymbolsConfig, resolveDistDir } from '../helpers/symbolsConfig.js'
|
|
16
16
|
import { loadCliConfig, readLock, writeLock, updateLegacySymbolsJson } from '../helpers/config.js'
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
async function buildLocalProject () {
|
|
19
|
+
async function buildLocalProject (distDir) {
|
|
20
20
|
try {
|
|
21
|
-
const distDir = path.join(process.cwd(), 'smbls')
|
|
22
21
|
const outputDirectory = path.join(distDir, 'dist')
|
|
23
22
|
|
|
24
23
|
await buildDirectory(distDir, outputDirectory)
|
|
@@ -114,11 +113,15 @@ export async function pushProjectChanges(options) {
|
|
|
114
113
|
const appKey = cliConfig.projectKey || symbolsConfig.key
|
|
115
114
|
const branch = cliConfig.branch || symbolsConfig.branch || 'main'
|
|
116
115
|
|
|
116
|
+
const distDir =
|
|
117
|
+
resolveDistDir(symbolsConfig) ||
|
|
118
|
+
path.join(process.cwd(), 'smbls')
|
|
119
|
+
|
|
117
120
|
// Build and load local project
|
|
118
121
|
console.log(chalk.dim('Building local project...'))
|
|
119
122
|
let localProject
|
|
120
123
|
try {
|
|
121
|
-
localProject = await buildLocalProject()
|
|
124
|
+
localProject = await buildLocalProject(distDir)
|
|
122
125
|
console.log(chalk.gray('Local project built successfully'))
|
|
123
126
|
} catch (buildError) {
|
|
124
127
|
showBuildErrorMessages(buildError)
|
package/bin/sync.js
CHANGED
|
@@ -11,15 +11,13 @@ import { buildDirectory } from '../helpers/fileUtils.js'
|
|
|
11
11
|
import { generateDiffDisplay, showDiffPager } from '../helpers/diffUtils.js'
|
|
12
12
|
import { normalizeKeys } from '../helpers/compareUtils.js'
|
|
13
13
|
import { getCurrentProjectData, postProjectChanges } from '../helpers/apiUtils.js'
|
|
14
|
-
import {
|
|
14
|
+
import { threeWayRebase, computeOrdersForTuples, preprocessChanges } from '../helpers/changesUtils.js'
|
|
15
15
|
import { createFs } from './fs.js'
|
|
16
16
|
import { showAuthRequiredMessages, showBuildErrorMessages } from '../helpers/buildMessages.js'
|
|
17
|
-
import { loadSymbolsConfig } from '../helpers/symbolsConfig.js'
|
|
17
|
+
import { loadSymbolsConfig, resolveDistDir } from '../helpers/symbolsConfig.js'
|
|
18
18
|
import { loadCliConfig, readLock, writeLock, getConfigPaths, updateLegacySymbolsJson } from '../helpers/config.js'
|
|
19
|
-
const RC_PATH = process.cwd() + '/symbols.json'
|
|
20
|
-
const distDir = path.join(process.cwd(), 'smbls')
|
|
21
19
|
|
|
22
|
-
async function buildLocalProject() {
|
|
20
|
+
async function buildLocalProject(distDir) {
|
|
23
21
|
try {
|
|
24
22
|
const outputDirectory = path.join(distDir, 'dist')
|
|
25
23
|
await buildDirectory(distDir, outputDirectory)
|
|
@@ -165,6 +163,10 @@ export async function syncProjectChanges(options) {
|
|
|
165
163
|
const appKey = cliConfig.projectKey || legacyKey
|
|
166
164
|
const localBranch = cliConfig.branch || symbolsConfig.branch || 'main'
|
|
167
165
|
|
|
166
|
+
const distDir =
|
|
167
|
+
resolveDistDir(symbolsConfig) ||
|
|
168
|
+
path.join(process.cwd(), 'smbls')
|
|
169
|
+
|
|
168
170
|
if (options.verbose) {
|
|
169
171
|
console.log(chalk.dim('\nSync configuration:'))
|
|
170
172
|
console.log(chalk.gray(`App Key: ${chalk.cyan(appKey)}`))
|
|
@@ -179,7 +181,7 @@ export async function syncProjectChanges(options) {
|
|
|
179
181
|
console.log(chalk.dim('Building local project...'))
|
|
180
182
|
let localProject
|
|
181
183
|
try {
|
|
182
|
-
localProject = await buildLocalProject()
|
|
184
|
+
localProject = await buildLocalProject(distDir)
|
|
183
185
|
console.log(chalk.gray('Local project built successfully'))
|
|
184
186
|
} catch (buildError) {
|
|
185
187
|
showBuildErrorMessages(buildError)
|
package/helpers/changesUtils.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+
import * as utils from '@domql/utils'
|
|
1
2
|
import { normalizeKeys } from './compareUtils.js'
|
|
2
3
|
|
|
4
|
+
const { objectToString } = utils.default || utils
|
|
5
|
+
|
|
3
6
|
// Keys managed by the CLI filesystem representation (exclude settings/schema/key/thumbnail/etc.)
|
|
4
7
|
export const DATA_KEYS = [
|
|
5
8
|
'designSystem','components','state','pages','snippets',
|
|
6
9
|
'methods','functions','dependencies','files'
|
|
7
10
|
]
|
|
8
11
|
|
|
12
|
+
const SCHEMA_CODE_TYPES = new Set(['pages', 'components', 'functions', 'methods', 'snippets'])
|
|
13
|
+
|
|
9
14
|
function stripMetaDeep(val) {
|
|
10
15
|
if (Array.isArray(val)) {
|
|
11
16
|
return val.map(stripMetaDeep)
|
|
@@ -61,9 +66,12 @@ export function computeCoarseChanges(base, local, keys = DATA_KEYS) {
|
|
|
61
66
|
|
|
62
67
|
// Generate per-item granular changes one level deeper for each data type.
|
|
63
68
|
// Ignore 'schema' comparisons; manage schema side-effects below.
|
|
69
|
+
const baseSchema = a?.schema || {}
|
|
70
|
+
|
|
64
71
|
for (const typeKey of [...keys]) {
|
|
65
72
|
const aSection = a?.[typeKey] || {}
|
|
66
73
|
const bSection = b?.[typeKey] || {}
|
|
74
|
+
const aSchemaSection = baseSchema?.[typeKey] || {}
|
|
67
75
|
|
|
68
76
|
// If sections are not plain objects (or are arrays), fallback to coarse replacement on the section itself
|
|
69
77
|
const aIsObject = aSection && typeof aSection === 'object' && !Array.isArray(aSection)
|
|
@@ -90,11 +98,17 @@ export function computeCoarseChanges(base, local, keys = DATA_KEYS) {
|
|
|
90
98
|
for (const itemKey of Object.keys(bSection)) {
|
|
91
99
|
const aVal = aSection[itemKey]
|
|
92
100
|
const bVal = bSection[itemKey]
|
|
93
|
-
|
|
101
|
+
const hadPrev = typeof aVal !== 'undefined'
|
|
102
|
+
if (!hadPrev) {
|
|
94
103
|
// New item
|
|
95
104
|
changes.push(['update', [typeKey, itemKey], bVal])
|
|
96
|
-
|
|
97
|
-
|
|
105
|
+
const hadSchema = aSchemaSection && Object.prototype.hasOwnProperty.call(aSchemaSection, itemKey)
|
|
106
|
+
if (SCHEMA_CODE_TYPES.has(typeKey) && !hadSchema) {
|
|
107
|
+
const schemaItem = buildSchemaItemFromData(typeKey, itemKey, bVal)
|
|
108
|
+
if (schemaItem) {
|
|
109
|
+
changes.push(['update', ['schema', typeKey, itemKey], schemaItem])
|
|
110
|
+
}
|
|
111
|
+
}
|
|
98
112
|
} else if (!equal(aVal, bVal)) {
|
|
99
113
|
// Updated item
|
|
100
114
|
changes.push(['update', [typeKey, itemKey], bVal])
|
|
@@ -112,8 +126,18 @@ export function threeWayRebase(base, local, remote, keys = DATA_KEYS) {
|
|
|
112
126
|
const theirsKeys = computeChangedKeys(base, remote, keys)
|
|
113
127
|
const conflicts = oursKeys.filter(k => theirsKeys.includes(k))
|
|
114
128
|
|
|
115
|
-
const
|
|
116
|
-
const
|
|
129
|
+
const allOurs = computeCoarseChanges(base, local, keys)
|
|
130
|
+
const allTheirs = computeCoarseChanges(base, remote, keys)
|
|
131
|
+
|
|
132
|
+
const ownsKey = (path, set) => {
|
|
133
|
+
if (!Array.isArray(path) || !path.length) return false
|
|
134
|
+
const [rootKey, typeKey] = path
|
|
135
|
+
const primary = rootKey === 'schema' ? typeKey : rootKey
|
|
136
|
+
return set.includes(primary)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const ours = allOurs.filter(([, path]) => ownsKey(path, oursKeys))
|
|
140
|
+
const theirs = allTheirs.filter(([, path]) => ownsKey(path, theirsKeys))
|
|
117
141
|
|
|
118
142
|
let finalChanges = []
|
|
119
143
|
if (conflicts.length === 0) {
|
|
@@ -224,6 +248,13 @@ function normaliseSchemaCode(code) {
|
|
|
224
248
|
.replaceAll('/////tilde', '`')
|
|
225
249
|
}
|
|
226
250
|
|
|
251
|
+
function encodeSchemaCode(code) {
|
|
252
|
+
if (typeof code !== 'string' || !code.length) return ''
|
|
253
|
+
return code
|
|
254
|
+
.replaceAll('\n', '/////n')
|
|
255
|
+
.replaceAll('`', '/////tilde')
|
|
256
|
+
}
|
|
257
|
+
|
|
227
258
|
function parseExportedObject(code) {
|
|
228
259
|
const src = normaliseSchemaCode(code)
|
|
229
260
|
if (!src) return null
|
|
@@ -236,6 +267,46 @@ function parseExportedObject(code) {
|
|
|
236
267
|
}
|
|
237
268
|
}
|
|
238
269
|
|
|
270
|
+
export function buildSchemaCodeFromObject(obj) {
|
|
271
|
+
if (!obj || typeof obj !== 'object') return ''
|
|
272
|
+
const body = objectToString(obj, 2)
|
|
273
|
+
const src = `export default ${body}`
|
|
274
|
+
return encodeSchemaCode(src)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function buildSchemaItemFromData(type, key, value) {
|
|
278
|
+
const schemaType = type
|
|
279
|
+
|
|
280
|
+
const base = {
|
|
281
|
+
title: key,
|
|
282
|
+
key,
|
|
283
|
+
type: schemaType
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (['pages', 'components'].includes(schemaType)) {
|
|
287
|
+
base.settings = {
|
|
288
|
+
gridOptions: {}
|
|
289
|
+
}
|
|
290
|
+
base.props = {}
|
|
291
|
+
base.interactivity = []
|
|
292
|
+
base.dataTypes = []
|
|
293
|
+
base.error = null
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (SCHEMA_CODE_TYPES.has(schemaType)) {
|
|
297
|
+
try {
|
|
298
|
+
const code = buildSchemaCodeFromObject(value)
|
|
299
|
+
if (code) {
|
|
300
|
+
base.code = code
|
|
301
|
+
}
|
|
302
|
+
} catch (_) {
|
|
303
|
+
// Fallback: omit code field if serialisation fails
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return base
|
|
308
|
+
}
|
|
309
|
+
|
|
239
310
|
function extractTopLevelKeysFromCode(code) {
|
|
240
311
|
const obj = parseExportedObject(code)
|
|
241
312
|
if (!obj || typeof obj !== 'object') return []
|
package/helpers/symbolsConfig.js
CHANGED
|
@@ -32,4 +32,35 @@ export const loadSymbolsConfig = async (options = {}) => {
|
|
|
32
32
|
if (required) process.exit(1)
|
|
33
33
|
return null
|
|
34
34
|
}
|
|
35
|
-
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Resolve the effective dist directory for the current workspace.
|
|
39
|
+
*
|
|
40
|
+
* Precedence:
|
|
41
|
+
* - explicit override (e.g. CLI flag)
|
|
42
|
+
* - symbols.json.distDir
|
|
43
|
+
*
|
|
44
|
+
* Returns an absolute path when possible; null when no distDir
|
|
45
|
+
* configuration is available so callers can decide on a default.
|
|
46
|
+
*/
|
|
47
|
+
export function resolveDistDir (symbolsConfig, options = {}) {
|
|
48
|
+
const cfg = symbolsConfig || {}
|
|
49
|
+
const {
|
|
50
|
+
// Prefer explicit override from callers (e.g. CLI flag)
|
|
51
|
+
distDirOverride,
|
|
52
|
+
distDir: overrideDistDir,
|
|
53
|
+
cwd = process.cwd()
|
|
54
|
+
} = options
|
|
55
|
+
|
|
56
|
+
const raw =
|
|
57
|
+
distDirOverride ||
|
|
58
|
+
overrideDistDir ||
|
|
59
|
+
cfg.distDir
|
|
60
|
+
|
|
61
|
+
if (!raw) return null
|
|
62
|
+
|
|
63
|
+
// If already absolute, return as-is; otherwise resolve against cwd
|
|
64
|
+
if (path.isAbsolute(raw)) return raw
|
|
65
|
+
return path.resolve(cwd, raw)
|
|
66
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbo.ls/cli",
|
|
3
|
-
"version": "2.33.
|
|
3
|
+
"version": "2.33.28",
|
|
4
4
|
"description": "Fetch your Symbols configuration",
|
|
5
5
|
"main": "bin/fetch.js",
|
|
6
6
|
"author": "Symbols",
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
"vpatch": "npm version patch && npm publish"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@symbo.ls/fetch": "^2.33.
|
|
19
|
-
"@symbo.ls/init": "^2.33.
|
|
20
|
-
"@symbo.ls/socket": "^2.33.
|
|
18
|
+
"@symbo.ls/fetch": "^2.33.28",
|
|
19
|
+
"@symbo.ls/init": "^2.33.28",
|
|
20
|
+
"@symbo.ls/socket": "^2.33.28",
|
|
21
21
|
"chalk": "^5.4.1",
|
|
22
22
|
"chokidar": "^4.0.3",
|
|
23
23
|
"commander": "^13.1.0",
|
|
@@ -28,5 +28,5 @@
|
|
|
28
28
|
"socket.io-client": "^4.8.1",
|
|
29
29
|
"v8-compile-cache": "^2.4.0"
|
|
30
30
|
},
|
|
31
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "58b2f9f34b228712ccc4352e15913c52d6007afb"
|
|
32
32
|
}
|