@symbo.ls/cli 2.11.159 → 2.11.162

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/convert.js CHANGED
@@ -1,10 +1,11 @@
1
1
  'use strict'
2
2
 
3
+ import fs from 'fs'
4
+ import chalk from 'chalk'
5
+ import path from 'path'
3
6
  import { program } from './program.js'
4
7
  import { convert } from 'kalduna'
5
8
  import { parse } from 'globusa'
6
- import fs from 'fs'
7
- import path from 'path'
8
9
 
9
10
  import * as esbuild from 'esbuild'
10
11
 
@@ -38,7 +39,7 @@ const INTERNAL_UIKIT_CONF = {
38
39
  'DatePickerGridContainer',
39
40
 
40
41
  // Not a domql object (headless-datepicker)
41
- 'calendar',
42
+ 'calendar'
42
43
  ],
43
44
 
44
45
  // Can be strings or regex patterns
@@ -46,8 +47,8 @@ const INTERNAL_UIKIT_CONF = {
46
47
  // TODO: Review these ignores with @nikoloza
47
48
  /Threejs$/,
48
49
  /Editorjs$/,
49
- /User$/,
50
- ],
50
+ /User$/
51
+ ]
51
52
  }
52
53
  const TMP_DIR_NAME = '.smbls_convert_tmp'
