@0xsequence/catapult 1.3.17 → 1.5.0
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 +276 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +1 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +12 -0
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/provenance.d.ts +3 -0
- package/dist/commands/provenance.d.ts.map +1 -0
- package/dist/commands/provenance.js +138 -0
- package/dist/commands/provenance.js.map +1 -0
- package/dist/lib/__tests__/deployer.spec.js +118 -1
- package/dist/lib/__tests__/deployer.spec.js.map +1 -1
- package/dist/lib/__tests__/network-loader.spec.js.map +1 -1
- package/dist/lib/__tests__/provenance.spec.d.ts +2 -0
- package/dist/lib/__tests__/provenance.spec.d.ts.map +1 -0
- package/dist/lib/__tests__/provenance.spec.js +205 -0
- package/dist/lib/__tests__/provenance.spec.js.map +1 -0
- package/dist/lib/contracts/__tests__/repository.spec.js +243 -0
- package/dist/lib/contracts/__tests__/repository.spec.js.map +1 -1
- package/dist/lib/contracts/repository.d.ts +9 -1
- package/dist/lib/contracts/repository.d.ts.map +1 -1
- package/dist/lib/contracts/repository.js +93 -7
- package/dist/lib/contracts/repository.js.map +1 -1
- package/dist/lib/core/__tests__/assert-action.spec.d.ts +2 -0
- package/dist/lib/core/__tests__/assert-action.spec.d.ts.map +1 -0
- package/dist/lib/core/__tests__/assert-action.spec.js +377 -0
- package/dist/lib/core/__tests__/assert-action.spec.js.map +1 -0
- package/dist/lib/core/__tests__/engine.spec.js +80 -0
- package/dist/lib/core/__tests__/engine.spec.js.map +1 -1
- package/dist/lib/core/__tests__/loader.spec.js +29 -0
- package/dist/lib/core/__tests__/loader.spec.js.map +1 -1
- package/dist/lib/core/__tests__/resolver.spec.js +405 -0
- package/dist/lib/core/__tests__/resolver.spec.js.map +1 -1
- package/dist/lib/core/__tests__/sign-actions.spec.d.ts +2 -0
- package/dist/lib/core/__tests__/sign-actions.spec.d.ts.map +1 -0
- package/dist/lib/core/__tests__/sign-actions.spec.js +128 -0
- package/dist/lib/core/__tests__/sign-actions.spec.js.map +1 -0
- package/dist/lib/core/__tests__/signer.spec.d.ts +2 -0
- package/dist/lib/core/__tests__/signer.spec.d.ts.map +1 -0
- package/dist/lib/core/__tests__/signer.spec.js +40 -0
- package/dist/lib/core/__tests__/signer.spec.js.map +1 -0
- package/dist/lib/core/context.d.ts +3 -2
- package/dist/lib/core/context.d.ts.map +1 -1
- package/dist/lib/core/context.js +3 -2
- package/dist/lib/core/context.js.map +1 -1
- package/dist/lib/core/engine.d.ts +4 -0
- package/dist/lib/core/engine.d.ts.map +1 -1
- package/dist/lib/core/engine.js +206 -0
- package/dist/lib/core/engine.js.map +1 -1
- package/dist/lib/core/loader.d.ts +1 -0
- package/dist/lib/core/loader.d.ts.map +1 -1
- package/dist/lib/core/loader.js +6 -1
- package/dist/lib/core/loader.js.map +1 -1
- package/dist/lib/core/resolver.d.ts +2 -0
- package/dist/lib/core/resolver.d.ts.map +1 -1
- package/dist/lib/core/resolver.js +89 -0
- package/dist/lib/core/resolver.js.map +1 -1
- package/dist/lib/core/signer.d.ts +7 -0
- package/dist/lib/core/signer.d.ts.map +1 -0
- package/dist/lib/core/signer.js +60 -0
- package/dist/lib/core/signer.js.map +1 -0
- package/dist/lib/deployer.d.ts.map +1 -1
- package/dist/lib/deployer.js +21 -4
- package/dist/lib/deployer.js.map +1 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +1 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/parsers/__tests__/job.spec.js +77 -0
- package/dist/lib/parsers/__tests__/job.spec.js.map +1 -1
- package/dist/lib/parsers/__tests__/source.spec.d.ts +2 -0
- package/dist/lib/parsers/__tests__/source.spec.d.ts.map +1 -0
- package/dist/lib/parsers/__tests__/source.spec.js +158 -0
- package/dist/lib/parsers/__tests__/source.spec.js.map +1 -0
- package/dist/lib/parsers/index.d.ts +1 -0
- package/dist/lib/parsers/index.d.ts.map +1 -1
- package/dist/lib/parsers/index.js +1 -0
- package/dist/lib/parsers/index.js.map +1 -1
- package/dist/lib/parsers/job.d.ts.map +1 -1
- package/dist/lib/parsers/job.js +11 -0
- package/dist/lib/parsers/job.js.map +1 -1
- package/dist/lib/parsers/source.d.ts +4 -0
- package/dist/lib/parsers/source.d.ts.map +1 -0
- package/dist/lib/parsers/source.js +107 -0
- package/dist/lib/parsers/source.js.map +1 -0
- package/dist/lib/provenance.d.ts +34 -0
- package/dist/lib/provenance.d.ts.map +1 -0
- package/dist/lib/provenance.js +694 -0
- package/dist/lib/provenance.js.map +1 -0
- package/dist/lib/types/actions.d.ts +42 -2
- package/dist/lib/types/actions.d.ts.map +1 -1
- package/dist/lib/types/actions.js +4 -0
- package/dist/lib/types/actions.js.map +1 -1
- package/dist/lib/types/contracts.d.ts +3 -0
- package/dist/lib/types/contracts.d.ts.map +1 -1
- package/dist/lib/types/definitions.d.ts +1 -0
- package/dist/lib/types/definitions.d.ts.map +1 -1
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/index.d.ts.map +1 -1
- package/dist/lib/types/index.js +1 -0
- package/dist/lib/types/index.js.map +1 -1
- package/dist/lib/types/source.d.ts +26 -0
- package/dist/lib/types/source.d.ts.map +1 -0
- package/dist/lib/types/source.js +3 -0
- package/dist/lib/types/source.js.map +1 -0
- package/dist/lib/types/values.d.ts +33 -1
- package/dist/lib/types/values.d.ts.map +1 -1
- package/package.json +4 -1
- package/.eslintrc.json +0 -29
- package/.github/workflows/ci.yml +0 -181
- package/CONCEPT.md +0 -24
- package/contracts/checked-call.huff +0 -65
- package/eslint.config.js +0 -48
- package/examples/jobs/guards-v1.yaml +0 -17
- package/examples/jobs/sequence-seq-0001-patch.yaml +0 -59
- package/examples/jobs/sequence-v1.yaml +0 -59
- package/examples/templates/sequence-factory-v1.yaml +0 -56
- package/jest.config.js +0 -25
- package/src/cli.ts +0 -17
- package/src/commands/common.ts +0 -61
- package/src/commands/dry.ts +0 -209
- package/src/commands/etherscan.ts +0 -360
- package/src/commands/index.ts +0 -5
- package/src/commands/list.ts +0 -249
- package/src/commands/run.ts +0 -146
- package/src/commands/utils.ts +0 -215
- package/src/index.ts +0 -67
- package/src/lib/__tests__/deployer-events.spec.ts +0 -338
- package/src/lib/__tests__/deployer.spec.ts +0 -2093
- package/src/lib/__tests__/network-loader.spec.ts +0 -150
- package/src/lib/__tests__/network-selection.spec.ts +0 -41
- package/src/lib/__tests__/network-utils.spec.ts +0 -230
- package/src/lib/artifacts/__tests__/fixtures/contract1.json +0 -19
- package/src/lib/artifacts/__tests__/fixtures/contract2.json +0 -19
- package/src/lib/artifacts/__tests__/fixtures/duplicate-name.json +0 -19
- package/src/lib/artifacts/__tests__/fixtures/nested/nested-contract.json +0 -18
- package/src/lib/artifacts/__tests__/fixtures/not-an-artifact.json +0 -8
- package/src/lib/artifacts/__tests__/fixtures/readme.txt +0 -2
- package/src/lib/contracts/__tests__/repository.spec.ts +0 -344
- package/src/lib/contracts/repository.ts +0 -313
- package/src/lib/core/__tests__/context.spec.ts +0 -37
- package/src/lib/core/__tests__/engine.spec.ts +0 -1889
- package/src/lib/core/__tests__/graph.spec.ts +0 -125
- package/src/lib/core/__tests__/json-integration.spec.ts +0 -425
- package/src/lib/core/__tests__/loader.spec.ts +0 -334
- package/src/lib/core/__tests__/multi-platform-verification.spec.ts +0 -406
- package/src/lib/core/__tests__/resolver.spec.ts +0 -2053
- package/src/lib/core/__tests__/static-action.spec.ts +0 -172
- package/src/lib/core/context.ts +0 -127
- package/src/lib/core/engine.ts +0 -1782
- package/src/lib/core/graph.ts +0 -252
- package/src/lib/core/loader.ts +0 -247
- package/src/lib/core/resolver.ts +0 -757
- package/src/lib/deployer.ts +0 -981
- package/src/lib/events/__tests__/event-system.spec.ts +0 -392
- package/src/lib/events/cli-adapter.ts +0 -369
- package/src/lib/events/emitter.ts +0 -62
- package/src/lib/events/index.ts +0 -3
- package/src/lib/events/types.ts +0 -520
- package/src/lib/index.ts +0 -14
- package/src/lib/network-loader.ts +0 -90
- package/src/lib/network-selection.ts +0 -73
- package/src/lib/network-utils.ts +0 -64
- package/src/lib/parsers/__tests__/buildinfo.spec.ts +0 -122
- package/src/lib/parsers/__tests__/fixtures/buildinfo/invalid-bytecode-buildinfo.json +0 -62
- package/src/lib/parsers/__tests__/fixtures/buildinfo/invalid-json.txt +0 -2
- package/src/lib/parsers/__tests__/fixtures/buildinfo/multi-contract-buildinfo.json +0 -89
- package/src/lib/parsers/__tests__/fixtures/buildinfo/no-contracts-buildinfo.json +0 -17
- package/src/lib/parsers/__tests__/fixtures/buildinfo/simple-buildinfo.json +0 -63
- package/src/lib/parsers/__tests__/fixtures/buildinfo/wrong-format.json +0 -4
- package/src/lib/parsers/__tests__/job.spec.ts +0 -358
- package/src/lib/parsers/__tests__/template.spec.ts +0 -111
- package/src/lib/parsers/artifact/__tests__/artifact.spec.ts +0 -117
- package/src/lib/parsers/artifact/__tests__/fixtures/empty-bytecode.json +0 -5
- package/src/lib/parsers/artifact/__tests__/fixtures/hardhat-artifact.json +0 -67
- package/src/lib/parsers/artifact/__tests__/fixtures/invalid-bytecode.json +0 -5
- package/src/lib/parsers/artifact/__tests__/fixtures/invalid-json.txt +0 -11
- package/src/lib/parsers/artifact/__tests__/fixtures/minimal-artifact.json +0 -5
- package/src/lib/parsers/artifact/__tests__/fixtures/missing-abi.json +0 -4
- package/src/lib/parsers/artifact/__tests__/fixtures/missing-bytecode.json +0 -11
- package/src/lib/parsers/artifact/__tests__/fixtures/missing-contract-name.json +0 -11
- package/src/lib/parsers/artifact/__tests__/fixtures/simple-artifact.json +0 -40
- package/src/lib/parsers/artifact/__tests__/fixtures/wrong-types.json +0 -7
- package/src/lib/parsers/artifact/foundry-1.2.ts +0 -72
- package/src/lib/parsers/artifact/index.ts +0 -27
- package/src/lib/parsers/artifact/types.ts +0 -9
- package/src/lib/parsers/buildinfo.ts +0 -127
- package/src/lib/parsers/constants.ts +0 -56
- package/src/lib/parsers/index.ts +0 -5
- package/src/lib/parsers/job.ts +0 -148
- package/src/lib/parsers/template.ts +0 -135
- package/src/lib/std/templates/arachnid-deterministic-deployment-proxy.yaml +0 -68
- package/src/lib/std/templates/assured-deployment.yaml +0 -46
- package/src/lib/std/templates/era-evm-predeploy.yaml +0 -35
- package/src/lib/std/templates/erc-2470.yaml +0 -70
- package/src/lib/std/templates/min-balance.yaml +0 -35
- package/src/lib/std/templates/nano-universal-deployer.yaml +0 -61
- package/src/lib/std/templates/raw-erc-2470.yaml +0 -62
- package/src/lib/std/templates/raw-nano-universal-deployer.yaml +0 -54
- package/src/lib/std/templates/raw-sequence-universal-deployer-2.yaml +0 -52
- package/src/lib/std/templates/sequence-universal-deployer-2.yaml +0 -61
- package/src/lib/types/__tests__/json-request-action.spec.ts +0 -243
- package/src/lib/types/__tests__/read-json-value.spec.ts +0 -278
- package/src/lib/types/__tests__/resolve-json-value.spec.ts +0 -769
- package/src/lib/types/actions.ts +0 -127
- package/src/lib/types/artifacts.ts +0 -21
- package/src/lib/types/buildinfo.ts +0 -116
- package/src/lib/types/conditions.ts +0 -50
- package/src/lib/types/contracts.ts +0 -23
- package/src/lib/types/definitions.ts +0 -70
- package/src/lib/types/index.ts +0 -8
- package/src/lib/types/network.ts +0 -33
- package/src/lib/types/project.ts +0 -9
- package/src/lib/types/task.ts +0 -9
- package/src/lib/types/values.ts +0 -150
- package/src/lib/utils/assertion.ts +0 -24
- package/src/lib/utils/validation.ts +0 -116
- package/src/lib/validation/contract-references.ts +0 -210
- package/src/lib/validation/index.ts +0 -1
- package/src/lib/verification/__tests__/etherscan.spec.ts +0 -710
- package/src/lib/verification/__tests__/sourcify.spec.ts +0 -288
- package/src/lib/verification/etherscan.ts +0 -547
- package/src/lib/verification/sourcify.ts +0 -248
- package/test_validation/artifacts/TestContract.json +0 -9
- package/test_validation/jobs/test-missing.yaml +0 -16
- package/test_validation/networks.yaml +0 -3
- package/tsconfig.json +0 -36
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"contractName": "SimpleToken",
|
|
3
|
-
"abi": [
|
|
4
|
-
{
|
|
5
|
-
"type": "constructor",
|
|
6
|
-
"inputs": [
|
|
7
|
-
{
|
|
8
|
-
"name": "name",
|
|
9
|
-
"type": "string"
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"name": "symbol",
|
|
13
|
-
"type": "string"
|
|
14
|
-
}
|
|
15
|
-
]
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
"type": "function",
|
|
19
|
-
"name": "transfer",
|
|
20
|
-
"inputs": [
|
|
21
|
-
{
|
|
22
|
-
"name": "to",
|
|
23
|
-
"type": "address"
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"name": "amount",
|
|
27
|
-
"type": "uint256"
|
|
28
|
-
}
|
|
29
|
-
],
|
|
30
|
-
"outputs": [
|
|
31
|
-
{
|
|
32
|
-
"name": "",
|
|
33
|
-
"type": "bool"
|
|
34
|
-
}
|
|
35
|
-
]
|
|
36
|
-
}
|
|
37
|
-
],
|
|
38
|
-
"bytecode": "0x608060405234801561001057600080fd5b506040516103e93803806103e98339818101604052810190610032919061007a565b80600090805190602001906100489291906100ad565b50506100fb565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6100a982610060565b810181811067ffffffffffffffff821117156100c8576100c7610071565b5b80604052505050565b60006100db6100a0565b90506100e782826100a0565b919050565b6000819050919050565b6100ff816100ec565b811461010a57600080fd5b50565b60008151905061011c816100f6565b92915050565b6000602082840312156101385761013761005b565b5b60006101468482850161010d565b91505092915050565b6102df8061015f6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a9059cbb1461003b578063dd62ed3e14610057575b600080fd5b61005560048036038101906100509190610123565b610087565b005b610071600480360381019061006c9190610163565b6100a1565b60405161007e91906101b2565b60405180910390f35b6000610094338484610121565b50505050565b50565b600082600082815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a26469706673582212206a",
|
|
39
|
-
"deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a9059cbb1461003b578063dd62ed3e14610057575b600080fd5b61005560048036038101906100509190610123565b610087565b005b610071600480360381019061006c9190610163565b6100a1565b60405161007e91906101b2565b60405180910390f35b6000610094338484610121565b50505050565b50565b600082600082815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a26469706673582212206a"
|
|
40
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { ArtifactParser } from './types'
|
|
2
|
-
import { Artifact } from '../../types'
|
|
3
|
-
import * as path from 'path'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* A parser for Foundry 1.2+ artifact format.
|
|
7
|
-
* Can handle artifacts with or without explicit "contractName" field.
|
|
8
|
-
* If no contractName is present, it attempts to extract it from:
|
|
9
|
-
* 1. metadata.settings.compilationTarget
|
|
10
|
-
* 2. The filename as a fallback
|
|
11
|
-
*/
|
|
12
|
-
export const foundry12Parser: ArtifactParser = (content: string, filePath: string): Omit<Artifact, '_path' | '_hash'> | null => {
|
|
13
|
-
try {
|
|
14
|
-
const json = JSON.parse(content)
|
|
15
|
-
|
|
16
|
-
// Basic validation to see if it matches our expected structure
|
|
17
|
-
if (
|
|
18
|
-
typeof json === 'object' &&
|
|
19
|
-
json !== null &&
|
|
20
|
-
Array.isArray(json.abi) &&
|
|
21
|
-
(typeof json.bytecode === 'string' || (typeof json.bytecode === 'object' && typeof json.bytecode.object === 'string'))
|
|
22
|
-
) {
|
|
23
|
-
// Handle Hardhat-style bytecode object vs. simple string
|
|
24
|
-
const bytecode = typeof json.bytecode === 'object' ? json.bytecode.object : json.bytecode
|
|
25
|
-
if (!bytecode || !bytecode.startsWith('0x')) {
|
|
26
|
-
return null // Bytecode must be a hex string
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const deployedBytecode = typeof json.deployedBytecode === 'object' ? json.deployedBytecode?.object : json.deployedBytecode
|
|
30
|
-
|
|
31
|
-
// Extract contract name from various sources
|
|
32
|
-
let contractName = json.contractName
|
|
33
|
-
|
|
34
|
-
// If no explicit contractName, prefer filename over metadata to match file-based lookups
|
|
35
|
-
if (!contractName && filePath) {
|
|
36
|
-
const basename = path.basename(filePath, '.json')
|
|
37
|
-
contractName = basename
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// If still no contract name, try to extract from metadata as fallback
|
|
41
|
-
if (!contractName && json.metadata?.settings?.compilationTarget) {
|
|
42
|
-
const compilationTarget = json.metadata.settings.compilationTarget
|
|
43
|
-
// compilationTarget is like {"src/Counter.sol": "Counter"}
|
|
44
|
-
const contractNames = Object.values(compilationTarget)
|
|
45
|
-
if (contractNames.length > 0) {
|
|
46
|
-
contractName = contractNames[0]
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Must have a contract name to proceed
|
|
51
|
-
if (!contractName) {
|
|
52
|
-
return null
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// We have a likely match
|
|
56
|
-
return {
|
|
57
|
-
contractName: contractName,
|
|
58
|
-
sourceName: json.sourceName,
|
|
59
|
-
abi: json.abi,
|
|
60
|
-
bytecode: bytecode,
|
|
61
|
-
deployedBytecode: deployedBytecode,
|
|
62
|
-
compiler: json.compiler,
|
|
63
|
-
source: json.source,
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return null
|
|
68
|
-
} catch (error) {
|
|
69
|
-
// Not valid JSON, so it's not for this parser
|
|
70
|
-
return null
|
|
71
|
-
}
|
|
72
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { ArtifactParser } from './types'
|
|
2
|
-
import { foundry12Parser } from './foundry-1.2'
|
|
3
|
-
import { Artifact } from '../../types'
|
|
4
|
-
|
|
5
|
-
// Array of all available artifact parsers.
|
|
6
|
-
// To add a new format, create a new parser and add it to this list.
|
|
7
|
-
const parsers: ArtifactParser[] = [
|
|
8
|
-
foundry12Parser,
|
|
9
|
-
// Future parsers (e.g., truffleParser) would go here.
|
|
10
|
-
]
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Attempts to parse a file's content using a series of registered parsers.
|
|
14
|
-
* Returns the first successfully parsed Artifact.
|
|
15
|
-
* @param content The raw string content of the file.
|
|
16
|
-
* @param filePath The path to the file being parsed.
|
|
17
|
-
* @returns A parsed Artifact object or null if no parser succeeds.
|
|
18
|
-
*/
|
|
19
|
-
export function parseArtifact(content: string, filePath: string): Omit<Artifact, '_path' | '_hash'> | null {
|
|
20
|
-
for (const parser of parsers) {
|
|
21
|
-
const result = parser(content, filePath)
|
|
22
|
-
if (result) {
|
|
23
|
-
return result
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return null
|
|
27
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Artifact } from '../../types'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A function that attempts to parse a file's content into a standard Artifact object.
|
|
5
|
-
* @param content The raw string content of the file.
|
|
6
|
-
* @param filePath The path to the file being parsed.
|
|
7
|
-
* @returns An object conforming to the Artifact interface (without internal properties), or null if parsing fails.
|
|
8
|
-
*/
|
|
9
|
-
export type ArtifactParser = (content: string, filePath: string) => Omit<Artifact, '_path' | '_hash'> | null
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'crypto'
|
|
2
|
-
import { keccak256, toUtf8Bytes } from 'ethers'
|
|
3
|
-
import { BuildInfo, ExtractedContract } from '../types'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Validates if a parsed object is a valid build-info file
|
|
7
|
-
* Supports standard build-info formats and factory-style formats
|
|
8
|
-
*/
|
|
9
|
-
function isValidBuildInfo(data: any): data is BuildInfo {
|
|
10
|
-
return (
|
|
11
|
-
data &&
|
|
12
|
-
typeof data === 'object' &&
|
|
13
|
-
// _format field is optional (for factory-style formats)
|
|
14
|
-
(data._format === undefined || data._format === 'hh-sol-build-info-1' || data._format === 'ethers-rs-sol-build-info-1') &&
|
|
15
|
-
typeof data.id === 'string' &&
|
|
16
|
-
typeof data.solcVersion === 'string' &&
|
|
17
|
-
// solcLongVersion is optional (for factory-style formats)
|
|
18
|
-
(data.solcLongVersion === undefined || typeof data.solcLongVersion === 'string') &&
|
|
19
|
-
data.input &&
|
|
20
|
-
typeof data.input === 'object' &&
|
|
21
|
-
data.output &&
|
|
22
|
-
typeof data.output === 'object' &&
|
|
23
|
-
data.output.contracts &&
|
|
24
|
-
typeof data.output.contracts === 'object'
|
|
25
|
-
)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Parses a build-info file and extracts individual contracts
|
|
30
|
-
* @param content The raw string content of the build-info file
|
|
31
|
-
* @param filePath The path to the build-info file
|
|
32
|
-
* @returns Array of extracted contracts or null if parsing fails
|
|
33
|
-
*/
|
|
34
|
-
export function parseBuildInfo(content: string, filePath: string): ExtractedContract[] | null {
|
|
35
|
-
try {
|
|
36
|
-
const data = JSON.parse(content)
|
|
37
|
-
|
|
38
|
-
if (!isValidBuildInfo(data)) {
|
|
39
|
-
return null
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const extractedContracts: ExtractedContract[] = []
|
|
43
|
-
|
|
44
|
-
// Extract contracts from output.contracts
|
|
45
|
-
for (const [sourceName, sourceContracts] of Object.entries(data.output.contracts)) {
|
|
46
|
-
for (const [contractName, contractData] of Object.entries(sourceContracts)) {
|
|
47
|
-
// Validate contract data
|
|
48
|
-
if (!contractData.abi || !Array.isArray(contractData.abi)) {
|
|
49
|
-
continue
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Handle both Hardhat format (with 0x prefix) and ethers-rs format (without 0x prefix)
|
|
53
|
-
if (!contractData.evm?.bytecode?.object ||
|
|
54
|
-
(!contractData.evm.bytecode.object.startsWith('0x') && !/^[0-9a-fA-F]+$/.test(contractData.evm.bytecode.object))) {
|
|
55
|
-
continue
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Get source content if available
|
|
59
|
-
const sourceContent = data.input.sources[sourceName]?.content
|
|
60
|
-
|
|
61
|
-
// Normalize bytecode to ensure it has 0x prefix (required by the rest of the system)
|
|
62
|
-
const bytecode = contractData.evm.bytecode.object.startsWith('0x')
|
|
63
|
-
? contractData.evm.bytecode.object
|
|
64
|
-
: '0x' + contractData.evm.bytecode.object
|
|
65
|
-
|
|
66
|
-
const deployedBytecode = contractData.evm.deployedBytecode?.object
|
|
67
|
-
? (contractData.evm.deployedBytecode.object.startsWith('0x')
|
|
68
|
-
? contractData.evm.deployedBytecode.object
|
|
69
|
-
: '0x' + contractData.evm.deployedBytecode.object)
|
|
70
|
-
: undefined
|
|
71
|
-
|
|
72
|
-
// Create the extracted contract
|
|
73
|
-
const extractedContract: ExtractedContract = {
|
|
74
|
-
contractName,
|
|
75
|
-
sourceName,
|
|
76
|
-
fullyQualifiedName: `${sourceName}:${contractName}`,
|
|
77
|
-
abi: contractData.abi,
|
|
78
|
-
bytecode,
|
|
79
|
-
deployedBytecode,
|
|
80
|
-
source: sourceContent,
|
|
81
|
-
compiler: {
|
|
82
|
-
// Use solcLongVersion if available, otherwise fallback to solcVersion
|
|
83
|
-
version: data.solcLongVersion || data.solcVersion
|
|
84
|
-
},
|
|
85
|
-
buildInfoId: data.id,
|
|
86
|
-
buildInfoPath: filePath
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
extractedContracts.push(extractedContract)
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return extractedContracts.length > 0 ? extractedContracts : null
|
|
94
|
-
|
|
95
|
-
} catch (error) {
|
|
96
|
-
// Not valid JSON or other parsing error
|
|
97
|
-
return null
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Checks if a file path looks like a build-info file
|
|
103
|
-
* Follows the conventions: artifacts/build-info/*.json or out/build-info/*.json
|
|
104
|
-
*/
|
|
105
|
-
export function isBuildInfoFile(filePath: string): boolean {
|
|
106
|
-
// Standard build-info file patterns
|
|
107
|
-
if (filePath.includes('/build-info/') && filePath.endsWith('.json')) {
|
|
108
|
-
return true
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return false
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Converts an ExtractedContract to an Artifact-compatible format
|
|
116
|
-
*/
|
|
117
|
-
export function extractedContractToArtifact(extracted: ExtractedContract): Omit<import('../types').Artifact, '_path' | '_hash'> {
|
|
118
|
-
return {
|
|
119
|
-
contractName: extracted.contractName,
|
|
120
|
-
abi: extracted.abi,
|
|
121
|
-
bytecode: extracted.bytecode,
|
|
122
|
-
deployedBytecode: extracted.deployedBytecode,
|
|
123
|
-
sourceName: extracted.sourceName,
|
|
124
|
-
source: extracted.source,
|
|
125
|
-
compiler: extracted.compiler
|
|
126
|
-
}
|
|
127
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { parse as parseYaml, YAMLParseError } from 'yaml'
|
|
2
|
-
import { ConstantsDocument } from '../types'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Parses a YAML string defining a constants document into a structured ConstantsDocument.
|
|
6
|
-
* Accepts files with `type: "constants"`, optional `name`, and required `constants` object.
|
|
7
|
-
* Returns null if the YAML is not a constants document.
|
|
8
|
-
*/
|
|
9
|
-
export function parseConstants(yamlContent: string): ConstantsDocument | null {
|
|
10
|
-
let rawObject: any
|
|
11
|
-
try {
|
|
12
|
-
rawObject = parseYaml(yamlContent)
|
|
13
|
-
} catch (e) {
|
|
14
|
-
if (e instanceof YAMLParseError) {
|
|
15
|
-
const line = (e as any).linePos?.[0]?.line ? ` at line ${(e as any).linePos[0].line}` : ''
|
|
16
|
-
throw new Error(`Failed to parse constants YAML: ${e.message}${line}.`)
|
|
17
|
-
}
|
|
18
|
-
throw e
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (!rawObject || typeof rawObject !== 'object') {
|
|
22
|
-
return null
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (rawObject.type !== 'constants') {
|
|
26
|
-
return null
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (rawObject.name !== undefined && typeof rawObject.name !== 'string') {
|
|
30
|
-
throw new Error('Invalid constants: "name" must be a string if provided.')
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (!rawObject.constants || typeof rawObject.constants !== 'object' || Array.isArray(rawObject.constants)) {
|
|
34
|
-
throw new Error('Invalid constants: "constants" field is required and must be an object.')
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const doc: ConstantsDocument = {
|
|
38
|
-
type: 'constants',
|
|
39
|
-
name: rawObject.name,
|
|
40
|
-
constants: rawObject.constants
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return doc
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Validates and extracts optional job-level constants from a parsed job raw object.
|
|
48
|
-
* Throws if present but not an object.
|
|
49
|
-
*/
|
|
50
|
-
export function extractJobConstants(rawJob: any, jobNameForErrors: string): Record<string, any> | undefined {
|
|
51
|
-
if (rawJob.constants === undefined) return undefined
|
|
52
|
-
if (typeof rawJob.constants !== 'object' || Array.isArray(rawJob.constants)) {
|
|
53
|
-
throw new Error(`Invalid job "${jobNameForErrors}": "constants" field must be an object if provided.`)
|
|
54
|
-
}
|
|
55
|
-
return rawJob.constants as Record<string, any>
|
|
56
|
-
}
|
package/src/lib/parsers/index.ts
DELETED
package/src/lib/parsers/job.ts
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { parse as parseYaml, YAMLParseError } from 'yaml'
|
|
2
|
-
import { Condition, Job, JobAction } from '../types'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Determines whether a raw YAML item is a valid Condition.
|
|
6
|
-
* Mirrors the validation logic used for templates so job-level
|
|
7
|
-
* skip conditions behave consistently.
|
|
8
|
-
*/
|
|
9
|
-
function isCondition(item: any): item is Condition {
|
|
10
|
-
if (!item || typeof item !== 'object' || typeof item.type !== 'string') {
|
|
11
|
-
return false
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
if (['contract-exists', 'job-completed'].includes(item.type)) {
|
|
15
|
-
return true
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (item.type === 'basic-arithmetic') {
|
|
19
|
-
const op = item.arguments?.operation
|
|
20
|
-
return typeof op === 'string' && ['eq', 'neq', 'gt', 'lt', 'gte', 'lte'].includes(op)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return false
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Parses a YAML string defining a job into a structured `Job` object.
|
|
28
|
-
* This function validates the presence and basic types of required fields
|
|
29
|
-
* for both the job and its nested actions.
|
|
30
|
-
*
|
|
31
|
-
* @param yamlContent The raw YAML content of the job file as a string.
|
|
32
|
-
* @returns The parsed and validated `Job` object.
|
|
33
|
-
* @throws {Error} If the YAML is malformed or if the job is missing required fields.
|
|
34
|
-
*/
|
|
35
|
-
export function parseJob(yamlContent: string): Job {
|
|
36
|
-
let rawObject: any
|
|
37
|
-
try {
|
|
38
|
-
rawObject = parseYaml(yamlContent)
|
|
39
|
-
} catch (e) {
|
|
40
|
-
if (e instanceof YAMLParseError) {
|
|
41
|
-
const line = e.linePos?.[0].line ? ` at line ${e.linePos[0].line}` : ''
|
|
42
|
-
throw new Error(`Failed to parse job YAML: ${e.message}${line}.`)
|
|
43
|
-
}
|
|
44
|
-
throw e
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (!rawObject || typeof rawObject !== 'object') {
|
|
48
|
-
throw new Error('Invalid job: YAML content must resolve to an object.')
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// If a top-level discriminator exists and is not a job, bail out early with a helpful error
|
|
52
|
-
if (rawObject.type && rawObject.type !== 'job') {
|
|
53
|
-
throw new Error('Invalid job: unexpected type discriminator. Did you mean a template file with type: "template"?')
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// --- Validate required top-level fields ---
|
|
57
|
-
if (!rawObject.name || typeof rawObject.name !== 'string') {
|
|
58
|
-
throw new Error('Invalid job: "name" field is required and must be a string.')
|
|
59
|
-
}
|
|
60
|
-
// The YAML parser may interpret a version like "1.0" as a number, so we ensure it's a string.
|
|
61
|
-
if (!rawObject.version) {
|
|
62
|
-
throw new Error(`Invalid job "${rawObject.name}": "version" field is required.`)
|
|
63
|
-
}
|
|
64
|
-
rawObject.version = String(rawObject.version)
|
|
65
|
-
|
|
66
|
-
if (!rawObject.actions || !Array.isArray(rawObject.actions)) {
|
|
67
|
-
throw new Error(`Invalid job "${rawObject.name}": "actions" field is required and must be an array.`)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// --- Validate each action within the job ---
|
|
71
|
-
for (const action of rawObject.actions) {
|
|
72
|
-
if (!action || typeof action !== 'object') {
|
|
73
|
-
throw new Error(`Invalid job "${rawObject.name}": contains a non-object item in "actions" array.`)
|
|
74
|
-
}
|
|
75
|
-
if (!action.name || typeof action.name !== 'string') {
|
|
76
|
-
throw new Error(`Invalid job "${rawObject.name}": an action is missing the required "name" field.`)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Validate that the action has either a template or type field, but not both
|
|
80
|
-
const hasTemplate = action.template && typeof action.template === 'string'
|
|
81
|
-
const hasType = action.type && typeof action.type === 'string'
|
|
82
|
-
|
|
83
|
-
if (!hasTemplate && !hasType) {
|
|
84
|
-
throw new Error(`Invalid job "${rawObject.name}": action "${action.name}" must have either a "template" field (for template actions) or a "type" field (for primitive actions).`)
|
|
85
|
-
}
|
|
86
|
-
if (hasTemplate && hasType) {
|
|
87
|
-
throw new Error(`Invalid job "${rawObject.name}": action "${action.name}" cannot have both "template" and "type" fields. Use only one.`)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (!action.arguments || typeof action.arguments !== 'object' || Array.isArray(action.arguments)) {
|
|
91
|
-
throw new Error(`Invalid job "${rawObject.name}": action "${action.name}" is missing the required "arguments" field or it is not an object.`)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Validate the optional output field
|
|
95
|
-
if (action.output !== undefined) {
|
|
96
|
-
const t = typeof action.output
|
|
97
|
-
const isObject = t === 'object' && action.output !== null && !Array.isArray(action.output)
|
|
98
|
-
if (t !== 'boolean' && !isObject) {
|
|
99
|
-
throw new Error(`Invalid job "${rawObject.name}": action "${action.name}" has an invalid "output" field. It must be either a boolean (true/false) or an object mapping custom outputs.`)
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// --- Optional: validate deprecated flag if present ---
|
|
105
|
-
if (rawObject.deprecated !== undefined && typeof rawObject.deprecated !== 'boolean') {
|
|
106
|
-
throw new Error(`Invalid job "${rawObject.name}": "deprecated" must be a boolean if provided.`)
|
|
107
|
-
}
|
|
108
|
-
// --- Optional: validate min_evm_version if present ---
|
|
109
|
-
if (rawObject.min_evm_version !== undefined && typeof rawObject.min_evm_version !== 'string') {
|
|
110
|
-
throw new Error(`Invalid job "${rawObject.name}": "min_evm_version" must be a string if provided.`)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// --- Optional: validate job-level skip_condition and constants ---
|
|
114
|
-
if (rawObject.skip_condition !== undefined) {
|
|
115
|
-
if (!Array.isArray(rawObject.skip_condition)) {
|
|
116
|
-
throw new Error(`Invalid job "${rawObject.name}": "skip_condition" must be an array if provided.`)
|
|
117
|
-
}
|
|
118
|
-
for (const condition of rawObject.skip_condition) {
|
|
119
|
-
if (!isCondition(condition)) {
|
|
120
|
-
throw new Error(`Invalid job "${rawObject.name}": "skip_condition" contains an invalid condition entry.`)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (rawObject.constants !== undefined) {
|
|
126
|
-
if (typeof rawObject.constants !== 'object' || rawObject.constants === null || Array.isArray(rawObject.constants)) {
|
|
127
|
-
throw new Error(`Invalid job "${rawObject.name}": "constants" field must be an object if provided.`)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// --- Construct and return the strongly-typed Job object ---
|
|
132
|
-
const job: Job = {
|
|
133
|
-
name: rawObject.name,
|
|
134
|
-
version: rawObject.version,
|
|
135
|
-
description: rawObject.description,
|
|
136
|
-
depends_on: rawObject.depends_on,
|
|
137
|
-
// We've validated the necessary parts, so a cast is reasonable here.
|
|
138
|
-
actions: rawObject.actions as JobAction[],
|
|
139
|
-
only_networks: rawObject.only_networks,
|
|
140
|
-
skip_networks: rawObject.skip_networks,
|
|
141
|
-
min_evm_version: rawObject.min_evm_version,
|
|
142
|
-
deprecated: rawObject.deprecated === true,
|
|
143
|
-
skip_condition: rawObject.skip_condition as Condition[] | undefined,
|
|
144
|
-
constants: rawObject.constants,
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return job
|
|
148
|
-
}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { parse as parseYaml, YAMLParseError } from 'yaml'
|
|
2
|
-
import { Template, Action, Condition, Value } from '../types'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Helper to check if a parsed YAML object represents a Condition.
|
|
6
|
-
* Conditions are specific checks that resolve to a boolean, used in `skip_condition` blocks.
|
|
7
|
-
* @param item The parsed object from YAML.
|
|
8
|
-
* @returns True if the item is a Condition, false otherwise.
|
|
9
|
-
*/
|
|
10
|
-
function isCondition(item: any): item is Condition {
|
|
11
|
-
// A 'Condition' must be an object with a 'type' property.
|
|
12
|
-
if (!item || typeof item !== 'object' || typeof item.type !== 'string') {
|
|
13
|
-
return false
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// Check against known, specific condition types from `src/lib/types/conditions.ts`.
|
|
17
|
-
if (['contract-exists', 'job-completed'].includes(item.type)) {
|
|
18
|
-
return true
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (item.type === 'value-empty') {
|
|
22
|
-
return !!(item.arguments && typeof item.arguments === 'object' && 'value' in item.arguments)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// The 'basic-arithmetic' ValueResolver can also act as a Condition
|
|
26
|
-
// if it performs a boolean comparison operation.
|
|
27
|
-
if (item.type === 'basic-arithmetic') {
|
|
28
|
-
if (item.arguments && typeof item.arguments.operation === 'string') {
|
|
29
|
-
const booleanOperations = ['eq', 'neq', 'gt', 'lt', 'gte', 'lte']
|
|
30
|
-
return booleanOperations.includes(item.arguments.operation)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return false
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Parses a YAML string defining an action template into a structured `Template` object.
|
|
39
|
-
* This function handles validation and normalization of the template structure, including
|
|
40
|
-
* the flexible `setup` block which can be an array of mixed actions/conditions or
|
|
41
|
-
* a structured object.
|
|
42
|
-
*
|
|
43
|
-
* @param yamlContent The raw YAML content of the template file as a string.
|
|
44
|
-
* @returns The parsed and validated `Template` object.
|
|
45
|
-
* @throws {Error} If the YAML is malformed, or if the template is missing required fields
|
|
46
|
-
* like `name`, `actions`, or `outputs`.
|
|
47
|
-
*/
|
|
48
|
-
export function parseTemplate(yamlContent: string): Template {
|
|
49
|
-
let rawObject: any
|
|
50
|
-
try {
|
|
51
|
-
rawObject = parseYaml(yamlContent)
|
|
52
|
-
} catch (e) {
|
|
53
|
-
if (e instanceof YAMLParseError) {
|
|
54
|
-
// Provide a more user-friendly error message including the line number
|
|
55
|
-
const line = e.linePos?.[0].line ? ` at line ${e.linePos[0].line}` : ''
|
|
56
|
-
throw new Error(`Failed to parse template YAML: ${e.message}${line}.`)
|
|
57
|
-
}
|
|
58
|
-
throw e
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (!rawObject || typeof rawObject !== 'object') {
|
|
62
|
-
throw new Error('Invalid template: YAML content must resolve to an object.')
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// If a discriminator is provided, ensure it matches
|
|
66
|
-
if (rawObject.type !== undefined && rawObject.type !== 'template') {
|
|
67
|
-
throw new Error('Invalid template: expected type to be "template" if provided.')
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// --- Validate required fields ---
|
|
71
|
-
if (!rawObject.name || typeof rawObject.name !== 'string') {
|
|
72
|
-
throw new Error('Invalid template: "name" field is required and must be a string.')
|
|
73
|
-
}
|
|
74
|
-
if (!rawObject.actions || !Array.isArray(rawObject.actions)) {
|
|
75
|
-
throw new Error(`Invalid template "${rawObject.name}": "actions" field is required and must be an array.`)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Allow 'outputs' to be optional. If it exists, it must be an object.
|
|
79
|
-
if (rawObject.outputs && (typeof rawObject.outputs !== 'object' || Array.isArray(rawObject.outputs))) {
|
|
80
|
-
throw new Error(`Invalid template "${rawObject.name}": "outputs" field must be an object if provided.`)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// --- Construct the base template object ---
|
|
84
|
-
const template: Template = {
|
|
85
|
-
type: 'template',
|
|
86
|
-
name: rawObject.name,
|
|
87
|
-
description: rawObject.description,
|
|
88
|
-
arguments: rawObject.arguments,
|
|
89
|
-
returns: rawObject.returns,
|
|
90
|
-
actions: rawObject.actions as Action[],
|
|
91
|
-
skip_condition: rawObject.skip_condition as Condition[],
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Only include outputs if it was provided in the YAML
|
|
95
|
-
if (rawObject.outputs) {
|
|
96
|
-
template.outputs = rawObject.outputs as Record<string, Value<any>>
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// --- Handle the 'setup' block which can have multiple formats ---
|
|
100
|
-
if (rawObject.setup) {
|
|
101
|
-
if (Array.isArray(rawObject.setup)) {
|
|
102
|
-
// Format 1: An array of mixed actions and conditions (e.g., sequence-factory-v1.yaml).
|
|
103
|
-
// We need to iterate and categorize each item.
|
|
104
|
-
const setupActions: Action[] = []
|
|
105
|
-
const setupConditions: Condition[] = []
|
|
106
|
-
|
|
107
|
-
for (const item of rawObject.setup) {
|
|
108
|
-
if (isCondition(item)) {
|
|
109
|
-
setupConditions.push(item)
|
|
110
|
-
} else {
|
|
111
|
-
// If it's not an explicit condition, we assume it's an action.
|
|
112
|
-
setupActions.push(item as Action)
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
template.setup = {}
|
|
117
|
-
if (setupActions.length > 0) {
|
|
118
|
-
template.setup.actions = setupActions
|
|
119
|
-
}
|
|
120
|
-
if (setupConditions.length > 0) {
|
|
121
|
-
template.setup.skip_condition = setupConditions
|
|
122
|
-
}
|
|
123
|
-
} else if (typeof rawObject.setup === 'object') {
|
|
124
|
-
// Format 2: A structured object (e.g., nano-universal-deployer.yaml), which maps directly to our type.
|
|
125
|
-
template.setup = {
|
|
126
|
-
actions: (rawObject.setup.actions || []) as Action[],
|
|
127
|
-
skip_condition: (rawObject.setup.skip_condition || []) as Condition[],
|
|
128
|
-
}
|
|
129
|
-
} else {
|
|
130
|
-
throw new Error(`Invalid template "${rawObject.name}": "setup" field must be an array or an object if provided.`)
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return template
|
|
135
|
-
}
|