t44 0.2.0-rc.1
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.
Potentially problematic release.
This version of t44 might be problematic. Click here for more details.
- package/LICENSE.md +203 -0
- package/README.md +154 -0
- package/bin/activate +36 -0
- package/bin/activate.ts +30 -0
- package/bin/postinstall.sh +19 -0
- package/bin/shell +27 -0
- package/bin/t44 +27 -0
- package/caps/HomeRegistry.v0.ts +298 -0
- package/caps/OpenApiSchema.v0.ts +192 -0
- package/caps/ProjectDeployment.v0.ts +363 -0
- package/caps/ProjectDevelopment.v0.ts +246 -0
- package/caps/ProjectPublishing.v0.ts +307 -0
- package/caps/ProjectRack.v0.ts +128 -0
- package/caps/WorkspaceCli.v0.ts +391 -0
- package/caps/WorkspaceConfig.v0.ts +626 -0
- package/caps/WorkspaceConfig.yaml +53 -0
- package/caps/WorkspaceConnection.v0.ts +240 -0
- package/caps/WorkspaceEntityConfig.v0.ts +64 -0
- package/caps/WorkspaceEntityFact.v0.ts +193 -0
- package/caps/WorkspaceInfo.v0.ts +554 -0
- package/caps/WorkspaceInit.v0.ts +30 -0
- package/caps/WorkspaceKey.v0.ts +186 -0
- package/caps/WorkspaceProjects.v0.ts +455 -0
- package/caps/WorkspacePrompt.v0.ts +396 -0
- package/caps/WorkspaceShell.sh +39 -0
- package/caps/WorkspaceShell.v0.ts +104 -0
- package/caps/WorkspaceShell.yaml +65 -0
- package/caps/WorkspaceShellCli.v0.ts +109 -0
- package/caps/WorkspaceTest.v0.ts +167 -0
- package/caps/providers/LICENSE.md +8 -0
- package/caps/providers/README.md +2 -0
- package/caps/providers/bunny.net/ProjectDeployment.v0.ts +328 -0
- package/caps/providers/bunny.net/api-pull.v0.test.ts +319 -0
- package/caps/providers/bunny.net/api-pull.v0.ts +161 -0
- package/caps/providers/bunny.net/api-storage.v0.test.ts +168 -0
- package/caps/providers/bunny.net/api-storage.v0.ts +245 -0
- package/caps/providers/bunny.net/api.v0.ts +95 -0
- package/caps/providers/dynadot.com/ProjectDeployment.v0.ts +207 -0
- package/caps/providers/dynadot.com/api-domains.v0.test.ts +147 -0
- package/caps/providers/dynadot.com/api-domains.v0.ts +137 -0
- package/caps/providers/dynadot.com/api.v0.ts +88 -0
- package/caps/providers/git-scm.com/ProjectPublishing.v0.ts +231 -0
- package/caps/providers/github.com/ProjectPublishing.v0.ts +75 -0
- package/caps/providers/github.com/api.v0.ts +90 -0
- package/caps/providers/npmjs.com/ProjectPublishing.v0.ts +741 -0
- package/caps/providers/vercel.com/ProjectDeployment.v0.ts +339 -0
- package/caps/providers/vercel.com/api.v0.test.ts +67 -0
- package/caps/providers/vercel.com/api.v0.ts +132 -0
- package/caps/providers/vercel.com/bun.lock +194 -0
- package/caps/providers/vercel.com/package.json +10 -0
- package/caps/providers/vercel.com/project.v0.test.ts +108 -0
- package/caps/providers/vercel.com/project.v0.ts +150 -0
- package/caps/providers/vercel.com/tsconfig.json +28 -0
- package/docs/Overview.drawio +189 -0
- package/docs/Overview.svg +4 -0
- package/lib/crypto.ts +53 -0
- package/lib/openapi.ts +132 -0
- package/lib/ucan.ts +137 -0
- package/package.json +41 -0
- package/structs/HomeRegistryConfig.v0.ts +27 -0
- package/structs/ProjectDeploymentConfig.v0.ts +27 -0
- package/structs/ProjectDeploymentFact.v0.ts +110 -0
- package/structs/ProjectPublishingFact.v0.ts +69 -0
- package/structs/ProjectRackConfig.v0.ts +27 -0
- package/structs/WorkspaceCliConfig.v0.ts +27 -0
- package/structs/WorkspaceConfig.v0.ts +27 -0
- package/structs/WorkspaceKeyConfig.v0.ts +27 -0
- package/structs/WorkspaceMappings.v0.ts +27 -0
- package/structs/WorkspaceProjectsConfig.v0.ts +27 -0
- package/structs/WorkspaceRepositories.v0.ts +27 -0
- package/structs/WorkspaceShellConfig.v0.ts +45 -0
- package/structs/providers/LICENSE.md +8 -0
- package/structs/providers/README.md +2 -0
- package/structs/providers/bunny.net/ProjectDeploymentFact.v0.ts +41 -0
- package/structs/providers/bunny.net/WorkspaceConnectionConfig.v0.ts +42 -0
- package/structs/providers/dynadot.com/DomainFact.v0.ts +146 -0
- package/structs/providers/dynadot.com/WorkspaceConnectionConfig.v0.ts +41 -0
- package/structs/providers/git-scm.com/ProjectPublishingFact.v0.ts +46 -0
- package/structs/providers/github.com/ProjectPublishingFact.v0.ts +52 -0
- package/structs/providers/github.com/WorkspaceConnectionConfig.v0.ts +42 -0
- package/structs/providers/npmjs.com/ProjectPublishingFact.v0.ts +48 -0
- package/structs/providers/vercel.com/ProjectDeploymentFact.v0.ts +38 -0
- package/structs/providers/vercel.com/WorkspaceConnectionConfig.v0.ts +48 -0
- package/tsconfig.json +28 -0
- package/workspace-rt.ts +134 -0
- package/workspace.yaml +5 -0
|
@@ -0,0 +1,741 @@
|
|
|
1
|
+
|
|
2
|
+
import { join } from 'path'
|
|
3
|
+
import { $ } from 'bun'
|
|
4
|
+
import { mkdir, access, writeFile, readFile } from 'fs/promises'
|
|
5
|
+
import { constants } from 'fs'
|
|
6
|
+
import glob from 'fast-glob'
|
|
7
|
+
import chalk from 'chalk'
|
|
8
|
+
import { createHash } from 'crypto'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export async function capsule({
|
|
12
|
+
encapsulate,
|
|
13
|
+
CapsulePropertyTypes,
|
|
14
|
+
makeImportStack
|
|
15
|
+
}: {
|
|
16
|
+
encapsulate: any
|
|
17
|
+
CapsulePropertyTypes: any
|
|
18
|
+
makeImportStack: any
|
|
19
|
+
}) {
|
|
20
|
+
return encapsulate({
|
|
21
|
+
'#@stream44.studio/encapsulate/spine-contracts/CapsuleSpineContract.v0': {
|
|
22
|
+
'#@stream44.studio/encapsulate/structs/Capsule.v0': {},
|
|
23
|
+
'#t44/structs/WorkspaceRepositories.v0': {
|
|
24
|
+
as: '$WorkspaceRepositories'
|
|
25
|
+
},
|
|
26
|
+
'#t44/structs/providers/npmjs.com/ProjectPublishingFact.v0': {
|
|
27
|
+
as: '$NpmFact'
|
|
28
|
+
},
|
|
29
|
+
'#t44/structs/ProjectPublishingFact.v0': {
|
|
30
|
+
as: '$StatusFact'
|
|
31
|
+
},
|
|
32
|
+
'#': {
|
|
33
|
+
WorkspacePrompt: {
|
|
34
|
+
type: CapsulePropertyTypes.Mapping,
|
|
35
|
+
value: 't44/caps/WorkspacePrompt.v0'
|
|
36
|
+
},
|
|
37
|
+
prepare: {
|
|
38
|
+
type: CapsulePropertyTypes.Function,
|
|
39
|
+
value: async function (this: any, { projectionDir, config, repoSourceDir }: { projectionDir: string, config: any, repoSourceDir?: string }) {
|
|
40
|
+
const repositoriesConfig = await this.$WorkspaceRepositories.config
|
|
41
|
+
const { publicNpmPackageNames, workspaceNpmPackageNames, workspacePackageSourceDirs } = await buildWorkspacePackageMaps(repositoriesConfig)
|
|
42
|
+
|
|
43
|
+
const name = config.provider.config.PackageSettings.name
|
|
44
|
+
const projectSourceDir = join(config.sourceDir)
|
|
45
|
+
const projectProjectionDir = join(projectionDir, 'packages', name.replace(/[@:\/]/g, '~'))
|
|
46
|
+
|
|
47
|
+
await mkdir(projectProjectionDir, { recursive: true })
|
|
48
|
+
|
|
49
|
+
const gitignorePath = join(projectSourceDir, '.gitignore')
|
|
50
|
+
const npmignorePath = join(projectSourceDir, '.npmignore')
|
|
51
|
+
|
|
52
|
+
let gitignoreExists = false
|
|
53
|
+
let npmignoreExists = false
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
await access(gitignorePath, constants.F_OK)
|
|
57
|
+
gitignoreExists = true
|
|
58
|
+
} catch { }
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
await access(npmignorePath, constants.F_OK)
|
|
62
|
+
npmignoreExists = true
|
|
63
|
+
} catch { }
|
|
64
|
+
|
|
65
|
+
const rsyncArgs = ['rsync', '-a', '--delete', '--delete-excluded', '--exclude', '.git']
|
|
66
|
+
if (gitignoreExists) rsyncArgs.push('--exclude-from=' + gitignorePath)
|
|
67
|
+
if (npmignoreExists) rsyncArgs.push('--exclude-from=' + npmignorePath)
|
|
68
|
+
rsyncArgs.push(projectSourceDir + '/', projectProjectionDir + '/')
|
|
69
|
+
await $`${rsyncArgs}`
|
|
70
|
+
|
|
71
|
+
const packageJsonPath = join(projectProjectionDir, 'package.json')
|
|
72
|
+
const packageJsonContent = await readFile(packageJsonPath, 'utf-8')
|
|
73
|
+
const originalPackageJson = JSON.parse(packageJsonContent)
|
|
74
|
+
const packageJson = JSON.parse(packageJsonContent)
|
|
75
|
+
|
|
76
|
+
// Only remove private flag if not explicitly set to private in config
|
|
77
|
+
const isPrivate = config.provider.config.PackageSettings?.private === true
|
|
78
|
+
if (!isPrivate) {
|
|
79
|
+
delete packageJson.private
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Replace package name with public npm name
|
|
83
|
+
packageJson.name = name
|
|
84
|
+
|
|
85
|
+
// Collect workspace packages that need to be renamed
|
|
86
|
+
// Do this BEFORE updating dependencies so we have the original workspace names
|
|
87
|
+
const renameWorkspacePackages = new Set<string>()
|
|
88
|
+
|
|
89
|
+
// Always include the package's own workspace name for self-references
|
|
90
|
+
const ownWorkspaceName = originalPackageJson.name
|
|
91
|
+
if (ownWorkspaceName && publicNpmPackageNames[ownWorkspaceName]) {
|
|
92
|
+
renameWorkspacePackages.add(ownWorkspaceName)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Also include workspace packages used in dependencies
|
|
96
|
+
const dependencyFields = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies']
|
|
97
|
+
for (const depField of dependencyFields) {
|
|
98
|
+
if (packageJson[depField]) {
|
|
99
|
+
for (const depName of Object.keys(packageJson[depField])) {
|
|
100
|
+
// Check if this is a workspace package
|
|
101
|
+
const workspaceDepName = workspaceNpmPackageNames[depName] || depName
|
|
102
|
+
if (workspacePackageSourceDirs[workspaceDepName]) {
|
|
103
|
+
renameWorkspacePackages.add(workspaceDepName)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Replace workspace package names in files for both projection and central directories
|
|
110
|
+
if (renameWorkspacePackages.size > 0) {
|
|
111
|
+
const dirsToProcess = [projectProjectionDir]
|
|
112
|
+
if (repoSourceDir) dirsToProcess.push(repoSourceDir)
|
|
113
|
+
|
|
114
|
+
for (const dir of dirsToProcess) {
|
|
115
|
+
const files = await glob('**/*.{ts,tsx,js,jsx,json,md,txt,yml,yaml}', {
|
|
116
|
+
cwd: dir,
|
|
117
|
+
absolute: true,
|
|
118
|
+
onlyFiles: true
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
for (const file of files) {
|
|
122
|
+
try {
|
|
123
|
+
let content = await readFile(file, 'utf-8')
|
|
124
|
+
let modified = false
|
|
125
|
+
|
|
126
|
+
// Only replace workspace packages that are used in dependencies
|
|
127
|
+
for (const workspaceName of Array.from(renameWorkspacePackages)) {
|
|
128
|
+
const publicName = publicNpmPackageNames[workspaceName]
|
|
129
|
+
if (publicName) {
|
|
130
|
+
const regex = new RegExp(workspaceName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g')
|
|
131
|
+
if (regex.test(content)) {
|
|
132
|
+
content = content.replace(regex, publicName)
|
|
133
|
+
modified = true
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (modified) {
|
|
139
|
+
await writeFile(file, content, 'utf-8')
|
|
140
|
+
}
|
|
141
|
+
} catch (e) {
|
|
142
|
+
// Skip files that can't be read as text (binary files, etc.)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
await updateWorkspaceDependencies(packageJson, workspaceNpmPackageNames, workspacePackageSourceDirs, publicNpmPackageNames)
|
|
149
|
+
|
|
150
|
+
const modifiedPackageJsonContent = JSON.stringify(packageJson, null, 4) + '\n'
|
|
151
|
+
await writeFile(packageJsonPath, modifiedPackageJsonContent, 'utf-8')
|
|
152
|
+
|
|
153
|
+
// Also update package.json in central source directory if provided
|
|
154
|
+
if (repoSourceDir) {
|
|
155
|
+
const centralPackageJsonPath = join(repoSourceDir, 'package.json')
|
|
156
|
+
await writeFile(centralPackageJsonPath, modifiedPackageJsonContent, 'utf-8')
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const localVersion = packageJson.version
|
|
160
|
+
|
|
161
|
+
let publishedInfo: any = null
|
|
162
|
+
let publishedFiles: Map<string, string> = new Map()
|
|
163
|
+
let hasChanges = false
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
const viewResult = await $`npm view ${name} --json`.cwd(projectProjectionDir).quiet()
|
|
167
|
+
const result = viewResult.text()
|
|
168
|
+
|
|
169
|
+
if (result && result.trim()) {
|
|
170
|
+
publishedInfo = JSON.parse(result)
|
|
171
|
+
|
|
172
|
+
if (publishedInfo && publishedInfo['dist-tags']) {
|
|
173
|
+
try {
|
|
174
|
+
// Determine which tag to compare against based on local version
|
|
175
|
+
const isReleaseCandidate = localVersion.includes('-rc.')
|
|
176
|
+
const compareTag = isReleaseCandidate ? 'next' : 'latest'
|
|
177
|
+
const distTags = publishedInfo['dist-tags']
|
|
178
|
+
const compareVersion = distTags[compareTag]
|
|
179
|
+
|
|
180
|
+
if (compareVersion) {
|
|
181
|
+
// Include version in directory name for proper caching
|
|
182
|
+
const publishedDir = join(projectionDir, 'packages-published', `${name.replace(/[@:\/]/g, '~')}@${compareVersion}`)
|
|
183
|
+
const publishedPackageDir = join(publishedDir, 'package')
|
|
184
|
+
|
|
185
|
+
// Check if already downloaded
|
|
186
|
+
let alreadyDownloaded = false
|
|
187
|
+
try {
|
|
188
|
+
await access(publishedPackageDir, constants.F_OK)
|
|
189
|
+
alreadyDownloaded = true
|
|
190
|
+
} catch { }
|
|
191
|
+
|
|
192
|
+
if (!alreadyDownloaded) {
|
|
193
|
+
await mkdir(publishedDir, { recursive: true })
|
|
194
|
+
|
|
195
|
+
await $`npm pack ${name}@${compareVersion}`.cwd(publishedDir).quiet()
|
|
196
|
+
|
|
197
|
+
const tarballFiles = await glob('*.tgz', { cwd: publishedDir, absolute: false })
|
|
198
|
+
if (tarballFiles.length > 0) {
|
|
199
|
+
await $`tar -xzf ${tarballFiles[0]}`.cwd(publishedDir).quiet()
|
|
200
|
+
await $`rm ${tarballFiles[0]}`.cwd(publishedDir).quiet()
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Read file hashes from extracted package
|
|
205
|
+
const publishedFilePaths = await glob('**/*', {
|
|
206
|
+
cwd: publishedPackageDir,
|
|
207
|
+
absolute: false,
|
|
208
|
+
onlyFiles: true
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
for (const filePath of publishedFilePaths) {
|
|
212
|
+
const fullPath = join(publishedPackageDir, filePath)
|
|
213
|
+
const fileBuffer = await readFile(fullPath)
|
|
214
|
+
const fileHash = createHash('sha1').update(fileBuffer).digest('hex')
|
|
215
|
+
publishedFiles.set(filePath, fileHash)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
} catch (e) { }
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
} catch (error: any) {
|
|
222
|
+
hasChanges = true
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const localPackResult = await $`npm pack`.cwd(projectProjectionDir).quiet()
|
|
226
|
+
const localTarballName = localPackResult.text().trim().split('\n').pop()?.trim()
|
|
227
|
+
const localTarballPath = join(projectProjectionDir, localTarballName || '')
|
|
228
|
+
|
|
229
|
+
const localTarballBuffer = await readFile(localTarballPath)
|
|
230
|
+
const localShasum = createHash('sha1').update(localTarballBuffer).digest('hex')
|
|
231
|
+
const localIntegrity = 'sha512-' + createHash('sha512').update(localTarballBuffer).digest('base64')
|
|
232
|
+
|
|
233
|
+
await $`rm ${localTarballPath}`.quiet()
|
|
234
|
+
|
|
235
|
+
let versionExistsOnNpm = false
|
|
236
|
+
let versionMatchesChecksum = false
|
|
237
|
+
let localMatchesAnyTag = false
|
|
238
|
+
|
|
239
|
+
if (publishedInfo) {
|
|
240
|
+
// Check if local version exists in any tag
|
|
241
|
+
const distTags = publishedInfo['dist-tags'] || {}
|
|
242
|
+
for (const [tag, version] of Object.entries(distTags)) {
|
|
243
|
+
if (version === localVersion) {
|
|
244
|
+
versionExistsOnNpm = true
|
|
245
|
+
|
|
246
|
+
// Fetch version-specific info to check shasum
|
|
247
|
+
try {
|
|
248
|
+
const versionResult = await $`npm view ${name}@${version as string} --json`.cwd(projectProjectionDir).quiet()
|
|
249
|
+
const versionInfo = JSON.parse(versionResult.text())
|
|
250
|
+
const publishedShasum = versionInfo.dist?.shasum || ''
|
|
251
|
+
const publishedIntegrity = versionInfo.dist?.integrity || ''
|
|
252
|
+
|
|
253
|
+
if (publishedShasum === localShasum || publishedIntegrity === localIntegrity) {
|
|
254
|
+
versionMatchesChecksum = true
|
|
255
|
+
localMatchesAnyTag = true
|
|
256
|
+
}
|
|
257
|
+
} catch (e) { }
|
|
258
|
+
|
|
259
|
+
break
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (!publishedInfo || !localMatchesAnyTag) {
|
|
265
|
+
hasChanges = true
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return {
|
|
269
|
+
name,
|
|
270
|
+
localVersion,
|
|
271
|
+
projectSourceDir,
|
|
272
|
+
projectProjectionDir,
|
|
273
|
+
publishedInfo,
|
|
274
|
+
localShasum,
|
|
275
|
+
localIntegrity,
|
|
276
|
+
versionExistsOnNpm,
|
|
277
|
+
versionMatchesChecksum,
|
|
278
|
+
localMatchesAnyTag,
|
|
279
|
+
hasChanges,
|
|
280
|
+
publishedFiles,
|
|
281
|
+
workspaceNpmPackageNames,
|
|
282
|
+
workspacePackageSourceDirs
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
bump: {
|
|
287
|
+
type: CapsulePropertyTypes.Function,
|
|
288
|
+
value: async function (this: any, { config, options, repoSourceDir, metadata }: { config: any, options?: { rc?: boolean, release?: boolean }, repoSourceDir?: string, metadata?: any }) {
|
|
289
|
+
const { rc, release } = options || {}
|
|
290
|
+
|
|
291
|
+
const projectSourceDir = join(config.sourceDir)
|
|
292
|
+
const packageJsonPath = join(projectSourceDir, 'package.json')
|
|
293
|
+
|
|
294
|
+
const packageJsonContent = await readFile(packageJsonPath, 'utf-8')
|
|
295
|
+
const packageJson = JSON.parse(packageJsonContent)
|
|
296
|
+
const currentVersion = packageJson.version
|
|
297
|
+
|
|
298
|
+
// Check if current version is already newer than published version for the appropriate tag
|
|
299
|
+
if (metadata && metadata.publishedInfo) {
|
|
300
|
+
const isReleaseCandidate = currentVersion.includes('-rc.')
|
|
301
|
+
const targetTag = isReleaseCandidate ? 'next' : 'latest'
|
|
302
|
+
const distTags = metadata.publishedInfo['dist-tags'] || {}
|
|
303
|
+
const publishedVersion = distTags[targetTag]
|
|
304
|
+
|
|
305
|
+
if (publishedVersion) {
|
|
306
|
+
// Compare versions using Bun's semver - if current is already ahead, skip bump
|
|
307
|
+
const currentIsNewer = currentVersion !== publishedVersion &&
|
|
308
|
+
!Bun.semver.satisfies(currentVersion, `<=${publishedVersion}`)
|
|
309
|
+
|
|
310
|
+
if (currentIsNewer) {
|
|
311
|
+
console.log(chalk.yellow(` Current version ${currentVersion} is already newer than published ${targetTag}@${publishedVersion}`))
|
|
312
|
+
console.log(chalk.yellow(` Skipping bump - publish this version first\n`))
|
|
313
|
+
return
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
let newVersion: string
|
|
319
|
+
|
|
320
|
+
if (release) {
|
|
321
|
+
const rcMatch = currentVersion.match(/^(.+)-rc\.\d+$/)
|
|
322
|
+
if (rcMatch) {
|
|
323
|
+
newVersion = rcMatch[1]
|
|
324
|
+
console.log(chalk.cyan(` Removing RC suffix: ${currentVersion} → ${newVersion}`))
|
|
325
|
+
} else {
|
|
326
|
+
console.log(chalk.yellow(` Version ${currentVersion} has no RC suffix, skipping bump`))
|
|
327
|
+
return
|
|
328
|
+
}
|
|
329
|
+
} else if (rc) {
|
|
330
|
+
const rcMatch = currentVersion.match(/^(.+)-rc\.(\d+)$/)
|
|
331
|
+
if (rcMatch) {
|
|
332
|
+
const baseVersion = rcMatch[1]
|
|
333
|
+
const rcNumber = parseInt(rcMatch[2], 10)
|
|
334
|
+
newVersion = `${baseVersion}-rc.${rcNumber + 1}`
|
|
335
|
+
console.log(chalk.cyan(` Incrementing RC version: ${currentVersion} → ${newVersion}`))
|
|
336
|
+
} else {
|
|
337
|
+
const versionParts = currentVersion.split('.')
|
|
338
|
+
if (versionParts.length !== 3) {
|
|
339
|
+
throw new Error(`Invalid version format: ${currentVersion}`)
|
|
340
|
+
}
|
|
341
|
+
const [major, minor, patch] = versionParts
|
|
342
|
+
const newMinor = parseInt(minor, 10) + 1
|
|
343
|
+
newVersion = `${major}.${newMinor}.0-rc.1`
|
|
344
|
+
console.log(chalk.cyan(` Bumping minor version and adding RC: ${currentVersion} → ${newVersion}`))
|
|
345
|
+
}
|
|
346
|
+
} else {
|
|
347
|
+
console.log(chalk.yellow(` No version bump requested`))
|
|
348
|
+
return
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
packageJson.version = newVersion
|
|
352
|
+
const updatedContent = JSON.stringify(packageJson, null, 2) + '\n'
|
|
353
|
+
await writeFile(packageJsonPath, updatedContent, 'utf-8')
|
|
354
|
+
|
|
355
|
+
// Also update package.json in central source directory if provided
|
|
356
|
+
if (repoSourceDir) {
|
|
357
|
+
const centralPackageJsonPath = join(repoSourceDir, 'package.json')
|
|
358
|
+
await writeFile(centralPackageJsonPath, updatedContent, 'utf-8')
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
console.log(chalk.green(` ✓ Updated ${packageJsonPath} to version ${newVersion}\n`))
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
finalize: {
|
|
365
|
+
type: CapsulePropertyTypes.Function,
|
|
366
|
+
value: async function (this: any, { config }: { config: any }) {
|
|
367
|
+
const repositoriesConfig = await this.$WorkspaceRepositories.config
|
|
368
|
+
const { publicNpmPackageNames, workspaceNpmPackageNames, workspacePackageSourceDirs } = await buildWorkspacePackageMaps(repositoriesConfig)
|
|
369
|
+
|
|
370
|
+
const projectSourceDir = join(config.sourceDir)
|
|
371
|
+
const packageJsonPath = join(projectSourceDir, 'package.json')
|
|
372
|
+
|
|
373
|
+
const packageJsonContent = await readFile(packageJsonPath, 'utf-8')
|
|
374
|
+
const packageJson = JSON.parse(packageJsonContent)
|
|
375
|
+
|
|
376
|
+
await updateWorkspaceDependencies(packageJson, workspaceNpmPackageNames, workspacePackageSourceDirs, publicNpmPackageNames)
|
|
377
|
+
|
|
378
|
+
await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf-8')
|
|
379
|
+
|
|
380
|
+
console.log(chalk.green(` ✓ Updated workspace dependencies in ${packageJsonPath}\n`))
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
push: {
|
|
384
|
+
type: CapsulePropertyTypes.Function,
|
|
385
|
+
value: async function (this: any, { projectionDir, config, metadata }: { projectionDir: string, config: any, metadata?: any }) {
|
|
386
|
+
|
|
387
|
+
if (!metadata) {
|
|
388
|
+
throw new Error('Push method requires metadata from prepare phase')
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Check if package is marked as private in config
|
|
392
|
+
const isPrivate = config.provider.config.PackageSettings?.private === true
|
|
393
|
+
if (isPrivate) {
|
|
394
|
+
console.log(chalk.yellow(`\n⚠️ Package is marked as private - skipping npm publish\n`))
|
|
395
|
+
return
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const {
|
|
399
|
+
name,
|
|
400
|
+
localVersion,
|
|
401
|
+
projectSourceDir,
|
|
402
|
+
projectProjectionDir,
|
|
403
|
+
publishedInfo,
|
|
404
|
+
localShasum,
|
|
405
|
+
localIntegrity,
|
|
406
|
+
versionExistsOnNpm,
|
|
407
|
+
versionMatchesChecksum,
|
|
408
|
+
localMatchesAnyTag,
|
|
409
|
+
hasChanges,
|
|
410
|
+
publishedFiles
|
|
411
|
+
} = metadata
|
|
412
|
+
|
|
413
|
+
console.log(chalk.cyan(`\n📋 Package Details:`))
|
|
414
|
+
console.log(chalk.gray(` Package: ${chalk.white(name)}`))
|
|
415
|
+
console.log(chalk.gray(` Version: ${chalk.white(localVersion)}`))
|
|
416
|
+
console.log(chalk.gray(` Shasum: ${chalk.white(localShasum)}`))
|
|
417
|
+
console.log(chalk.gray(` Source: ${chalk.white(projectSourceDir)}`))
|
|
418
|
+
console.log(chalk.gray(` Build: ${chalk.white(projectProjectionDir)}`))
|
|
419
|
+
|
|
420
|
+
if (publishedInfo) {
|
|
421
|
+
const npmUrl = `https://www.npmjs.com/package/${name}`
|
|
422
|
+
const distTags = publishedInfo['dist-tags'] || {}
|
|
423
|
+
|
|
424
|
+
console.log(chalk.cyan(`\n📦 Published package: ${chalk.underline(npmUrl)}`))
|
|
425
|
+
|
|
426
|
+
// Fetch and display info for each tag
|
|
427
|
+
const tagInfos: Array<{ tag: string, version: string, shasum: string, matches: boolean }> = []
|
|
428
|
+
let anyTagMatches = false
|
|
429
|
+
|
|
430
|
+
for (const [tag, version] of Object.entries(distTags)) {
|
|
431
|
+
try {
|
|
432
|
+
const tagVersionResult = await $`npm view ${name}@${version as string} --json`.cwd(projectProjectionDir).quiet()
|
|
433
|
+
const tagVersionInfo = JSON.parse(tagVersionResult.text())
|
|
434
|
+
|
|
435
|
+
const publishedShasum = tagVersionInfo.dist?.shasum || ''
|
|
436
|
+
const publishedIntegrity = tagVersionInfo.dist?.integrity || ''
|
|
437
|
+
const matches = publishedShasum === localShasum || publishedIntegrity === localIntegrity
|
|
438
|
+
|
|
439
|
+
if (matches) anyTagMatches = true
|
|
440
|
+
|
|
441
|
+
tagInfos.push({ tag, version: version as string, shasum: publishedShasum, matches })
|
|
442
|
+
} catch (e) {
|
|
443
|
+
tagInfos.push({ tag, version: version as string, shasum: '', matches: false })
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
console.log(chalk.gray(` Versions:`))
|
|
448
|
+
for (const { tag, version, shasum } of tagInfos) {
|
|
449
|
+
console.log(chalk.white(` ${tag.padEnd(10)} v${version}`))
|
|
450
|
+
console.log(chalk.gray(` ${shasum}`))
|
|
451
|
+
}
|
|
452
|
+
console.log('')
|
|
453
|
+
|
|
454
|
+
// Store for later use
|
|
455
|
+
metadata.anyTagMatches = anyTagMatches
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Show file list (always show, even for first publish)
|
|
459
|
+
const localFilePaths = await glob('**/*', {
|
|
460
|
+
cwd: projectProjectionDir,
|
|
461
|
+
absolute: false,
|
|
462
|
+
onlyFiles: true
|
|
463
|
+
})
|
|
464
|
+
|
|
465
|
+
const localFileHashes = new Map<string, string>()
|
|
466
|
+
for (const filePath of localFilePaths) {
|
|
467
|
+
const fullPath = join(projectProjectionDir, filePath)
|
|
468
|
+
const fileBuffer = await readFile(fullPath)
|
|
469
|
+
const localHash = createHash('sha1').update(fileBuffer).digest('hex')
|
|
470
|
+
localFileHashes.set(filePath, localHash)
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
console.log(chalk.cyan(`\n📄 Files to be published:`))
|
|
474
|
+
if (publishedInfo && publishedFiles.size > 0) {
|
|
475
|
+
console.log(chalk.gray(` Legend: ${chalk.green('● new')} ${chalk.yellow('● modified')} ${chalk.gray('● unchanged')}\n`))
|
|
476
|
+
} else {
|
|
477
|
+
console.log(chalk.gray(` Legend: ${chalk.green('● new')}\n`))
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
for (const filePath of localFilePaths) {
|
|
481
|
+
const localHash = localFileHashes.get(filePath)
|
|
482
|
+
const publishedHash = publishedFiles.get(filePath)
|
|
483
|
+
|
|
484
|
+
const stats = await readFile(join(projectProjectionDir, filePath))
|
|
485
|
+
const sizeKB = (stats.length / 1024).toFixed(1) + 'kB'
|
|
486
|
+
const sizeB = stats.length + 'B'
|
|
487
|
+
const displaySize = stats.length >= 1024 ? sizeKB : sizeB
|
|
488
|
+
|
|
489
|
+
let status = ''
|
|
490
|
+
let color = chalk.gray
|
|
491
|
+
|
|
492
|
+
if (!publishedHash) {
|
|
493
|
+
status = chalk.green('● ')
|
|
494
|
+
color = chalk.green
|
|
495
|
+
} else if (publishedHash !== localHash) {
|
|
496
|
+
status = chalk.yellow('● ')
|
|
497
|
+
color = chalk.yellow
|
|
498
|
+
} else {
|
|
499
|
+
status = chalk.gray('● ')
|
|
500
|
+
color = chalk.gray
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
console.log(` ${status}${color(displaySize.padEnd(8))} ${color(filePath)}`)
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
if (publishedInfo && publishedFiles.size > 0) {
|
|
507
|
+
const deletedFiles = Array.from(publishedFiles.keys()).filter(f => !localFilePaths.includes(f as any))
|
|
508
|
+
if (deletedFiles.length > 0) {
|
|
509
|
+
console.log(chalk.red(`\n Removed files from previous version:`))
|
|
510
|
+
for (const fileName of deletedFiles) {
|
|
511
|
+
console.log(chalk.red(` ✗ ${fileName}`))
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
console.log('\n')
|
|
516
|
+
|
|
517
|
+
// Display package.json diff comparing our code to published package for same tag
|
|
518
|
+
if (publishedInfo && publishedFiles.size > 0) {
|
|
519
|
+
// Determine which tag to compare against based on local version
|
|
520
|
+
const isReleaseCandidate = localVersion.includes('-rc.')
|
|
521
|
+
const compareTag = isReleaseCandidate ? 'next' : 'latest'
|
|
522
|
+
const distTags = publishedInfo['dist-tags'] || {}
|
|
523
|
+
const compareVersion = distTags[compareTag]
|
|
524
|
+
|
|
525
|
+
if (compareVersion) {
|
|
526
|
+
const publishedDir = join(projectionDir, 'packages-published', `${name.replace(/[@:\/]/g, '~')}@${compareVersion}`)
|
|
527
|
+
const publishedPackageDir = join(publishedDir, 'package')
|
|
528
|
+
const publishedPackageJsonPath = join(publishedPackageDir, 'package.json')
|
|
529
|
+
|
|
530
|
+
// Check if published package.json exists
|
|
531
|
+
try {
|
|
532
|
+
await access(publishedPackageJsonPath, constants.F_OK)
|
|
533
|
+
|
|
534
|
+
// Read both package.json files
|
|
535
|
+
const publishedPackageJsonContent = await readFile(publishedPackageJsonPath, 'utf-8')
|
|
536
|
+
const localPackageJsonPath = join(projectSourceDir, 'package.json')
|
|
537
|
+
const localPackageJsonContent = await readFile(localPackageJsonPath, 'utf-8')
|
|
538
|
+
|
|
539
|
+
// Only show diff if they differ
|
|
540
|
+
if (publishedPackageJsonContent.trim() !== localPackageJsonContent.trim()) {
|
|
541
|
+
console.log(chalk.cyan(`\n📝 package.json changes (comparing to ${compareTag}@${compareVersion}):`))
|
|
542
|
+
console.log(chalk.gray('─'.repeat(80)))
|
|
543
|
+
|
|
544
|
+
try {
|
|
545
|
+
const diffResult = await $`diff -u ${publishedPackageJsonPath} ${localPackageJsonPath}`.quiet().nothrow()
|
|
546
|
+
const diffLines = diffResult.text().split('\n')
|
|
547
|
+
|
|
548
|
+
for (const line of diffLines) {
|
|
549
|
+
if (line.startsWith('---') || line.startsWith('+++')) {
|
|
550
|
+
console.log(chalk.gray(line))
|
|
551
|
+
} else if (line.startsWith('@@')) {
|
|
552
|
+
console.log(chalk.cyan(line))
|
|
553
|
+
} else if (line.startsWith('+')) {
|
|
554
|
+
console.log(chalk.green(line))
|
|
555
|
+
} else if (line.startsWith('-')) {
|
|
556
|
+
console.log(chalk.red(line))
|
|
557
|
+
} else {
|
|
558
|
+
console.log(chalk.gray(line))
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
} catch (e) {
|
|
562
|
+
// diff command failed
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
console.log(chalk.gray('─'.repeat(80)))
|
|
566
|
+
console.log('')
|
|
567
|
+
}
|
|
568
|
+
} catch (e) {
|
|
569
|
+
// Published package.json doesn't exist or can't be read
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Get anyTagMatches from the earlier section
|
|
575
|
+
const anyTagMatches = metadata.anyTagMatches || localMatchesAnyTag
|
|
576
|
+
|
|
577
|
+
if (anyTagMatches) {
|
|
578
|
+
console.log(chalk.green(`✓ Local package matches published version - no publish needed\n`))
|
|
579
|
+
return
|
|
580
|
+
} else if (versionExistsOnNpm && versionMatchesChecksum) {
|
|
581
|
+
console.log(chalk.green(`✓ Version ${localVersion} already published with matching content\n`))
|
|
582
|
+
return
|
|
583
|
+
} else if (versionExistsOnNpm && !versionMatchesChecksum) {
|
|
584
|
+
console.log(chalk.red(`\n✗ ERROR: Version ${localVersion} already exists on npm with different content!`))
|
|
585
|
+
console.log(chalk.magenta(` Run with --rc flag to bump the version and publish these changes`))
|
|
586
|
+
return
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// Determine npm tag based on version
|
|
590
|
+
const isReleaseCandidate = localVersion.includes('-rc.')
|
|
591
|
+
const npmTag = isReleaseCandidate ? 'next' : 'latest'
|
|
592
|
+
|
|
593
|
+
if (publishedInfo && !versionExistsOnNpm) {
|
|
594
|
+
console.log(chalk.yellow(`\n⚠️ Ready to publish new package ${name} version ${localVersion} to npmjs.com`))
|
|
595
|
+
console.log(chalk.yellow(` Will be tagged as: ${chalk.bold(npmTag)}\n`))
|
|
596
|
+
} else {
|
|
597
|
+
console.log(chalk.yellow(`\n⚠️ Ready to publish new package ${name} version ${localVersion} to npmjs.com (first publish)`))
|
|
598
|
+
console.log(chalk.yellow(` Will be tagged as: ${chalk.bold(npmTag)}\n`))
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
try {
|
|
602
|
+
const otp = await this.WorkspacePrompt.input({
|
|
603
|
+
message: 'Enter your npmjs.com OTP (one-time password):',
|
|
604
|
+
defaultValue: '',
|
|
605
|
+
validate: (input: string) => {
|
|
606
|
+
if (!input || input.trim().length === 0) {
|
|
607
|
+
return 'OTP is required'
|
|
608
|
+
}
|
|
609
|
+
return true
|
|
610
|
+
}
|
|
611
|
+
})
|
|
612
|
+
|
|
613
|
+
console.log(chalk.cyan(`\n🚀 Publishing '${name}' version ${localVersion} to npm with tag '${npmTag}'...`))
|
|
614
|
+
await $`npm publish --access public --tag ${npmTag} --otp=${otp}`.cwd(projectProjectionDir)
|
|
615
|
+
console.log(chalk.green(`✅ Successfully published '${name}' version ${localVersion} to npm (tag: ${npmTag})\n`))
|
|
616
|
+
|
|
617
|
+
// Write fact files after successful publish
|
|
618
|
+
const npmFactName = name.replace(/[@:\/]/g, '~')
|
|
619
|
+
|
|
620
|
+
await this.$NpmFact.set('packages', npmFactName, 'NpmPackage', {
|
|
621
|
+
name,
|
|
622
|
+
version: localVersion,
|
|
623
|
+
private: false,
|
|
624
|
+
shasum: localShasum,
|
|
625
|
+
integrity: localIntegrity,
|
|
626
|
+
publishedAt: new Date().toISOString(),
|
|
627
|
+
npmUrl: `https://www.npmjs.com/package/${name}`
|
|
628
|
+
})
|
|
629
|
+
|
|
630
|
+
await this.$StatusFact.set('ProjectPublishingStatus', npmFactName, 'ProjectPublishingStatus', {
|
|
631
|
+
projectName: name,
|
|
632
|
+
provider: 'npmjs.com',
|
|
633
|
+
status: 'PUBLISHED',
|
|
634
|
+
publicUrl: `https://www.npmjs.com/package/${name}`,
|
|
635
|
+
updatedAt: new Date().toISOString()
|
|
636
|
+
})
|
|
637
|
+
} catch (error: any) {
|
|
638
|
+
if (error.message?.includes('force closed') || error.message?.includes('SIGINT')) {
|
|
639
|
+
console.log(chalk.red(`\nABORTED\n`))
|
|
640
|
+
process.exit(1)
|
|
641
|
+
}
|
|
642
|
+
throw error
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
},
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}, {
|
|
649
|
+
// @ts-ignore - import.meta is supported in Bun
|
|
650
|
+
importMeta: import.meta,
|
|
651
|
+
importStack: makeImportStack(),
|
|
652
|
+
capsuleName: capsule['#'],
|
|
653
|
+
})
|
|
654
|
+
}
|
|
655
|
+
capsule['#'] = 't44/caps/providers/npmjs.com/ProjectPublishing.v0'
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
async function buildWorkspacePackageMaps(repositoriesConfig: any) {
|
|
660
|
+
const publicNpmPackageNames: Record<string, string> = {}
|
|
661
|
+
const workspaceNpmPackageNames: Record<string, string> = {}
|
|
662
|
+
const workspacePackageSourceDirs: Record<string, string> = {}
|
|
663
|
+
|
|
664
|
+
if (repositoriesConfig?.repositories) {
|
|
665
|
+
for (const [repoKey, repoConfig] of Object.entries(repositoriesConfig.repositories as any)) {
|
|
666
|
+
const providers = (repoConfig as any).providers || ((repoConfig as any).provider ? [(repoConfig as any).provider] : [])
|
|
667
|
+
|
|
668
|
+
for (const provider of providers) {
|
|
669
|
+
if (provider.capsule === 't44/caps/providers/npmjs.com/ProjectPublishing.v0') {
|
|
670
|
+
const sourceDir = (repoConfig as any).sourceDir
|
|
671
|
+
const packageJsonPath = join(sourceDir, 'package.json')
|
|
672
|
+
|
|
673
|
+
try {
|
|
674
|
+
const packageJsonContent = await readFile(packageJsonPath, 'utf-8')
|
|
675
|
+
const packageJson = JSON.parse(packageJsonContent)
|
|
676
|
+
const workspacePackageName = packageJson.name
|
|
677
|
+
const publicPackageName = provider.config.PackageSettings.name
|
|
678
|
+
|
|
679
|
+
publicNpmPackageNames[workspacePackageName] = publicPackageName
|
|
680
|
+
workspaceNpmPackageNames[publicPackageName] = workspacePackageName
|
|
681
|
+
workspacePackageSourceDirs[workspacePackageName] = sourceDir
|
|
682
|
+
} catch (error) {
|
|
683
|
+
console.warn(`Could not read package.json from ${packageJsonPath}:`, error)
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
return { publicNpmPackageNames, workspaceNpmPackageNames, workspacePackageSourceDirs }
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
async function updateWorkspaceDependencies(
|
|
694
|
+
packageJson: any,
|
|
695
|
+
workspaceNpmPackageNames: Record<string, string>,
|
|
696
|
+
workspacePackageSourceDirs: Record<string, string>,
|
|
697
|
+
publicNpmPackageNames: Record<string, string>
|
|
698
|
+
) {
|
|
699
|
+
const dependencyFields = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies']
|
|
700
|
+
const currentPackageName = packageJson.name
|
|
701
|
+
|
|
702
|
+
for (const depField of dependencyFields) {
|
|
703
|
+
if (packageJson[depField]) {
|
|
704
|
+
const updatedDeps: Record<string, string> = {}
|
|
705
|
+
|
|
706
|
+
for (const [depName, depVersion] of Object.entries(packageJson[depField])) {
|
|
707
|
+
// Skip self-referencing dependencies
|
|
708
|
+
if (depName === currentPackageName) {
|
|
709
|
+
continue
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
if (typeof depVersion === 'string' && depVersion.startsWith('workspace:')) {
|
|
713
|
+
try {
|
|
714
|
+
const workspaceDepName = workspaceNpmPackageNames[depName] || depName
|
|
715
|
+
const depSourceDir = workspacePackageSourceDirs[workspaceDepName]
|
|
716
|
+
|
|
717
|
+
if (!depSourceDir) {
|
|
718
|
+
console.warn(`Could not find source directory for workspace dependency ${depName} (${workspaceDepName})`)
|
|
719
|
+
continue
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
const depPackageJsonPath = join(depSourceDir, 'package.json')
|
|
723
|
+
const depPackageJsonContent = await readFile(depPackageJsonPath, 'utf-8')
|
|
724
|
+
const depPackageJson = JSON.parse(depPackageJsonContent)
|
|
725
|
+
|
|
726
|
+
// Replace workspace package name with public package name
|
|
727
|
+
const publicDepName = publicNpmPackageNames[workspaceDepName] || depName
|
|
728
|
+
updatedDeps[publicDepName] = `^${depPackageJson.version}`
|
|
729
|
+
} catch (error) {
|
|
730
|
+
console.warn(`Could not resolve workspace dependency ${depName}:`, error)
|
|
731
|
+
}
|
|
732
|
+
} else {
|
|
733
|
+
// Keep non-workspace dependencies as-is
|
|
734
|
+
updatedDeps[depName] = depVersion as string
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
packageJson[depField] = updatedDeps
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|