@symbo.ls/cli 2.11.127 → 2.11.131

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.
Files changed (3) hide show
  1. package/bin/convert.js +167 -120
  2. package/package.json +6 -3
  3. package/LICENSE +0 -21
package/bin/convert.js CHANGED
@@ -1,14 +1,18 @@
1
1
  'use strict'
2
2
 
3
- import * as esbuild from 'esbuild'
4
3
  import { program } from './program.js'
5
4
  import { convert } from 'kalduna'
5
+ import { parse } from 'globusa'
6
6
  import fs from 'fs'
7
7
  import path from 'path'
8
- import { JSDOM } from 'jsdom'
9
8
 
10
- const l = (n) => console.log(`mark${n}`) // eslint-disable-line no-unused-vars
9
+ // Set up webpack
10
+ import syncWebpack from 'webpack'
11
+ import { promisify } from 'util'
12
+ const webpack = promisify(syncWebpack)
11
13
 
14
+ // Set up jsdom
15
+ import { JSDOM } from 'jsdom'
12
16
  const jsdom = new JSDOM('<html><head></head><body></body></html>')
13
17
  global.window = jsdom.window
14
18
  global.document = window.document
@@ -54,71 +58,150 @@ async function mkdirp (dir) {
54
58
  return null
55
59
  }
56
60
 
