@chainlink/cre-sdk 1.6.0-alpha.1 → 1.6.0-alpha.2
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/README.md +1 -7
- package/bin/cre-compile.ts +17 -34
- package/dist/generated/chain-selectors/mainnet/evm/ab-mainnet.d.ts +3 -0
- package/dist/generated/chain-selectors/mainnet/evm/ab-mainnet.js +12 -0
- package/dist/generated/chain-selectors/mainnet/evm/adi-mainnet.d.ts +3 -0
- package/dist/generated/chain-selectors/mainnet/evm/adi-mainnet.js +12 -0
- package/dist/generated/chain-selectors/mainnet/evm/edge-mainnet.d.ts +3 -0
- package/dist/generated/chain-selectors/mainnet/evm/edge-mainnet.js +12 -0
- package/dist/generated/chain-selectors/mainnet/evm/everclear-mainnet.d.ts +3 -0
- package/dist/generated/chain-selectors/mainnet/evm/everclear-mainnet.js +12 -0
- package/dist/generated/chain-selectors/mainnet/evm/gate-chain-mainnet.d.ts +3 -0
- package/dist/generated/chain-selectors/mainnet/evm/gate-chain-mainnet.js +12 -0
- package/dist/generated/chain-selectors/mainnet/evm/gate-layer-mainnet.d.ts +3 -0
- package/dist/generated/chain-selectors/mainnet/evm/gate-layer-mainnet.js +12 -0
- package/dist/generated/chain-selectors/mainnet/evm/jovay-mainnet.d.ts +3 -0
- package/dist/generated/chain-selectors/mainnet/evm/jovay-mainnet.js +12 -0
- package/dist/generated/chain-selectors/mainnet/evm/megaeth-mainnet.d.ts +3 -0
- package/dist/generated/chain-selectors/mainnet/evm/megaeth-mainnet.js +12 -0
- package/dist/generated/chain-selectors/mainnet/evm/pharos-mainnet.d.ts +3 -0
- package/dist/generated/chain-selectors/mainnet/evm/pharos-mainnet.js +12 -0
- package/dist/generated/chain-selectors/mainnet/evm/stable-mainnet.d.ts +3 -0
- package/dist/generated/chain-selectors/mainnet/evm/stable-mainnet.js +12 -0
- package/dist/generated/chain-selectors/mainnet/evm/tempo-mainnet.d.ts +3 -0
- package/dist/generated/chain-selectors/mainnet/evm/tempo-mainnet.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/0g-testnet-galileo-1.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/0g-testnet-galileo-1.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/ab-testnet.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/ab-testnet.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/adi-testnet.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/adi-testnet.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/arc-testnet.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/arc-testnet.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/celo-sepolia.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/celo-sepolia.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/dogeos-testnet-chikyu.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/dogeos-testnet-chikyu.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/edge-testnet.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/edge-testnet.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/ethereum-testnet-hoodi-morph.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/ethereum-testnet-hoodi-morph.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/ethereum-testnet-hoodi-taiko-1.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/ethereum-testnet-hoodi-taiko-1.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/ethereum-testnet-hoodi-taiko.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/ethereum-testnet-hoodi-taiko.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/ethereum-testnet-hoodi.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/ethereum-testnet-hoodi.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/ethereum-testnet-sepolia-ronin-1.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/ethereum-testnet-sepolia-ronin-1.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/everclear-testnet-sepolia.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/everclear-testnet-sepolia.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/gate-chain-testnet-meteora.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/gate-chain-testnet-meteora.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/gate-layer-testnet.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/gate-layer-testnet.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/megaeth-testnet-2.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/megaeth-testnet-2.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/pharos-atlantic-testnet.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/pharos-atlantic-testnet.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/robinhood-testnet.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/robinhood-testnet.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/sonic-testnet.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/sonic-testnet.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/stable-testnet.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/stable-testnet.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/tempo-testnet-moderato.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/tempo-testnet-moderato.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/tempo-testnet.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/tempo-testnet.js +12 -0
- package/dist/generated/chain-selectors/testnet/evm/xlayer-testnet.d.ts +3 -0
- package/dist/generated/chain-selectors/testnet/evm/xlayer-testnet.js +12 -0
- package/dist/generated/networks.d.ts +2 -2
- package/dist/generated/networks.js +238 -0
- package/dist/sdk/don-info.d.ts +10 -0
- package/dist/sdk/don-info.js +9 -0
- package/dist/sdk/errors.d.ts +24 -1
- package/dist/sdk/errors.js +46 -1
- package/dist/sdk/index.d.ts +2 -0
- package/dist/sdk/index.js +2 -0
- package/dist/sdk/report-internals.d.ts +6 -0
- package/dist/sdk/report-internals.js +3 -0
- package/dist/sdk/report.d.ts +38 -0
- package/dist/sdk/report.js +489 -2
- package/dist/sdk/testutils/test-runtime.js +4 -0
- package/package.json +2 -2
- package/scripts/run-standard-tests.sh +3 -3
- package/scripts/run.ts +1 -5
- package/scripts/src/compile-to-js.ts +7 -46
- package/scripts/src/compile-to-wasm.ts +32 -18
- package/scripts/src/compile-workflow.ts +27 -55
- package/scripts/src/compile-cli-args.test.ts +0 -32
- package/scripts/src/compile-cli-args.ts +0 -35
- package/scripts/src/compile-to-js.test.ts +0 -90
- package/scripts/src/typecheck-workflow.test.ts +0 -77
- package/scripts/src/typecheck-workflow.ts +0 -96
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chainlink/cre-sdk",
|
|
3
|
-
"version": "1.6.0-alpha.
|
|
3
|
+
"version": "1.6.0-alpha.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@bufbuild/protobuf": "2.6.3",
|
|
62
62
|
"@bufbuild/protoc-gen-es": "2.6.3",
|
|
63
|
-
"@chainlink/cre-sdk-javy-plugin": "1.
|
|
63
|
+
"@chainlink/cre-sdk-javy-plugin": "1.6.0-alpha.2",
|
|
64
64
|
"@standard-schema/spec": "1.0.0",
|
|
65
65
|
"viem": "2.34.0",
|
|
66
66
|
"zod": "3.25.76"
|
|
@@ -8,9 +8,9 @@ set -e
|
|
|
8
8
|
# Create dist test workflow folder
|
|
9
9
|
mkdir -p ./dist/workflows/standard_tests
|
|
10
10
|
|
|
11
|
-
#
|
|
12
|
-
if [ ! -f ../cre-sdk-javy-plugin/dist/
|
|
13
|
-
echo "Error:
|
|
11
|
+
# Plugin package must be built (initialized plugin is what we ship).
|
|
12
|
+
if [ ! -f ../cre-sdk-javy-plugin/dist/javy-chainlink-sdk.plugin.wasm ]; then
|
|
13
|
+
echo "Error: javy-chainlink-sdk.plugin.wasm not found (run cre-sdk-javy-plugin build first)"
|
|
14
14
|
exit 1
|
|
15
15
|
fi
|
|
16
16
|
|
package/scripts/run.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
import { WorkflowTypecheckError } from './src/typecheck-workflow'
|
|
4
3
|
import { WorkflowRuntimeCompatibilityError } from './src/validate-workflow-runtime-compat'
|
|
5
4
|
|
|
6
5
|
const availableScripts = [
|
|
@@ -40,10 +39,7 @@ const main = async () => {
|
|
|
40
39
|
process.exit(1)
|
|
41
40
|
}
|
|
42
41
|
} catch (error) {
|
|
43
|
-
if (
|
|
44
|
-
error instanceof WorkflowRuntimeCompatibilityError ||
|
|
45
|
-
error instanceof WorkflowTypecheckError
|
|
46
|
-
) {
|
|
42
|
+
if (error instanceof WorkflowRuntimeCompatibilityError) {
|
|
47
43
|
console.error(`\n❌ ${error.message}`)
|
|
48
44
|
} else {
|
|
49
45
|
console.error(`Failed to run script ${scriptName}:`, error)
|
|
@@ -2,63 +2,24 @@ import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'
|
|
|
2
2
|
import { mkdir } from 'node:fs/promises'
|
|
3
3
|
import path from 'node:path'
|
|
4
4
|
import { $ } from 'bun'
|
|
5
|
-
import { parseCompileCliArgs, skipTypeChecksFlag } from './compile-cli-args'
|
|
6
|
-
import { assertWorkflowTypecheck } from './typecheck-workflow'
|
|
7
5
|
import { assertWorkflowRuntimeCompatibility } from './validate-workflow-runtime-compat'
|
|
8
6
|
import { wrapWorkflowCode } from './workflow-wrapper'
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const printUsage = () => {
|
|
15
|
-
console.error(`Usage: bun compile:ts-to-js <path-to-file> [output-file] [${skipTypeChecksFlag}]`)
|
|
16
|
-
console.error('Example:')
|
|
17
|
-
console.error(' bun compile:ts-to-js src/tests/foo.ts dist/tests/foo.bundle.js')
|
|
18
|
-
console.error(
|
|
19
|
-
` bun compile:ts-to-js src/tests/foo.ts dist/tests/foo.bundle.js ${skipTypeChecksFlag}`,
|
|
20
|
-
)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export const main = async (
|
|
24
|
-
tsFilePath?: string,
|
|
25
|
-
outputFilePath?: string,
|
|
26
|
-
options?: CompileToJsOptions,
|
|
27
|
-
) => {
|
|
28
|
-
let parsedInputPath: string | undefined
|
|
29
|
-
let parsedOutputPath: string | undefined
|
|
30
|
-
let parsedSkipTypeChecks = false
|
|
31
|
-
|
|
32
|
-
if (tsFilePath != null || outputFilePath != null || options?.skipTypeChecks != null) {
|
|
33
|
-
parsedInputPath = tsFilePath
|
|
34
|
-
parsedOutputPath = outputFilePath
|
|
35
|
-
parsedSkipTypeChecks = options?.skipTypeChecks ?? false
|
|
36
|
-
} else {
|
|
37
|
-
try {
|
|
38
|
-
const parsed = parseCompileCliArgs(process.argv.slice(3))
|
|
39
|
-
parsedInputPath = parsed.inputPath
|
|
40
|
-
parsedOutputPath = parsed.outputPath
|
|
41
|
-
parsedSkipTypeChecks = parsed.skipTypeChecks
|
|
42
|
-
} catch (error) {
|
|
43
|
-
console.error(error instanceof Error ? error.message : error)
|
|
44
|
-
printUsage()
|
|
45
|
-
process.exit(1)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
8
|
+
export const main = async (tsFilePath?: string, outputFilePath?: string) => {
|
|
9
|
+
const cliArgs = process.argv.slice(3)
|
|
48
10
|
|
|
49
11
|
// Prefer function params, fallback to CLI args
|
|
50
|
-
const inputPath =
|
|
51
|
-
const outputPathArg =
|
|
12
|
+
const inputPath = tsFilePath ?? cliArgs[0]
|
|
13
|
+
const outputPathArg = outputFilePath ?? cliArgs[1]
|
|
52
14
|
|
|
53
15
|
if (!inputPath) {
|
|
54
|
-
|
|
16
|
+
console.error('Usage: bun test:standard:compile:js <path-to-file> [output-file]')
|
|
17
|
+
console.error('Example:')
|
|
18
|
+
console.error(' bun test:standard:compile:js src/tests/foo.ts dist/tests/foo.bundle.js')
|
|
55
19
|
process.exit(1)
|
|
56
20
|
}
|
|
57
21
|
|
|
58
22
|
const resolvedInput = path.resolve(inputPath)
|
|
59
|
-
if (!parsedSkipTypeChecks) {
|
|
60
|
-
assertWorkflowTypecheck(resolvedInput)
|
|
61
|
-
}
|
|
62
23
|
assertWorkflowRuntimeCompatibility(resolvedInput)
|
|
63
24
|
console.info(`📁 Using input file: ${resolvedInput}`)
|
|
64
25
|
|
|
@@ -2,6 +2,7 @@ import { spawn } from 'node:child_process'
|
|
|
2
2
|
import { existsSync } from 'node:fs'
|
|
3
3
|
import { mkdir } from 'node:fs/promises'
|
|
4
4
|
import path from 'node:path'
|
|
5
|
+
import { parseCompileFlags } from '../../../cre-sdk-javy-plugin/scripts/parse-compile-flags'
|
|
5
6
|
|
|
6
7
|
function runBun(args: string[]): Promise<void> {
|
|
7
8
|
return new Promise((resolve, reject) => {
|
|
@@ -19,20 +20,29 @@ function runBun(args: string[]): Promise<void> {
|
|
|
19
20
|
|
|
20
21
|
const isJsFile = (p: string) => ['.js', '.mjs', '.cjs'].includes(path.extname(p).toLowerCase())
|
|
21
22
|
|
|
22
|
-
export const main = async (
|
|
23
|
+
export const main = async (
|
|
24
|
+
inputFile?: string,
|
|
25
|
+
outputFile?: string,
|
|
26
|
+
creExportsPaths?: string[],
|
|
27
|
+
pluginPath?: string | null,
|
|
28
|
+
) => {
|
|
23
29
|
const cliArgs = process.argv.slice(3)
|
|
30
|
+
const { creExports: cliCreExports, plugin: cliPlugin, rest: cliRest } = parseCompileFlags(cliArgs)
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
const
|
|
32
|
+
const inputPath = inputFile ?? cliRest[0]
|
|
33
|
+
const outputPathArg = outputFile ?? cliRest[1]
|
|
34
|
+
const creExports = creExportsPaths ?? cliCreExports
|
|
35
|
+
const plugin = pluginPath !== undefined ? pluginPath : cliPlugin
|
|
36
|
+
|
|
37
|
+
if (plugin !== null && plugin !== undefined && creExports.length > 0) {
|
|
38
|
+
console.error('❌ Error: --plugin and --cre-exports are mutually exclusive.')
|
|
39
|
+
process.exit(1)
|
|
40
|
+
}
|
|
28
41
|
|
|
29
42
|
if (!inputPath) {
|
|
30
43
|
console.error(
|
|
31
44
|
'Usage: bun compile:js-to-wasm <path/to/input.(js|mjs|cjs)> [path/to/output.wasm]',
|
|
32
45
|
)
|
|
33
|
-
console.error('Examples:')
|
|
34
|
-
console.error(' bun compile:js-to-wasm ./build/workflows/test.js')
|
|
35
|
-
console.error(' bun compile:js-to-wasm ./build/workflows/test.mjs ./artifacts/test.wasm')
|
|
36
46
|
process.exit(1)
|
|
37
47
|
}
|
|
38
48
|
|
|
@@ -47,31 +57,35 @@ export const main = async (inputFile?: string, outputFile?: string) => {
|
|
|
47
57
|
process.exit(1)
|
|
48
58
|
}
|
|
49
59
|
|
|
50
|
-
// Default output = same dir, same basename, .wasm extension
|
|
51
60
|
const defaultOut = path.join(
|
|
52
61
|
path.dirname(resolvedInput),
|
|
53
62
|
path.basename(resolvedInput).replace(/\.(m|c)?js$/i, '.wasm'),
|
|
54
63
|
)
|
|
55
64
|
const resolvedOutput = outputPathArg ? path.resolve(outputPathArg) : defaultOut
|
|
56
65
|
|
|
57
|
-
// Ensure output directory exists
|
|
58
66
|
await mkdir(path.dirname(resolvedOutput), { recursive: true })
|
|
59
67
|
|
|
60
|
-
console.info(
|
|
68
|
+
console.info('🔨 Compiling to WASM')
|
|
61
69
|
console.info(`📁 Input: ${resolvedInput}`)
|
|
62
70
|
console.info(`🎯 Output: ${resolvedOutput}`)
|
|
63
71
|
|
|
64
|
-
|
|
65
|
-
|
|
72
|
+
const compileArgs: string[] = []
|
|
73
|
+
if (plugin != null && plugin !== '') {
|
|
74
|
+
compileArgs.push('--plugin', path.resolve(plugin))
|
|
75
|
+
} else {
|
|
76
|
+
compileArgs.push(...creExports.flatMap((p) => ['--cre-exports', path.resolve(p)]))
|
|
77
|
+
}
|
|
78
|
+
compileArgs.push(resolvedInput, resolvedOutput)
|
|
79
|
+
|
|
66
80
|
const scriptDir = import.meta.dir
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
'../../../cre-sdk-javy-plugin
|
|
70
|
-
)
|
|
81
|
+
const javyPluginRoot = process.env.CRE_SDK_JAVY_PLUGIN_HOME
|
|
82
|
+
? path.resolve(process.env.CRE_SDK_JAVY_PLUGIN_HOME)
|
|
83
|
+
: path.resolve(scriptDir, '../../../cre-sdk-javy-plugin')
|
|
84
|
+
const compilerPath = path.join(javyPluginRoot, 'bin/compile-workflow.ts')
|
|
71
85
|
if (existsSync(compilerPath)) {
|
|
72
|
-
await runBun(['--bun', compilerPath,
|
|
86
|
+
await runBun(['--bun', compilerPath, ...compileArgs])
|
|
73
87
|
} else {
|
|
74
|
-
await runBun(['x', 'cre-compile-workflow',
|
|
88
|
+
await runBun(['x', 'cre-compile-workflow', ...compileArgs])
|
|
75
89
|
}
|
|
76
90
|
|
|
77
91
|
console.info(`✅ Compiled: ${resolvedOutput}`)
|
|
@@ -1,59 +1,31 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
2
|
import { mkdir } from 'node:fs/promises'
|
|
3
3
|
import path from 'node:path'
|
|
4
|
-
import {
|
|
4
|
+
import { parseCompileFlags } from '../../../cre-sdk-javy-plugin/scripts/parse-compile-flags'
|
|
5
5
|
import { main as compileToJs } from './compile-to-js'
|
|
6
6
|
import { main as compileToWasm } from './compile-to-wasm'
|
|
7
7
|
|
|
8
|
-
type CompileWorkflowOptions = {
|
|
9
|
-
skipTypeChecks?: boolean
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const printUsage = () => {
|
|
13
|
-
console.error(
|
|
14
|
-
`Usage: bun compile:workflow <path/to/workflow.ts> [path/to/output.wasm] [${skipTypeChecksFlag}]`,
|
|
15
|
-
)
|
|
16
|
-
console.error('Examples:')
|
|
17
|
-
console.error(' bun compile:workflow src/standard_tests/secrets/test.ts')
|
|
18
|
-
console.error(
|
|
19
|
-
' bun compile:workflow src/standard_tests/secrets/test.ts .temp/standard_tests/secrets/test.wasm',
|
|
20
|
-
)
|
|
21
|
-
console.error(
|
|
22
|
-
` bun compile:workflow src/standard_tests/secrets/test.ts .temp/standard_tests/secrets/test.wasm ${skipTypeChecksFlag}`,
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
8
|
export const main = async (
|
|
27
9
|
inputFile?: string,
|
|
28
10
|
outputWasmFile?: string,
|
|
29
|
-
|
|
11
|
+
creExportsPaths?: string[],
|
|
12
|
+
pluginPath?: string | null,
|
|
30
13
|
) => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
let parsedSkipTypeChecks = false
|
|
14
|
+
const cliArgs = process.argv.slice(3)
|
|
15
|
+
const { creExports: cliCreExports, plugin: cliPlugin, rest: cliRest } = parseCompileFlags(cliArgs)
|
|
34
16
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
} else {
|
|
40
|
-
try {
|
|
41
|
-
const parsed = parseCompileCliArgs(process.argv.slice(3))
|
|
42
|
-
parsedInputPath = parsed.inputPath
|
|
43
|
-
parsedOutputPath = parsed.outputPath
|
|
44
|
-
parsedSkipTypeChecks = parsed.skipTypeChecks
|
|
45
|
-
} catch (error) {
|
|
46
|
-
console.error(error instanceof Error ? error.message : error)
|
|
47
|
-
printUsage()
|
|
48
|
-
process.exit(1)
|
|
49
|
-
}
|
|
50
|
-
}
|
|
17
|
+
const inputPath = inputFile ?? cliRest[0]
|
|
18
|
+
const outputPathArg = outputWasmFile ?? cliRest[1]
|
|
19
|
+
const creExports = creExportsPaths ?? cliCreExports
|
|
20
|
+
const plugin = pluginPath !== undefined ? pluginPath : cliPlugin
|
|
51
21
|
|
|
52
|
-
|
|
53
|
-
|
|
22
|
+
if (plugin != null && plugin !== '' && creExports.length > 0) {
|
|
23
|
+
console.error('❌ Error: --plugin and --cre-exports are mutually exclusive.')
|
|
24
|
+
process.exit(1)
|
|
25
|
+
}
|
|
54
26
|
|
|
55
27
|
if (!inputPath) {
|
|
56
|
-
|
|
28
|
+
console.error('Usage: bun compile:workflow <path/to/workflow.ts> [path/to/output.wasm]')
|
|
57
29
|
process.exit(1)
|
|
58
30
|
}
|
|
59
31
|
|
|
@@ -63,33 +35,33 @@ export const main = async (
|
|
|
63
35
|
process.exit(1)
|
|
64
36
|
}
|
|
65
37
|
|
|
66
|
-
// Default final output = same dir, same basename, .wasm
|
|
67
38
|
const defaultWasmOut = path.join(
|
|
68
39
|
path.dirname(resolvedInput),
|
|
69
40
|
path.basename(resolvedInput).replace(/\.[^.]+$/, '.wasm'),
|
|
70
41
|
)
|
|
71
42
|
const resolvedWasmOutput = outputPathArg ? path.resolve(outputPathArg) : defaultWasmOut
|
|
72
|
-
|
|
73
|
-
// Put the intermediate JS next to the final wasm (so custom outputs stay together)
|
|
74
43
|
const resolvedJsOutput = resolvedWasmOutput.replace(/\.wasm$/i, '.js')
|
|
75
44
|
|
|
76
|
-
// Ensure directories exist (handles both intermediate JS dir and wasm dir)
|
|
77
45
|
await mkdir(path.dirname(resolvedJsOutput), { recursive: true })
|
|
78
46
|
|
|
79
|
-
console.info(
|
|
80
|
-
console.info(`📁 Input: ${resolvedInput}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
47
|
+
console.info('🚀 Compiling workflow')
|
|
48
|
+
console.info(`📁 Input: ${resolvedInput}`)
|
|
49
|
+
console.info(`🧪 JS out: ${resolvedJsOutput}`)
|
|
50
|
+
console.info(`🎯 WASM out:${resolvedWasmOutput}\n`)
|
|
84
51
|
|
|
85
|
-
// Step 1: TS/JS → JS (bundled)
|
|
86
52
|
console.info('📦 Step 1: Compiling JS...')
|
|
87
|
-
await compileToJs(resolvedInput, resolvedJsOutput
|
|
53
|
+
await compileToJs(resolvedInput, resolvedJsOutput)
|
|
88
54
|
|
|
89
|
-
// Step 2: JS → WASM
|
|
90
55
|
console.info('\n🔨 Step 2: Compiling to WASM...')
|
|
91
|
-
await compileToWasm(resolvedJsOutput, resolvedWasmOutput)
|
|
56
|
+
await compileToWasm(resolvedJsOutput, resolvedWasmOutput, creExports, plugin)
|
|
92
57
|
|
|
93
58
|
console.info(`\n✅ Workflow built: ${resolvedWasmOutput}`)
|
|
94
59
|
return resolvedWasmOutput
|
|
95
60
|
}
|
|
61
|
+
|
|
62
|
+
if (import.meta.main) {
|
|
63
|
+
main().catch((e) => {
|
|
64
|
+
console.error(e)
|
|
65
|
+
process.exit(1)
|
|
66
|
+
})
|
|
67
|
+
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'bun:test'
|
|
2
|
-
import { parseCompileCliArgs } from './compile-cli-args'
|
|
3
|
-
|
|
4
|
-
describe('parseCompileCliArgs', () => {
|
|
5
|
-
test('parses positional input and output', () => {
|
|
6
|
-
const parsed = parseCompileCliArgs(['src/workflow.ts', 'dist/workflow.wasm'])
|
|
7
|
-
expect(parsed).toEqual({
|
|
8
|
-
inputPath: 'src/workflow.ts',
|
|
9
|
-
outputPath: 'dist/workflow.wasm',
|
|
10
|
-
skipTypeChecks: false,
|
|
11
|
-
})
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
test('parses --skip-type-checks flag', () => {
|
|
15
|
-
const parsed = parseCompileCliArgs(['src/workflow.ts', '--skip-type-checks'])
|
|
16
|
-
expect(parsed).toEqual({
|
|
17
|
-
inputPath: 'src/workflow.ts',
|
|
18
|
-
outputPath: undefined,
|
|
19
|
-
skipTypeChecks: true,
|
|
20
|
-
})
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
test('throws on unknown flags', () => {
|
|
24
|
-
expect(() => parseCompileCliArgs(['src/workflow.ts', '--foo'])).toThrow('Unknown option: --foo')
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
test('throws on too many positional args', () => {
|
|
28
|
-
expect(() => parseCompileCliArgs(['src/workflow.ts', 'dist/workflow.wasm', 'extra'])).toThrow(
|
|
29
|
-
'Too many positional arguments.',
|
|
30
|
-
)
|
|
31
|
-
})
|
|
32
|
-
})
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export const skipTypeChecksFlag = '--skip-type-checks'
|
|
2
|
-
|
|
3
|
-
export type ParsedCompileArgs = {
|
|
4
|
-
inputPath?: string
|
|
5
|
-
outputPath?: string
|
|
6
|
-
skipTypeChecks: boolean
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const parseCompileCliArgs = (args: string[]): ParsedCompileArgs => {
|
|
10
|
-
const positionalArgs: string[] = []
|
|
11
|
-
let skipTypeChecks = false
|
|
12
|
-
|
|
13
|
-
for (const arg of args) {
|
|
14
|
-
if (arg === skipTypeChecksFlag) {
|
|
15
|
-
skipTypeChecks = true
|
|
16
|
-
continue
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (arg.startsWith('-')) {
|
|
20
|
-
throw new Error(`Unknown option: ${arg}`)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
positionalArgs.push(arg)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (positionalArgs.length > 2) {
|
|
27
|
-
throw new Error('Too many positional arguments.')
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
inputPath: positionalArgs[0],
|
|
32
|
-
outputPath: positionalArgs[1],
|
|
33
|
-
skipTypeChecks,
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
|
|
2
|
-
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
|
3
|
-
import path from 'node:path'
|
|
4
|
-
import { main as compileToJs } from './compile-to-js'
|
|
5
|
-
import { WorkflowTypecheckError } from './typecheck-workflow'
|
|
6
|
-
|
|
7
|
-
let tempDir: string
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
tempDir = mkdtempSync(path.join(process.cwd(), '.tmp-cre-compile-to-js-test-'))
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
afterEach(() => {
|
|
14
|
-
rmSync(tempDir, { recursive: true, force: true })
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
const writeTemp = (filename: string, content: string): string => {
|
|
18
|
-
const filePath = path.join(tempDir, filename)
|
|
19
|
-
mkdirSync(path.dirname(filePath), { recursive: true })
|
|
20
|
-
writeFileSync(filePath, content, 'utf-8')
|
|
21
|
-
return filePath
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
describe('compile-to-js typecheck behavior', () => {
|
|
25
|
-
test('fails on type errors by default', async () => {
|
|
26
|
-
writeTemp(
|
|
27
|
-
'tsconfig.json',
|
|
28
|
-
JSON.stringify(
|
|
29
|
-
{
|
|
30
|
-
compilerOptions: {
|
|
31
|
-
target: 'ES2022',
|
|
32
|
-
module: 'ESNext',
|
|
33
|
-
moduleResolution: 'Bundler',
|
|
34
|
-
skipLibCheck: true,
|
|
35
|
-
strict: true,
|
|
36
|
-
types: [],
|
|
37
|
-
lib: ['ESNext'],
|
|
38
|
-
},
|
|
39
|
-
include: ['src/**/*.ts'],
|
|
40
|
-
},
|
|
41
|
-
null,
|
|
42
|
-
2,
|
|
43
|
-
),
|
|
44
|
-
)
|
|
45
|
-
const entry = writeTemp('src/workflow.ts', "export const shouldBeNumber: number = 'oops'\n")
|
|
46
|
-
const output = path.join(tempDir, 'dist/workflow.js')
|
|
47
|
-
|
|
48
|
-
await expect(compileToJs(entry, output)).rejects.toBeInstanceOf(WorkflowTypecheckError)
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
test('continues when --skip-type-checks is enabled', async () => {
|
|
52
|
-
writeTemp(
|
|
53
|
-
'tsconfig.json',
|
|
54
|
-
JSON.stringify(
|
|
55
|
-
{
|
|
56
|
-
compilerOptions: {
|
|
57
|
-
target: 'ES2022',
|
|
58
|
-
module: 'ESNext',
|
|
59
|
-
moduleResolution: 'Bundler',
|
|
60
|
-
skipLibCheck: true,
|
|
61
|
-
strict: true,
|
|
62
|
-
types: [],
|
|
63
|
-
lib: ['ESNext'],
|
|
64
|
-
},
|
|
65
|
-
include: ['src/**/*.ts'],
|
|
66
|
-
},
|
|
67
|
-
null,
|
|
68
|
-
2,
|
|
69
|
-
),
|
|
70
|
-
)
|
|
71
|
-
const entry = writeTemp('src/workflow.ts', "export const shouldBeNumber: number = 'oops'\n")
|
|
72
|
-
const output = path.join(tempDir, 'dist/workflow.js')
|
|
73
|
-
|
|
74
|
-
let thrownError: unknown
|
|
75
|
-
let result: string | undefined
|
|
76
|
-
try {
|
|
77
|
-
result = await compileToJs(entry, output, {
|
|
78
|
-
skipTypeChecks: true,
|
|
79
|
-
})
|
|
80
|
-
} catch (error) {
|
|
81
|
-
thrownError = error
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
expect(thrownError).not.toBeInstanceOf(WorkflowTypecheckError)
|
|
85
|
-
if (typeof result === 'string') {
|
|
86
|
-
expect(result).toEqual(output)
|
|
87
|
-
expect(existsSync(output)).toBeTrue()
|
|
88
|
-
}
|
|
89
|
-
})
|
|
90
|
-
})
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
|
|
2
|
-
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
|
3
|
-
import { tmpdir } from 'node:os'
|
|
4
|
-
import path from 'node:path'
|
|
5
|
-
import { assertWorkflowTypecheck, WorkflowTypecheckError } from './typecheck-workflow'
|
|
6
|
-
|
|
7
|
-
let tempDir: string
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
tempDir = mkdtempSync(path.join(tmpdir(), 'cre-typecheck-test-'))
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
afterEach(() => {
|
|
14
|
-
rmSync(tempDir, { recursive: true, force: true })
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
const writeTemp = (filename: string, content: string): string => {
|
|
18
|
-
const filePath = path.join(tempDir, filename)
|
|
19
|
-
mkdirSync(path.dirname(filePath), { recursive: true })
|
|
20
|
-
writeFileSync(filePath, content, 'utf-8')
|
|
21
|
-
return filePath
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
describe('assertWorkflowTypecheck', () => {
|
|
25
|
-
test('passes for valid project using nearby tsconfig', () => {
|
|
26
|
-
writeTemp(
|
|
27
|
-
'tsconfig.json',
|
|
28
|
-
JSON.stringify(
|
|
29
|
-
{
|
|
30
|
-
compilerOptions: {
|
|
31
|
-
target: 'ES2022',
|
|
32
|
-
module: 'ESNext',
|
|
33
|
-
moduleResolution: 'Bundler',
|
|
34
|
-
skipLibCheck: true,
|
|
35
|
-
},
|
|
36
|
-
include: ['src/**/*.ts'],
|
|
37
|
-
},
|
|
38
|
-
null,
|
|
39
|
-
2,
|
|
40
|
-
),
|
|
41
|
-
)
|
|
42
|
-
const entry = writeTemp('src/workflow.ts', 'export const value: number = 42\n')
|
|
43
|
-
expect(() => assertWorkflowTypecheck(entry)).not.toThrow()
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
test('fails when tsconfig cannot be found', () => {
|
|
47
|
-
const entry = writeTemp('src/workflow.ts', 'export const value = 1\n')
|
|
48
|
-
expect(() => assertWorkflowTypecheck(entry)).toThrow(WorkflowTypecheckError)
|
|
49
|
-
expect(() => assertWorkflowTypecheck(entry)).toThrow('Could not find tsconfig.json')
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
test('fails on whole-project type errors outside entry file', () => {
|
|
53
|
-
writeTemp(
|
|
54
|
-
'tsconfig.json',
|
|
55
|
-
JSON.stringify(
|
|
56
|
-
{
|
|
57
|
-
compilerOptions: {
|
|
58
|
-
target: 'ES2022',
|
|
59
|
-
module: 'ESNext',
|
|
60
|
-
moduleResolution: 'Bundler',
|
|
61
|
-
skipLibCheck: true,
|
|
62
|
-
strict: true,
|
|
63
|
-
},
|
|
64
|
-
include: ['src/**/*.ts'],
|
|
65
|
-
},
|
|
66
|
-
null,
|
|
67
|
-
2,
|
|
68
|
-
),
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
const entry = writeTemp('src/workflow.ts', 'export const value: number = 1\n')
|
|
72
|
-
writeTemp('src/unrelated.ts', "export const shouldBeNumber: number = 'not-a-number'\n")
|
|
73
|
-
|
|
74
|
-
expect(() => assertWorkflowTypecheck(entry)).toThrow(WorkflowTypecheckError)
|
|
75
|
-
expect(() => assertWorkflowTypecheck(entry)).toThrow('unrelated.ts')
|
|
76
|
-
})
|
|
77
|
-
})
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
import * as ts from 'typescript'
|
|
3
|
-
import { skipTypeChecksFlag } from './compile-cli-args'
|
|
4
|
-
|
|
5
|
-
const toAbsolutePath = (filePath: string) => path.resolve(filePath)
|
|
6
|
-
|
|
7
|
-
const formatDiagnostic = (diagnostic: ts.Diagnostic): string => {
|
|
8
|
-
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')
|
|
9
|
-
if (!diagnostic.file || diagnostic.start == null) {
|
|
10
|
-
return message
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const absoluteFilePath = toAbsolutePath(diagnostic.file.fileName)
|
|
14
|
-
const relativeFilePath = path.relative(process.cwd(), absoluteFilePath)
|
|
15
|
-
const displayPath = relativeFilePath || absoluteFilePath
|
|
16
|
-
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start)
|
|
17
|
-
return `${displayPath}:${line + 1}:${character + 1} ${message}`
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
class WorkflowTypecheckError extends Error {
|
|
21
|
-
constructor(message: string) {
|
|
22
|
-
super(message)
|
|
23
|
-
this.name = 'WorkflowTypecheckError'
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const findNearestTsconfigPath = (entryFilePath: string): string | null => {
|
|
28
|
-
const configPath = ts.findConfigFile(
|
|
29
|
-
path.dirname(entryFilePath),
|
|
30
|
-
ts.sys.fileExists,
|
|
31
|
-
'tsconfig.json',
|
|
32
|
-
)
|
|
33
|
-
return configPath ?? null
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export const assertWorkflowTypecheck = (entryFilePath: string) => {
|
|
37
|
-
const rootFile = toAbsolutePath(entryFilePath)
|
|
38
|
-
const configPath = findNearestTsconfigPath(rootFile)
|
|
39
|
-
if (!configPath) {
|
|
40
|
-
throw new WorkflowTypecheckError(
|
|
41
|
-
`TypeScript typecheck failed before workflow compilation.
|
|
42
|
-
Could not find tsconfig.json near: ${rootFile}
|
|
43
|
-
Create a tsconfig.json in your workflow project, or re-run compile with ${skipTypeChecksFlag}.`,
|
|
44
|
-
)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
let unrecoverableDiagnostic: ts.Diagnostic | null = null
|
|
48
|
-
const parsedConfig = ts.getParsedCommandLineOfConfigFile(
|
|
49
|
-
configPath,
|
|
50
|
-
{},
|
|
51
|
-
{
|
|
52
|
-
...ts.sys,
|
|
53
|
-
onUnRecoverableConfigFileDiagnostic: (diagnostic) => {
|
|
54
|
-
unrecoverableDiagnostic = diagnostic
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
if (!parsedConfig) {
|
|
60
|
-
const details = unrecoverableDiagnostic ? formatDiagnostic(unrecoverableDiagnostic) : ''
|
|
61
|
-
throw new WorkflowTypecheckError(
|
|
62
|
-
`TypeScript typecheck failed before workflow compilation.
|
|
63
|
-
Failed to parse tsconfig.json: ${configPath}
|
|
64
|
-
${details}
|
|
65
|
-
Fix your tsconfig.json, or re-run compile with ${skipTypeChecksFlag}.`,
|
|
66
|
-
)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const program = ts.createProgram({
|
|
70
|
-
rootNames: parsedConfig.fileNames,
|
|
71
|
-
options: {
|
|
72
|
-
...parsedConfig.options,
|
|
73
|
-
noEmit: true,
|
|
74
|
-
},
|
|
75
|
-
projectReferences: parsedConfig.projectReferences,
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
const diagnostics = [...parsedConfig.errors, ...ts.getPreEmitDiagnostics(program)].filter(
|
|
79
|
-
(diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error,
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
if (diagnostics.length > 0) {
|
|
83
|
-
const formatted = diagnostics.map(formatDiagnostic).join('\n')
|
|
84
|
-
const relativeConfigPath = path.relative(process.cwd(), toAbsolutePath(configPath))
|
|
85
|
-
const displayConfigPath = relativeConfigPath || toAbsolutePath(configPath)
|
|
86
|
-
throw new WorkflowTypecheckError(
|
|
87
|
-
`TypeScript typecheck failed before workflow compilation.
|
|
88
|
-
Using tsconfig: ${displayConfigPath}
|
|
89
|
-
Fix TypeScript errors, or re-run compile with ${skipTypeChecksFlag}.
|
|
90
|
-
|
|
91
|
-
${formatted}`,
|
|
92
|
-
)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export { WorkflowTypecheckError }
|