@bubblelab/bubble-runtime 0.1.14 → 0.1.16
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/dist/extraction/BubbleParser.d.ts +187 -8
- package/dist/extraction/BubbleParser.d.ts.map +1 -1
- package/dist/extraction/BubbleParser.js +2271 -117
- package/dist/extraction/BubbleParser.js.map +1 -1
- package/dist/extraction/index.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/injection/BubbleInjector.d.ts +27 -2
- package/dist/injection/BubbleInjector.d.ts.map +1 -1
- package/dist/injection/BubbleInjector.js +343 -35
- package/dist/injection/BubbleInjector.js.map +1 -1
- package/dist/injection/LoggerInjector.d.ts +12 -1
- package/dist/injection/LoggerInjector.d.ts.map +1 -1
- package/dist/injection/LoggerInjector.js +301 -13
- package/dist/injection/LoggerInjector.js.map +1 -1
- package/dist/injection/index.js +1 -0
- package/dist/parse/BubbleScript.d.ts +60 -3
- package/dist/parse/BubbleScript.d.ts.map +1 -1
- package/dist/parse/BubbleScript.js +133 -15
- package/dist/parse/BubbleScript.js.map +1 -1
- package/dist/parse/index.d.ts +0 -1
- package/dist/parse/index.d.ts.map +1 -1
- package/dist/parse/index.js +1 -1
- package/dist/parse/index.js.map +1 -1
- package/dist/runtime/BubbleRunner.d.ts +8 -2
- package/dist/runtime/BubbleRunner.d.ts.map +1 -1
- package/dist/runtime/BubbleRunner.js +41 -30
- package/dist/runtime/BubbleRunner.js.map +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/types.js +1 -0
- package/dist/types/index.js +1 -0
- package/dist/utils/bubble-helper.d.ts +2 -2
- package/dist/utils/bubble-helper.d.ts.map +1 -1
- package/dist/utils/bubble-helper.js +6 -1
- package/dist/utils/bubble-helper.js.map +1 -1
- package/dist/utils/normalize-control-flow.d.ts +14 -0
- package/dist/utils/normalize-control-flow.d.ts.map +1 -0
- package/dist/utils/normalize-control-flow.js +179 -0
- package/dist/utils/normalize-control-flow.js.map +1 -0
- package/dist/utils/parameter-formatter.d.ts +14 -5
- package/dist/utils/parameter-formatter.d.ts.map +1 -1
- package/dist/utils/parameter-formatter.js +164 -45
- package/dist/utils/parameter-formatter.js.map +1 -1
- package/dist/utils/sanitize-script.d.ts +11 -0
- package/dist/utils/sanitize-script.d.ts.map +1 -0
- package/dist/utils/sanitize-script.js +43 -0
- package/dist/utils/sanitize-script.js.map +1 -0
- package/dist/validation/BubbleValidator.d.ts +15 -0
- package/dist/validation/BubbleValidator.d.ts.map +1 -1
- package/dist/validation/BubbleValidator.js +168 -1
- package/dist/validation/BubbleValidator.js.map +1 -1
- package/dist/validation/index.d.ts +6 -3
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +33 -9
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/lint-rules.d.ts +91 -0
- package/dist/validation/lint-rules.d.ts.map +1 -0
- package/dist/validation/lint-rules.js +755 -0
- package/dist/validation/lint-rules.js.map +1 -0
- package/package.json +4 -4
- package/dist/parse/traceDependencies.d.ts +0 -18
- package/dist/parse/traceDependencies.d.ts.map +0 -1
- package/dist/parse/traceDependencies.js +0 -195
- package/dist/parse/traceDependencies.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA4B,MAAM,gBAAgB,CAAC"}
|
package/dist/runtime/types.js
CHANGED
package/dist/types/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { BubbleFactory } from '@bubblelab/bubble-core';
|
|
2
|
-
import { BubbleNodeType } from '@bubblelab/shared-schemas';
|
|
2
|
+
import { BubbleName, BubbleNodeType } from '@bubblelab/shared-schemas';
|
|
3
3
|
/**
|
|
4
4
|
* Build a lookup map from className to bubble metadata
|
|
5
5
|
*/
|
|
6
6
|
export declare function buildClassNameLookup(factory: BubbleFactory): Map<string, {
|
|
7
|
-
bubbleName:
|
|
7
|
+
bubbleName: BubbleName;
|
|
8
8
|
className: string;
|
|
9
9
|
nodeType: BubbleNodeType;
|
|
10
10
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bubble-helper.d.ts","sourceRoot":"","sources":["../../src/utils/bubble-helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"bubble-helper.d.ts","sourceRoot":"","sources":["../../src/utils/bubble-helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEvE;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,aAAa,GACrB,GAAG,CACJ,MAAM,EACN;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAA;CAAE,CACxE,CAqBA"}
|
|
@@ -8,7 +8,12 @@ export function buildClassNameLookup(factory) {
|
|
|
8
8
|
const className = ctor.name;
|
|
9
9
|
const bubbleName = ctor.bubbleName ?? className;
|
|
10
10
|
const nodeType = ctor.type ?? 'unknown';
|
|
11
|
-
lookup.set(className, {
|
|
11
|
+
lookup.set(className, {
|
|
12
|
+
bubbleName: bubbleName,
|
|
13
|
+
className,
|
|
14
|
+
nodeType,
|
|
15
|
+
});
|
|
12
16
|
}
|
|
13
17
|
return lookup;
|
|
14
18
|
}
|
|
19
|
+
//# sourceMappingURL=bubble-helper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bubble-helper.js","sourceRoot":"","sources":["../../src/utils/bubble-helper.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAsB;IAKtB,MAAM,MAAM,GAAG,IAAI,GAAG,EAGnB,CAAC;IACJ,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,EAA+B,CAAC;IAE1D,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;QACvB,MAAM,SAAS,GAAI,IAAoC,CAAC,IAAI,CAAC;QAC7D,MAAM,UAAU,GACb,IAA2C,CAAC,UAAU,IAAI,SAAS,CAAC;QACvE,MAAM,QAAQ,GACX,IAA6C,CAAC,IAAI,IAAI,SAAS,CAAC;QACnE,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"bubble-helper.js","sourceRoot":"","sources":["../../src/utils/bubble-helper.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAsB;IAKtB,MAAM,MAAM,GAAG,IAAI,GAAG,EAGnB,CAAC;IACJ,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,EAA+B,CAAC;IAE1D,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;QACvB,MAAM,SAAS,GAAI,IAAoC,CAAC,IAAI,CAAC;QAC7D,MAAM,UAAU,GACb,IAA2C,CAAC,UAAU,IAAI,SAAS,CAAC;QACvE,MAAM,QAAQ,GACX,IAA6C,CAAC,IAAI,IAAI,SAAS,CAAC;QACnE,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE;YACpB,UAAU,EAAE,UAAwB;YACpC,SAAS;YACT,QAAQ;SACT,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes braceless control flow statements by wrapping them with braces.
|
|
3
|
+
* This prevents issues when injecting logging or other statements into the code.
|
|
4
|
+
*
|
|
5
|
+
* Transforms:
|
|
6
|
+
* if (x) doSomething();
|
|
7
|
+
* else doOther();
|
|
8
|
+
*
|
|
9
|
+
* Into:
|
|
10
|
+
* if (x) { doSomething(); }
|
|
11
|
+
* else { doOther(); }
|
|
12
|
+
*/
|
|
13
|
+
export declare function normalizeBracelessControlFlow(code: string): string;
|
|
14
|
+
//# sourceMappingURL=normalize-control-flow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-control-flow.d.ts","sourceRoot":"","sources":["../../src/utils/normalize-control-flow.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;GAWG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkClE"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { parse } from '@typescript-eslint/typescript-estree';
|
|
2
|
+
/**
|
|
3
|
+
* Normalizes braceless control flow statements by wrapping them with braces.
|
|
4
|
+
* This prevents issues when injecting logging or other statements into the code.
|
|
5
|
+
*
|
|
6
|
+
* Transforms:
|
|
7
|
+
* if (x) doSomething();
|
|
8
|
+
* else doOther();
|
|
9
|
+
*
|
|
10
|
+
* Into:
|
|
11
|
+
* if (x) { doSomething(); }
|
|
12
|
+
* else { doOther(); }
|
|
13
|
+
*/
|
|
14
|
+
export function normalizeBracelessControlFlow(code) {
|
|
15
|
+
let ast;
|
|
16
|
+
try {
|
|
17
|
+
ast = parse(code, {
|
|
18
|
+
range: true,
|
|
19
|
+
loc: true,
|
|
20
|
+
sourceType: 'module',
|
|
21
|
+
ecmaVersion: 2022,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// If parsing fails, return original code
|
|
26
|
+
return code;
|
|
27
|
+
}
|
|
28
|
+
const insertions = [];
|
|
29
|
+
// Collect all braceless control flow bodies
|
|
30
|
+
collectBracelessBodies(ast, code, insertions);
|
|
31
|
+
if (insertions.length === 0) {
|
|
32
|
+
return code;
|
|
33
|
+
}
|
|
34
|
+
// Sort insertions by position in reverse order to preserve positions during modification
|
|
35
|
+
insertions.sort((a, b) => b.openBracePos - a.openBracePos);
|
|
36
|
+
// Apply insertions
|
|
37
|
+
let result = code;
|
|
38
|
+
for (const insertion of insertions) {
|
|
39
|
+
result = applyBraceInsertion(result, insertion);
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
function collectBracelessBodies(node, code, insertions) {
|
|
44
|
+
if (!node || typeof node !== 'object')
|
|
45
|
+
return;
|
|
46
|
+
// Check if statement
|
|
47
|
+
if (node.type === 'IfStatement') {
|
|
48
|
+
const ifStmt = node;
|
|
49
|
+
// Check consequent (then branch)
|
|
50
|
+
if (ifStmt.consequent.type !== 'BlockStatement') {
|
|
51
|
+
const insertion = createBraceInsertion(ifStmt, ifStmt.consequent, code, 'consequent');
|
|
52
|
+
if (insertion) {
|
|
53
|
+
insertions.push(insertion);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Check alternate (else branch) - but not if it's another IfStatement (else if)
|
|
57
|
+
if (ifStmt.alternate &&
|
|
58
|
+
ifStmt.alternate.type !== 'BlockStatement' &&
|
|
59
|
+
ifStmt.alternate.type !== 'IfStatement') {
|
|
60
|
+
const insertion = createBraceInsertion(ifStmt, ifStmt.alternate, code, 'alternate');
|
|
61
|
+
if (insertion) {
|
|
62
|
+
insertions.push(insertion);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Check for statement
|
|
67
|
+
if (node.type === 'ForStatement') {
|
|
68
|
+
const forStmt = node;
|
|
69
|
+
if (forStmt.body.type !== 'BlockStatement') {
|
|
70
|
+
const insertion = createBraceInsertion(forStmt, forStmt.body, code);
|
|
71
|
+
if (insertion) {
|
|
72
|
+
insertions.push(insertion);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Check for-in statement
|
|
77
|
+
if (node.type === 'ForInStatement') {
|
|
78
|
+
const forInStmt = node;
|
|
79
|
+
if (forInStmt.body.type !== 'BlockStatement') {
|
|
80
|
+
const insertion = createBraceInsertion(forInStmt, forInStmt.body, code);
|
|
81
|
+
if (insertion) {
|
|
82
|
+
insertions.push(insertion);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Check for-of statement
|
|
87
|
+
if (node.type === 'ForOfStatement') {
|
|
88
|
+
const forOfStmt = node;
|
|
89
|
+
if (forOfStmt.body.type !== 'BlockStatement') {
|
|
90
|
+
const insertion = createBraceInsertion(forOfStmt, forOfStmt.body, code);
|
|
91
|
+
if (insertion) {
|
|
92
|
+
insertions.push(insertion);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Check while statement
|
|
97
|
+
if (node.type === 'WhileStatement') {
|
|
98
|
+
const whileStmt = node;
|
|
99
|
+
if (whileStmt.body.type !== 'BlockStatement') {
|
|
100
|
+
const insertion = createBraceInsertion(whileStmt, whileStmt.body, code);
|
|
101
|
+
if (insertion) {
|
|
102
|
+
insertions.push(insertion);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Check do-while statement
|
|
107
|
+
if (node.type === 'DoWhileStatement') {
|
|
108
|
+
const doWhileStmt = node;
|
|
109
|
+
if (doWhileStmt.body.type !== 'BlockStatement') {
|
|
110
|
+
const insertion = createBraceInsertion(doWhileStmt, doWhileStmt.body, code);
|
|
111
|
+
if (insertion) {
|
|
112
|
+
insertions.push(insertion);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Recursively process children
|
|
117
|
+
for (const key of Object.keys(node)) {
|
|
118
|
+
if (key === 'parent' || key === 'loc' || key === 'range')
|
|
119
|
+
continue;
|
|
120
|
+
const child = node[key];
|
|
121
|
+
if (Array.isArray(child)) {
|
|
122
|
+
for (const item of child) {
|
|
123
|
+
if (item && typeof item === 'object' && 'type' in item) {
|
|
124
|
+
collectBracelessBodies(item, code, insertions);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else if (child && typeof child === 'object' && 'type' in child) {
|
|
129
|
+
collectBracelessBodies(child, code, insertions);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function createBraceInsertion(parent, body, code, branchType) {
|
|
134
|
+
if (!body.range)
|
|
135
|
+
return null;
|
|
136
|
+
// For 'else' branches, we need to find where the 'else' keyword ends
|
|
137
|
+
let openBracePos;
|
|
138
|
+
if (branchType === 'alternate') {
|
|
139
|
+
// Find the 'else' keyword before this statement
|
|
140
|
+
// Search backwards from the body start to find 'else'
|
|
141
|
+
const searchStart = Math.max(0, body.range[0] - 20);
|
|
142
|
+
const searchRegion = code.substring(searchStart, body.range[0]);
|
|
143
|
+
const elseMatch = searchRegion.match(/else\s*$/);
|
|
144
|
+
if (elseMatch) {
|
|
145
|
+
openBracePos = body.range[0];
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
openBracePos = body.range[0];
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else if (branchType === 'consequent') {
|
|
152
|
+
// For 'if' consequent, insert after the closing paren of condition
|
|
153
|
+
openBracePos = body.range[0];
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
// For for/while loops, insert after the closing paren
|
|
157
|
+
openBracePos = body.range[0];
|
|
158
|
+
}
|
|
159
|
+
// Get the indentation of the parent statement
|
|
160
|
+
const parentLine = code.substring(0, parent.range[0]).split('\n').pop() || '';
|
|
161
|
+
const indentation = parentLine.match(/^\s*/)?.[0] || '';
|
|
162
|
+
return {
|
|
163
|
+
openBracePos,
|
|
164
|
+
closeBracePos: body.range[1],
|
|
165
|
+
indentation,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function applyBraceInsertion(code, insertion) {
|
|
169
|
+
const { openBracePos, closeBracePos, indentation } = insertion;
|
|
170
|
+
// Get the content between the positions
|
|
171
|
+
const beforeOpen = code.substring(0, openBracePos);
|
|
172
|
+
const bodyContent = code.substring(openBracePos, closeBracePos);
|
|
173
|
+
const afterClose = code.substring(closeBracePos);
|
|
174
|
+
// Always put the statement on its own line inside the braces
|
|
175
|
+
// This ensures logging can be injected after the statement but before the closing brace
|
|
176
|
+
const bodyIndent = indentation + ' ';
|
|
177
|
+
return `${beforeOpen}{\n${bodyIndent}${bodyContent.trim()}\n${indentation}}${afterClose}`;
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=normalize-control-flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-control-flow.js","sourceRoot":"","sources":["../../src/utils/normalize-control-flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Utility functions for formatting bubble parameters
|
|
3
3
|
*/
|
|
4
|
+
import { BubbleParameter, ParsedBubbleWithInfo } from '@bubblelab/shared-schemas';
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
+
* Check if a string contains function literal patterns.
|
|
7
|
+
* When function literals are present, the source code must be preserved as-is
|
|
8
|
+
* because functions cannot be safely serialized or condensed to single-line.
|
|
6
9
|
*/
|
|
7
|
-
|
|
10
|
+
export declare function containsFunctionLiteral(value: string): boolean;
|
|
8
11
|
export declare function buildParametersObject(parameters: BubbleParameter[], variableId?: number, includeLoggerConfig?: boolean, dependencyGraphLiteral?: string, currentUniqueId?: string): string;
|
|
9
12
|
/**
|
|
10
13
|
* Format a parameter value based on its type
|
|
@@ -15,13 +18,19 @@ export declare function formatParameterValue(value: unknown, type: string): stri
|
|
|
15
18
|
* Returns an array of objects with at least a name field, or null if parsing fails.
|
|
16
19
|
*/
|
|
17
20
|
export declare function parseToolsParamValue(raw: unknown): Array<Record<string, unknown>> | null;
|
|
21
|
+
/**
|
|
22
|
+
* Condense a parameters string to a single line.
|
|
23
|
+
* Used when parameters don't contain function literals.
|
|
24
|
+
*/
|
|
25
|
+
export declare function condenseToSingleLine(input: string): string;
|
|
18
26
|
/**
|
|
19
27
|
* Replace a bubble instantiation with updated parameters
|
|
20
28
|
*
|
|
21
29
|
* This function:
|
|
22
|
-
* 1. Replaces the bubble instantiation line with
|
|
23
|
-
* 2.
|
|
24
|
-
* 3.
|
|
30
|
+
* 1. Replaces the bubble instantiation line with updated parameters
|
|
31
|
+
* 2. Preserves multi-line structure when function literals are present
|
|
32
|
+
* 3. Condenses to single-line otherwise
|
|
33
|
+
* 4. Uses bubble.location.endLine to know exactly where to stop deleting
|
|
25
34
|
*/
|
|
26
35
|
export declare function replaceBubbleInstantiation(lines: string[], bubble: ParsedBubbleWithInfo): void;
|
|
27
36
|
//# sourceMappingURL=parameter-formatter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parameter-formatter.d.ts","sourceRoot":"","sources":["../../src/utils/parameter-formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH
|
|
1
|
+
{"version":3,"file":"parameter-formatter.d.ts","sourceRoot":"","sources":["../../src/utils/parameter-formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,eAAe,EACf,oBAAoB,EACrB,MAAM,2BAA2B,CAAC;AAkBnC;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE9D;AAuBD,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,eAAe,EAAE,EAC7B,UAAU,CAAC,EAAE,MAAM,EACnB,mBAAmB,GAAE,OAAc,EACnC,sBAAsB,CAAC,EAAE,MAAM,EAC/B,eAAe,GAAE,MAAW,GAC3B,MAAM,CAgJR;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAsDzE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,OAAO,GACX,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,CAyBvC;AAoID;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ1D;AAmCD;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,EAAE,EACf,MAAM,EAAE,oBAAoB,QA0E7B"}
|
|
@@ -1,53 +1,128 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Utility functions for formatting bubble parameters
|
|
3
3
|
*/
|
|
4
|
+
const INVOCATION_KEY_EXPR = '__bubbleFlowSelf?.__getInvocationCallSiteKey?.() ?? ""';
|
|
5
|
+
/**
|
|
6
|
+
* Patterns that indicate function literals in source code.
|
|
7
|
+
* Used to detect when parameters contain functions that cannot be safely condensed.
|
|
8
|
+
*/
|
|
9
|
+
const FUNCTION_LITERAL_PATTERNS = [
|
|
10
|
+
'func:', // Object property with function value
|
|
11
|
+
'=>', // Arrow function
|
|
12
|
+
'function(', // Function expression
|
|
13
|
+
'function (', // Function expression with space
|
|
14
|
+
'async(', // Async arrow function
|
|
15
|
+
'async (', // Async function with space
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* Check if a string contains function literal patterns.
|
|
19
|
+
* When function literals are present, the source code must be preserved as-is
|
|
20
|
+
* because functions cannot be safely serialized or condensed to single-line.
|
|
21
|
+
*/
|
|
22
|
+
export function containsFunctionLiteral(value) {
|
|
23
|
+
return FUNCTION_LITERAL_PATTERNS.some((pattern) => value.includes(pattern));
|
|
24
|
+
}
|
|
25
|
+
function buildInvocationOverrideReference(variableId) {
|
|
26
|
+
if (typeof variableId !== 'number') {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
return `globalThis["__bubbleInvocationDependencyGraphs"]?.[${INVOCATION_KEY_EXPR}]?.[${JSON.stringify(String(variableId))}]`;
|
|
30
|
+
}
|
|
31
|
+
function buildDependencyGraphExpression(dependencyGraphLiteral, overrideRef) {
|
|
32
|
+
if (overrideRef) {
|
|
33
|
+
return `${overrideRef} ?? ${dependencyGraphLiteral}`;
|
|
34
|
+
}
|
|
35
|
+
return dependencyGraphLiteral;
|
|
36
|
+
}
|
|
4
37
|
export function buildParametersObject(parameters, variableId, includeLoggerConfig = true, dependencyGraphLiteral, currentUniqueId = '') {
|
|
5
38
|
if (!parameters || parameters.length === 0) {
|
|
6
39
|
return '{}';
|
|
7
40
|
}
|
|
41
|
+
const dependencyGraphLiteralSafe = dependencyGraphLiteral && dependencyGraphLiteral.length > 0
|
|
42
|
+
? dependencyGraphLiteral
|
|
43
|
+
: undefined;
|
|
44
|
+
const invocationOverrideRef = buildInvocationOverrideReference(variableId);
|
|
45
|
+
const dependencyGraphExpr = dependencyGraphLiteralSafe !== undefined
|
|
46
|
+
? buildDependencyGraphExpression(dependencyGraphLiteralSafe, invocationOverrideRef)
|
|
47
|
+
: (invocationOverrideRef ?? undefined);
|
|
48
|
+
const currentUniqueIdLiteral = JSON.stringify(currentUniqueId);
|
|
49
|
+
const currentUniqueIdExpr = invocationOverrideRef !== undefined
|
|
50
|
+
? `${invocationOverrideRef}?.uniqueId ?? ${currentUniqueIdLiteral}`
|
|
51
|
+
: currentUniqueIdLiteral;
|
|
8
52
|
// Handle single variable parameter case (e.g., new GoogleDriveBubble(params))
|
|
9
53
|
if (parameters.length === 1 && parameters[0].type === 'variable') {
|
|
10
54
|
const paramValue = formatParameterValue(parameters[0].value, parameters[0].type);
|
|
11
55
|
if (includeLoggerConfig) {
|
|
12
|
-
const
|
|
13
|
-
?
|
|
56
|
+
const variableIdExpr = typeof variableId === 'number'
|
|
57
|
+
? `(__bubbleFlowSelf?.__computeInvocationVariableId?.(${variableId}) ?? ${variableId})`
|
|
58
|
+
: 'undefined';
|
|
59
|
+
const depGraphPart = dependencyGraphExpr !== undefined
|
|
60
|
+
? `, dependencyGraph: ${dependencyGraphExpr}`
|
|
14
61
|
: '';
|
|
15
|
-
const currentIdPart = `, currentUniqueId: ${
|
|
16
|
-
|
|
62
|
+
const currentIdPart = `, currentUniqueId: ${currentUniqueIdExpr}`;
|
|
63
|
+
const invocationKeyPart = ', invocationCallSiteKey: __bubbleFlowSelf?.__getInvocationCallSiteKey?.()';
|
|
64
|
+
return `${paramValue}, {logger: __bubbleFlowSelf.logger, variableId: ${variableIdExpr}${depGraphPart}${currentIdPart}${invocationKeyPart}}`;
|
|
17
65
|
}
|
|
18
66
|
return paramValue;
|
|
19
67
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
68
|
+
const nonCredentialParams = parameters.filter((p) => p.name !== 'credentials');
|
|
69
|
+
const credentialsParam = parameters.find((p) => p.name === 'credentials' && p.type === 'object');
|
|
70
|
+
// Separate spreads from regular properties
|
|
71
|
+
const spreadParams = nonCredentialParams.filter((p) => p.source === 'spread');
|
|
72
|
+
const regularParams = nonCredentialParams.filter((p) => p.source !== 'spread');
|
|
73
|
+
// Handle single variable parameter + credentials case (existing logic)
|
|
74
|
+
if (credentialsParam &&
|
|
75
|
+
nonCredentialParams.length === 1 &&
|
|
76
|
+
nonCredentialParams[0].type === 'variable') {
|
|
77
|
+
const paramsParam = nonCredentialParams[0];
|
|
78
|
+
// Only spread if the parameter source is 'first-arg' (represents entire first argument),
|
|
79
|
+
// or if source is undefined (backward compatibility) and name is 'arg0' (parser's fallback).
|
|
80
|
+
const shouldSpread = paramsParam.source === 'first-arg' ||
|
|
81
|
+
(paramsParam.source === undefined && paramsParam.name === 'arg0');
|
|
82
|
+
if (shouldSpread) {
|
|
27
83
|
const paramsValue = formatParameterValue(paramsParam.value, paramsParam.type);
|
|
28
84
|
const credentialsValue = formatParameterValue(credentialsParam.value, credentialsParam.type);
|
|
29
85
|
if (includeLoggerConfig) {
|
|
30
|
-
const
|
|
31
|
-
?
|
|
86
|
+
const variableIdExpr = typeof variableId === 'number'
|
|
87
|
+
? `(__bubbleFlowSelf?.__computeInvocationVariableId?.(${variableId}) ?? ${variableId})`
|
|
88
|
+
: 'undefined';
|
|
89
|
+
const depGraphPart = dependencyGraphExpr !== undefined
|
|
90
|
+
? `, dependencyGraph: ${dependencyGraphExpr}`
|
|
32
91
|
: '';
|
|
33
|
-
const currentIdPart = `, currentUniqueId: ${
|
|
34
|
-
|
|
92
|
+
const currentIdPart = `, currentUniqueId: ${currentUniqueIdExpr}`;
|
|
93
|
+
const invocationKeyPart = ', invocationCallSiteKey: __bubbleFlowSelf?.__getInvocationCallSiteKey?.()';
|
|
94
|
+
return `{...${paramsValue}, credentials: ${credentialsValue}}, {logger: __bubbleFlowSelf.logger, variableId: ${variableIdExpr}${depGraphPart}${currentIdPart}${invocationKeyPart}}`;
|
|
35
95
|
}
|
|
36
96
|
return `{...${paramsValue}, credentials: ${credentialsValue}}`;
|
|
37
97
|
}
|
|
38
98
|
}
|
|
39
|
-
|
|
99
|
+
// Build parameter entries: regular properties first, then spreads
|
|
100
|
+
const regularEntries = regularParams.map((param) => {
|
|
40
101
|
const value = formatParameterValue(param.value, param.type);
|
|
41
102
|
return `${param.name}: ${value}`;
|
|
42
103
|
});
|
|
43
|
-
const
|
|
104
|
+
const spreadEntries = spreadParams.map((param) => {
|
|
105
|
+
const value = formatParameterValue(param.value, param.type);
|
|
106
|
+
return `...${value}`;
|
|
107
|
+
});
|
|
108
|
+
// Combine all entries: regular properties, spreads, then credentials
|
|
109
|
+
const allEntries = [...regularEntries, ...spreadEntries];
|
|
110
|
+
if (credentialsParam) {
|
|
111
|
+
const credentialsValue = formatParameterValue(credentialsParam.value, credentialsParam.type);
|
|
112
|
+
allEntries.push(`credentials: ${credentialsValue}`);
|
|
113
|
+
}
|
|
114
|
+
const paramsString = `{\n ${allEntries.join(',\n ')}\n }`;
|
|
44
115
|
// Only add the logger configuration if explicitly requested
|
|
45
116
|
if (includeLoggerConfig) {
|
|
46
|
-
const
|
|
47
|
-
?
|
|
117
|
+
const variableIdExpr = typeof variableId === 'number'
|
|
118
|
+
? `(__bubbleFlowSelf?.__computeInvocationVariableId?.(${variableId}) ?? ${variableId})`
|
|
119
|
+
: 'undefined';
|
|
120
|
+
const depGraphPart = dependencyGraphExpr !== undefined
|
|
121
|
+
? `, dependencyGraph: ${dependencyGraphExpr}`
|
|
48
122
|
: '';
|
|
49
|
-
const currentIdPart = `, currentUniqueId: ${
|
|
50
|
-
|
|
123
|
+
const currentIdPart = `, currentUniqueId: ${currentUniqueIdExpr}`;
|
|
124
|
+
const invocationKeyPart = ', invocationCallSiteKey: __bubbleFlowSelf?.__getInvocationCallSiteKey?.()';
|
|
125
|
+
return `${paramsString}, {logger: __bubbleFlowSelf.logger, variableId: ${variableIdExpr}${depGraphPart}${currentIdPart}${invocationKeyPart}}`;
|
|
51
126
|
}
|
|
52
127
|
return paramsString;
|
|
53
128
|
}
|
|
@@ -75,6 +150,10 @@ export function formatParameterValue(value, type) {
|
|
|
75
150
|
// If caller provided a source literal string, keep it as code
|
|
76
151
|
if (typeof value === 'string') {
|
|
77
152
|
const trimmed = value.trim();
|
|
153
|
+
// Preserve source code if it contains function literals
|
|
154
|
+
if (containsFunctionLiteral(trimmed)) {
|
|
155
|
+
return value;
|
|
156
|
+
}
|
|
78
157
|
if ((trimmed.startsWith('{') && trimmed.endsWith('}')) ||
|
|
79
158
|
trimmed.startsWith('new ')) {
|
|
80
159
|
return value;
|
|
@@ -84,6 +163,10 @@ export function formatParameterValue(value, type) {
|
|
|
84
163
|
case 'array':
|
|
85
164
|
if (typeof value === 'string') {
|
|
86
165
|
const trimmed = value.trim();
|
|
166
|
+
// Preserve source code if it contains function literals
|
|
167
|
+
if (containsFunctionLiteral(trimmed)) {
|
|
168
|
+
return value;
|
|
169
|
+
}
|
|
87
170
|
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
|
|
88
171
|
return value;
|
|
89
172
|
}
|
|
@@ -250,29 +333,73 @@ function stripCommentsOutsideStrings(input) {
|
|
|
250
333
|
}
|
|
251
334
|
return result;
|
|
252
335
|
}
|
|
336
|
+
/**
|
|
337
|
+
* Condense a parameters string to a single line.
|
|
338
|
+
* Used when parameters don't contain function literals.
|
|
339
|
+
*/
|
|
340
|
+
export function condenseToSingleLine(input) {
|
|
341
|
+
return input
|
|
342
|
+
.replace(/\s*\n\s*/g, ' ')
|
|
343
|
+
.replace(/\s{2,}/g, ' ')
|
|
344
|
+
.replace(/\{\s+/g, '{ ')
|
|
345
|
+
.replace(/\s+\}/g, ' }')
|
|
346
|
+
.replace(/\s*,\s*/g, ', ')
|
|
347
|
+
.trim();
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Replace lines in an array, handling both single-line and multi-line replacements.
|
|
351
|
+
* Returns the number of lines that were effectively added or removed.
|
|
352
|
+
*/
|
|
353
|
+
function replaceLines(lines, startIndex, deleteCount, replacement) {
|
|
354
|
+
const replacementLines = replacement.split('\n');
|
|
355
|
+
const isMultiLine = replacementLines.length > 1;
|
|
356
|
+
if (isMultiLine) {
|
|
357
|
+
// Multi-line replacement: replace first line, delete old lines, insert remaining
|
|
358
|
+
lines[startIndex] = replacementLines[0];
|
|
359
|
+
if (deleteCount > 0) {
|
|
360
|
+
lines.splice(startIndex + 1, deleteCount);
|
|
361
|
+
}
|
|
362
|
+
if (replacementLines.length > 1) {
|
|
363
|
+
lines.splice(startIndex + 1, 0, ...replacementLines.slice(1));
|
|
364
|
+
}
|
|
365
|
+
return replacementLines.length - 1 - deleteCount;
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
// Single-line replacement
|
|
369
|
+
lines[startIndex] = replacement;
|
|
370
|
+
if (deleteCount > 0) {
|
|
371
|
+
lines.splice(startIndex + 1, deleteCount);
|
|
372
|
+
}
|
|
373
|
+
return -deleteCount;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
253
376
|
/**
|
|
254
377
|
* Replace a bubble instantiation with updated parameters
|
|
255
378
|
*
|
|
256
379
|
* This function:
|
|
257
|
-
* 1. Replaces the bubble instantiation line with
|
|
258
|
-
* 2.
|
|
259
|
-
* 3.
|
|
380
|
+
* 1. Replaces the bubble instantiation line with updated parameters
|
|
381
|
+
* 2. Preserves multi-line structure when function literals are present
|
|
382
|
+
* 3. Condenses to single-line otherwise
|
|
383
|
+
* 4. Uses bubble.location.endLine to know exactly where to stop deleting
|
|
260
384
|
*/
|
|
261
385
|
export function replaceBubbleInstantiation(lines, bubble) {
|
|
386
|
+
if (bubble.invocationCallSiteKey) {
|
|
387
|
+
// Invocation-specific clones are logical constructs and shouldn't rewrite source
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
262
390
|
const { location, className, parameters } = bubble;
|
|
263
|
-
// Build the
|
|
391
|
+
// Build the parameters object string
|
|
264
392
|
const dependencyGraphLiteral = JSON.stringify(bubble.dependencyGraph || { name: bubble.bubbleName, dependencies: [] }).replace(/</g, '\u003c');
|
|
265
|
-
|
|
266
|
-
|
|
393
|
+
const currentUniqueIdValue = bubble.dependencyGraph?.uniqueId ?? String(bubble.variableId);
|
|
394
|
+
let parametersObject = buildParametersObject(parameters, bubble.variableId, true, dependencyGraphLiteral, currentUniqueIdValue);
|
|
395
|
+
// Remove JS/TS comments that would otherwise break formatting
|
|
267
396
|
parametersObject = stripCommentsOutsideStrings(parametersObject);
|
|
268
|
-
//
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
.replace(/\s*,\s*/g, ', ')
|
|
275
|
-
.trim();
|
|
397
|
+
// Check if parameters contain function literals before condensing
|
|
398
|
+
// Function literals cannot be safely condensed to single-line
|
|
399
|
+
const hasFunctions = containsFunctionLiteral(parametersObject);
|
|
400
|
+
if (!hasFunctions) {
|
|
401
|
+
parametersObject = condenseToSingleLine(parametersObject);
|
|
402
|
+
}
|
|
276
403
|
const newInstantiationBase = `new ${className}(${parametersObject})`;
|
|
277
404
|
// Find the line with the bubble instantiation
|
|
278
405
|
for (let i = location.startLine - 1; i < lines.length; i++) {
|
|
@@ -286,12 +413,8 @@ export function replaceBubbleInstantiation(lines, bubble) {
|
|
|
286
413
|
const actionCall = bubble.hasActionCall ? '.action()' : '';
|
|
287
414
|
const newExpression = `${hadAwait ? 'await ' : ''}${newInstantiationBase}${actionCall}`;
|
|
288
415
|
const replacement = `${indentation}${declaration} ${variableName} = ${newExpression}`;
|
|
289
|
-
lines[i] = replacement;
|
|
290
|
-
// Delete all lines that were part of the old multi-line parameters
|
|
291
416
|
const linesToDelete = location.endLine - (i + 1);
|
|
292
|
-
|
|
293
|
-
lines.splice(i + 1, linesToDelete);
|
|
294
|
-
}
|
|
417
|
+
replaceLines(lines, i, linesToDelete, replacement);
|
|
295
418
|
}
|
|
296
419
|
// Pattern 2: Anonymous bubble (await new Bubble(...).action())
|
|
297
420
|
else if (bubble.variableName.startsWith('_anonymous_')) {
|
|
@@ -301,12 +424,8 @@ export function replaceBubbleInstantiation(lines, bubble) {
|
|
|
301
424
|
const newExpression = `${hadAwait ? 'await ' : ''}${newInstantiationBase}${actionCall}`;
|
|
302
425
|
const beforeClean = beforePattern.replace(/\bawait\s*$/, '');
|
|
303
426
|
const replacement = `${beforeClean}${newExpression}`;
|
|
304
|
-
lines[i] = replacement;
|
|
305
|
-
// Delete all lines that were part of the old multi-line parameters
|
|
306
427
|
const linesToDelete = location.endLine - (i + 1);
|
|
307
|
-
|
|
308
|
-
lines.splice(i + 1, linesToDelete);
|
|
309
|
-
}
|
|
428
|
+
replaceLines(lines, i, linesToDelete, replacement);
|
|
310
429
|
}
|
|
311
430
|
break;
|
|
312
431
|
}
|