@bubblelab/bubble-runtime 0.1.15 → 0.1.17
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 +12 -3
- package/dist/extraction/BubbleParser.d.ts.map +1 -1
- package/dist/extraction/BubbleParser.js +63 -60
- package/dist/extraction/BubbleParser.js.map +1 -1
- package/dist/injection/BubbleInjector.d.ts +0 -1
- package/dist/injection/BubbleInjector.d.ts.map +1 -1
- package/dist/injection/BubbleInjector.js +6 -10
- package/dist/injection/BubbleInjector.js.map +1 -1
- package/dist/parse/BubbleScript.d.ts +14 -1
- package/dist/parse/BubbleScript.d.ts.map +1 -1
- package/dist/parse/BubbleScript.js +94 -4
- package/dist/parse/BubbleScript.js.map +1 -1
- package/dist/runtime/BubbleRunner.d.ts.map +1 -1
- package/dist/runtime/BubbleRunner.js +1 -12
- package/dist/runtime/BubbleRunner.js.map +1 -1
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +1 -0
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/lint-rules.d.ts +34 -0
- package/dist/validation/lint-rules.d.ts.map +1 -1
- package/dist/validation/lint-rules.js +219 -0
- package/dist/validation/lint-rules.js.map +1 -1
- package/package.json +4 -4
|
@@ -38,7 +38,9 @@ export declare class BubbleParser {
|
|
|
38
38
|
/**
|
|
39
39
|
* Build a JSON Schema object for the payload parameter of the top-level `handle` entrypoint.
|
|
40
40
|
* Supports primitives, arrays, unions (anyOf), intersections (allOf), type literals, and
|
|
41
|
-
* same-file interfaces/type aliases.
|
|
41
|
+
* same-file interfaces/type aliases. When an interface extends a known trigger event type
|
|
42
|
+
* (e.g., SlackMentionEvent), the schema includes an `extendsEvent` field and only contains
|
|
43
|
+
* the additional custom properties defined in the interface.
|
|
42
44
|
*/
|
|
43
45
|
getPayloadJsonSchema(ast: TSESTree.Program): Record<string, unknown> | null;
|
|
44
46
|
/**
|
|
@@ -55,9 +57,15 @@ export declare class BubbleParser {
|
|
|
55
57
|
private tsTypeToJsonSchema;
|
|
56
58
|
private extractTypeReferenceName;
|
|
57
59
|
private objectTypeToJsonSchema;
|
|
58
|
-
private eventKeyToSchema;
|
|
59
60
|
/** Resolve in-file interface/type alias by name to JSON Schema */
|
|
60
61
|
private resolveTypeNameToJson;
|
|
62
|
+
/**
|
|
63
|
+
* Resolve an interface declaration to JSON Schema, handling extends clauses.
|
|
64
|
+
* If the interface extends a known trigger event type, the schema will include
|
|
65
|
+
* an `extendsEvent` field indicating the base trigger type, and `properties`
|
|
66
|
+
* will only contain the additional custom properties.
|
|
67
|
+
*/
|
|
68
|
+
private resolveInterfaceToJsonSchema;
|
|
61
69
|
/**
|
|
62
70
|
* Find the main class that extends BubbleFlow
|
|
63
71
|
*/
|
|
@@ -125,8 +133,9 @@ export declare class BubbleParser {
|
|
|
125
133
|
**/
|
|
126
134
|
private extractCommentForNode;
|
|
127
135
|
/**
|
|
128
|
-
* Extract JSDoc info including description and @
|
|
136
|
+
* Extract JSDoc info including description, @canBeFile, and @canBeGoogleFile tags from a node's preceding comments.
|
|
129
137
|
* The @canBeFile tag controls whether file upload is enabled for string fields in the UI.
|
|
138
|
+
* The @canBeGoogleFile tag enables Google Picker UI for Google Drive file/folder ID fields.
|
|
130
139
|
*/
|
|
131
140
|
private extractJSDocForNode;
|
|
132
141
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BubbleParser.d.ts","sourceRoot":"","sources":["../../src/extraction/BubbleParser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAErE,OAAO,KAAK,EAAS,YAAY,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,
|
|
1
|
+
{"version":3,"file":"BubbleParser.d.ts","sourceRoot":"","sources":["../../src/extraction/BubbleParser.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree';
|
|
2
2
|
import { buildClassNameLookup } from '../utils/bubble-helper';
|
|
3
|
-
import { BubbleParameterType, hashToVariableId, buildCallSiteKey, } from '@bubblelab/shared-schemas';
|
|
3
|
+
import { BubbleParameterType, hashToVariableId, buildCallSiteKey, getTriggerEventConfig, isValidBubbleTriggerEvent, getTriggerEventTypeFromInterfaceName, } from '@bubblelab/shared-schemas';
|
|
4
4
|
import { parseToolsParamValue } from '../utils/parameter-formatter';
|
|
5
5
|
export class BubbleParser {
|
|
6
6
|
bubbleScript;
|
|
@@ -323,7 +323,9 @@ export class BubbleParser {
|
|
|
323
323
|
/**
|
|
324
324
|
* Build a JSON Schema object for the payload parameter of the top-level `handle` entrypoint.
|
|
325
325
|
* Supports primitives, arrays, unions (anyOf), intersections (allOf), type literals, and
|
|
326
|
-
* same-file interfaces/type aliases.
|
|
326
|
+
* same-file interfaces/type aliases. When an interface extends a known trigger event type
|
|
327
|
+
* (e.g., SlackMentionEvent), the schema includes an `extendsEvent` field and only contains
|
|
328
|
+
* the additional custom properties defined in the interface.
|
|
327
329
|
*/
|
|
328
330
|
getPayloadJsonSchema(ast) {
|
|
329
331
|
const handleNode = this.findHandleFunctionNode(ast);
|
|
@@ -595,10 +597,11 @@ export class BubbleParser {
|
|
|
595
597
|
obj.typeName.name === 'BubbleTriggerEventRegistry' &&
|
|
596
598
|
idx.type === 'TSLiteralType' &&
|
|
597
599
|
idx.literal.type === 'Literal' &&
|
|
598
|
-
typeof idx.literal.value === 'string'
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
600
|
+
typeof idx.literal.value === 'string' &&
|
|
601
|
+
isValidBubbleTriggerEvent(idx.literal.value)) {
|
|
602
|
+
const config = getTriggerEventConfig(idx.literal.value);
|
|
603
|
+
if (config?.payloadSchema)
|
|
604
|
+
return config.payloadSchema;
|
|
602
605
|
}
|
|
603
606
|
return {};
|
|
604
607
|
}
|
|
@@ -644,6 +647,10 @@ export class BubbleParser {
|
|
|
644
647
|
if (jsDocInfo.canBeFile !== undefined) {
|
|
645
648
|
propSchema.canBeFile = jsDocInfo.canBeFile;
|
|
646
649
|
}
|
|
650
|
+
// Add canBeGoogleFile flag to schema if explicitly specified in JSDoc
|
|
651
|
+
if (jsDocInfo.canBeGoogleFile !== undefined) {
|
|
652
|
+
propSchema.canBeGoogleFile = jsDocInfo.canBeGoogleFile;
|
|
653
|
+
}
|
|
647
654
|
properties[keyName] = propSchema;
|
|
648
655
|
if (!m.optional)
|
|
649
656
|
required.push(keyName);
|
|
@@ -653,60 +660,11 @@ export class BubbleParser {
|
|
|
653
660
|
schema.required = required;
|
|
654
661
|
return schema;
|
|
655
662
|
}
|
|
656
|
-
// Minimal mapping for known trigger event keys to JSON Schema shapes
|
|
657
|
-
// Used for the input schema in the BubbleFlow editor if defined as BubbleTriggerEventRegistry[eventType]
|
|
658
|
-
eventKeyToSchema(eventKey) {
|
|
659
|
-
if (eventKey === 'slack/bot_mentioned') {
|
|
660
|
-
return {
|
|
661
|
-
type: 'object',
|
|
662
|
-
properties: {
|
|
663
|
-
text: { type: 'string' },
|
|
664
|
-
channel: { type: 'string' },
|
|
665
|
-
thread_ts: { type: 'string' },
|
|
666
|
-
user: { type: 'string' },
|
|
667
|
-
slack_event: { type: 'object' },
|
|
668
|
-
// Allow additional field used in flows
|
|
669
|
-
monthlyLimitError: {},
|
|
670
|
-
},
|
|
671
|
-
required: ['text', 'channel', 'user', 'slack_event'],
|
|
672
|
-
};
|
|
673
|
-
}
|
|
674
|
-
if (eventKey === 'webhook/http') {
|
|
675
|
-
return {
|
|
676
|
-
type: 'object',
|
|
677
|
-
properties: {
|
|
678
|
-
body: { type: 'object' },
|
|
679
|
-
},
|
|
680
|
-
};
|
|
681
|
-
}
|
|
682
|
-
if (eventKey === 'schedule/cron') {
|
|
683
|
-
return {
|
|
684
|
-
type: 'object',
|
|
685
|
-
properties: {
|
|
686
|
-
body: { type: 'object' },
|
|
687
|
-
},
|
|
688
|
-
};
|
|
689
|
-
}
|
|
690
|
-
if (eventKey === 'slack/message_received') {
|
|
691
|
-
return {
|
|
692
|
-
type: 'object',
|
|
693
|
-
properties: {
|
|
694
|
-
text: { type: 'string' },
|
|
695
|
-
channel: { type: 'string' },
|
|
696
|
-
user: { type: 'string' },
|
|
697
|
-
channel_type: { type: 'string' },
|
|
698
|
-
slack_event: { type: 'object' },
|
|
699
|
-
},
|
|
700
|
-
required: ['text', 'channel', 'user', 'slack_event'],
|
|
701
|
-
};
|
|
702
|
-
}
|
|
703
|
-
return null;
|
|
704
|
-
}
|
|
705
663
|
/** Resolve in-file interface/type alias by name to JSON Schema */
|
|
706
664
|
resolveTypeNameToJson(name, ast) {
|
|
707
665
|
for (const stmt of ast.body) {
|
|
708
666
|
if (stmt.type === 'TSInterfaceDeclaration' && stmt.id.name === name) {
|
|
709
|
-
return this.
|
|
667
|
+
return this.resolveInterfaceToJsonSchema(stmt, ast);
|
|
710
668
|
}
|
|
711
669
|
if (stmt.type === 'TSTypeAliasDeclaration' && stmt.id.name === name) {
|
|
712
670
|
return this.tsTypeToJsonSchema(stmt.typeAnnotation, ast) || {};
|
|
@@ -714,7 +672,7 @@ export class BubbleParser {
|
|
|
714
672
|
if (stmt.type === 'ExportNamedDeclaration' &&
|
|
715
673
|
stmt.declaration?.type === 'TSInterfaceDeclaration' &&
|
|
716
674
|
stmt.declaration.id.name === name) {
|
|
717
|
-
return this.
|
|
675
|
+
return this.resolveInterfaceToJsonSchema(stmt.declaration, ast);
|
|
718
676
|
}
|
|
719
677
|
if (stmt.type === 'ExportNamedDeclaration' &&
|
|
720
678
|
stmt.declaration?.type === 'TSTypeAliasDeclaration' &&
|
|
@@ -724,6 +682,39 @@ export class BubbleParser {
|
|
|
724
682
|
}
|
|
725
683
|
return null;
|
|
726
684
|
}
|
|
685
|
+
/**
|
|
686
|
+
* Resolve an interface declaration to JSON Schema, handling extends clauses.
|
|
687
|
+
* If the interface extends a known trigger event type, the schema will include
|
|
688
|
+
* an `extendsEvent` field indicating the base trigger type, and `properties`
|
|
689
|
+
* will only contain the additional custom properties.
|
|
690
|
+
*/
|
|
691
|
+
resolveInterfaceToJsonSchema(interfaceDecl, ast) {
|
|
692
|
+
// Check if this interface extends a known trigger event type
|
|
693
|
+
if (interfaceDecl.extends && interfaceDecl.extends.length > 0) {
|
|
694
|
+
for (const heritage of interfaceDecl.extends) {
|
|
695
|
+
// Get the extended interface name
|
|
696
|
+
let extendedName = null;
|
|
697
|
+
if (heritage.expression.type === 'Identifier') {
|
|
698
|
+
extendedName = heritage.expression.name;
|
|
699
|
+
}
|
|
700
|
+
if (extendedName) {
|
|
701
|
+
// Check if it's a known trigger event interface
|
|
702
|
+
const triggerEventType = getTriggerEventTypeFromInterfaceName(extendedName);
|
|
703
|
+
if (triggerEventType) {
|
|
704
|
+
// Extract only the additional properties from this interface
|
|
705
|
+
const additionalSchema = this.objectTypeToJsonSchema(interfaceDecl.body, ast);
|
|
706
|
+
// Return schema with extendsEvent marker for the UI to handle
|
|
707
|
+
return {
|
|
708
|
+
...additionalSchema,
|
|
709
|
+
extendsEvent: triggerEventType,
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
// No trigger event extension found, use normal processing
|
|
716
|
+
return this.objectTypeToJsonSchema(interfaceDecl.body, ast);
|
|
717
|
+
}
|
|
727
718
|
/**
|
|
728
719
|
* Find the main class that extends BubbleFlow
|
|
729
720
|
*/
|
|
@@ -1757,8 +1748,9 @@ export class BubbleParser {
|
|
|
1757
1748
|
return cleaned || undefined;
|
|
1758
1749
|
}
|
|
1759
1750
|
/**
|
|
1760
|
-
* Extract JSDoc info including description and @
|
|
1751
|
+
* Extract JSDoc info including description, @canBeFile, and @canBeGoogleFile tags from a node's preceding comments.
|
|
1761
1752
|
* The @canBeFile tag controls whether file upload is enabled for string fields in the UI.
|
|
1753
|
+
* The @canBeGoogleFile tag enables Google Picker UI for Google Drive file/folder ID fields.
|
|
1762
1754
|
*/
|
|
1763
1755
|
extractJSDocForNode(node) {
|
|
1764
1756
|
// Get the line number where this node starts
|
|
@@ -1808,11 +1800,17 @@ export class BubbleParser {
|
|
|
1808
1800
|
return {};
|
|
1809
1801
|
const fullComment = commentLines.join('\n');
|
|
1810
1802
|
let canBeFile;
|
|
1803
|
+
let canBeGoogleFile;
|
|
1811
1804
|
// Parse @canBeFile tag from the raw comment
|
|
1812
1805
|
const canBeFileMatch = fullComment.match(/@canBeFile\s+(true|false)/i);
|
|
1813
1806
|
if (canBeFileMatch) {
|
|
1814
1807
|
canBeFile = canBeFileMatch[1].toLowerCase() === 'true';
|
|
1815
1808
|
}
|
|
1809
|
+
// Parse @canBeGoogleFile tag from the raw comment
|
|
1810
|
+
const canBeGoogleFileMatch = fullComment.match(/@canBeGoogleFile\s+(true|false)/i);
|
|
1811
|
+
if (canBeGoogleFileMatch) {
|
|
1812
|
+
canBeGoogleFile = canBeGoogleFileMatch[1].toLowerCase() === 'true';
|
|
1813
|
+
}
|
|
1816
1814
|
let description;
|
|
1817
1815
|
if (isBlockComment) {
|
|
1818
1816
|
description = fullComment
|
|
@@ -1820,7 +1818,9 @@ export class BubbleParser {
|
|
|
1820
1818
|
.replace(/\s*\*\/\s*$/, '')
|
|
1821
1819
|
.split('\n')
|
|
1822
1820
|
.map((line) => line.replace(/^\s*\*\s?/, '').trim())
|
|
1823
|
-
.filter((line) => line.length > 0 &&
|
|
1821
|
+
.filter((line) => line.length > 0 &&
|
|
1822
|
+
!line.startsWith('@canBeFile') &&
|
|
1823
|
+
!line.startsWith('@canBeGoogleFile'))
|
|
1824
1824
|
.join(' ')
|
|
1825
1825
|
.trim();
|
|
1826
1826
|
}
|
|
@@ -1828,13 +1828,16 @@ export class BubbleParser {
|
|
|
1828
1828
|
description = fullComment
|
|
1829
1829
|
.split('\n')
|
|
1830
1830
|
.map((line) => line.replace(/^\/\/\s?/, '').trim())
|
|
1831
|
-
.filter((line) => line.length > 0 &&
|
|
1831
|
+
.filter((line) => line.length > 0 &&
|
|
1832
|
+
!line.startsWith('@canBeFile') &&
|
|
1833
|
+
!line.startsWith('@canBeGoogleFile'))
|
|
1832
1834
|
.join(' ')
|
|
1833
1835
|
.trim();
|
|
1834
1836
|
}
|
|
1835
1837
|
return {
|
|
1836
1838
|
description: description || undefined,
|
|
1837
1839
|
canBeFile,
|
|
1840
|
+
canBeGoogleFile,
|
|
1838
1841
|
};
|
|
1839
1842
|
}
|
|
1840
1843
|
/**
|