@chainlink/cre-sdk 1.0.2 → 1.0.3
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/package.json
CHANGED
|
@@ -128,9 +128,23 @@ export async function main() {
|
|
|
128
128
|
main()`
|
|
129
129
|
const result = wrapWorkflowCode(input, 'test.ts')
|
|
130
130
|
|
|
131
|
-
// Should
|
|
132
|
-
expect(result
|
|
133
|
-
expect(result
|
|
131
|
+
// Should replace the original main() call
|
|
132
|
+
expect(result.match(/main\(\)\.catch\(sendErrorResponse\)/g)?.length).toBe(1)
|
|
133
|
+
expect(result.match(/(^|\n)\s*main\(\)\s*;?\s*$/g)?.length ?? 0).toBe(0)
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
test('replaces await main() with await main().catch()', () => {
|
|
137
|
+
const input = `import { Runner } from '@chainlink/cre-sdk'
|
|
138
|
+
|
|
139
|
+
export async function main() {
|
|
140
|
+
const runner = await Runner.newRunner()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
await main()`
|
|
144
|
+
const result = wrapWorkflowCode(input, 'test.ts')
|
|
145
|
+
|
|
146
|
+
expect(result).toContain('await main().catch(sendErrorResponse)')
|
|
147
|
+
expect(result.match(/main\(\)\.catch\(sendErrorResponse\)/g)?.length).toBe(1)
|
|
134
148
|
})
|
|
135
149
|
})
|
|
136
150
|
|
|
@@ -7,7 +7,8 @@ import * as ts from 'typescript'
|
|
|
7
7
|
* 2. Detects if `main()` function is exported.
|
|
8
8
|
* 3. Detects if there's already a top-level `main()` call with `.catch()` handler.
|
|
9
9
|
* 4. Adds `sendErrorResponse` to imports if missing.
|
|
10
|
-
* 5.
|
|
10
|
+
* 5. Replaces top-level `main()` or `await main()` with `main().catch(sendErrorResponse)`.
|
|
11
|
+
* 6. Appends `main().catch(sendErrorResponse)` only if no error handling exists and no call exists.
|
|
11
12
|
*
|
|
12
13
|
* @param sourceCode - The TypeScript source code to wrap
|
|
13
14
|
* @param filePath - The file path (used for source file creation)
|
|
@@ -17,10 +18,9 @@ export function wrapWorkflowCode(sourceCode: string, filePath: string): string {
|
|
|
17
18
|
const sourceFile = ts.createSourceFile(filePath, sourceCode, ts.ScriptTarget.Latest, true)
|
|
18
19
|
|
|
19
20
|
// Analysis state
|
|
20
|
-
let hasSendErrorResponseImport = false
|
|
21
|
-
let creSdkImportDeclaration: ts.ImportDeclaration | null = null
|
|
22
21
|
let hasMainExport = false
|
|
23
22
|
let hasExistingErrorHandling = false
|
|
23
|
+
const mainCallStatements: { start: number; end: number; useAwait: boolean }[] = []
|
|
24
24
|
|
|
25
25
|
// Helper to check if a node is a main() call expression
|
|
26
26
|
const isMainCall = (node: ts.Node): boolean => {
|
|
@@ -43,24 +43,18 @@ export function wrapWorkflowCode(sourceCode: string, filePath: string): string {
|
|
|
43
43
|
return false
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (ts.isImportDeclaration(statement)) {
|
|
50
|
-
const moduleSpecifier = statement.moduleSpecifier
|
|
51
|
-
if (ts.isStringLiteral(moduleSpecifier) && moduleSpecifier.text === '@chainlink/cre-sdk') {
|
|
52
|
-
creSdkImportDeclaration = statement
|
|
53
|
-
if (
|
|
54
|
-
statement.importClause?.namedBindings &&
|
|
55
|
-
ts.isNamedImports(statement.importClause.namedBindings)
|
|
56
|
-
) {
|
|
57
|
-
hasSendErrorResponseImport = statement.importClause.namedBindings.elements.some(
|
|
58
|
-
(element) => element.name.text === 'sendErrorResponse',
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
46
|
+
const getMainCallFromExpression = (expr: ts.Expression): { useAwait: boolean } | null => {
|
|
47
|
+
if (isMainCall(expr)) {
|
|
48
|
+
return { useAwait: false }
|
|
62
49
|
}
|
|
50
|
+
if (ts.isAwaitExpression(expr) && isMainCall(expr.expression)) {
|
|
51
|
+
return { useAwait: true }
|
|
52
|
+
}
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
63
55
|
|
|
56
|
+
// First pass: analyze AST
|
|
57
|
+
for (const statement of sourceFile.statements) {
|
|
64
58
|
// Check for main() export
|
|
65
59
|
if (ts.isFunctionDeclaration(statement) && statement.name?.text === 'main') {
|
|
66
60
|
if (statement.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword)) {
|
|
@@ -71,16 +65,17 @@ export function wrapWorkflowCode(sourceCode: string, filePath: string): string {
|
|
|
71
65
|
// Check for top-level main() call with error handling
|
|
72
66
|
if (ts.isExpressionStatement(statement)) {
|
|
73
67
|
const expr = statement.expression
|
|
68
|
+
const exprToCheck = ts.isAwaitExpression(expr) ? expr.expression : expr
|
|
74
69
|
|
|
75
70
|
// Check for main().catch(...)
|
|
76
|
-
if (isWrappedWithCatch(
|
|
71
|
+
if (isWrappedWithCatch(exprToCheck)) {
|
|
77
72
|
hasExistingErrorHandling = true
|
|
78
73
|
}
|
|
79
74
|
|
|
80
75
|
// Also check for: main().then(...).catch(...) or other chained patterns
|
|
81
|
-
if (ts.isCallExpression(
|
|
76
|
+
if (ts.isCallExpression(exprToCheck)) {
|
|
82
77
|
// Walk the chain to find if there's a .catch anywhere
|
|
83
|
-
let current: ts.Expression =
|
|
78
|
+
let current: ts.Expression = exprToCheck
|
|
84
79
|
while (ts.isCallExpression(current)) {
|
|
85
80
|
const propAccess = current.expression
|
|
86
81
|
if (ts.isPropertyAccessExpression(propAccess)) {
|
|
@@ -105,13 +100,53 @@ export function wrapWorkflowCode(sourceCode: string, filePath: string): string {
|
|
|
105
100
|
}
|
|
106
101
|
}
|
|
107
102
|
}
|
|
103
|
+
|
|
104
|
+
if (!hasExistingErrorHandling) {
|
|
105
|
+
const mainCall = getMainCallFromExpression(expr)
|
|
106
|
+
if (mainCall) {
|
|
107
|
+
mainCallStatements.push({
|
|
108
|
+
start: statement.getStart(sourceFile),
|
|
109
|
+
end: statement.end,
|
|
110
|
+
useAwait: mainCall.useAwait,
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
}
|
|
108
114
|
}
|
|
109
115
|
}
|
|
110
116
|
|
|
111
117
|
// Build the transformed code
|
|
112
118
|
let result = sourceCode
|
|
113
119
|
|
|
120
|
+
if (!hasExistingErrorHandling && mainCallStatements.length > 0) {
|
|
121
|
+
for (const statement of [...mainCallStatements].sort((a, b) => b.start - a.start)) {
|
|
122
|
+
const replacement = `${statement.useAwait ? 'await ' : ''}main().catch(sendErrorResponse)`
|
|
123
|
+
result = result.slice(0, statement.start) + replacement + result.slice(statement.end)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
114
127
|
// If we need to add sendErrorResponse import
|
|
128
|
+
const nextSourceFile = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true)
|
|
129
|
+
let hasSendErrorResponseImport = false
|
|
130
|
+
let creSdkImportDeclaration: ts.ImportDeclaration | null = null
|
|
131
|
+
|
|
132
|
+
for (const statement of nextSourceFile.statements) {
|
|
133
|
+
// Check for @chainlink/cre-sdk import
|
|
134
|
+
if (ts.isImportDeclaration(statement)) {
|
|
135
|
+
const moduleSpecifier = statement.moduleSpecifier
|
|
136
|
+
if (ts.isStringLiteral(moduleSpecifier) && moduleSpecifier.text === '@chainlink/cre-sdk') {
|
|
137
|
+
creSdkImportDeclaration = statement
|
|
138
|
+
if (
|
|
139
|
+
statement.importClause?.namedBindings &&
|
|
140
|
+
ts.isNamedImports(statement.importClause.namedBindings)
|
|
141
|
+
) {
|
|
142
|
+
hasSendErrorResponseImport = statement.importClause.namedBindings.elements.some(
|
|
143
|
+
(element) => element.name.text === 'sendErrorResponse',
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
115
150
|
if (!hasSendErrorResponseImport) {
|
|
116
151
|
if (creSdkImportDeclaration) {
|
|
117
152
|
// Add to existing import
|
|
@@ -131,7 +166,7 @@ export function wrapWorkflowCode(sourceCode: string, filePath: string): string {
|
|
|
131
166
|
|
|
132
167
|
// Find the last import declaration to insert after it
|
|
133
168
|
let lastImportEnd = 0
|
|
134
|
-
for (const statement of
|
|
169
|
+
for (const statement of nextSourceFile.statements) {
|
|
135
170
|
if (ts.isImportDeclaration(statement)) {
|
|
136
171
|
lastImportEnd = statement.end
|
|
137
172
|
}
|
|
@@ -154,7 +189,7 @@ export function wrapWorkflowCode(sourceCode: string, filePath: string): string {
|
|
|
154
189
|
}
|
|
155
190
|
|
|
156
191
|
// Append main().catch(sendErrorResponse) if no error handling exists
|
|
157
|
-
if (!hasExistingErrorHandling) {
|
|
192
|
+
if (!hasExistingErrorHandling && mainCallStatements.length === 0) {
|
|
158
193
|
const trimmedResult = result.trimEnd()
|
|
159
194
|
result = trimmedResult + '\n\nmain().catch(sendErrorResponse)\n'
|
|
160
195
|
}
|