57
- async function importDomqlModule (modulePath) {
58
- console.log(`importing ${modulePath}`)
59
- return (await import(modulePath)).default
60
- }
61
-
62
- function convertDomqlModule (domqlModule, desiredFormat, options) {
61
+ // Returns a string
62
+ function convertDomqlModule(domqlModule, globusaStruct, desiredFormat, options) {
63
63
  let convertedStr = ''
64
64
  const whitelist = (options.only ? options.only.split(',') : null)
65
65
 
66
66
  console.group()
67
+ const exports = Object.keys(domqlModule)
68
+ .filter(exportName => {
69
+ if (!whitelist) return true
70
+ if (whitelist.includes(exportName)) {
71
+ console.log(`Skipping ${exportName} component due to whitelist exclusion`)
72
+ return false
73
+ }
74
+ return true
75
+ })
76
+ .filter(exportName => {
77
+ if (!options.internalUikit) return true
78
+ if (EXCLUDED_FROM_INTERNAL_UIKIT.includes(exportName)) {
79
+ console.log(`Skipping ${exportName} component due to internal uikit exclusion`)
80
+ return false
81
+ }
82
+ return true
83
+ })
84
+
85
+ const isSingleComponent = (exports.length === 1)
67
86
  const uniqueImports = []
68
- const first = true
69
- let currentExportIdx = 0
70
- const exportCount = Object.keys(domqlModule).length
71
- for (const key in domqlModule) {
72
- // Skip if not found in whitelist
73
- if (whitelist && !whitelist.includes(key)) { continue }
74
-
75
- // Skip some components if converting smbls uikit
76
- if (options.internalUikit &&
77
- EXCLUDED_FROM_INTERNAL_UIKIT.includes(key)) {
78
- console.log(`Skipping ${key} component due to exclusion`)
79
- continue
87
+ for (const idx in exports) {
88
+ const exportName = exports[idx]
89
+
90
+ const dobj = domqlModule[exportName]
91
+
92
+ // Set component name (if not present)
93
+ if (!dobj.__name) {
94
+ dobj.__name = exportName
80
95
  }
81
96
 
82
- if (convert) {
83
- console.group()
84
- const component = domqlModule[key]
85
- component.__name = key
86
- console.log(key) // NOTE: @nikoloza don't remove this (again)
87
-
88
- const isSingleComponent = exportCount === 1
89
- const isFirst = currentExportIdx === 0
90
- const isLast = currentExportIdx === exportCount - 1
91
-
92
- const out = convert(component, desiredFormat, {
93
- verbose: false,
94
- exportDefault: isSingleComponent,
95
- returnMitosisIR: true,
96
- importsToRemove: uniqueImports,
97
- removeReactImport: !isFirst
98
- })
97
+ console.group()
98
+ console.log(dobj.__name) // NOTE(Nikaoto): @nikoloza, don't remove this
99
99
 
100
- convertedStr = convertedStr + out.str
101
- if (options.trailingNewLine && !isLast) {
102
- convertedStr += '\n'
103
- }
100
+ const isFirst = (idx == 0)
101
+ const isLast = (idx == (exports.length - 1)) // NOTE: Don't use '===' here!
102
+
103
+ const kaldunaOpts = {
104
+ verbose: false,
105
+ returnMitosisIR: true,
106
+ exportDefault: isSingleComponent,
107
+ importsToRemove: uniqueImports,
104
108
 
105
- uniqueImports.push(...out.mitosisIR.imports)
106
- console.groupEnd()
107
- currentExportIdx++
109
+ /* NOTE: The option below prevents a name collision bug. For example:
110
+ export const A = { ... }
111
+ export const B = { extends: A }
112
+
113
+ Normally, converting component B will generate an import for A like:
114
+ 'import { A } from @symbo.ls/react'
115
+ But, in this case, because A is in local scope as one of the exports,
116
+ the component import will be ignored, preventing the collision.
117
+ */
118
+ componentImportsToIgnore: exports,
119
+ }
120
+
121
+ let out = null
122
+ if (isFirst) {
123
+ out = convert(dobj, desiredFormat, {
124
+ ...kaldunaOpts,
125
+ removeReactImport: false,
126
+ importsToInclude: globusaStruct.imports,
127
+ declarationsToInclude: globusaStruct.declarations,
128
+ })
108
129
  } else {
109
- throw new Error(
110
- 'Convert from `domql-to-mitosis` is not defined. Try to install' +
111
- '`domql-to-mitosis` and run this command again.')
130
+ out = convert(dobj, desiredFormat, {
131
+ ...kaldunaOpts,
132
+ removeReactImport: true,
133
+ })
134
+ }
135
+
136
+ convertedStr = convertedStr + out.str
137
+ if (!isLast) {
138
+ convertedStr += '\n'
112
139
  }
140
+ uniqueImports.push(...out.mitosisIR.imports)
141
+ console.groupEnd()
113
142
  }
114
143
  console.groupEnd()
115
144
 
116
145
  return convertedStr
117
146
  }
118
147
 
148
+ // Takes a source file, then bundles, parses and converts it and writes the
149
+ // result to the destination. The tmpDirPath is used as a working directory for
150
+ // temporary files.
151
+ async function convertFile(srcPath, tmpDirPath, destPath,
152
+ desiredFormat, options) {
153
+ // Parse with globusa
154
+ console.log(`Parsing components in ${srcPath}`)
155
+ const fileContent = await fs.promises.readFile(srcPath, 'utf8')
156
+ const globusaStruct = parse(fileContent)
157
+
158
+ // Bundle with webpack
159
+ const libraryName = 'banunu' // This can literally be anything
160
+ const fileName = path.basename(srcPath)
161
+ const bundledFilePath = path.resolve(tmpDirPath, fileName)
162
+ console.log(`Webpack ${srcPath} -> ${bundledFilePath}`)
163
+ await webpack({
164
+ entry: srcPath,
165
+ output: {
166
+ path: tmpDirPath,
167
+ filename: fileName,
168
+ chunkFormat: 'commonjs',
169
+ library: { name: libraryName,
170
+ type: 'commonjs-static' },
171
+ },
172
+ // experiments: { outputModule: true },
173
+ target: 'node',
174
+ mode: 'development'
175
+ })
176
+
177
+ // Import the bundled module to obtain exported domql objects
178
+ console.log(`Importing ${bundledFilePath}`)
179
+ const domqlModule = (await import(bundledFilePath))[libraryName]
180
+
181
+ // Convert it/them with kalduna
182
+ console.log(`Converting components in ${bundledFilePath}:`)
183
+ const convertedModuleStr = convertDomqlModule(
184
+ domqlModule,
185
+ globusaStruct,
186
+ desiredFormat,
187
+ options
188
+ )
189
+
190
+ // Create dest dir
191
+ await mkdirp(path.dirname(destPath))
192
+
193
+ // Write file
194
+ if (convertedModuleStr && convertedModuleStr.length > 0) {
195
+ const fh = await fs.promises.open(destPath, 'w')
196
+ await fh.writeFile(convertedModuleStr, 'utf8')
197
+ await fh.close()
198
+ }
199
+ }
200
+
119
201
  program
120
202
  .command('convert')
121
- .description('Convert and copy all DomQL components under a directory')
203
+ .description('(DEPRECATED) Convert and copy all DomQL components ' +
204
+ 'under a directory')
122
205
  .argument('[src]', 'Source directory/file. By default, it is "src/"')
123
206
  .argument('[dest]',
124
207
  'Destination directory/file. Will be overwritten. By ' +
@@ -137,6 +220,22 @@ program
137
220
  '(For internal use only). ' +
138
221
  'Excludes particular components from the conversion')
139
222
  .action(async (src, dest, options) => {
223
+ console.log('smbls convert is deprecated. ' +
224
+ 'Please use the Kalduna build script instead.')
225
+ return 1
226
+
227
+ if (!convert) {
228
+ throw new Error(
229
+ 'convert() from `kalduna` is not defined. Try to install ' +
230
+ '`kalduna` and run this command again.')
231
+ }
232
+
233
+ if (!parse) {
234
+ throw new Error(
235
+ 'parse() from `globusa` is not defined. Try to install ' +
236
+ '`globusa` and run this command again.')
237
+ }
238
+
140
239
  // Desired format
141
240
  let desiredFormat = 'react'
142
241
  if (options.angular) {
@@ -191,41 +290,18 @@ program
191
290
  destFilePath = path.join(destDir, path.basename(srcPath))
192
291
  }
193
292
 
194
- const bundledFilePath = path.join(tmpDirPath, path.basename(srcPath))
195
- console.log(`ESbuild ${srcPath} -> ${bundledFilePath}`)
196
-
197
- // Bundle the component
198
- await esbuild.build({
199
- entryPoints: [srcPath],
200
- bundle: true,
201
- sourcemap: true,
202
- target: 'node12',
203
- format: 'cjs',
204
- outfile: bundledFilePath
205
- })
206
-
207
- // Import the module
208
- const domqlModule = await importDomqlModule(bundledFilePath, options)
209
-
210
- // Convert & append each exported domql object
211
- console.log(`Converting modules in ${bundledFilePath}:`)
212
- const convertedModuleStr = convertDomqlModule(
213
- domqlModule,
293
+ await convertFile(
294
+ srcPath,
295
+ tmpDirPath,
296
+ destFilePath,
214
297
  desiredFormat,
215
298
  options
216
299
  )
217
300
 
218
- // Write file
219
- if (convertedModuleStr.length > 0) {
220
- const fh = await fs.promises.open(destFilePath, 'w')
221
- await fh.writeFile(convertedModuleStr, 'utf8')
222
- await fh.close()
223
- }
224
-
225
301
  return 0
226
302
  }
227
303
 
228
- // We're converting multiple files (in a directory)
304
+ // We're converting multiple files (in a directory).
229
305
  // Determine destDirPath & create it if needed
230
306
  if (!dest) dest = path.resolve(desiredFormat)
231
307
  let destDirPath
@@ -239,52 +315,23 @@ program
239
315
  } else {
240
316
  // dest exists and is not a directory.
241
317
  console.error(
242
- `The destination ('${path.resolve(dest)}') must be a directory when` +
318
+ `The destination ('${path.resolve(dest)}') must be a directory when ` +
243
319
  `the source ('${srcPath}') is a directory`)
244
320
  return 1
245
321
  }
246
322
 
247
- const origFiles = (await fs.promises.readdir(srcPath))
248
- .filter(file => !IGNORED_FILES.includes(file))
249
-
250
- // Bundle components
251
- await esbuild.build({
252
- entryPoints: origFiles.map(file =>
253
- path.join(srcPath, file,'./index.js')),
254
- bundle: true,
255
- sourcemap: true,
256
- target: 'node12',
257
- format: 'cjs',
258
- outdir: tmpDirPath
259
- })
260
-
261
- // Convert components
262
- const componentDirs = await fs.promises.readdir(tmpDirPath)
263
- for (const componentDir of componentDirs) {
264
- const importDir = path.join(tmpDirPath, componentDir)
265
- if ((await fs.promises.stat(importDir)).isDirectory()) {
266
- // Import the module
267
- const importPath = `${importDir}/index.js`
268
- const domqlModule = await importDomqlModule(importPath)
269
-
270
- // Create directory for component in dest dir
271
- const destComponentDirPath = `${destDirPath}/${componentDir}`
272
- await mkdirp(destComponentDirPath)
273
-
274
- // Convert & append each exported domql object
275
- const convertedStr = convertDomqlModule(
276
- domqlModule,
277
- desiredFormat,
278
- { ...options, trailingNewLine: true }
279
- )
280
-
281
- // Write file
282
- if (convertedStr.length > 0) {
283
- const fh = await fs.promises
284
- .open(`${destComponentDirPath}/index.js`, 'w')
285
- await fh.writeFile(convertedStr, 'utf8')
286
- await fh.close()
287
- }
288
- }
323
+ const sourceFileNames = (await fs.promises.readdir(srcPath))
324
+ .filter(file => !IGNORED_FILES.includes(file))
325
+
326
+ for (const file of sourceFileNames) {
327
+ const indexFilePath = path.join(srcPath, file, 'index.js')
328
+
329
+ await convertFile(
330
+ indexFilePath,
331
+ path.join(tmpDirPath, file),
332
+ path.join(destDirPath, file, 'index.js'),
333
+ desiredFormat,
334
+ options
335
+ )
289
336
  }
290
337
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbo.ls/cli",
3
- "version": "2.11.127",
3
+ "version": "2.11.131",
4
4
  "description": "Fetch your Symbols configuration",
5
5
  "main": "bin/fetch.js",
6
6
  "author": "Symbols",
@@ -19,10 +19,13 @@
19
19
  "@symbo.ls/socket": "latest",
20
20
  "chalk": "^5.0.0",
21
21
  "commander": "latest",
22
- "esbuild": "latest",
22
+ "globusa": "latest",
23
23
  "jsdom": "^21.1.0",
24
24
  "node-fetch": "^3.1.0",
25
25
  "v8-compile-cache": "^2.3.0"
26
26
  },
27
- "gitHead": "997ec287b7bf139764e90bf460e5a6a67537bff6"
27
+ "gitHead": "e139ece289d929e41123a0a72e55155eb1eac605",
28
+ "devDependencies": {
29
+ "webpack": "^5.88.2"
30
+ }
28
31
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 symbo.ls
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.