@symbo.ls/cli 2.33.20 → 2.33.25
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 +3 -3
- package/bin/fetch.js +3 -4
- package/bin/index.js +1 -0
- package/bin/init-helpers/init-repo.js +13 -5
- package/bin/login.js +2 -1
- package/bin/push.js +8 -8
- package/bin/servers.js +49 -0
- package/bin/sync.js +7 -8
- package/helpers/config.js +14 -4
- package/helpers/credentialManager.js +150 -25
- package/package.json +5 -5
package/bin/collab.js
CHANGED
|
@@ -35,15 +35,15 @@ function debounce(fn, wait) {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
export async function startCollab(options) {
|
|
38
|
+
const symbolsConfig = await loadSymbolsConfig()
|
|
39
|
+
const cliConfig = loadCliConfig()
|
|
38
40
|
const credManager = new CredentialManager()
|
|
39
|
-
const authToken = credManager.ensureAuthToken()
|
|
41
|
+
const authToken = credManager.ensureAuthToken(cliConfig.apiBaseUrl)
|
|
40
42
|
if (!authToken) {
|
|
41
43
|
console.log(chalk.yellow('\nAuthentication required. Please run: smbls login\n'))
|
|
42
44
|
process.exit(1)
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
const symbolsConfig = await loadSymbolsConfig()
|
|
46
|
-
const cliConfig = loadCliConfig()
|
|
47
47
|
const lock = readLock()
|
|
48
48
|
const branch = options.branch || cliConfig.branch || symbolsConfig.branch || 'main'
|
|
49
49
|
const appKey = cliConfig.projectKey || symbolsConfig.key
|
package/bin/fetch.js
CHANGED
|
@@ -26,17 +26,16 @@ const debugMsg = chalk.dim(
|
|
|
26
26
|
export const fetchFromCli = async (opts) => {
|
|
27
27
|
const { dev, verbose, prettify, convert: convertOpt, metadata: metadataOpt, update, force } = opts
|
|
28
28
|
|
|
29
|
+
const symbolsConfig = await loadSymbolsConfig()
|
|
30
|
+
const cliConfig = loadCliConfig()
|
|
29
31
|
const credManager = new CredentialManager()
|
|
30
|
-
const authToken = credManager.ensureAuthToken()
|
|
32
|
+
const authToken = credManager.ensureAuthToken(cliConfig.apiBaseUrl)
|
|
31
33
|
|
|
32
34
|
if (!authToken) {
|
|
33
35
|
showAuthRequiredMessages()
|
|
34
|
-
|
|
35
36
|
process.exit(1)
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
const symbolsConfig = await loadSymbolsConfig()
|
|
39
|
-
const cliConfig = loadCliConfig()
|
|
40
39
|
const projectKey = cliConfig.projectKey || symbolsConfig.key
|
|
41
40
|
const branch = cliConfig.branch || symbolsConfig.branch || 'main'
|
|
42
41
|
const { framework, distDir, metadata } = symbolsConfig
|
package/bin/index.js
CHANGED
|
@@ -48,14 +48,22 @@ export async function initRepo (dest, framework) {
|
|
|
48
48
|
// Copy design system file
|
|
49
49
|
console.log()
|
|
50
50
|
const dsfilePath = path.join(dest, 'DesignSystem.js')
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
if (fs.existsSync(dsfilePath)) {
|
|
52
|
+
console.log(chalk.yellow('Skipping existing'), chalk.bold(dsfilePath))
|
|
53
|
+
} else {
|
|
54
|
+
console.log('Creating', chalk.bold(dsfilePath))
|
|
55
|
+
await fs.promises.copyFile(DESIGN_SYSTEM_FILE_PATH, dsfilePath)
|
|
56
|
+
}
|
|
53
57
|
|
|
54
58
|
// Copy design system file
|
|
55
59
|
const rcfilePath = path.join(dest, 'symbols.json')
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
if (fs.existsSync(rcfilePath)) {
|
|
61
|
+
console.log(chalk.yellow('Skipping existing'), chalk.bold(rcfilePath))
|
|
62
|
+
} else {
|
|
63
|
+
console.log('Creating', chalk.bold(rcfilePath))
|
|
64
|
+
await fs.promises.copyFile(SYMBOLS_FILE_PATH, rcfilePath)
|
|
65
|
+
}
|
|
66
|
+
if (framework !== 'domql') addToJson(rcfilePath, 'framework', framework)
|
|
59
67
|
console.log()
|
|
60
68
|
|
|
61
69
|
console.log(chalk.green.bold('Initialized project successfully.'))
|
package/bin/login.js
CHANGED
|
@@ -98,6 +98,7 @@ program
|
|
|
98
98
|
// Save credentials
|
|
99
99
|
const credManager = new CredentialManager()
|
|
100
100
|
credManager.saveCredentials({
|
|
101
|
+
apiBaseUrl: answers.apiBaseUrl,
|
|
101
102
|
authToken: token,
|
|
102
103
|
refreshToken,
|
|
103
104
|
authTokenExpiresAt: accessTokenExp,
|
|
@@ -105,7 +106,7 @@ program
|
|
|
105
106
|
email: user?.email || answers.email
|
|
106
107
|
})
|
|
107
108
|
|
|
108
|
-
// Persist API base URL to local config
|
|
109
|
+
// Persist API base URL to local config for this project as well
|
|
109
110
|
saveCliConfig({ apiBaseUrl: answers.apiBaseUrl })
|
|
110
111
|
|
|
111
112
|
console.log(chalk.green('\n✨ Successfully logged in!'))
|
package/bin/push.js
CHANGED
|
@@ -99,17 +99,17 @@ async function confirmChanges (changes, base, local) {
|
|
|
99
99
|
|
|
100
100
|
export async function pushProjectChanges(options) {
|
|
101
101
|
const { verbose, message, type = 'patch' } = options
|
|
102
|
-
const credManager = new CredentialManager()
|
|
103
|
-
const authToken = credManager.ensureAuthToken()
|
|
104
|
-
|
|
105
|
-
if (!authToken) {
|
|
106
|
-
showAuthRequiredMessages()
|
|
107
|
-
process.exit(1)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
102
|
try {
|
|
111
103
|
const symbolsConfig = await loadSymbolsConfig()
|
|
112
104
|
const cliConfig = loadCliConfig()
|
|
105
|
+
const credManager = new CredentialManager()
|
|
106
|
+
const authToken = credManager.ensureAuthToken(cliConfig.apiBaseUrl)
|
|
107
|
+
|
|
108
|
+
if (!authToken) {
|
|
109
|
+
showAuthRequiredMessages()
|
|
110
|
+
process.exit(1)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
113
|
const lock = readLock()
|
|
114
114
|
const appKey = cliConfig.projectKey || symbolsConfig.key
|
|
115
115
|
const branch = cliConfig.branch || symbolsConfig.branch || 'main'
|
package/bin/servers.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import inquirer from 'inquirer'
|
|
4
|
+
import chalk from 'chalk'
|
|
5
|
+
import { program } from './program.js'
|
|
6
|
+
import { CredentialManager } from '../helpers/credentialManager.js'
|
|
7
|
+
|
|
8
|
+
program
|
|
9
|
+
.command('servers')
|
|
10
|
+
.description('List and switch Symbols CLI servers (API base URLs)')
|
|
11
|
+
.option('-s, --select', 'Interactively select active server')
|
|
12
|
+
.action(async (opts) => {
|
|
13
|
+
const cm = new CredentialManager()
|
|
14
|
+
const profiles = cm.getProfiles()
|
|
15
|
+
const current = cm.getCurrentApiBaseUrl()
|
|
16
|
+
|
|
17
|
+
const urls = Object.keys(profiles || {})
|
|
18
|
+
|
|
19
|
+
if (!urls.length) {
|
|
20
|
+
console.log(chalk.yellow('No servers configured yet. Run `smbls login` first.'))
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
console.log(chalk.bold('\nConfigured servers:'))
|
|
25
|
+
urls.forEach((apiBaseUrl) => {
|
|
26
|
+
const profile = profiles[apiBaseUrl] || {}
|
|
27
|
+
const marker = apiBaseUrl === current ? chalk.green('●') : '○'
|
|
28
|
+
const email = profile.email ? chalk.dim(` (${profile.email})`) : ''
|
|
29
|
+
console.log(`${marker} ${chalk.cyan(apiBaseUrl)}${email}`)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
if (!opts.select) return
|
|
33
|
+
|
|
34
|
+
const { next } = await inquirer.prompt([
|
|
35
|
+
{
|
|
36
|
+
type: 'list',
|
|
37
|
+
name: 'next',
|
|
38
|
+
message: 'Select active server:',
|
|
39
|
+
choices: urls.map((url) => ({
|
|
40
|
+
name: `${url}${url === current ? ' (current)' : ''}`,
|
|
41
|
+
value: url
|
|
42
|
+
}))
|
|
43
|
+
}
|
|
44
|
+
])
|
|
45
|
+
|
|
46
|
+
cm.setCurrentApiBaseUrl(next)
|
|
47
|
+
console.log(chalk.green(`\nActive server set to ${next}`))
|
|
48
|
+
})
|
|
49
|
+
|
package/bin/sync.js
CHANGED
|
@@ -148,18 +148,17 @@ async function confirmChanges(localChanges, remoteChanges, base, local, remote)
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
export async function syncProjectChanges(options) {
|
|
151
|
-
const credManager = new CredentialManager()
|
|
152
|
-
const authToken = credManager.ensureAuthToken()
|
|
153
|
-
|
|
154
|
-
if (!authToken) {
|
|
155
|
-
showAuthRequiredMessages()
|
|
156
|
-
process.exit(1)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
151
|
try {
|
|
160
152
|
// Load configuration
|
|
161
153
|
const symbolsConfig = await loadSymbolsConfig()
|
|
162
154
|
const cliConfig = loadCliConfig()
|
|
155
|
+
const credManager = new CredentialManager()
|
|
156
|
+
const authToken = credManager.ensureAuthToken(cliConfig.apiBaseUrl)
|
|
157
|
+
|
|
158
|
+
if (!authToken) {
|
|
159
|
+
showAuthRequiredMessages()
|
|
160
|
+
process.exit(1)
|
|
161
|
+
}
|
|
163
162
|
const lock = readLock()
|
|
164
163
|
const { projectPath } = getConfigPaths()
|
|
165
164
|
const { key: legacyKey } = symbolsConfig
|
package/helpers/config.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'fs'
|
|
2
2
|
import path from 'path'
|
|
3
|
+
import { CredentialManager } from './credentialManager.js'
|
|
3
4
|
|
|
4
5
|
// New configuration layout
|
|
5
6
|
// .symbols/config.json -> project runtime configuration (apiBaseUrl, projectKey|projectId, branch)
|
|
@@ -67,12 +68,21 @@ export function loadCliConfig() {
|
|
|
67
68
|
// Legacy rc might include apiUrl
|
|
68
69
|
const legacyRc = readJsonSafe(LEGACY_RC_PATH) || {}
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
// Prefer explicit env / project config, then legacy rc, then global current server
|
|
72
|
+
let apiBaseUrl =
|
|
71
73
|
envApi ||
|
|
72
74
|
symbolsConfig.apiBaseUrl ||
|
|
73
|
-
legacyRc.apiUrl
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
legacyRc.apiUrl
|
|
76
|
+
|
|
77
|
+
if (!apiBaseUrl) {
|
|
78
|
+
const credManager = new CredentialManager()
|
|
79
|
+
apiBaseUrl = credManager.getCurrentApiBaseUrl()
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!apiBaseUrl) {
|
|
83
|
+
// default to production if nothing set anywhere
|
|
84
|
+
apiBaseUrl = 'https://api.symbols.app'
|
|
85
|
+
}
|
|
76
86
|
|
|
77
87
|
const projectKey = envProjectKey || symbolsConfig.projectKey || legacySymbols.key
|
|
78
88
|
const projectId = envProjectId || symbolsConfig.projectId || null
|
|
@@ -3,28 +3,27 @@ import path from 'path'
|
|
|
3
3
|
import os from 'os'
|
|
4
4
|
|
|
5
5
|
const RC_FILE = '.smblsrc'
|
|
6
|
+
const DEFAULT_API = 'https://api.symbols.app'
|
|
6
7
|
|
|
7
8
|
export class CredentialManager {
|
|
8
9
|
constructor() {
|
|
9
10
|
this.rcPath = path.join(os.homedir(), RC_FILE)
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
//
|
|
13
|
-
|
|
13
|
+
// --- Low-level helpers ----------------------------------------------------
|
|
14
|
+
|
|
15
|
+
loadRaw() {
|
|
14
16
|
try {
|
|
15
17
|
const data = fs.readFileSync(this.rcPath, 'utf8')
|
|
16
18
|
return JSON.parse(data)
|
|
17
|
-
} catch (
|
|
19
|
+
} catch (_) {
|
|
18
20
|
return {}
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
saveCredentials(credentials) {
|
|
24
|
+
saveRaw(obj) {
|
|
24
25
|
try {
|
|
25
|
-
|
|
26
|
-
const merged = { ...existing, ...credentials }
|
|
27
|
-
fs.writeFileSync(this.rcPath, JSON.stringify(merged, null, 2))
|
|
26
|
+
fs.writeFileSync(this.rcPath, JSON.stringify(obj, null, 2))
|
|
28
27
|
return true
|
|
29
28
|
} catch (err) {
|
|
30
29
|
console.error('Failed to save credentials:', err)
|
|
@@ -32,35 +31,161 @@ export class CredentialManager {
|
|
|
32
31
|
}
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
//
|
|
36
|
-
|
|
34
|
+
// Ensure we always work with a "profiles" structure and migrate legacy files
|
|
35
|
+
loadState() {
|
|
36
|
+
const raw = this.loadRaw()
|
|
37
|
+
if (raw && typeof raw === 'object' && raw.profiles) return raw
|
|
38
|
+
|
|
39
|
+
// Legacy shape: single set of credentials at the top level
|
|
40
|
+
const {
|
|
41
|
+
authToken,
|
|
42
|
+
token,
|
|
43
|
+
accessToken,
|
|
44
|
+
jwt,
|
|
45
|
+
refreshToken,
|
|
46
|
+
authTokenExpiresAt,
|
|
47
|
+
userId,
|
|
48
|
+
email,
|
|
49
|
+
apiBaseUrl,
|
|
50
|
+
...rest
|
|
51
|
+
} = raw || {}
|
|
52
|
+
|
|
53
|
+
const legacyToken = authToken || token || accessToken || jwt
|
|
54
|
+
const hasLegacyCreds =
|
|
55
|
+
legacyToken || refreshToken || authTokenExpiresAt || userId || email
|
|
56
|
+
|
|
57
|
+
if (!hasLegacyCreds) {
|
|
58
|
+
// Nothing to migrate
|
|
59
|
+
return raw || {}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const baseUrl = apiBaseUrl || DEFAULT_API
|
|
63
|
+
const profileCreds = {
|
|
64
|
+
authToken: legacyToken || null,
|
|
65
|
+
refreshToken: refreshToken || null,
|
|
66
|
+
authTokenExpiresAt: authTokenExpiresAt || null,
|
|
67
|
+
userId: userId || null,
|
|
68
|
+
email: email || null,
|
|
69
|
+
apiBaseUrl: baseUrl
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const migrated = {
|
|
73
|
+
...rest,
|
|
74
|
+
profiles: { [baseUrl]: profileCreds },
|
|
75
|
+
currentApiBaseUrl: baseUrl
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
this.saveRaw(migrated)
|
|
79
|
+
return migrated
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
getProfiles() {
|
|
83
|
+
const state = this.loadState()
|
|
84
|
+
return state.profiles || {}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
getCurrentApiBaseUrl() {
|
|
88
|
+
const state = this.loadState()
|
|
89
|
+
return state.currentApiBaseUrl || DEFAULT_API
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
setCurrentApiBaseUrl(apiBaseUrl) {
|
|
93
|
+
const state = this.loadState()
|
|
94
|
+
const next = { ...state, currentApiBaseUrl: apiBaseUrl || DEFAULT_API }
|
|
95
|
+
this.saveRaw(next)
|
|
96
|
+
return next
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// --- High-level token helpers ---------------------------------------------
|
|
100
|
+
|
|
101
|
+
// Get stored auth token for a specific API base URL (or current if omitted)
|
|
102
|
+
getAuthToken(apiBaseUrl) {
|
|
37
103
|
const envToken = process.env.SYMBOLS_TOKEN || process.env.SMBLS_TOKEN
|
|
38
104
|
if (envToken) return envToken
|
|
39
|
-
|
|
40
|
-
|
|
105
|
+
|
|
106
|
+
const state = this.loadState() || {}
|
|
107
|
+
const baseUrl = apiBaseUrl || state.currentApiBaseUrl || DEFAULT_API
|
|
108
|
+
|
|
109
|
+
if (state.profiles && typeof state.profiles === 'object') {
|
|
110
|
+
const profile = state.profiles[baseUrl] || {}
|
|
111
|
+
return (
|
|
112
|
+
profile.authToken ||
|
|
113
|
+
profile.token ||
|
|
114
|
+
profile.accessToken ||
|
|
115
|
+
profile.jwt ||
|
|
116
|
+
null
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Fallback: legacy flat shape
|
|
121
|
+
return (
|
|
122
|
+
state.authToken ||
|
|
123
|
+
state.token ||
|
|
124
|
+
state.accessToken ||
|
|
125
|
+
state.jwt ||
|
|
126
|
+
null
|
|
127
|
+
)
|
|
41
128
|
}
|
|
42
129
|
|
|
43
130
|
// Ensure token presence; returns token or null
|
|
44
|
-
ensureAuthToken() {
|
|
45
|
-
const token = this.getAuthToken()
|
|
131
|
+
ensureAuthToken(apiBaseUrl) {
|
|
132
|
+
const token = this.getAuthToken(apiBaseUrl)
|
|
46
133
|
return token || null
|
|
47
134
|
}
|
|
48
135
|
|
|
49
136
|
// Optional: get refresh token if present
|
|
50
|
-
getRefreshToken() {
|
|
137
|
+
getRefreshToken(apiBaseUrl) {
|
|
51
138
|
const envToken = process.env.SYMBOLS_REFRESH_TOKEN
|
|
52
139
|
if (envToken) return envToken
|
|
53
|
-
|
|
54
|
-
|
|
140
|
+
|
|
141
|
+
const state = this.loadState() || {}
|
|
142
|
+
const baseUrl = apiBaseUrl || state.currentApiBaseUrl || DEFAULT_API
|
|
143
|
+
|
|
144
|
+
if (state.profiles && typeof state.profiles === 'object') {
|
|
145
|
+
return state.profiles[baseUrl]?.refreshToken || null
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return state.refreshToken || null
|
|
55
149
|
}
|
|
56
150
|
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
151
|
+
// Save credentials for a specific API base URL
|
|
152
|
+
saveCredentials(credentials) {
|
|
153
|
+
const state = this.loadState() || {}
|
|
154
|
+
const baseUrl = credentials.apiBaseUrl || state.currentApiBaseUrl || DEFAULT_API
|
|
155
|
+
const profiles = state.profiles || {}
|
|
156
|
+
const existing = profiles[baseUrl] || {}
|
|
157
|
+
|
|
158
|
+
const mergedProfile = { ...existing, ...credentials, apiBaseUrl: baseUrl }
|
|
159
|
+
|
|
160
|
+
const next = {
|
|
161
|
+
...state,
|
|
162
|
+
profiles: { ...profiles, [baseUrl]: mergedProfile },
|
|
163
|
+
currentApiBaseUrl: baseUrl
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return this.saveRaw(next)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Clear stored credentials; if apiBaseUrl provided, clear only that profile
|
|
170
|
+
clearCredentials(apiBaseUrl) {
|
|
171
|
+
const state = this.loadState() || {}
|
|
172
|
+
|
|
173
|
+
if (!state.profiles || typeof state.profiles !== 'object') {
|
|
174
|
+
// Legacy: remove entire file
|
|
175
|
+
try {
|
|
176
|
+
fs.unlinkSync(this.rcPath)
|
|
177
|
+
return true
|
|
178
|
+
} catch (_) {
|
|
179
|
+
return false
|
|
180
|
+
}
|
|
64
181
|
}
|
|
182
|
+
|
|
183
|
+
const baseUrl = apiBaseUrl || state.currentApiBaseUrl
|
|
184
|
+
if (!baseUrl) return false
|
|
185
|
+
|
|
186
|
+
const { [baseUrl]: _, ...restProfiles } = state.profiles
|
|
187
|
+
const next = { ...state, profiles: restProfiles }
|
|
188
|
+
this.saveRaw(next)
|
|
189
|
+
return true
|
|
65
190
|
}
|
|
66
|
-
}
|
|
191
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbo.ls/cli",
|
|
3
|
-
"version": "2.33.
|
|
3
|
+
"version": "2.33.25",
|
|
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.25",
|
|
19
|
+
"@symbo.ls/init": "^2.33.25",
|
|
20
|
+
"@symbo.ls/socket": "^2.33.25",
|
|
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": "b0524b9f29fed6070d8e718d73b290097696ac48"
|
|
32
32
|
}
|