@stream44.studio/encapsulate 0.2.0-rc.2 → 0.2.0-rc.4
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 @stream44.studio/encapsulate might be problematic. Click here for more details.
- package/LICENSE.md +4 -199
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/capsule-projectors/CapsuleModuleProjector.v0.ts +81 -72
- package/src/encapsulate.ts +175 -25
- package/src/spine-contracts/CapsuleSpineContract.v0/Membrane.v0.ts +207 -135
- package/src/spine-contracts/CapsuleSpineContract.v0/Static.v0.ts +131 -37
- package/src/spine-factories/CapsuleSpineFactory.v0.ts +53 -6
- package/src/static-analyzer.v0.ts +291 -52
|
@@ -49,25 +49,25 @@ async function constructCacheFilePath(moduleFilepath: string, importStackLine: n
|
|
|
49
49
|
async function constructNpmUriForCache(absoluteFilepath: string, spineRoot: string): Promise<string | null> {
|
|
50
50
|
let currentDir = dirname(absoluteFilepath)
|
|
51
51
|
const maxDepth = 20 // Prevent infinite loops
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
for (let i = 0; i < maxDepth; i++) {
|
|
54
54
|
const packageJsonPath = join(currentDir, 'package.json')
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
try {
|
|
57
57
|
await stat(packageJsonPath)
|
|
58
58
|
// Found package.json, read it
|
|
59
59
|
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'))
|
|
60
60
|
const packageName = packageJson.name
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
if (!packageName) {
|
|
63
63
|
// No name in package.json, continue searching
|
|
64
64
|
currentDir = dirname(currentDir)
|
|
65
65
|
continue
|
|
66
66
|
}
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
// Get the relative path from the package root to the file
|
|
69
69
|
const relativeFromPackage = relative(currentDir, absoluteFilepath)
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
// Construct npm URI: packageName/relativePath
|
|
72
72
|
return `${packageName}/${relativeFromPackage}`
|
|
73
73
|
} catch (error) {
|
|
@@ -80,7 +80,7 @@ async function constructNpmUriForCache(absoluteFilepath: string, spineRoot: stri
|
|
|
80
80
|
currentDir = parentDir
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
return null
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -149,17 +149,17 @@ export function CapsuleModuleProjector({
|
|
|
149
149
|
})
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
// If not found in ambient refs, try string-based mapping
|
|
154
154
|
if (mapped.length === 0 && prop.valueExpression && capsules) {
|
|
155
155
|
const mappingValue = prop.valueExpression.replace(/['"]/g, '')
|
|
156
|
-
|
|
156
|
+
|
|
157
157
|
// Look through all capsules to find one that matches
|
|
158
158
|
for (const [key, potentialCapsule] of Object.entries(capsules)) {
|
|
159
159
|
if (potentialCapsule === capsule) continue
|
|
160
|
-
|
|
160
|
+
|
|
161
161
|
const mappedModulePath = potentialCapsule.cst?.source?.moduleFilepath
|
|
162
|
-
|
|
162
|
+
|
|
163
163
|
if (mappedModulePath && (
|
|
164
164
|
mappedModulePath === mappingValue ||
|
|
165
165
|
mappedModulePath.endsWith(mappingValue) ||
|
|
@@ -199,17 +199,17 @@ export function CapsuleModuleProjector({
|
|
|
199
199
|
foundInAmbient = true
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
|
-
|
|
202
|
+
|
|
203
203
|
// If not found in ambient refs, try string-based mapping
|
|
204
204
|
if (!foundInAmbient && nestedProp.valueExpression && capsules) {
|
|
205
205
|
const mappingValue = nestedProp.valueExpression.replace(/['"]/g, '')
|
|
206
|
-
|
|
206
|
+
|
|
207
207
|
// Look through all capsules to find one that matches
|
|
208
208
|
for (const [key, potentialCapsule] of Object.entries(capsules)) {
|
|
209
209
|
if (potentialCapsule === capsule) continue
|
|
210
|
-
|
|
210
|
+
|
|
211
211
|
const mappedModulePath = potentialCapsule.cst?.source?.moduleFilepath
|
|
212
|
-
|
|
212
|
+
|
|
213
213
|
if (mappedModulePath && (
|
|
214
214
|
mappedModulePath === mappingValue ||
|
|
215
215
|
mappedModulePath.endsWith(mappingValue) ||
|
|
@@ -238,13 +238,13 @@ export function CapsuleModuleProjector({
|
|
|
238
238
|
// Helper: Traverse CST to collect all capsule URIs from mappings and property contracts
|
|
239
239
|
function collectAllCapsuleUris(capsule: any, spineContractUri: string): Set<string> {
|
|
240
240
|
const uris = new Set<string>()
|
|
241
|
-
|
|
241
|
+
|
|
242
242
|
function traverseProperties(properties: any) {
|
|
243
243
|
if (!properties) return
|
|
244
|
-
|
|
244
|
+
|
|
245
245
|
for (const [key, prop] of Object.entries(properties)) {
|
|
246
246
|
const propTyped = prop as any
|
|
247
|
-
|
|
247
|
+
|
|
248
248
|
// Check for Mapping type
|
|
249
249
|
if (propTyped.type === 'CapsulePropertyTypes.Mapping') {
|
|
250
250
|
if (propTyped.valueExpression) {
|
|
@@ -255,19 +255,19 @@ export function CapsuleModuleProjector({
|
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
|
-
|
|
258
|
+
|
|
259
259
|
// Recursively traverse nested properties
|
|
260
260
|
if (propTyped.properties) {
|
|
261
261
|
traverseProperties(propTyped.properties)
|
|
262
262
|
}
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
|
-
|
|
265
|
+
|
|
266
266
|
const spineContract = capsule.cst.spineContracts[spineContractUri]
|
|
267
267
|
if (spineContract?.properties) {
|
|
268
268
|
traverseProperties(spineContract.properties)
|
|
269
269
|
}
|
|
270
|
-
|
|
270
|
+
|
|
271
271
|
return uris
|
|
272
272
|
}
|
|
273
273
|
|
|
@@ -277,7 +277,7 @@ export function CapsuleModuleProjector({
|
|
|
277
277
|
// Check both top-level and nested under '#' property contract
|
|
278
278
|
const topLevelProps = spineContract?.properties || {}
|
|
279
279
|
const nestedProps = spineContract?.properties?.['#']?.properties || {}
|
|
280
|
-
|
|
280
|
+
|
|
281
281
|
// Check for solidjs.com/standalone specifically
|
|
282
282
|
for (const key of Object.keys(topLevelProps)) {
|
|
283
283
|
if (key === 'solidjs.com/standalone') return true
|
|
@@ -294,7 +294,7 @@ export function CapsuleModuleProjector({
|
|
|
294
294
|
// Check both top-level and nested under '#' property contract
|
|
295
295
|
const topLevelProps = spineContract?.properties || {}
|
|
296
296
|
const nestedProps = spineContract?.properties?.['#']?.properties || {}
|
|
297
|
-
|
|
297
|
+
|
|
298
298
|
// Check for exact match or with suffix
|
|
299
299
|
for (const key of Object.keys(topLevelProps)) {
|
|
300
300
|
if (key === 'encapsulate.dev/standalone' || key.startsWith('encapsulate.dev/standalone/')) return true
|
|
@@ -312,7 +312,7 @@ export function CapsuleModuleProjector({
|
|
|
312
312
|
// Check nested under '#' property contract first, looking for solidjs.com/standalone
|
|
313
313
|
const nestedProps = spineContract?.properties?.['#']?.properties || {}
|
|
314
314
|
const topLevelProps = spineContract?.properties || {}
|
|
315
|
-
|
|
315
|
+
|
|
316
316
|
let solidjsProp = null
|
|
317
317
|
for (const key of Object.keys(nestedProps)) {
|
|
318
318
|
if (key === 'solidjs.com/standalone') {
|
|
@@ -372,7 +372,7 @@ export function CapsuleModuleProjector({
|
|
|
372
372
|
// Check nested under '#' property contract first, looking for encapsulate.dev/standalone or encapsulate.dev/standalone/*
|
|
373
373
|
const nestedProps = spineContract?.properties?.['#']?.properties || {}
|
|
374
374
|
const topLevelProps = spineContract?.properties || {}
|
|
375
|
-
|
|
375
|
+
|
|
376
376
|
let standaloneProp = null
|
|
377
377
|
for (const key of Object.keys(nestedProps)) {
|
|
378
378
|
if (key === 'encapsulate.dev/standalone' || key.startsWith('encapsulate.dev/standalone/')) {
|
|
@@ -452,7 +452,7 @@ export function CapsuleModuleProjector({
|
|
|
452
452
|
const sourceExtension = capsule.cst.source.moduleFilepath?.endsWith('.tsx') ? '.tsx' : '.ts'
|
|
453
453
|
|
|
454
454
|
let projectedPath: string
|
|
455
|
-
|
|
455
|
+
|
|
456
456
|
// Use capsuleName if it exists (WITHOUT line number), otherwise use capsuleSourceUriLineRef (WITH line number)
|
|
457
457
|
if (capsule.cst.source.capsuleName) {
|
|
458
458
|
// Use capsuleName as the path - NO line number
|
|
@@ -490,7 +490,16 @@ export function CapsuleModuleProjector({
|
|
|
490
490
|
}
|
|
491
491
|
}
|
|
492
492
|
|
|
493
|
-
const projectCapsule = async ({ capsule, capsules, snapshotValues, spineContractUri }: { capsule: any, capsules?: Record<string, any>, snapshotValues?: any, spineContractUri: string }): Promise<boolean> => {
|
|
493
|
+
const projectCapsule = async ({ capsule, capsules, snapshotValues, spineContractUri, projectingCapsules }: { capsule: any, capsules?: Record<string, any>, snapshotValues?: any, spineContractUri: string, projectingCapsules?: Set<string> }): Promise<boolean> => {
|
|
494
|
+
|
|
495
|
+
// Check for circular dependency - if already projecting this capsule, skip
|
|
496
|
+
if (projectingCapsules) {
|
|
497
|
+
const capsuleId = capsule.cst?.capsuleSourceNameRefHash || capsule.capsuleSourceLineRef
|
|
498
|
+
if (projectingCapsules.has(capsuleId)) {
|
|
499
|
+
return true
|
|
500
|
+
}
|
|
501
|
+
projectingCapsules.add(capsuleId)
|
|
502
|
+
}
|
|
494
503
|
|
|
495
504
|
timing?.record(`Projector: Start projection for ${capsule.cst.source.moduleFilepath}`)
|
|
496
505
|
|
|
@@ -580,7 +589,7 @@ export function CapsuleModuleProjector({
|
|
|
580
589
|
mappedModulePath.endsWith(mappingValue + '.tsx') ||
|
|
581
590
|
mappedModulePath.includes(mappingValue.replace('./', ''))
|
|
582
591
|
)) {
|
|
583
|
-
await projectCapsule({ capsule: potentialMappedCapsule, capsules, snapshotValues, spineContractUri })
|
|
592
|
+
await projectCapsule({ capsule: potentialMappedCapsule, capsules, snapshotValues, spineContractUri, projectingCapsules })
|
|
584
593
|
}
|
|
585
594
|
}
|
|
586
595
|
}
|
|
@@ -607,7 +616,7 @@ export function CapsuleModuleProjector({
|
|
|
607
616
|
// Helper: Rewrite capsule expression to inline CST using regex
|
|
608
617
|
function rewriteCapsuleExpressionWithCST(targetCapsule: any): string {
|
|
609
618
|
let expression = targetCapsule.cst.source.capsuleExpression || ''
|
|
610
|
-
|
|
619
|
+
|
|
611
620
|
const cstJson = JSON.stringify(targetCapsule.cst, null, 4)
|
|
612
621
|
const crtJson = JSON.stringify(targetCapsule.crt || {}, null, 4)
|
|
613
622
|
const moduleFilepath = targetCapsule.cst.source.moduleFilepath
|
|
@@ -810,7 +819,7 @@ export function CapsuleModuleProjector({
|
|
|
810
819
|
if (solidjsComponent) {
|
|
811
820
|
// Collect all capsule URIs from CST (mappings and property contracts)
|
|
812
821
|
const allCapsuleUris = collectAllCapsuleUris(capsule, spineContractUri)
|
|
813
|
-
|
|
822
|
+
|
|
814
823
|
// Also collect from ambient references and build import paths from snapshots
|
|
815
824
|
const capsuleDeps: Array<{ uri: string, importName: string, importPath: string }> = []
|
|
816
825
|
for (const [name, ref] of Object.entries(ambientReferences)) {
|
|
@@ -819,20 +828,20 @@ export function CapsuleModuleProjector({
|
|
|
819
828
|
const snapshot = await buildCapsuleSnapshotForReference(refTyped, capsules, spineContractUri)
|
|
820
829
|
const capsuleName = snapshot.spineContracts?.['#@stream44.studio/encapsulate/spine-contracts/CapsuleSpineContract.v0']?.['#@stream44.studio/encapsulate/structs/Capsule.v0']?.capsuleName
|
|
821
830
|
const projectedFilepath = snapshot.spineContracts?.['#@stream44.studio/encapsulate/spine-contracts/CapsuleSpineContract.v0']?.['#@stream44.studio/encapsulate/structs/Capsule.v0']?.projectedCapsuleFilepath
|
|
822
|
-
|
|
831
|
+
|
|
823
832
|
if (capsuleName && projectedFilepath) {
|
|
824
833
|
allCapsuleUris.add(capsuleName)
|
|
825
|
-
|
|
834
|
+
|
|
826
835
|
// Build import path from projected filepath
|
|
827
836
|
const importName = `_capsule_${capsuleName.replace(/[^a-zA-Z0-9]/g, '_')}`
|
|
828
837
|
// Remove .~caps/ prefix and strip extension
|
|
829
838
|
const importPath = projectedFilepath.replace(/^\.~caps\//, '').replace(/\.(ts|tsx)$/, '')
|
|
830
|
-
|
|
839
|
+
|
|
831
840
|
capsuleDeps.push({ uri: capsuleName, importName, importPath })
|
|
832
841
|
}
|
|
833
842
|
}
|
|
834
843
|
}
|
|
835
|
-
|
|
844
|
+
|
|
836
845
|
// Generate static imports for all capsule dependencies
|
|
837
846
|
// Compute relative path from projected file to .~caps directory
|
|
838
847
|
let importPrefix: string
|
|
@@ -844,15 +853,15 @@ export function CapsuleModuleProjector({
|
|
|
844
853
|
const relativePathToCaps = relative(projectedFileDir, capsDir)
|
|
845
854
|
importPrefix = relativePathToCaps.startsWith('.') ? relativePathToCaps : './' + relativePathToCaps
|
|
846
855
|
}
|
|
847
|
-
const capsuleImports = capsuleDeps.map(dep =>
|
|
856
|
+
const capsuleImports = capsuleDeps.map(dep =>
|
|
848
857
|
`import * as ${dep.importName} from '${importPrefix}/${dep.importPath}'`
|
|
849
858
|
).join('\n')
|
|
850
|
-
|
|
859
|
+
|
|
851
860
|
// Generate capsules map
|
|
852
861
|
const capsulesMapEntries = capsuleDeps.map(dep =>
|
|
853
862
|
` '${dep.uri}': ${dep.importName}`
|
|
854
863
|
).join(',\n')
|
|
855
|
-
|
|
864
|
+
|
|
856
865
|
defaultExport = `
|
|
857
866
|
${capsuleImports}
|
|
858
867
|
|
|
@@ -965,10 +974,10 @@ export default function({ onMembraneEvent }: { onMembraneEvent?: (event: any) =>
|
|
|
965
974
|
} else if (hasStandalone) {
|
|
966
975
|
// Generate a wrapper function that directly invokes the standalone function
|
|
967
976
|
const capsuleSourceLineRef = capsule.cst.capsuleSourceLineRef
|
|
968
|
-
|
|
977
|
+
|
|
969
978
|
// Collect all capsule URIs from CST (mappings and property contracts)
|
|
970
979
|
const allCapsuleUris = collectAllCapsuleUris(capsule, spineContractUri)
|
|
971
|
-
|
|
980
|
+
|
|
972
981
|
// Also collect from ambient references
|
|
973
982
|
for (const [name, ref] of Object.entries(ambientReferences)) {
|
|
974
983
|
const refTyped = ref as any
|
|
@@ -980,7 +989,7 @@ export default function({ onMembraneEvent }: { onMembraneEvent?: (event: any) =>
|
|
|
980
989
|
}
|
|
981
990
|
}
|
|
982
991
|
}
|
|
983
|
-
|
|
992
|
+
|
|
984
993
|
// Build import paths from snapshots for ALL collected URIs
|
|
985
994
|
const capsuleDeps: Array<{ uri: string, importName: string, importPath: string }> = []
|
|
986
995
|
for (const uri of allCapsuleUris) {
|
|
@@ -995,22 +1004,22 @@ export default function({ onMembraneEvent }: { onMembraneEvent?: (event: any) =>
|
|
|
995
1004
|
}
|
|
996
1005
|
}
|
|
997
1006
|
}
|
|
998
|
-
|
|
1007
|
+
|
|
999
1008
|
if (capsuleRef) {
|
|
1000
1009
|
const snapshot = await buildCapsuleSnapshotForReference(capsuleRef, capsules, spineContractUri)
|
|
1001
1010
|
const projectedFilepath = snapshot.spineContracts?.['#@stream44.studio/encapsulate/spine-contracts/CapsuleSpineContract.v0']?.['#@stream44.studio/encapsulate/structs/Capsule.v0']?.projectedCapsuleFilepath
|
|
1002
|
-
|
|
1011
|
+
|
|
1003
1012
|
if (projectedFilepath) {
|
|
1004
1013
|
// Build import path from projected filepath
|
|
1005
1014
|
const importName = `_capsule_${uri.replace(/[^a-zA-Z0-9]/g, '_')}`
|
|
1006
1015
|
// Remove .~caps/ prefix and strip extension
|
|
1007
1016
|
const importPath = projectedFilepath.replace(/^\.~caps\//, '').replace(/\.(ts|tsx)$/, '')
|
|
1008
|
-
|
|
1017
|
+
|
|
1009
1018
|
capsuleDeps.push({ uri, importName, importPath })
|
|
1010
1019
|
}
|
|
1011
1020
|
}
|
|
1012
1021
|
}
|
|
1013
|
-
|
|
1022
|
+
|
|
1014
1023
|
// Generate static imports for all capsule dependencies
|
|
1015
1024
|
// Compute relative path from projected file to .~caps directory
|
|
1016
1025
|
let importPrefix: string
|
|
@@ -1022,15 +1031,15 @@ export default function({ onMembraneEvent }: { onMembraneEvent?: (event: any) =>
|
|
|
1022
1031
|
const relativePathToCaps = relative(projectedFileDir, capsDir)
|
|
1023
1032
|
importPrefix = relativePathToCaps.startsWith('.') ? relativePathToCaps : './' + relativePathToCaps
|
|
1024
1033
|
}
|
|
1025
|
-
const capsuleImports = capsuleDeps.map(dep =>
|
|
1034
|
+
const capsuleImports = capsuleDeps.map(dep =>
|
|
1026
1035
|
`import * as ${dep.importName} from '${importPrefix}/${dep.importPath}'`
|
|
1027
1036
|
).join('\n')
|
|
1028
|
-
|
|
1037
|
+
|
|
1029
1038
|
// Generate capsules map
|
|
1030
1039
|
const capsulesMapEntries = capsuleDeps.map(dep =>
|
|
1031
1040
|
` '${dep.uri}': ${dep.importName}`
|
|
1032
1041
|
).join(',\n')
|
|
1033
|
-
|
|
1042
|
+
|
|
1034
1043
|
defaultExport = `
|
|
1035
1044
|
${capsuleImports}
|
|
1036
1045
|
|
|
@@ -1116,7 +1125,7 @@ ${capsulesMapEntries}
|
|
|
1116
1125
|
// Prepare literal references with proper indentation
|
|
1117
1126
|
const indentedLiteralRefs = literalReferences ? literalReferences.split('\n').map(line => line ? ` ${line}` : '').join('\n') + '\n' : ''
|
|
1118
1127
|
const indentedInstanceInits = instanceInitializations ? ' ' + instanceInitializations.split('\n').join('\n ') + '\n' : ''
|
|
1119
|
-
|
|
1128
|
+
|
|
1120
1129
|
const fileContent = `${runtimeImport}${importStatements}
|
|
1121
1130
|
${moduleLocalFunctions}
|
|
1122
1131
|
|
|
@@ -1297,7 +1306,7 @@ ${defaultExport}
|
|
|
1297
1306
|
|
|
1298
1307
|
// Add runtime imports for SolidJS and standalone functions
|
|
1299
1308
|
const mappedRuntimeImport = mappedNeedsRuntime ? `"use client"\nimport { Spine, SpineRuntime } from '@stream44.studio/encapsulate/encapsulate'\nimport { CapsuleSpineContract } from '@stream44.studio/encapsulate/spine-contracts/CapsuleSpineContract.v0/Membrane.v0'\n${mappedSolidJsImport}` : ''
|
|
1300
|
-
|
|
1309
|
+
|
|
1301
1310
|
let mappedDefaultExport = ''
|
|
1302
1311
|
if (mappedHasSolidJs) {
|
|
1303
1312
|
// Generate a wrapper that sets up runtime and exports the SolidJS component
|
|
@@ -1306,7 +1315,7 @@ ${defaultExport}
|
|
|
1306
1315
|
if (solidjsComponent) {
|
|
1307
1316
|
// Collect all capsule URIs from CST (mappings and property contracts)
|
|
1308
1317
|
const allMappedCapsuleUris = collectAllCapsuleUris(mappedCapsule, spineContractUri)
|
|
1309
|
-
|
|
1318
|
+
|
|
1310
1319
|
// Also collect from ambient references
|
|
1311
1320
|
for (const [name, ref] of Object.entries(mappedAmbientRefs)) {
|
|
1312
1321
|
const refTyped = ref as any
|
|
@@ -1318,7 +1327,7 @@ ${defaultExport}
|
|
|
1318
1327
|
}
|
|
1319
1328
|
}
|
|
1320
1329
|
}
|
|
1321
|
-
|
|
1330
|
+
|
|
1322
1331
|
// Build capsule dependencies array
|
|
1323
1332
|
const mappedCapsuleDeps: Array<{ uri: string, importName: string, importPath: string }> = []
|
|
1324
1333
|
for (const uri of allMappedCapsuleUris) {
|
|
@@ -1327,7 +1336,7 @@ ${defaultExport}
|
|
|
1327
1336
|
const importPath = uri.startsWith('@') ? uri.substring(1) : uri
|
|
1328
1337
|
mappedCapsuleDeps.push({ uri, importName, importPath })
|
|
1329
1338
|
}
|
|
1330
|
-
|
|
1339
|
+
|
|
1331
1340
|
// Generate static imports for all capsule dependencies
|
|
1332
1341
|
// Compute relative path from projected file to .~caps directory
|
|
1333
1342
|
let importPrefix: string
|
|
@@ -1339,15 +1348,15 @@ ${defaultExport}
|
|
|
1339
1348
|
const relativePathToCaps = relative(projectedFileDir, capsDir)
|
|
1340
1349
|
importPrefix = relativePathToCaps.startsWith('.') ? relativePathToCaps : './' + relativePathToCaps
|
|
1341
1350
|
}
|
|
1342
|
-
const mappedCapsuleImports = mappedCapsuleDeps.map(dep =>
|
|
1351
|
+
const mappedCapsuleImports = mappedCapsuleDeps.map(dep =>
|
|
1343
1352
|
`import * as ${dep.importName} from '${importPrefix}/${dep.importPath}'`
|
|
1344
1353
|
).join('\n')
|
|
1345
|
-
|
|
1354
|
+
|
|
1346
1355
|
// Generate capsules map
|
|
1347
1356
|
const mappedCapsulesMapEntries = mappedCapsuleDeps.map(dep =>
|
|
1348
1357
|
` '${dep.uri}': ${dep.importName}`
|
|
1349
1358
|
).join(',\n')
|
|
1350
|
-
|
|
1359
|
+
|
|
1351
1360
|
mappedDefaultExport = `
|
|
1352
1361
|
${mappedCapsuleImports}
|
|
1353
1362
|
|
|
@@ -1457,10 +1466,10 @@ export default function({ onMembraneEvent }: { onMembraneEvent?: (event: any) =>
|
|
|
1457
1466
|
} else if (mappedHasStandalone) {
|
|
1458
1467
|
// Generate a wrapper function that directly invokes the standalone function
|
|
1459
1468
|
const mappedCapsuleSourceLineRef = mappedCapsule.cst.capsuleSourceLineRef
|
|
1460
|
-
|
|
1469
|
+
|
|
1461
1470
|
// Collect all capsule URIs from CST (mappings and property contracts)
|
|
1462
1471
|
const allMappedCapsuleUris = collectAllCapsuleUris(mappedCapsule, spineContractUri)
|
|
1463
|
-
|
|
1472
|
+
|
|
1464
1473
|
// Also collect from ambient references
|
|
1465
1474
|
for (const [name, ref] of Object.entries(mappedAmbientRefs)) {
|
|
1466
1475
|
const refTyped = ref as any
|
|
@@ -1472,7 +1481,7 @@ export default function({ onMembraneEvent }: { onMembraneEvent?: (event: any) =>
|
|
|
1472
1481
|
}
|
|
1473
1482
|
}
|
|
1474
1483
|
}
|
|
1475
|
-
|
|
1484
|
+
|
|
1476
1485
|
// Build capsule dependencies array
|
|
1477
1486
|
const mappedCapsuleDeps: Array<{ uri: string, importName: string, importPath: string }> = []
|
|
1478
1487
|
for (const uri of allMappedCapsuleUris) {
|
|
@@ -1481,7 +1490,7 @@ export default function({ onMembraneEvent }: { onMembraneEvent?: (event: any) =>
|
|
|
1481
1490
|
const importPath = uri.startsWith('@') ? uri.substring(1) : uri
|
|
1482
1491
|
mappedCapsuleDeps.push({ uri, importName, importPath })
|
|
1483
1492
|
}
|
|
1484
|
-
|
|
1493
|
+
|
|
1485
1494
|
// Generate static imports for all capsule dependencies
|
|
1486
1495
|
// Compute relative path from projected file to .~caps directory
|
|
1487
1496
|
let importPrefix: string
|
|
@@ -1493,15 +1502,15 @@ export default function({ onMembraneEvent }: { onMembraneEvent?: (event: any) =>
|
|
|
1493
1502
|
const relativePathToCaps = relative(projectedFileDir, capsDir)
|
|
1494
1503
|
importPrefix = relativePathToCaps.startsWith('.') ? relativePathToCaps : './' + relativePathToCaps
|
|
1495
1504
|
}
|
|
1496
|
-
const mappedCapsuleImports = mappedCapsuleDeps.map(dep =>
|
|
1505
|
+
const mappedCapsuleImports = mappedCapsuleDeps.map(dep =>
|
|
1497
1506
|
`import * as ${dep.importName} from '${importPrefix}/${dep.importPath}'`
|
|
1498
1507
|
).join('\n')
|
|
1499
|
-
|
|
1508
|
+
|
|
1500
1509
|
// Generate capsules map
|
|
1501
1510
|
const mappedCapsulesMapEntries = mappedCapsuleDeps.map(dep =>
|
|
1502
1511
|
` '${dep.uri}': ${dep.importName}`
|
|
1503
1512
|
).join(',\n')
|
|
1504
|
-
|
|
1513
|
+
|
|
1505
1514
|
mappedDefaultExport = `
|
|
1506
1515
|
${mappedCapsuleImports}
|
|
1507
1516
|
|
|
@@ -1627,7 +1636,7 @@ ${mappedDefaultExport}
|
|
|
1627
1636
|
if (registryCapsule === capsule) {
|
|
1628
1637
|
continue
|
|
1629
1638
|
}
|
|
1630
|
-
|
|
1639
|
+
|
|
1631
1640
|
// Skip if this capsule doesn't have the required CST structure
|
|
1632
1641
|
if (!registryCapsule.cst?.source?.moduleFilepath || !registryCapsule.cst?.source?.importStackLine) {
|
|
1633
1642
|
continue
|
|
@@ -1645,16 +1654,16 @@ ${mappedDefaultExport}
|
|
|
1645
1654
|
snapshotData: await buildCapsuleSnapshotForReference({ value: registryCapsule.cst }, capsules, spineContractUri)
|
|
1646
1655
|
}
|
|
1647
1656
|
await projectionCacheStore.writeFile(capsuleCacheFilename, JSON.stringify(capsuleCacheData, null, 2))
|
|
1648
|
-
|
|
1657
|
+
|
|
1649
1658
|
// Also project the capsule to .~caps
|
|
1650
1659
|
const projectedPath = capsuleCacheData.snapshotData.spineContracts[spineContractUri]['#@stream44.studio/encapsulate/structs/Capsule.v0'].projectedCapsuleFilepath
|
|
1651
|
-
|
|
1660
|
+
|
|
1652
1661
|
// Generate the capsule file content with proper imports and ambient reference loading
|
|
1653
1662
|
const capsuleExpression = rewriteCapsuleExpressionWithCST(registryCapsule)
|
|
1654
|
-
|
|
1663
|
+
|
|
1655
1664
|
// Get ambient references for this capsule
|
|
1656
1665
|
const capsuleAmbientRefs = registryCapsule.cst.source?.ambientReferences || {}
|
|
1657
|
-
|
|
1666
|
+
|
|
1658
1667
|
// Generate literal references
|
|
1659
1668
|
const capsuleLiteralRefs = Object.entries(capsuleAmbientRefs)
|
|
1660
1669
|
.map(([name, ref]: [string, any]) => {
|
|
@@ -1665,7 +1674,7 @@ ${mappedDefaultExport}
|
|
|
1665
1674
|
})
|
|
1666
1675
|
.filter(Boolean)
|
|
1667
1676
|
.join('\n')
|
|
1668
|
-
|
|
1677
|
+
|
|
1669
1678
|
// Generate instance initializations for ambient references
|
|
1670
1679
|
const capsuleInstanceInitPromises = Object.entries(capsuleAmbientRefs)
|
|
1671
1680
|
.map(async ([name, ref]: [string, any]) => {
|
|
@@ -1678,26 +1687,26 @@ ${mappedDefaultExport}
|
|
|
1678
1687
|
const capsuleInstanceInits = (await Promise.all(capsuleInstanceInitPromises))
|
|
1679
1688
|
.filter(Boolean)
|
|
1680
1689
|
.join('\n ')
|
|
1681
|
-
|
|
1690
|
+
|
|
1682
1691
|
// Add necessary imports
|
|
1683
1692
|
const imports = `import { CapsulePropertyTypes } from '@stream44.studio/encapsulate/encapsulate'
|
|
1684
1693
|
import { makeImportStack } from '@stream44.studio/encapsulate/encapsulate'
|
|
1685
1694
|
`
|
|
1686
|
-
|
|
1695
|
+
|
|
1687
1696
|
// Get the capsule name for the assignment
|
|
1688
1697
|
const capsuleName = registryCapsule.cst.source.capsuleName || ''
|
|
1689
|
-
|
|
1698
|
+
|
|
1690
1699
|
// Combine literal refs and instance inits with proper indentation
|
|
1691
1700
|
const indentedLiterals = capsuleLiteralRefs ? capsuleLiteralRefs.split('\n').map(line => ` ${line}`).join('\n') + '\n' : ''
|
|
1692
1701
|
const indentedInits = capsuleInstanceInits ? ' ' + capsuleInstanceInits + '\n' : ''
|
|
1693
|
-
|
|
1702
|
+
|
|
1694
1703
|
const capsuleFileContent = `${imports}
|
|
1695
1704
|
export async function capsule({ encapsulate, loadCapsule }: { encapsulate: any, loadCapsule: any }) {
|
|
1696
1705
|
${indentedLiterals}${indentedInits} return ${capsuleExpression}
|
|
1697
1706
|
}
|
|
1698
1707
|
capsule['#'] = ${JSON.stringify(capsuleName)}
|
|
1699
1708
|
`
|
|
1700
|
-
|
|
1709
|
+
|
|
1701
1710
|
if (projectionStore) {
|
|
1702
1711
|
await projectionStore.writeFile(projectedPath, capsuleFileContent)
|
|
1703
1712
|
}
|