53
54
  const TMP_DIR_PACKAGE_JSON_STR = JSON.stringify({
@@ -57,7 +58,7 @@ const TMP_DIR_PACKAGE_JSON_STR = JSON.stringify({
57
58
  license: 'ISC'
58
59
  })
59
60
 
60
- function generatePackageJsonFile(
61
+ function generatePackageJsonFile (
61
62
  sourcePackageJsonPath,
62
63
  destPath,
63
64
  globusaStruct,
@@ -71,7 +72,7 @@ function generatePackageJsonFile(
71
72
  packageStruct = JSON.parse(str)
72
73
  } catch (error) {
73
74
  console.error(`Error when parsing ${sourcePackageJsonPath}`)
74
- return;
75
+ return
75
76
  }
76
77
  const split = packageStruct.name.split('/')
77
78
  const packageName = split[split.length - 1]
@@ -82,12 +83,12 @@ function generatePackageJsonFile(
82
83
  [`@emotion/${desiredFormat}`]: '^11.11.0',
83
84
  '@emotion/css': '^11.11.0',
84
85
  '@symbo.ls/create': 'latest',
85
- '@symbo.ls/react': 'latest',
86
+ '@symbo.ls/react': 'latest'
86
87
  }
87
88
  globusaStruct.imports
88
89
  .filter(imp => imp.path.match(/^@symbo\.ls\//))
89
90
  .filter(imp => imp.path !== packageName)
90
- .forEach(imp => deps[imp.path] = 'latest')
91
+ .forEach(imp => { deps[imp.path] = 'latest' })
91
92
 
92
93
  // Generate final package.json string
93
94
  const genStr = JSON.stringify({
@@ -96,7 +97,7 @@ function generatePackageJsonFile(
96
97
  license: packageStruct.license ?? 'UNLICENSED',
97
98
  dependencies: deps,
98
99
  peerDependencies: {
99
- 'react': '^18.2.0',
100
+ react: '^18.2.0',
100
101
  'react-dom': '^18.2.0'
101
102
  },
102
103
  main: 'index.js',
@@ -114,9 +115,9 @@ function isDirectory (dir) {
114
115
  }
115
116
 
116
117
  // Essentially does 'mkdir -P'
117
- async function mkdirp (dir) {
118
+ function mkdirp (dir) {
118
119
  try {
119
- return await fs.promises.mkdir(dir)
120
+ return fs.mkdirSync(dir, { recursive: true })
120
121
  } catch (err) {
121
122
  if (err.code !== 'EEXIST') {
122
123
  throw err
@@ -126,30 +127,29 @@ async function mkdirp (dir) {
126
127
  }
127
128
 
128
129
  // Returns a string
129
- function convertDomqlModule(domqlModule, globusaStruct, desiredFormat, options) {
130
+ export function convertDomqlModule (domqlModule, globusaStruct, desiredFormat, options = {}) {
130
131
  let convertedStr = ''
131
132
  const whitelist = (options.only ? options.only.split(',') : null)
132
133
 
133
134
  console.group()
134
135
  const exports = Object.keys(domqlModule)
135
- .filter(exportName => {
136
- if (!whitelist) return true
137
- if (whitelist.includes(exportName)) {
138
- console.log(`Skipping ${exportName} component due to whitelist exclusion`)
139
- return false
140
- }
141
- return true
142
- })
143
- .filter(exportName => {
144
- if (!options.internalUikit) return true
145
- if (INTERNAL_UIKIT_CONF.excludedComponents.includes(exportName)) {
146
- console.log(`Skipping ${exportName} component due to internal uikit exclusion`)
147
- return false
148
- }
149
- return true
150
- })
151
-
152
- const isSingleComponent = (exports.length === 1)
136
+ .filter(exportName => {
137
+ if (!whitelist) return true
138
+ if (!whitelist.includes(exportName)) {
139
+ console.log(`Skipping ${exportName} component due to whitelist exclusion`)
140
+ return false
141
+ }
142
+ return true
143
+ })
144
+ .filter(exportName => {
145
+ if (!options.internalUikit) return true
146
+ if (INTERNAL_UIKIT_CONF.excludedComponents.includes(exportName)) {
147
+ console.log(`Skipping ${exportName} component due to internal uikit exclusion`)
148
+ return false
149
+ }
150
+ return true
151
+ })
152
+
153
153
  const uniqueImports = []
154
154
  let globalSymbolTable = {}
155
155
  for (const idx in exports) {
@@ -163,16 +163,17 @@ function convertDomqlModule(domqlModule, globusaStruct, desiredFormat, options)
163
163
  }
164
164
 
165
165
  console.group()
166
- console.log(dobj.__name) // NOTE(Nikaoto): @nikoloza, don't remove this
166
+ console.log(dobj.__name) // NOTE: Don't remove this
167
167
 
168
- const isFirst = (idx == 0)
169
- const isLast = (idx == (exports.length - 1)) // NOTE: Don't use '===' here!
168
+ // NOTE: Don't use '===' here!
169
+ const isFirst = (idx == 0) // eslint-disable-line
170
+ const isLast = (idx == (exports.length - 1)) // eslint-disable-line
170
171
 
171
172
  const kaldunaOpts = {
172
173
  verbose: false,
173
174
  returnMitosisIR: true,
174
175
  globalSymbolTable,
175
- exportDefault: isSingleComponent,
176
+ exportDefault: false,
176
177
  importsToRemove: uniqueImports,
177
178
 
178
179
  /* NOTE: The option below prevents a name collision bug. For example:
@@ -184,14 +185,14 @@ function convertDomqlModule(domqlModule, globusaStruct, desiredFormat, options)
184
185
  But, in this case, because A is in local scope as one of the exports,
185
186
  the component import will be ignored, preventing the collision.
186
187
  */
187
- componentImportsToIgnore: exports,
188
+ componentImportsToIgnore: exports
188
189
  }
189
190
 
190
191
  let out = null
191
192
  if (isFirst) {
192
193
  out = convert(dobj, desiredFormat, {
193
194
  ...kaldunaOpts,
194
- removeReactImport: false,
195
+ removeReactImport: false
195
196
  // NOTE(nikaoto): Commented these out because we're using deps now, so
196
197
  // all the imports and decls are going to be redundant
197
198
  // importsToInclude: globusaStruct.imports,
@@ -200,7 +201,7 @@ function convertDomqlModule(domqlModule, globusaStruct, desiredFormat, options)
200
201
  } else {
201
202
  out = convert(dobj, desiredFormat, {
202
203
  ...kaldunaOpts,
203
- removeReactImport: true,
204
+ removeReactImport: true
204
205
  })
205
206
  }
206
207
 
@@ -221,8 +222,8 @@ function convertDomqlModule(domqlModule, globusaStruct, desiredFormat, options)
221
222
  // result to the destination. The tmpDirPath is used as a working directory for
222
223
  // temporary files.
223
224
  // Returns globusaStruct for later usage.
224
- async function convertFile(srcPath, tmpDirPath, destPath,
225
- desiredFormat, options) {
225
+ async function convertFile (srcPath, tmpDirPath, destPath,
226
+ desiredFormat, options) {
226
227
  // Parse with globusa
227
228
  console.log(`Parsing components in ${srcPath}`)
228
229
  const fileContent = await fs.promises.readFile(srcPath, 'utf8')
@@ -236,6 +237,7 @@ async function convertFile(srcPath, tmpDirPath, destPath,
236
237
  entryPoints: [srcPath],
237
238
  bundle: true,
238
239
  sourcemap: true,
240
+ keepNames: false,
239
241
  target: 'node12',
240
242
  format: 'cjs',
241
243
  outdir: tmpDirPath
@@ -256,7 +258,7 @@ async function convertFile(srcPath, tmpDirPath, destPath,
256
258
  )
257
259
 
258
260
  // Create dest dir
259
- await mkdirp(path.dirname(destPath))
261
+ mkdirp(path.dirname(destPath))
260
262
 
261
263
  // Write file
262
264
  if (convertedModuleStr && convertedModuleStr.length > 0) {
@@ -268,25 +270,147 @@ async function convertFile(srcPath, tmpDirPath, destPath,
268
270
  return globusaStruct
269
271
  }
270
272
 
273
+ // Aborts copying if destination exists
274
+ function recursiveCopy (src, dst, exclude) {
275
+ if (exclude && exclude.includes(src))
276
+ return
277
+
278
+ if (!fs.existsSync(src)) {
279
+ console.error(`Error (recursiveCopy): Source file '${src}' does not exist.`)
280
+ return
281
+ }
282
+
283
+ if (fs.existsSync(dst)) {
284
+ console.error(`Error (recursiveCopy): Destination file '${dst}' exists.`)
285
+ return
286
+ }
287
+
288
+ if (!isDirectory(src)) {
289
+ fs.copyFileSync(src, dst)
290
+ return
291
+ }
292
+
293
+ mkdirp(dst)
294
+ const files = fs.readdirSync(src)
295
+ for (const f of files) {
296
+ if (exclude && exclude.includes(f))
297
+ continue
298
+
299
+ recursiveCopy(path.join(src, f), path.join(dst, f), exclude)
300
+ }
301
+ }
302
+
303
+ function mergeDirectories (mrg, dst, { globusaMerge, exclude }) {
304
+ // Source doesn't exist, skip
305
+ if (!fs.existsSync(mrg)) {
306
+ console.error(`Error: Source merge directory '${mrg}' does not exist.`)
307
+ return
308
+ }
309
+
310
+ // Direct copy, no merging needed
311
+ if (!fs.existsSync(dst)) {
312
+ recursiveCopy(mrg, dst, exclude)
313
+ return
314
+ }
315
+
316
+ const isMrgDir = isDirectory(mrg)
317
+ const isDstDir = isDirectory(dst)
318
+
319
+ if (!isMrgDir && !isDstDir) {
320
+ return
321
+ }
322
+
323
+ if (!isMrgDir && isDstDir) {
324
+ console.error(`mergeDirectories('${mrg}', '${dst}') skipped. ` +
325
+ 'Merge source (mrg) is a regular file and the ' +
326
+ 'destination (dst) is a directory.')
327
+ return
328
+ }
329
+
330
+ if (isMrgDir && !isDstDir) {
331
+ console.error(`mergeDirectories('${mrg}', '${dst}') skipped. ` +
332
+ 'Merge source (mrg) is a directory and the ' +
333
+ 'destination (dst) is a regular file.')
334
+ return
335
+ }
336
+
337
+ const mrgFiles = fs.readdirSync(mrg).filter(f => !exclude.includes(f))
338
+ const dstFiles = fs.readdirSync(dst)
339
+
340
+ // Make a map of dstFiles for quick access
341
+ const dstFilesMap = {}
342
+ for (const f of dstFiles) {
343
+ dstFilesMap[f] = true
344
+ }
345
+
346
+ // Do a direct directory merge (without globusa)
347
+ const directMrgFiles = mrgFiles.filter(f => !globusaMerge.includes(f))
348
+ for (const f of directMrgFiles) {
349
+ if (!dstFilesMap[f]) {
350
+ recursiveCopy(path.resolve(mrg, f), path.resolve(dst, f), exclude)
351
+ } else {
352
+ mergeDirectories(path.resolve(mrg, f), path.resolve(dst, f), {
353
+ globusaMerge, exclude
354
+ })
355
+ }
356
+ }
357
+
358
+ // Do a smart file merge (with globusa)
359
+ const globusaMrgFiles = mrgFiles.filter(f => globusaMerge.includes(f))
360
+ for (const f of globusaMrgFiles) {
361
+ if (!dstFilesMap[f]) {
362
+ // Nothing to merge. Do a direct copy
363
+ const p = path.resolve(mrg, f)
364
+ if (isDirectory(p)) {
365
+ console.error('Error: Globusa merge can only be done on files, ' +
366
+ `but '${p}' is a directory`)
367
+ } else {
368
+ fs.copyFileSync(p, path.resolve(dst, f))
369
+ }
370
+ } else {
371
+ // Concatenate the files
372
+ const mrgTxt = fs.readFileSync(path.resolve(mrg, f), { encoding: 'utf8' })
373
+ const dstTxt = fs.readFileSync(path.resolve(dst, f), { encoding: 'utf8' })
374
+ const outTxt = mrgTxt + '\n' + dstTxt
375
+
376
+ // TODO: Dedup the imports with globusa here
377
+
378
+ fs.writeFileSync(path.resolve(dst, f), outTxt, { encoding: 'utf8' })
379
+ }
380
+ }
381
+ }
382
+
383
+ export function convertFromCli (data, opts) {
384
+ const { framework, verbose, verboseCode } = opts
385
+ console.log(chalk.dim('\n----------------\n'))
386
+ console.log('Converting components to', chalk.bold(framework))
387
+ const convertedStrings = convertDomqlModule(data, null, framework)
388
+ if (verboseCode) console.log(convertedStrings)
389
+ console.log(chalk.bold.green('\nSuccessfully converted'))
390
+ return verbose
391
+ }
392
+
271
393
  program
272
394
  .command('convert')
273
395
  .description('Convert and copy all DomQL components under a directory')
274
396
  .argument('[src]', 'Source directory/file. By default, it is "src/"')
275
397
  .argument('[dest]',
276
- 'Destination directory/file. Will be overwritten. By ' +
398
+ 'Destination directory/file. Will be overwritten. By ' +
277
399
  'default, it becomes the name of the desired format')
278
400
  .option('--react', 'Convert all DomQL components to React')
279
401
  .option('--angular', 'Convert all DomQL components to Angular')
280
402
  .option('--vue2', 'Convert all DomQL components to Vue2')
281
403
  .option('--vue3', 'Convert all DomQL components to Vue3')
282
404
  .option('-t, --tmp-dir <path>',
283
- 'Use this directory for storing intermediate & build files instead of ' +
405
+ 'Use this directory for storing intermediate & build files instead of ' +
284
406
  `the default (dest/${TMP_DIR_NAME})`)
285
407
  .option('-o, --only <components>',
286
- 'Only convert these components; comma separated ' +
408
+ 'Only convert these components; comma separated ' +
287
409
  '(for example: --only=Flex,Img)')
410
+ .option('-m, --merge <dir>',
411
+ 'After converting an entire directory, perform a recursive merge that takes files from this directory and puts them in the dest directory. It also concatenates index.js files')
288
412
  .option('--internal-uikit',
289
- '(For internal use only). ' +
413
+ '(For internal use only). ' +
290
414
  'Excludes particular components from the conversion')
291
415
  .action(async (src, dest, options) => {
292
416
  if (!convert) {
@@ -314,14 +438,14 @@ program
314
438
  // Resolve source file/dir
315
439
  const srcPath = path.resolve(src || './src')
316
440
  if (!fs.existsSync(srcPath)) {
317
- console.erorr(`Source directory/file ('${srcPath}') does not exist`)
318
- return 1
441
+ console.error(`Source directory/file ('${srcPath}') does not exist`)
442
+ process.exit(1)
319
443
  }
320
444
 
321
445
  // Resolve & create tmp dir
322
446
  const tmpDirPath = options.tmpDir ??
323
447
  path.resolve(path.dirname(srcPath), TMP_DIR_NAME)
324
- await mkdirp(tmpDirPath)
448
+ mkdirp(tmpDirPath)
325
449
 
326
450
  // Put a package.json file so that when we import() the modules from the
327
451
  // directory, node doesn't recognize them as ES modules (in case the parent
@@ -350,7 +474,7 @@ program
350
474
  } else {
351
475
  // dest not given. Use default (desiredFormat as directory).
352
476
  const destDir = path.resolve(desiredFormat)
353
- await mkdirp(destDir)
477
+ mkdirp(destDir)
354
478
  destFilePath = path.join(destDir, path.basename(srcPath))
355
479
  }
356
480
 
@@ -362,7 +486,7 @@ program
362
486
  options
363
487
  )
364
488
 
365
- return 0
489
+ process.exit(0)
366
490
  }
367
491
 
368
492
  // We're converting multiple files (in a directory).
@@ -372,7 +496,7 @@ program
372
496
  if (!fs.existsSync(dest)) {
373
497
  // dest doesn't exist. Create it.
374
498
  destDirPath = path.resolve(dest)
375
- await mkdirp(destDirPath)
499
+ mkdirp(destDirPath)
376
500
  } else if (isDirectory(dest)) {
377
501
  // dest exists and is a directory.
378
502
  destDirPath = path.resolve(dest)
@@ -381,21 +505,31 @@ program
381
505
  console.error(
382
506
  `The destination ('${path.resolve(dest)}') must be a directory when ` +
383
507
  `the source ('${srcPath}') is a directory`)
384
- return 1
508
+ process.exit(1)
509
+ }
510
+
511
+ // Resolve merge dir
512
+ let mergeDirPath = null
513
+ if (options.merge && options.internalUikit) {
514
+ mergeDirPath = path.resolve(options.merge)
515
+ if (!fs.existsSync(mergeDirPath)) {
516
+ console.error(`Merge directory '${mergeDirPath}' does not exist`)
517
+ process.exit(1)
518
+ }
385
519
  }
386
520
 
387
- const ignoredFiles = ['index.js', 'package.json', 'node_modules', 'dist']
521
+ const dontConvert = ['index.js', 'package.json', 'node_modules', 'dist']
388
522
  const sourceDirNames = (await fs.promises.readdir(srcPath))
389
- .filter(dir => !ignoredFiles.includes(dir))
523
+ .filter(dir => !dontConvert.includes(dir))
390
524
 
391
525
  const dirs = []
392
526
 
527
+ // Core convert loop
393
528
  for (const dir of sourceDirNames) {
394
529
  // Ignored directories
395
530
  if (options.internalUikit) {
396
531
  let skip = false
397
- for (const pat of INTERNAL_UIKIT_CONF.excludedDirectories)
398
- if (dir.match(pat)) { skip = true; break; }
532
+ for (const pat of INTERNAL_UIKIT_CONF.excludedDirectories) { if (dir.match(pat)) { skip = true; break } }
399
533
  if (skip) continue
400
534
  }
401
535
 
@@ -408,16 +542,16 @@ program
408
542
  const pjFilePath = path.join(dirPath, 'package.json')
409
543
 
410
544
  const globusaStruct = await convertFile(
411
- indexFilePath, // src
412
- path.join(tmpDirPath, dir), // tmp
545
+ indexFilePath, // src
546
+ path.join(tmpDirPath, dir), // tmp
413
547
  path.join(destDirPath, dir, 'index.js'), // dst
414
548
  desiredFormat,
415
549
  options
416
550
  )
417
551
 
418
- if (fs.existsSync(pjFilePath)) {
552
+ if (options.internalUikit && fs.existsSync(pjFilePath)) {
419
553
  generatePackageJsonFile(
420
- pjFilePath, // src
554
+ pjFilePath, // src
421
555
  path.join(destDirPath, dir, 'package.json'), // dst
422
556
  globusaStruct,
423
557
  desiredFormat,
@@ -430,13 +564,19 @@ program
430
564
 
431
565
  // Generate top index.js file
432
566
  if (dirs.length > 0) {
433
- //const importLines = dirs.map(d => `import ${d} from './${d}'`).join('\n') + '\n'
434
- //const exportLines = 'export {\n' + dirs.map(d => ` ${d}`).join(',\n') + '\n}\n'
435
- //const fileContent = importLines + '\n' + exportLines
436
567
  const fileContent = dirs.map(d => `export * from './${d}'`).join('\n')
437
-
438
568
  const fh = await fs.promises.open(path.join(destDirPath, 'index.js'), 'w')
439
569
  await fh.writeFile(fileContent, 'utf8')
440
570
  await fh.close()
441
571
  }
572
+
573
+ if (mergeDirPath) {
574
+ console.log(`Merging '${mergeDirPath}' and ${destDirPath}...`)
575
+ mergeDirectories(mergeDirPath, destDirPath, {
576
+ globusaMerge: ['index.js', 'index.jsx'],
577
+ exclude: ['dist', 'node_modules']
578
+ })
579
+ }
580
+
581
+ process.exit(0)
442
582
  })
package/bin/fetch.js CHANGED
@@ -3,112 +3,115 @@
3
3
  import fs from 'fs'
4
4
  import chalk from 'chalk'
5
5
  import { loadModule } from './require.js'
6
- import { exec } from 'child_process'
7
6
  import { program } from './program.js'
7
+ import * as fetch from '@symbo.ls/fetch'
8
8
 
9
- import fetch from '@symbo.ls/fetch'
10
- const { fetchRemote } = fetch
9
+ import * as utils from '@domql/utils'
10
+ import { convertFromCli } from './convert.js'
11
+ const { isObjectLike } = utils.default
12
+
13
+ const { fetchRemote } = fetch.default
11
14
 
12
- const PACKAGE_PATH = process.cwd() + '/package.json'
13
15
  const RC_PATH = process.cwd() + '/symbols.json'
14
16
  const LOCAL_CONFIG_PATH = process.cwd() + '/node_modules/@symbo.ls/init/dynamic.json'
15
17
  const DEFAULT_REMOTE_REPOSITORY = 'https://github.com/symbo-ls/default-config/'
16
- const DEFAULT_REMOTE_CONFIG_PATH = 'https://api.symbols.dev/' // eslint-disable-line
18
+ const DEFAULT_REMOTE_CONFIG_PATH = 'https://api.symbols.app/' // eslint-disable-line
17
19
 
18
- const API_URL = 'https://api.symbols.dev/' // eslint-disable-line
20
+ const API_URL_LOCAL = 'http://localhost:13335/'
21
+ const API_URL = 'https://api.symbols.app/'
19
22
 
20
- const pkg = loadModule(PACKAGE_PATH)
21
23
  const rcFile = loadModule(RC_PATH) // eslint-disable-line
22
24
  const localConfig = loadModule(LOCAL_CONFIG_PATH) // eslint-disable-line
23
25
 
26
+ const debugMsg = chalk.dim('Use --verbose to debug the error or open the issue at https://github.com/symbo-ls/smbls')
27
+
24
28
  let rc = {}
25
29
  try {
26
30
  rc = loadModule(RC_PATH) // eslint-disable-line
27
31
  } catch (e) { console.error('Please include symbols.json to your root of respository') }
28
32
 
29
- program
30
- .version(pkg.version ?? 'unknown')
33
+ export const fetchFromCli = async (opts) => {
34
+ const { dev, verbose, prettify } = opts
31
35
 
32
- program
33
- .command('install')
34
- .description('Install Symbols')
35
- .option('--framework', 'Which Symbols to install (domql, react)')
36
- .action(async (framework) => {
37
- if (!rcFile || !localConfig) {
38
- console.error('symbols.json not found in the root of the repository')
39
- return
40
- }
36
+ await rc.then(async data => {
37
+ const { key, framework } = data
41
38
 
42
- // const packageName = `@symbo.ls/${mode || 'uikit'}`
43
- const packageName = 'smbls'
44
- console.log('Adding', chalk.green.bold(packageName))
39
+ const endpoint = dev ? API_URL_LOCAL : API_URL
45
40
 
46
- if (framework === 'domql' || rcFile.framework === 'domql') {
47
- exec('yarn add domql@^1.15.26 --force', (error, stdout, stderr) => {
48
- if (error) {
49
- console.log(`error: ${error.message}`)
50
- return
51
- }
52
- if (stderr) {
53
- console.log(`stderr: ${stderr}`)
54
- // return;
55
- }
56
- })
57
- }
41
+ console.log('\nFetching from:', chalk.bold(endpoint), '\n')
58
42
 
59
- exec(`yarn add ${packageName}@^0.15.22 --force`, (error, stdout, stderr) => {
60
- if (error) {
61
- console.log(`error: ${error.message}`)
62
- return
43
+ const body = await fetchRemote(key, {
44
+ endpoint,
45
+ onError: (e) => {
46
+ console.log(chalk.red('Failed to fetch:'), key)
47
+ if (verbose) console.error(e)
48
+ else console.log(debugMsg)
63
49
  }
64
- if (stderr) {
65
- console.log(`stderr: ${stderr}`)
66
- // return;
67
- }
68
- console.log('')
69
- console.log(`stdout: ${stdout}`)
70
- console.log('\n')
71
- console.log(chalk.green.bold(packageName), 'successfuly added!')
72
- console.log('')
73
- console.log(chalk.dim('Now you can import components like:'), 'import { Button } from \'smbls')
74
50
  })
75
- })
76
-
77
- program
78
- .command('fetch [destination]')
79
- .description('Fetch symbols')
80
- .action(async (options) => {
81
- rc.then(async data => {
82
- const opts = { ...data, ...options } // eslint-disable-line
83
- const key = data.key || (options && options.key)
84
-
85
- const body = await fetchRemote(key, { endpoint: 'api.symbols.dev' })
86
- const { version, ...config } = body
87
-
88
- console.log(chalk.bold('Symbols'), 'config fetched:')
89
- if (key) console.log(chalk.green(key))
90
- else console.log(chalk.dim('- Default config from:'), chalk.dim.underline(DEFAULT_REMOTE_REPOSITORY))
91
- console.log('')
92
-
93
- console.log(chalk.dim('- dynamic.json updated:'), chalk.dim.underline(LOCAL_CONFIG_PATH))
94
- console.log('')
95
-
96
- for (const t in config) {
97
- const type = config[t]
98
- console.log(chalk.bold(t))
99
- const arr = []
100
- for (const v in type) arr.push(v)
101
- console.log(' ', chalk.dim(arr.join(', ')))
51
+ if (!body) return
52
+
53
+ const { version, ...config } = body
54
+
55
+ if (verbose) {
56
+ if (key) {
57
+ console.log(chalk.bold('Symbols'), 'data fetched for', chalk.green(body.name))
58
+ } else {
59
+ console.log(
60
+ chalk.bold('Symbols'),
61
+ 'config fetched from',
62
+ chalk.bold('default-config from:'),
63
+ chalk.dim.underline(DEFAULT_REMOTE_REPOSITORY)
64
+ )
102
65
  }
66
+ console.log()
67
+ }
103
68
 
104
- const bodyString = JSON.stringify(body)
105
- fs.writeFile(LOCAL_CONFIG_PATH, bodyString, err => {
106
- console.log('')
107
- if (err) {
108
- console.log('Error writing file', err)
69
+ for (const t in config) {
70
+ const type = config[t]
71
+ const arr = []
72
+ if (isObjectLike(type)) {
73
+ for (const v in type) arr.push(v)
74
+ if (arr.length) {
75
+ console.log(chalk.dim(t + ':'))
76
+ console.log(chalk.bold(arr.join(', ')))
109
77
  } else {
110
- console.log('Successfully wrote file')
78
+ console.log(chalk.dim(t + ':'), chalk.dim('- empty -'))
111
79
  }
112
- })
113
- })
80
+ } else console.log(chalk.dim(t + ':'), chalk.bold(type))
81
+ }
82
+
83
+ if (body.designsystem) {
84
+ body.designSystem = body.designsystem
85
+ delete body.designsystem
86
+ }
87
+
88
+ const bodyString = JSON.stringify(body, null, prettify ?? 2)
89
+
90
+ try {
91
+ await fs.writeFileSync(LOCAL_CONFIG_PATH, bodyString)
92
+
93
+ if (verbose) {
94
+ console.log(chalk.dim('\ndynamic.json has been updated:'))
95
+ console.log(chalk.dim.underline(LOCAL_CONFIG_PATH))
96
+ }
97
+
98
+ console.log(chalk.bold.green('\nSuccessfully wrote file'))
99
+ } catch (e) {
100
+ console.log(chalk.bold.red('\nError writing file'))
101
+ if (verbose) console.error(e)
102
+ else console.log(debugMsg)
103
+ }
104
+
105
+ if (body.components && framework) {
106
+ convertFromCli(body.components, { ...opts, framework })
107
+ }
114
108
  })
109
+ }
110
+
111
+ program
112
+ .command('fetch')
113
+ .description('Fetch symbols')
114
+ .option('-d, --dev', 'Running from local server')
115
+ .option('-v, --verbose', 'Verbose errors and warnings')
116
+ .option('--verbose-code', 'Verbose errors and warnings')
117
+ .action(fetchFromCli)
package/bin/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  import 'v8-compile-cache'
4
4
 
5
5
  import { program } from './program.js'
6
+ import './install.js'
6
7
  import './init.js'
7
8
  import './fetch.js'
8
9
  import './sync.js'
package/bin/install.js ADDED
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+
3
+ import chalk from 'chalk'
4
+ import { loadModule } from './require.js'
5
+ import { exec } from 'child_process'
6
+ import { program } from './program.js'
7
+
8
+ const PACKAGE_PATH = process.cwd() + '/package.json'
9
+ const RC_PATH = process.cwd() + '/symbols.json'
10
+ const LOCAL_CONFIG_PATH = process.cwd() + '/node_modules/@symbo.ls/init/dynamic.json'
11
+ const DEFAULT_REMOTE_CONFIG_PATH = 'https://api.symbols.app/' // eslint-disable-line
12
+
13
+ const pkg = loadModule(PACKAGE_PATH)
14
+ const rcFile = loadModule(RC_PATH) // eslint-disable-line
15
+ const localConfig = loadModule(LOCAL_CONFIG_PATH) // eslint-disable-line
16
+
17
+ let rc = {}
18
+ try {
19
+ rc = loadModule(RC_PATH) // eslint-disable-line
20
+ } catch (e) { console.error('Please include symbols.json to your root of respository') }
21
+
22
+ const makeCommand = (packageManager, packageName) => {
23
+ return packageManager === 'yarn'
24
+ ? `yarn add ${packageName}`
25
+ : packageManager === 'pnpm'
26
+ ? `pnpm add ${packageName}`
27
+ : `npm i ${packageName} --save`
28
+ }
29
+
30
+ export const installFromCli = async (options) => {
31
+ if (!rcFile || !localConfig) {
32
+ console.error('symbols.json not found in the root of the repository')
33
+ return
34
+ }
35
+
36
+ const framework = rcFile.framework || options.framework
37
+ const packageManager = rcFile.packageManager || options.packageManager
38
+
39
+ // const packageName = `@symbo.ls/${mode || 'uikit'}`
40
+ const packageName = framework === 'react' ? '@symbo.ls/react' : 'smbls'
41
+ console.log('Adding', chalk.green.bold(packageName))
42
+
43
+ const command = makeCommand(packageManager, packageName)
44
+ exec(command, (error, stdout, stderr) => {
45
+ if (error) {
46
+ console.log(`error: ${error.message}`)
47
+ return
48
+ }
49
+ if (stderr) {
50
+ console.log(`stderr: ${stderr}`)
51
+ // return;
52
+ }
53
+ console.log('')
54
+ console.log(`stdout: ${stdout}`)
55
+ console.log('\n')
56
+ console.log(chalk.green.bold(packageName), 'successfuly added!')
57
+ console.log('')
58
+ console.log(
59
+ chalk.dim('Now you can import components like:'),
60
+ `import { Button } from '${packageName}'`
61
+ )
62
+ })
63
+ }
64
+
65
+ program
66
+ .version(pkg.version ?? 'unknown')
67
+
68
+ program
69
+ .command('install')
70
+ .description('Install Symbols')
71
+ .option('-d, --dev', 'Running from local server')
72
+ .option('-v, --verbose', 'Verbose errors and warnings')
73
+ .option('-f, --fetch', 'Verbose errors and warnings', true)
74
+ .option('--framework', 'Which Symbols to install (domql, react)')
75
+ .action(installFromCli)
package/bin/require.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
- import { createRequire } from 'module'
4
3
  import fs from 'fs'
4
+ import { createRequire } from 'module'
5
5
 
6
6
  class ImportError extends Error {} /* Bring in the ability to create the 'require' method */ // eslint-disable-line
7
7
  const require = createRequire(import.meta.url) // construct the require method
package/bin/sync.js CHANGED
@@ -1,9 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { updateDynamycFile } from '@symbo.ls/socket'
4
- import * as socketClient from '@symbo.ls/socket/client.js'
3
+ import chalk from 'chalk'
5
4
  import { program } from './program.js'
6
5
  import { loadModule } from './require.js'
6
+ import { updateDynamycFile } from '@symbo.ls/socket'
7
+
8
+ import * as socketClient from '@symbo.ls/socket/client.js'
9
+ import { fetchFromCli } from './fetch.js'
10
+ import { convertFromCli } from './convert.js'
11
+
12
+ const SOCKET_API_URL_LOCAL = 'http://localhost:13336/'
13
+ const SOCKET_API_URL = 'https://socket.symbols.app/'
14
+
15
+ const debugMsg = chalk.dim('Use --verbose to debug the error or open the issue at https://github.com/symbo-ls/smbls')
7
16
 
8
17
  const RC_PATH = process.cwd() + '/symbols.json'
9
18
  let rc = {}
@@ -14,21 +23,52 @@ try {
14
23
  program
15
24
  .command('sync')
16
25
  .description('Sync with Symbols')
17
- .option('-l, --live', 'Bypass the local build')
18
- .option('--key', 'Bypass the local build')
19
- .action(async (options) => {
26
+ .option('-d, --dev', 'Running from local server')
27
+ .option('-v, --verbose', 'Verbose errors and warnings')
28
+ .option('-k, --key', 'Bypass the symbols.json key, overriding the key manually')
29
+ .option('-f, --fetch', 'Verbose errors and warnings', true)
30
+ .option('--verbose-code', 'Verbose errors and warnings')
31
+ .action(async (opts) => {
32
+ const { dev, verbose, fetch: fetchAlso } = opts
33
+
34
+ if (fetchAlso) {
35
+ await fetchFromCli(opts)
36
+ console.log(chalk.dim('\n----------------\n'))
37
+ }
38
+
20
39
  if (!rc) {
21
40
  console.error('symbols.json not found in the root of the repository')
22
41
  return
23
42
  }
24
- rc.then(data => {
25
- const opts = { ...data, ...options }
26
- const key = data.key || options.key
43
+
44
+ // if (rc) return false /// /////////////////////
45
+
46
+ await rc.then(symbolsrc => {
47
+ const options = { ...symbolsrc, ...opts }
48
+ const { framework } = symbolsrc
49
+ const key = symbolsrc.key || opts.key
50
+ const socketUrl = dev ? SOCKET_API_URL_LOCAL : SOCKET_API_URL
51
+
52
+ console.log('Connecting to:', chalk.bold(socketUrl))
53
+ console.log()
54
+
27
55
  socketClient.connect(key, {
56
+ source: 'cli',
57
+ socketUrl,
28
58
  onConnect: (id, socket) => {
29
- console.log(id)
59
+ console.log('Connected to', chalk.green(key), 'from', chalk.bold('Symbols'), 'socket server')
60
+ console.log('Socket id:', id)
61
+ console.log(chalk.dim('\nListening to updates...\n'))
30
62
  },
31
63
  onChange: (event, data) => {
64
+ if (event === 'clients') {
65
+ console.log(
66
+ 'Active clients:',
67
+ chalk.green.bold(Object.keys(data).join(', '))
68
+ )
69
+ return
70
+ }
71
+
32
72
  data = JSON.parse(data)
33
73
  const d = {}
34
74
  const {
@@ -36,19 +76,32 @@ program
36
76
  PROJECT_STATE,
37
77
  PROJECT_COMPONENTS,
38
78
  PROJECT_SNIPPETS,
39
- PROJECT_PAGES
79
+ PROJECT_PAGES,
80
+ DATA
40
81
  } = data
41
82
  if (PROJECT_DESIGN_SYSTEM) d.designSystem = PROJECT_DESIGN_SYSTEM
42
- if (PROJECT_STATE) d.designSystem = PROJECT_STATE
43
- if (PROJECT_COMPONENTS) d.designSystem = PROJECT_COMPONENTS
44
- if (PROJECT_SNIPPETS) d.designSystem = PROJECT_SNIPPETS
45
- if (PROJECT_PAGES) d.designSystem = PROJECT_PAGES
46
- if (Object.keys(d).length) updateDynamycFile(d)
83
+ if (PROJECT_STATE) d.state = PROJECT_STATE
84
+ if (PROJECT_COMPONENTS) d.components = PROJECT_COMPONENTS
85
+ if (DATA && DATA.components) d.components = DATA.components
86
+ if (PROJECT_SNIPPETS) d.snippets = PROJECT_SNIPPETS
87
+ if (PROJECT_PAGES) d.pages = PROJECT_PAGES
88
+
89
+ if (Object.keys(d).length) {
90
+ updateDynamycFile(d, { framework, ...options })
91
+ }
92
+
93
+ if (d.components && framework) {
94
+ convertFromCli(d.components, {
95
+ ...options, framework
96
+ })
97
+ }
47
98
  },
48
99
  onError: (err, socket) => {
49
- console.log(err)
100
+ console.log(chalk.bold.green('Error during connection'))
101
+ if (verbose) console.error(err)
102
+ else console.log(debugMsg)
50
103
  },
51
- ...opts
104
+ ...options
52
105
  })
53
106
  })
54
107
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbo.ls/cli",
3
- "version": "2.11.159",
3
+ "version": "2.11.162",
4
4
  "description": "Fetch your Symbols configuration",
5
5
  "main": "bin/fetch.js",
6
6
  "author": "Symbols",
@@ -25,5 +25,5 @@
25
25
  "node-fetch": "^3.1.0",
26
26
  "v8-compile-cache": "^2.3.0"
27
27
  },
28
- "gitHead": "4dbce17a65f09e9c7e9451f5d9042ddbe351280b"
28
+ "gitHead": "fe3359a1d6c14d38f45f5e5db10ef2056947a228"
29
29
  }