movehat 0.1.8 → 0.2.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 +2 -2
- package/dist/__tests__/deployContract.test.d.ts +2 -0
- package/dist/__tests__/deployContract.test.d.ts.map +1 -0
- package/dist/__tests__/deployContract.test.js +368 -0
- package/dist/__tests__/deployContract.test.js.map +1 -0
- package/dist/__tests__/errors.test.d.ts +2 -0
- package/dist/__tests__/errors.test.d.ts.map +1 -0
- package/dist/__tests__/errors.test.js +46 -0
- package/dist/__tests__/errors.test.js.map +1 -0
- package/dist/__tests__/fixtures/sigint-deploy-harness.d.ts +24 -0
- package/dist/__tests__/fixtures/sigint-deploy-harness.d.ts.map +1 -0
- package/dist/__tests__/fixtures/sigint-deploy-harness.js +82 -0
- package/dist/__tests__/fixtures/sigint-deploy-harness.js.map +1 -0
- package/dist/__tests__/fork/api.test.d.ts +2 -0
- package/dist/__tests__/fork/api.test.d.ts.map +1 -0
- package/dist/__tests__/fork/api.test.js +110 -0
- package/dist/__tests__/fork/api.test.js.map +1 -0
- package/dist/__tests__/harness/Harness.createLive.test.d.ts +2 -0
- package/dist/__tests__/harness/Harness.createLive.test.d.ts.map +1 -0
- package/dist/__tests__/harness/Harness.createLive.test.js +53 -0
- package/dist/__tests__/harness/Harness.createLive.test.js.map +1 -0
- package/dist/__tests__/harness/Harness.proxy.test.d.ts +2 -0
- package/dist/__tests__/harness/Harness.proxy.test.d.ts.map +1 -0
- package/dist/__tests__/harness/Harness.proxy.test.js +93 -0
- package/dist/__tests__/harness/Harness.proxy.test.js.map +1 -0
- package/dist/__tests__/harness/_fixture.d.ts +54 -0
- package/dist/__tests__/harness/_fixture.d.ts.map +1 -0
- package/dist/__tests__/harness/_fixture.js +69 -0
- package/dist/__tests__/harness/_fixture.js.map +1 -0
- package/dist/__tests__/harness/codeObject.deploy.test.d.ts +2 -0
- package/dist/__tests__/harness/codeObject.deploy.test.d.ts.map +1 -0
- package/dist/__tests__/harness/codeObject.deploy.test.js +288 -0
- package/dist/__tests__/harness/codeObject.deploy.test.js.map +1 -0
- package/dist/__tests__/harness/codeObject.upgrade.test.d.ts +2 -0
- package/dist/__tests__/harness/codeObject.upgrade.test.d.ts.map +1 -0
- package/dist/__tests__/harness/codeObject.upgrade.test.js +138 -0
- package/dist/__tests__/harness/codeObject.upgrade.test.js.map +1 -0
- package/dist/__tests__/harness/script.test.d.ts +2 -0
- package/dist/__tests__/harness/script.test.d.ts.map +1 -0
- package/dist/__tests__/harness/script.test.js +219 -0
- package/dist/__tests__/harness/script.test.js.map +1 -0
- package/dist/__tests__/harness/view.test.d.ts +2 -0
- package/dist/__tests__/harness/view.test.d.ts.map +1 -0
- package/dist/__tests__/harness/view.test.js +92 -0
- package/dist/__tests__/harness/view.test.js.map +1 -0
- package/dist/__tests__/runtime.test.d.ts +2 -0
- package/dist/__tests__/runtime.test.d.ts.map +1 -0
- package/dist/__tests__/runtime.test.js +141 -0
- package/dist/__tests__/runtime.test.js.map +1 -0
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/__tests__/compile.test.d.ts +2 -0
- package/dist/commands/__tests__/compile.test.d.ts.map +1 -0
- package/dist/commands/__tests__/compile.test.js +351 -0
- package/dist/commands/__tests__/compile.test.js.map +1 -0
- package/dist/commands/__tests__/init.test.d.ts +2 -0
- package/dist/commands/__tests__/init.test.d.ts.map +1 -0
- package/dist/commands/__tests__/init.test.js +101 -0
- package/dist/commands/__tests__/init.test.js.map +1 -0
- package/dist/commands/__tests__/run.test.d.ts +2 -0
- package/dist/commands/__tests__/run.test.d.ts.map +1 -0
- package/dist/commands/__tests__/run.test.js +166 -0
- package/dist/commands/__tests__/run.test.js.map +1 -0
- package/dist/commands/__tests__/test-move.test.d.ts +2 -0
- package/dist/commands/__tests__/test-move.test.d.ts.map +1 -0
- package/dist/commands/__tests__/test-move.test.js +59 -0
- package/dist/commands/__tests__/test-move.test.js.map +1 -0
- package/dist/commands/__tests__/test.test.d.ts +2 -0
- package/dist/commands/__tests__/test.test.d.ts.map +1 -0
- package/dist/commands/__tests__/test.test.js +168 -0
- package/dist/commands/__tests__/test.test.js.map +1 -0
- package/dist/commands/__tests__/update.test.d.ts +2 -0
- package/dist/commands/__tests__/update.test.d.ts.map +1 -0
- package/dist/commands/__tests__/update.test.js +176 -0
- package/dist/commands/__tests__/update.test.js.map +1 -0
- package/dist/commands/compile.d.ts +7 -1
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +150 -33
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/fork/__tests__/create.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/create.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/create.test.js +108 -0
- package/dist/commands/fork/__tests__/create.test.js.map +1 -0
- package/dist/commands/fork/__tests__/fund.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/fund.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/fund.test.js +72 -0
- package/dist/commands/fork/__tests__/fund.test.js.map +1 -0
- package/dist/commands/fork/__tests__/list.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/list.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/list.test.js +119 -0
- package/dist/commands/fork/__tests__/list.test.js.map +1 -0
- package/dist/commands/fork/__tests__/serve.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/serve.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/serve.test.js +97 -0
- package/dist/commands/fork/__tests__/serve.test.js.map +1 -0
- package/dist/commands/fork/__tests__/view-resource.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/view-resource.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/view-resource.test.js +77 -0
- package/dist/commands/fork/__tests__/view-resource.test.js.map +1 -0
- package/dist/commands/fork/create.d.ts +1 -1
- package/dist/commands/fork/create.d.ts.map +1 -1
- package/dist/commands/fork/create.js +3 -2
- package/dist/commands/fork/create.js.map +1 -1
- package/dist/commands/fork/fund.d.ts.map +1 -1
- package/dist/commands/fork/fund.js +15 -8
- package/dist/commands/fork/fund.js.map +1 -1
- package/dist/commands/fork/list.d.ts.map +1 -1
- package/dist/commands/fork/list.js +2 -1
- package/dist/commands/fork/list.js.map +1 -1
- package/dist/commands/fork/serve.d.ts +1 -0
- package/dist/commands/fork/serve.d.ts.map +1 -1
- package/dist/commands/fork/serve.js +4 -2
- package/dist/commands/fork/serve.js.map +1 -1
- package/dist/commands/fork/view-resource.d.ts.map +1 -1
- package/dist/commands/fork/view-resource.js +10 -5
- package/dist/commands/fork/view-resource.js.map +1 -1
- package/dist/commands/run.d.ts +15 -0
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +50 -27
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/test-move.d.ts.map +1 -1
- package/dist/commands/test-move.js +3 -2
- package/dist/commands/test-move.js.map +1 -1
- package/dist/commands/test.js +52 -46
- package/dist/commands/test.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +15 -13
- package/dist/commands/update.js.map +1 -1
- package/dist/core/AccountManager.d.ts +1 -1
- package/dist/core/AccountManager.d.ts.map +1 -1
- package/dist/core/AccountManager.js +20 -7
- package/dist/core/AccountManager.js.map +1 -1
- package/dist/core/Publisher.d.ts +31 -0
- package/dist/core/Publisher.d.ts.map +1 -0
- package/dist/core/Publisher.js +248 -0
- package/dist/core/Publisher.js.map +1 -0
- package/dist/core/__tests__/AccountManager.test.d.ts +2 -0
- package/dist/core/__tests__/AccountManager.test.d.ts.map +1 -0
- package/dist/core/__tests__/AccountManager.test.js +239 -0
- package/dist/core/__tests__/AccountManager.test.js.map +1 -0
- package/dist/core/__tests__/config.test.d.ts +2 -0
- package/dist/core/__tests__/config.test.d.ts.map +1 -0
- package/dist/core/__tests__/config.test.js +311 -0
- package/dist/core/__tests__/config.test.js.map +1 -0
- package/dist/core/__tests__/deployments.test.d.ts +2 -0
- package/dist/core/__tests__/deployments.test.d.ts.map +1 -0
- package/dist/core/__tests__/deployments.test.js +201 -0
- package/dist/core/__tests__/deployments.test.js.map +1 -0
- package/dist/core/__tests__/shell.test.d.ts +2 -0
- package/dist/core/__tests__/shell.test.d.ts.map +1 -0
- package/dist/core/__tests__/shell.test.js +107 -0
- package/dist/core/__tests__/shell.test.js.map +1 -0
- package/dist/core/config.d.ts +13 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +80 -11
- package/dist/core/config.js.map +1 -1
- package/dist/core/contract.d.ts +1 -1
- package/dist/core/contract.d.ts.map +1 -1
- package/dist/core/contract.js +15 -4
- package/dist/core/contract.js.map +1 -1
- package/dist/core/deployments.d.ts +2 -2
- package/dist/core/deployments.d.ts.map +1 -1
- package/dist/core/deployments.js +8 -6
- package/dist/core/deployments.js.map +1 -1
- package/dist/core/movementProfile.d.ts +34 -0
- package/dist/core/movementProfile.d.ts.map +1 -0
- package/dist/core/movementProfile.js +150 -0
- package/dist/core/movementProfile.js.map +1 -0
- package/dist/core/shell.d.ts +23 -7
- package/dist/core/shell.d.ts.map +1 -1
- package/dist/core/shell.js +32 -14
- package/dist/core/shell.js.map +1 -1
- package/dist/errors.d.ts +35 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +54 -0
- package/dist/errors.js.map +1 -1
- package/dist/fork/__tests__/manager.test.d.ts +2 -0
- package/dist/fork/__tests__/manager.test.d.ts.map +1 -0
- package/dist/fork/__tests__/manager.test.js +309 -0
- package/dist/fork/__tests__/manager.test.js.map +1 -0
- package/dist/fork/__tests__/server.test.d.ts +2 -0
- package/dist/fork/__tests__/server.test.d.ts.map +1 -0
- package/dist/fork/__tests__/server.test.js +54 -0
- package/dist/fork/__tests__/server.test.js.map +1 -0
- package/dist/fork/__tests__/storage.test.d.ts +2 -0
- package/dist/fork/__tests__/storage.test.d.ts.map +1 -0
- package/dist/fork/__tests__/storage.test.js +222 -0
- package/dist/fork/__tests__/storage.test.js.map +1 -0
- package/dist/fork/__tests__/test.test.d.ts +2 -0
- package/dist/fork/__tests__/test.test.d.ts.map +1 -0
- package/dist/fork/__tests__/test.test.js +81 -0
- package/dist/fork/__tests__/test.test.js.map +1 -0
- package/dist/fork/api.d.ts +14 -3
- package/dist/fork/api.d.ts.map +1 -1
- package/dist/fork/api.js +25 -14
- package/dist/fork/api.js.map +1 -1
- package/dist/fork/manager.d.ts +23 -9
- package/dist/fork/manager.d.ts.map +1 -1
- package/dist/fork/manager.js +79 -36
- package/dist/fork/manager.js.map +1 -1
- package/dist/fork/server.d.ts +11 -3
- package/dist/fork/server.d.ts.map +1 -1
- package/dist/fork/server.js +45 -13
- package/dist/fork/server.js.map +1 -1
- package/dist/fork/storage.d.ts +4 -4
- package/dist/fork/storage.d.ts.map +1 -1
- package/dist/fork/storage.js +7 -9
- package/dist/fork/storage.js.map +1 -1
- package/dist/fork/test.d.ts +13 -4
- package/dist/fork/test.d.ts.map +1 -1
- package/dist/fork/test.js +36 -27
- package/dist/fork/test.js.map +1 -1
- package/dist/harness/Harness.d.ts +124 -0
- package/dist/harness/Harness.d.ts.map +1 -0
- package/dist/harness/Harness.js +193 -0
- package/dist/harness/Harness.js.map +1 -0
- package/dist/harness/codeObject.d.ts +31 -0
- package/dist/harness/codeObject.d.ts.map +1 -0
- package/dist/harness/codeObject.js +271 -0
- package/dist/harness/codeObject.js.map +1 -0
- package/dist/harness/errors.d.ts +14 -0
- package/dist/harness/errors.d.ts.map +1 -0
- package/dist/harness/errors.js +22 -0
- package/dist/harness/errors.js.map +1 -0
- package/dist/harness/index.d.ts +4 -0
- package/dist/harness/index.d.ts.map +1 -0
- package/dist/harness/index.js +3 -0
- package/dist/harness/index.js.map +1 -0
- package/dist/harness/proxy.d.ts +7 -0
- package/dist/harness/proxy.d.ts.map +1 -0
- package/dist/harness/proxy.js +36 -0
- package/dist/harness/proxy.js.map +1 -0
- package/dist/harness/script.d.ts +21 -0
- package/dist/harness/script.d.ts.map +1 -0
- package/dist/harness/script.js +155 -0
- package/dist/harness/script.js.map +1 -0
- package/dist/harness/view.d.ts +22 -0
- package/dist/harness/view.d.ts.map +1 -0
- package/dist/harness/view.js +28 -0
- package/dist/harness/view.js.map +1 -0
- package/dist/helpers/__tests__/semver-utils.test.d.ts +2 -0
- package/dist/helpers/__tests__/semver-utils.test.d.ts.map +1 -0
- package/dist/helpers/__tests__/semver-utils.test.js +103 -0
- package/dist/helpers/__tests__/semver-utils.test.js.map +1 -0
- package/dist/helpers/index.d.ts +3 -2
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/index.js +2 -2
- package/dist/helpers/index.js.map +1 -1
- package/dist/helpers/move-tests.d.ts +3 -3
- package/dist/helpers/move-tests.d.ts.map +1 -1
- package/dist/helpers/move-tests.js +21 -20
- package/dist/helpers/move-tests.js.map +1 -1
- package/dist/helpers/npm-registry.d.ts.map +1 -1
- package/dist/helpers/npm-registry.js +1 -3
- package/dist/helpers/npm-registry.js.map +1 -1
- package/dist/helpers/semver-utils.d.ts.map +1 -1
- package/dist/helpers/semver-utils.js +4 -3
- package/dist/helpers/semver-utils.js.map +1 -1
- package/dist/helpers/setup.d.ts.map +1 -1
- package/dist/helpers/setup.js +10 -6
- package/dist/helpers/setup.js.map +1 -1
- package/dist/helpers/setupLocalTesting.d.ts +32 -27
- package/dist/helpers/setupLocalTesting.d.ts.map +1 -1
- package/dist/helpers/setupLocalTesting.js +179 -180
- package/dist/helpers/setupLocalTesting.js.map +1 -1
- package/dist/helpers/testFixtures.d.ts +19 -53
- package/dist/helpers/testFixtures.d.ts.map +1 -1
- package/dist/helpers/testFixtures.js +89 -107
- package/dist/helpers/testFixtures.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/node/LocalNodeManager.d.ts +9 -1
- package/dist/node/LocalNodeManager.d.ts.map +1 -1
- package/dist/node/LocalNodeManager.js +75 -58
- package/dist/node/LocalNodeManager.js.map +1 -1
- package/dist/node/__tests__/LocalNodeManager.test.d.ts +2 -0
- package/dist/node/__tests__/LocalNodeManager.test.d.ts.map +1 -0
- package/dist/node/__tests__/LocalNodeManager.test.js +349 -0
- package/dist/node/__tests__/LocalNodeManager.test.js.map +1 -0
- package/dist/runtime.d.ts +12 -15
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +32 -241
- package/dist/runtime.js.map +1 -1
- package/dist/templates/README.md +1 -1
- package/dist/templates/movehat.config.ts +10 -0
- package/dist/templates/package.json +2 -1
- package/dist/templates/scripts/deploy-counter.ts +46 -38
- package/dist/templates/tests/Counter.test.ts +51 -51
- package/dist/templates/types/movehat.d.ts +6 -9
- package/dist/types/config.d.ts +8 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/fork.d.ts +7 -1
- package/dist/types/fork.d.ts.map +1 -1
- package/dist/types/harness.d.ts +166 -0
- package/dist/types/harness.d.ts.map +1 -0
- package/dist/types/harness.js +2 -0
- package/dist/types/harness.js.map +1 -0
- package/dist/types/runtime.d.ts +7 -1
- package/dist/types/runtime.d.ts.map +1 -1
- package/dist/ui/__tests__/colors.test.d.ts +2 -0
- package/dist/ui/__tests__/colors.test.d.ts.map +1 -0
- package/dist/ui/__tests__/colors.test.js +127 -0
- package/dist/ui/__tests__/colors.test.js.map +1 -0
- package/dist/ui/colors.d.ts.map +1 -1
- package/dist/ui/colors.js +6 -2
- package/dist/ui/colors.js.map +1 -1
- package/dist/ui/logger.d.ts +17 -0
- package/dist/ui/logger.d.ts.map +1 -1
- package/dist/ui/logger.js +22 -0
- package/dist/ui/logger.js.map +1 -1
- package/dist/ui/symbols.d.ts +1 -0
- package/dist/ui/symbols.d.ts.map +1 -1
- package/dist/ui/symbols.js +7 -1
- package/dist/ui/symbols.js.map +1 -1
- package/dist/utils/__tests__/address.test.d.ts +2 -0
- package/dist/utils/__tests__/address.test.d.ts.map +1 -0
- package/dist/utils/__tests__/address.test.js +70 -0
- package/dist/utils/__tests__/address.test.js.map +1 -0
- package/dist/utils/__tests__/childProcessAdapter.test.d.ts +2 -0
- package/dist/utils/__tests__/childProcessAdapter.test.d.ts.map +1 -0
- package/dist/utils/__tests__/childProcessAdapter.test.js +217 -0
- package/dist/utils/__tests__/childProcessAdapter.test.js.map +1 -0
- package/dist/utils/__tests__/runCli.test.d.ts +2 -0
- package/dist/utils/__tests__/runCli.test.d.ts.map +1 -0
- package/dist/utils/__tests__/runCli.test.js +187 -0
- package/dist/utils/__tests__/runCli.test.js.map +1 -0
- package/dist/utils/address.d.ts +33 -0
- package/dist/utils/address.d.ts.map +1 -0
- package/dist/utils/address.js +52 -0
- package/dist/utils/address.js.map +1 -0
- package/dist/utils/childProcessAdapter.d.ts +93 -0
- package/dist/utils/childProcessAdapter.d.ts.map +1 -0
- package/dist/utils/childProcessAdapter.js +109 -0
- package/dist/utils/childProcessAdapter.js.map +1 -0
- package/dist/utils/parseCliOutput.d.ts +20 -0
- package/dist/utils/parseCliOutput.d.ts.map +1 -0
- package/dist/utils/parseCliOutput.js +26 -0
- package/dist/utils/parseCliOutput.js.map +1 -0
- package/dist/utils/redact.d.ts +15 -0
- package/dist/utils/redact.d.ts.map +1 -0
- package/dist/utils/redact.js +24 -0
- package/dist/utils/redact.js.map +1 -0
- package/dist/utils/runCli.d.ts +24 -0
- package/dist/utils/runCli.d.ts.map +1 -0
- package/dist/utils/runCli.js +37 -0
- package/dist/utils/runCli.js.map +1 -0
- package/package.json +14 -4
- package/src/__tests__/deployContract.test.ts +429 -0
- package/src/__tests__/errors.test.ts +84 -0
- package/src/__tests__/fixtures/sigint-deploy-harness.ts +95 -0
- package/src/__tests__/fork/api.test.ts +143 -0
- package/src/__tests__/harness/Harness.createLive.test.ts +57 -0
- package/src/__tests__/harness/Harness.proxy.test.ts +115 -0
- package/src/__tests__/harness/_fixture.ts +131 -0
- package/src/__tests__/harness/codeObject.deploy.test.ts +319 -0
- package/src/__tests__/harness/codeObject.upgrade.test.ts +156 -0
- package/src/__tests__/harness/script.test.ts +245 -0
- package/src/__tests__/harness/view.test.ts +104 -0
- package/src/__tests__/runtime.test.ts +182 -0
- package/src/cli.ts +2 -1
- package/src/commands/__tests__/compile.test.ts +407 -0
- package/src/commands/__tests__/init.test.ts +125 -0
- package/src/commands/__tests__/run.test.ts +192 -0
- package/src/commands/__tests__/test-move.test.ts +81 -0
- package/src/commands/__tests__/test.test.ts +204 -0
- package/src/commands/__tests__/update.test.ts +223 -0
- package/src/commands/compile.ts +168 -32
- package/src/commands/fork/__tests__/create.test.ts +132 -0
- package/src/commands/fork/__tests__/fund.test.ts +104 -0
- package/src/commands/fork/__tests__/list.test.ts +139 -0
- package/src/commands/fork/__tests__/serve.test.ts +121 -0
- package/src/commands/fork/__tests__/view-resource.test.ts +101 -0
- package/src/commands/fork/create.ts +4 -3
- package/src/commands/fork/fund.ts +16 -9
- package/src/commands/fork/list.ts +3 -2
- package/src/commands/fork/serve.ts +6 -3
- package/src/commands/fork/view-resource.ts +11 -6
- package/src/commands/run.ts +54 -28
- package/src/commands/test-move.ts +4 -3
- package/src/commands/test.ts +56 -44
- package/src/commands/update.ts +19 -16
- package/src/core/AccountManager.ts +23 -10
- package/src/core/Publisher.ts +322 -0
- package/src/core/__tests__/AccountManager.test.ts +290 -0
- package/src/core/__tests__/config.test.ts +377 -0
- package/src/core/__tests__/deployments.test.ts +247 -0
- package/src/core/__tests__/shell.test.ts +138 -0
- package/src/core/config.ts +96 -12
- package/src/core/contract.ts +13 -4
- package/src/core/deployments.ts +13 -11
- package/src/core/movementProfile.ts +179 -0
- package/src/core/shell.ts +34 -14
- package/src/errors.ts +60 -0
- package/src/fork/__tests__/manager.test.ts +385 -0
- package/src/fork/__tests__/server.test.ts +65 -0
- package/src/fork/__tests__/storage.test.ts +281 -0
- package/src/fork/__tests__/test.test.ts +97 -0
- package/src/fork/api.ts +28 -14
- package/src/fork/manager.ts +88 -43
- package/src/fork/server.ts +53 -19
- package/src/fork/storage.ts +12 -15
- package/src/fork/test.ts +58 -32
- package/src/harness/Harness.ts +228 -0
- package/src/harness/codeObject.ts +388 -0
- package/src/harness/errors.ts +22 -0
- package/src/harness/index.ts +3 -0
- package/src/harness/proxy.ts +40 -0
- package/src/harness/script.ts +196 -0
- package/src/harness/view.ts +34 -0
- package/src/helpers/__tests__/semver-utils.test.ts +121 -0
- package/src/helpers/index.ts +2 -8
- package/src/helpers/move-tests.ts +27 -23
- package/src/helpers/npm-registry.ts +4 -3
- package/src/helpers/semver-utils.ts +4 -3
- package/src/helpers/setup.ts +9 -5
- package/src/helpers/setupLocalTesting.ts +219 -200
- package/src/helpers/testFixtures.ts +106 -118
- package/src/index.ts +9 -3
- package/src/node/LocalNodeManager.ts +87 -62
- package/src/node/__tests__/LocalNodeManager.test.ts +452 -0
- package/src/runtime.ts +33 -289
- package/src/templates/README.md +1 -1
- package/src/templates/movehat.config.ts +10 -0
- package/src/templates/package.json +2 -1
- package/src/templates/scripts/deploy-counter.ts +46 -38
- package/src/templates/tests/Counter.test.ts +51 -51
- package/src/templates/types/movehat.d.ts +6 -9
- package/src/types/config.ts +8 -0
- package/src/types/fork.ts +7 -1
- package/src/types/harness.ts +182 -0
- package/src/types/runtime.ts +11 -3
- package/src/ui/__tests__/colors.test.ts +156 -0
- package/src/ui/colors.ts +5 -2
- package/src/ui/logger.ts +22 -0
- package/src/ui/symbols.ts +7 -1
- package/src/utils/__tests__/address.test.ts +93 -0
- package/src/utils/__tests__/childProcessAdapter.test.ts +266 -0
- package/src/utils/__tests__/runCli.test.ts +240 -0
- package/src/utils/address.ts +56 -0
- package/src/utils/childProcessAdapter.ts +215 -0
- package/src/utils/parseCliOutput.ts +27 -0
- package/src/utils/redact.ts +24 -0
- package/src/utils/runCli.ts +64 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
+
import { vol, fs as memfsFs } from 'memfs';
|
|
3
|
+
|
|
4
|
+
// Mock fs module
|
|
5
|
+
vi.mock('fs', () => ({
|
|
6
|
+
default: memfsFs,
|
|
7
|
+
...memfsFs,
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
// Import after mock
|
|
11
|
+
const {
|
|
12
|
+
validateSafeName,
|
|
13
|
+
saveDeployment,
|
|
14
|
+
loadDeployment,
|
|
15
|
+
getAllDeployments,
|
|
16
|
+
getDeployedAddress,
|
|
17
|
+
} = await import('../deployments.js');
|
|
18
|
+
|
|
19
|
+
describe('validateSafeName', () => {
|
|
20
|
+
it('should accept valid names', () => {
|
|
21
|
+
expect(() => validateSafeName('testnet', 'network')).not.toThrow();
|
|
22
|
+
expect(() => validateSafeName('counter', 'module')).not.toThrow();
|
|
23
|
+
expect(() => validateSafeName('my-module', 'module')).not.toThrow();
|
|
24
|
+
expect(() => validateSafeName('module_v2', 'module')).not.toThrow();
|
|
25
|
+
expect(() => validateSafeName('Module123', 'module')).not.toThrow();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should reject path traversal attempts', () => {
|
|
29
|
+
expect(() => validateSafeName('../etc/passwd', 'network')).toThrow('Path traversal');
|
|
30
|
+
expect(() => validateSafeName('..\\windows', 'network')).toThrow('Path traversal');
|
|
31
|
+
expect(() => validateSafeName('foo/../bar', 'module')).toThrow('Path traversal');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should reject slashes', () => {
|
|
35
|
+
expect(() => validateSafeName('path/to/file', 'network')).toThrow('Path traversal');
|
|
36
|
+
expect(() => validateSafeName('path\\to\\file', 'network')).toThrow('Path traversal');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should reject special characters', () => {
|
|
40
|
+
expect(() => validateSafeName('test;rm', 'module')).toThrow('Only alphanumeric');
|
|
41
|
+
expect(() => validateSafeName('test$var', 'module')).toThrow('Only alphanumeric');
|
|
42
|
+
expect(() => validateSafeName('test space', 'module')).toThrow('Only alphanumeric');
|
|
43
|
+
expect(() => validateSafeName('test.module', 'module')).toThrow('Only alphanumeric');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should reject hidden files (starting with dot)', () => {
|
|
47
|
+
expect(() => validateSafeName('.hidden', 'network')).toThrow('cannot start with a dot');
|
|
48
|
+
expect(() => validateSafeName('.gitignore', 'module')).toThrow('cannot start with a dot');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should reject empty strings', () => {
|
|
52
|
+
expect(() => validateSafeName('', 'network')).toThrow('must be a non-empty string');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should reject non-string input', () => {
|
|
56
|
+
expect(() => validateSafeName(null as any, 'network')).toThrow('must be a non-empty string');
|
|
57
|
+
expect(() => validateSafeName(undefined as any, 'module')).toThrow('must be a non-empty string');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should use correct type in error messages', () => {
|
|
61
|
+
expect(() => validateSafeName('bad name', 'network')).toThrow('Invalid network name');
|
|
62
|
+
expect(() => validateSafeName('bad name', 'module')).toThrow('Invalid module name');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('saveDeployment and loadDeployment', () => {
|
|
67
|
+
beforeEach(() => {
|
|
68
|
+
vol.reset();
|
|
69
|
+
// Create initial directory structure
|
|
70
|
+
vol.fromJSON({
|
|
71
|
+
'/project/.gitkeep': '',
|
|
72
|
+
});
|
|
73
|
+
// Mock process.cwd
|
|
74
|
+
vi.spyOn(process, 'cwd').mockReturnValue('/project');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
afterEach(() => {
|
|
78
|
+
vol.reset();
|
|
79
|
+
vi.restoreAllMocks();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should save and load deployment', () => {
|
|
83
|
+
const deployment = {
|
|
84
|
+
address: '0x1234',
|
|
85
|
+
moduleName: 'counter',
|
|
86
|
+
network: 'testnet',
|
|
87
|
+
deployer: '0xabcd',
|
|
88
|
+
timestamp: 1704985623564,
|
|
89
|
+
txHash: '0x5678',
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Mock console.log to suppress output
|
|
93
|
+
vi.spyOn(console, 'log').mockImplementation(() => {});
|
|
94
|
+
|
|
95
|
+
saveDeployment(deployment);
|
|
96
|
+
|
|
97
|
+
const loaded = loadDeployment('testnet', 'counter');
|
|
98
|
+
expect(loaded).toEqual(deployment);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should return null for non-existent deployment', () => {
|
|
102
|
+
const loaded = loadDeployment('testnet', 'nonexistent');
|
|
103
|
+
expect(loaded).toBeNull();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should create directories if they do not exist', () => {
|
|
107
|
+
const deployment = {
|
|
108
|
+
address: '0x1234',
|
|
109
|
+
moduleName: 'token',
|
|
110
|
+
network: 'mainnet',
|
|
111
|
+
deployer: '0xabcd',
|
|
112
|
+
timestamp: Date.now(),
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
vi.spyOn(console, 'log').mockImplementation(() => {});
|
|
116
|
+
|
|
117
|
+
saveDeployment(deployment);
|
|
118
|
+
|
|
119
|
+
expect(vol.existsSync('/project/deployments')).toBe(true);
|
|
120
|
+
expect(vol.existsSync('/project/deployments/mainnet')).toBe(true);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should reject invalid network names when saving', () => {
|
|
124
|
+
const deployment = {
|
|
125
|
+
address: '0x1234',
|
|
126
|
+
moduleName: 'counter',
|
|
127
|
+
network: '../etc',
|
|
128
|
+
deployer: '0xabcd',
|
|
129
|
+
timestamp: Date.now(),
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
expect(() => saveDeployment(deployment)).toThrow('Path traversal');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should reject invalid module names when saving', () => {
|
|
136
|
+
const deployment = {
|
|
137
|
+
address: '0x1234',
|
|
138
|
+
moduleName: 'counter;rm -rf',
|
|
139
|
+
network: 'testnet',
|
|
140
|
+
deployer: '0xabcd',
|
|
141
|
+
timestamp: Date.now(),
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
expect(() => saveDeployment(deployment)).toThrow('Only alphanumeric');
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('getAllDeployments', () => {
|
|
149
|
+
beforeEach(() => {
|
|
150
|
+
vol.reset();
|
|
151
|
+
vi.spyOn(process, 'cwd').mockReturnValue('/project');
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
afterEach(() => {
|
|
155
|
+
vol.reset();
|
|
156
|
+
vi.restoreAllMocks();
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should return empty object for non-existent network', () => {
|
|
160
|
+
vol.fromJSON({
|
|
161
|
+
'/project/.gitkeep': '',
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const deployments = getAllDeployments('nonexistent');
|
|
165
|
+
expect(deployments).toEqual({});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should return all deployments for a network', () => {
|
|
169
|
+
vol.fromJSON({
|
|
170
|
+
'/project/deployments/testnet/counter.json': JSON.stringify({
|
|
171
|
+
address: '0x1',
|
|
172
|
+
moduleName: 'counter',
|
|
173
|
+
network: 'testnet',
|
|
174
|
+
deployer: '0xd1',
|
|
175
|
+
timestamp: 1000,
|
|
176
|
+
}),
|
|
177
|
+
'/project/deployments/testnet/token.json': JSON.stringify({
|
|
178
|
+
address: '0x2',
|
|
179
|
+
moduleName: 'token',
|
|
180
|
+
network: 'testnet',
|
|
181
|
+
deployer: '0xd2',
|
|
182
|
+
timestamp: 2000,
|
|
183
|
+
}),
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const deployments = getAllDeployments('testnet');
|
|
187
|
+
|
|
188
|
+
expect(Object.keys(deployments)).toHaveLength(2);
|
|
189
|
+
expect(deployments['counter']?.address).toBe('0x1');
|
|
190
|
+
expect(deployments['token']?.address).toBe('0x2');
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('should ignore non-JSON files', () => {
|
|
194
|
+
vol.fromJSON({
|
|
195
|
+
'/project/deployments/testnet/counter.json': JSON.stringify({
|
|
196
|
+
address: '0x1',
|
|
197
|
+
moduleName: 'counter',
|
|
198
|
+
network: 'testnet',
|
|
199
|
+
deployer: '0xd1',
|
|
200
|
+
timestamp: 1000,
|
|
201
|
+
}),
|
|
202
|
+
'/project/deployments/testnet/README.md': '# Readme',
|
|
203
|
+
'/project/deployments/testnet/.gitkeep': '',
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const deployments = getAllDeployments('testnet');
|
|
207
|
+
|
|
208
|
+
expect(Object.keys(deployments)).toHaveLength(1);
|
|
209
|
+
expect(deployments['counter']).toBeDefined();
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
describe('getDeployedAddress', () => {
|
|
214
|
+
beforeEach(() => {
|
|
215
|
+
vol.reset();
|
|
216
|
+
vi.spyOn(process, 'cwd').mockReturnValue('/project');
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
afterEach(() => {
|
|
220
|
+
vol.reset();
|
|
221
|
+
vi.restoreAllMocks();
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('should return address for existing deployment', () => {
|
|
225
|
+
vol.fromJSON({
|
|
226
|
+
'/project/deployments/testnet/counter.json': JSON.stringify({
|
|
227
|
+
address: '0x1234abcd',
|
|
228
|
+
moduleName: 'counter',
|
|
229
|
+
network: 'testnet',
|
|
230
|
+
deployer: '0xd1',
|
|
231
|
+
timestamp: 1000,
|
|
232
|
+
}),
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
const address = getDeployedAddress('testnet', 'counter');
|
|
236
|
+
expect(address).toBe('0x1234abcd');
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('should return null for non-existent deployment', () => {
|
|
240
|
+
vol.fromJSON({
|
|
241
|
+
'/project/.gitkeep': '',
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
const address = getDeployedAddress('testnet', 'nonexistent');
|
|
245
|
+
expect(address).toBeNull();
|
|
246
|
+
});
|
|
247
|
+
});
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
escapeShellArg,
|
|
4
|
+
validateAndEscapePath,
|
|
5
|
+
validateAndEscapeProfile,
|
|
6
|
+
} from '../shell.js';
|
|
7
|
+
|
|
8
|
+
describe('escapeShellArg', () => {
|
|
9
|
+
it('should wrap simple strings in single quotes', () => {
|
|
10
|
+
expect(escapeShellArg('hello')).toBe("'hello'");
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should escape single quotes within strings', () => {
|
|
14
|
+
expect(escapeShellArg("it's")).toBe("'it'\\''s'");
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should handle multiple single quotes', () => {
|
|
18
|
+
expect(escapeShellArg("it's a 'test'")).toBe("'it'\\''s a '\\''test'\\'''");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should handle empty strings', () => {
|
|
22
|
+
expect(escapeShellArg('')).toBe("''");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should handle strings with spaces', () => {
|
|
26
|
+
expect(escapeShellArg('hello world')).toBe("'hello world'");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should handle paths with spaces', () => {
|
|
30
|
+
expect(escapeShellArg('/path/to/my project')).toBe("'/path/to/my project'");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should throw for non-string input', () => {
|
|
34
|
+
expect(() => escapeShellArg(123 as any)).toThrow('Shell argument must be a string');
|
|
35
|
+
expect(() => escapeShellArg(null as any)).toThrow('Shell argument must be a string');
|
|
36
|
+
expect(() => escapeShellArg(undefined as any)).toThrow('Shell argument must be a string');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should handle special characters safely', () => {
|
|
40
|
+
// These should be safely wrapped, not executed
|
|
41
|
+
expect(escapeShellArg('$(whoami)')).toBe("'$(whoami)'");
|
|
42
|
+
expect(escapeShellArg('`ls`')).toBe("'`ls`'");
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe('validateAndEscapePath', () => {
|
|
47
|
+
it('should accept valid paths', () => {
|
|
48
|
+
expect(validateAndEscapePath('/home/user/project')).toBe("'/home/user/project'");
|
|
49
|
+
expect(validateAndEscapePath('./my-project')).toBe("'./my-project'");
|
|
50
|
+
expect(validateAndEscapePath('C:\\Users\\project')).toBe("'C:\\Users\\project'");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should accept paths with spaces', () => {
|
|
54
|
+
expect(validateAndEscapePath('/home/user/my project')).toBe("'/home/user/my project'");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should accept paths with dots and underscores', () => {
|
|
58
|
+
expect(validateAndEscapePath('./my_project.test')).toBe("'./my_project.test'");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should reject paths with semicolons (command chaining)', () => {
|
|
62
|
+
expect(() => validateAndEscapePath('/path; rm -rf /')).toThrow('potentially dangerous characters');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should reject paths with pipes', () => {
|
|
66
|
+
expect(() => validateAndEscapePath('/path | cat /etc/passwd')).toThrow('potentially dangerous characters');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should reject paths with backticks (command substitution)', () => {
|
|
70
|
+
expect(() => validateAndEscapePath('/path/`whoami`')).toThrow('potentially dangerous characters');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should reject paths with $() (command substitution)', () => {
|
|
74
|
+
expect(() => validateAndEscapePath('/path/$(whoami)')).toThrow('potentially dangerous characters');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should reject paths with ampersand', () => {
|
|
78
|
+
expect(() => validateAndEscapePath('/path & echo hacked')).toThrow('potentially dangerous characters');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('should reject paths with curly braces', () => {
|
|
82
|
+
expect(() => validateAndEscapePath('/path/{a,b}')).toThrow('potentially dangerous characters');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should reject paths with redirects', () => {
|
|
86
|
+
expect(() => validateAndEscapePath('/path > /etc/passwd')).toThrow('potentially dangerous characters');
|
|
87
|
+
expect(() => validateAndEscapePath('/path < /etc/passwd')).toThrow('potentially dangerous characters');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should throw for empty paths', () => {
|
|
91
|
+
expect(() => validateAndEscapePath('')).toThrow('must be a non-empty string');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should throw for non-string input', () => {
|
|
95
|
+
expect(() => validateAndEscapePath(null as any)).toThrow('must be a non-empty string');
|
|
96
|
+
expect(() => validateAndEscapePath(undefined as any)).toThrow('must be a non-empty string');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should use custom name in error messages', () => {
|
|
100
|
+
expect(() => validateAndEscapePath('', 'Move directory')).toThrow('Invalid Move directory');
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
describe('validateAndEscapeProfile', () => {
|
|
105
|
+
it('should accept valid profile names', () => {
|
|
106
|
+
expect(validateAndEscapeProfile('default')).toBe("'default'");
|
|
107
|
+
expect(validateAndEscapeProfile('my-profile')).toBe("'my-profile'");
|
|
108
|
+
expect(validateAndEscapeProfile('profile_123')).toBe("'profile_123'");
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should accept alphanumeric names', () => {
|
|
112
|
+
expect(validateAndEscapeProfile('Profile1')).toBe("'Profile1'");
|
|
113
|
+
expect(validateAndEscapeProfile('test123')).toBe("'test123'");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('should reject profiles with spaces', () => {
|
|
117
|
+
expect(() => validateAndEscapeProfile('my profile')).toThrow('Only alphanumeric');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('should reject profiles with special characters', () => {
|
|
121
|
+
expect(() => validateAndEscapeProfile('profile;rm')).toThrow('Only alphanumeric');
|
|
122
|
+
expect(() => validateAndEscapeProfile('profile$test')).toThrow('Only alphanumeric');
|
|
123
|
+
expect(() => validateAndEscapeProfile('profile/test')).toThrow('Only alphanumeric');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should reject profiles with dots', () => {
|
|
127
|
+
expect(() => validateAndEscapeProfile('profile.test')).toThrow('Only alphanumeric');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should throw for empty profiles', () => {
|
|
131
|
+
expect(() => validateAndEscapeProfile('')).toThrow('must be a non-empty string');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should throw for non-string input', () => {
|
|
135
|
+
expect(() => validateAndEscapeProfile(null as any)).toThrow('must be a non-empty string');
|
|
136
|
+
expect(() => validateAndEscapeProfile(undefined as any)).toThrow('must be a non-empty string');
|
|
137
|
+
});
|
|
138
|
+
});
|
package/src/core/config.ts
CHANGED
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
import { pathToFileURL } from "url";
|
|
2
2
|
import { join } from "path";
|
|
3
|
-
import { existsSync } from "fs";
|
|
3
|
+
import { existsSync, statSync } from "fs";
|
|
4
|
+
import { Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
|
|
4
5
|
import { MovehatConfig, MovehatUserConfig } from "../types/config.js";
|
|
5
6
|
|
|
7
|
+
interface ConfigCacheEntry {
|
|
8
|
+
mtimeMs: number;
|
|
9
|
+
config: MovehatUserConfig;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Keyed by resolved absolute path. One entry per config file the process
|
|
13
|
+
// has loaded. Closes #62 — the previous `?t=Date.now()` cache-bust
|
|
14
|
+
// created a fresh Node loader module per call.
|
|
15
|
+
//
|
|
16
|
+
// Note on concurrency: two `loadUserConfig()` calls racing on a cold
|
|
17
|
+
// cache may both invoke `import()`. Node's loader cache deduplicates by
|
|
18
|
+
// URL so both resolve to the same module, and both writers store the
|
|
19
|
+
// same value here. No corruption, no in-flight-promise memoization
|
|
20
|
+
// needed.
|
|
21
|
+
const configCache = new Map<string, ConfigCacheEntry>();
|
|
22
|
+
|
|
6
23
|
/**
|
|
7
|
-
* Loads the user's movehat.config.js from the current working directory.
|
|
8
|
-
*
|
|
24
|
+
* Loads the user's movehat.config.{ts,js} from the current working directory.
|
|
25
|
+
*
|
|
26
|
+
* Cached by `{ absPath, mtimeMs }`: a second call with no edit returns
|
|
27
|
+
* the parsed object directly and skips both the tsx loader register
|
|
28
|
+
* dance and the dynamic `import()`. Edits invalidate via the file's
|
|
29
|
+
* mtime.
|
|
30
|
+
*
|
|
9
31
|
* @throws {Error} If the configuration file is not found or fails to load
|
|
10
32
|
* @security This function loads and executes code from the current working directory.
|
|
11
33
|
* It should only be called from trusted project directories.
|
|
@@ -13,7 +35,6 @@ import { MovehatConfig, MovehatUserConfig } from "../types/config.js";
|
|
|
13
35
|
export async function loadUserConfig(): Promise<MovehatUserConfig> {
|
|
14
36
|
const cwd = process.cwd();
|
|
15
37
|
|
|
16
|
-
// Try to find config file (.ts first, then .js)
|
|
17
38
|
const possiblePaths = [
|
|
18
39
|
join(cwd, "movehat.config.ts"),
|
|
19
40
|
join(cwd, "movehat.config.js"),
|
|
@@ -34,41 +55,56 @@ export async function loadUserConfig(): Promise<MovehatUserConfig> {
|
|
|
34
55
|
}
|
|
35
56
|
|
|
36
57
|
try {
|
|
58
|
+
const { mtimeMs } = statSync(configPath);
|
|
59
|
+
|
|
60
|
+
const cached = configCache.get(configPath);
|
|
61
|
+
if (cached && cached.mtimeMs === mtimeMs) {
|
|
62
|
+
return cached.config;
|
|
63
|
+
}
|
|
64
|
+
|
|
37
65
|
let configModule;
|
|
38
66
|
|
|
39
67
|
if (configPath.endsWith('.ts')) {
|
|
40
|
-
// For TypeScript files, we need to use tsx's import system
|
|
41
|
-
// Register tsx loader for .ts files
|
|
42
68
|
const { register } = await import('tsx/esm/api');
|
|
43
69
|
const unregister = register();
|
|
44
70
|
|
|
45
71
|
try {
|
|
46
72
|
const configUrl = pathToFileURL(configPath).href;
|
|
47
|
-
configModule = await import(configUrl + '?
|
|
73
|
+
configModule = await import(configUrl + '?mtime=' + mtimeMs);
|
|
48
74
|
} finally {
|
|
49
75
|
unregister();
|
|
50
76
|
}
|
|
51
77
|
} else {
|
|
52
|
-
// For .js files, use standard import
|
|
53
78
|
const configUrl = pathToFileURL(configPath).href;
|
|
54
|
-
configModule = await import(configUrl + '?
|
|
79
|
+
configModule = await import(configUrl + '?mtime=' + mtimeMs);
|
|
55
80
|
}
|
|
56
81
|
|
|
57
82
|
const userConfig = configModule.default as MovehatUserConfig;
|
|
58
83
|
|
|
59
|
-
// Validate that networks are defined
|
|
60
84
|
if (!userConfig.networks || Object.keys(userConfig.networks).length === 0) {
|
|
61
85
|
throw new Error(
|
|
62
86
|
"No networks defined in configuration. Add at least one network in the 'networks' field."
|
|
63
87
|
);
|
|
64
88
|
}
|
|
65
89
|
|
|
90
|
+
configCache.set(configPath, { mtimeMs, config: userConfig });
|
|
91
|
+
|
|
66
92
|
return userConfig;
|
|
67
93
|
} catch (error) {
|
|
68
94
|
throw new Error(`Failed to load configuration file '${configPath}': ${error}`);
|
|
69
95
|
}
|
|
70
96
|
}
|
|
71
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Clear the in-memory config cache. Test-only escape hatch.
|
|
100
|
+
*
|
|
101
|
+
* @internal Not part of the public API surface. Imported via relative
|
|
102
|
+
* path from `core/__tests__/config.test.ts` only.
|
|
103
|
+
*/
|
|
104
|
+
export function _resetConfigCache(): void {
|
|
105
|
+
configCache.clear();
|
|
106
|
+
}
|
|
107
|
+
|
|
72
108
|
/**
|
|
73
109
|
* Resolve configuration for a specific network
|
|
74
110
|
* Merges global settings with network-specific settings
|
|
@@ -178,18 +214,66 @@ export async function resolveNetworkConfig(
|
|
|
178
214
|
...(networkConfig.namedAddresses || {}),
|
|
179
215
|
};
|
|
180
216
|
|
|
217
|
+
// Capture the primary key after the L178 guard guaranteed it exists
|
|
218
|
+
// (either present from the start, or auto-assigned by the testnet/local
|
|
219
|
+
// branch; the else-branch throws). Pulling into a local lets TS see
|
|
220
|
+
// the non-undefined narrowing.
|
|
221
|
+
const primaryKey = accounts[0];
|
|
222
|
+
if (!primaryKey) {
|
|
223
|
+
throw new Error("invariant: accounts[0] must exist after the L178 guard");
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Derive the deployer account address from the resolved private key.
|
|
227
|
+
// Without this, consumers reading `config.account` got an empty string
|
|
228
|
+
// (the previous "Will be derived from privateKey in runtime" TODO was
|
|
229
|
+
// never wired). Falls back to "" on malformed keys so we don't break
|
|
230
|
+
// existing callers that don't need the field.
|
|
231
|
+
const accountAddress = deriveAccountAddress(primaryKey);
|
|
232
|
+
|
|
181
233
|
// Build resolved config
|
|
182
234
|
const resolvedConfig: MovehatConfig = {
|
|
183
235
|
network: selectedNetwork,
|
|
184
236
|
rpc: networkConfig.url,
|
|
185
|
-
privateKey:
|
|
237
|
+
privateKey: primaryKey,
|
|
186
238
|
allAccounts: accounts,
|
|
187
239
|
profile: networkConfig.profile || "default",
|
|
188
240
|
moveDir: userConfig.moveDir || "./move",
|
|
189
|
-
account:
|
|
241
|
+
account: accountAddress,
|
|
190
242
|
namedAddresses: mergedNamedAddresses,
|
|
191
243
|
networkConfig: networkConfig,
|
|
192
244
|
};
|
|
193
245
|
|
|
194
246
|
return resolvedConfig;
|
|
195
247
|
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Derive the on-chain account address from a private key. Strips the
|
|
251
|
+
* `ed25519-priv-` prefix that Movement CLI sometimes emits; returns ""
|
|
252
|
+
* on any parse failure so existing callers that don't consume the field
|
|
253
|
+
* keep working unchanged. Emits a console.warn on failure so a
|
|
254
|
+
* misconfigured `PRIVATE_KEY` surfaces here (loud, at config-resolution
|
|
255
|
+
* time) instead of as a cryptic "Hex string is too short" SDK error
|
|
256
|
+
* later in the call chain.
|
|
257
|
+
*/
|
|
258
|
+
function deriveAccountAddress(privateKeyHex: string | undefined): string {
|
|
259
|
+
if (!privateKeyHex) return "";
|
|
260
|
+
try {
|
|
261
|
+
const stripped = privateKeyHex.startsWith("ed25519-priv-")
|
|
262
|
+
? privateKeyHex.slice("ed25519-priv-".length)
|
|
263
|
+
: privateKeyHex;
|
|
264
|
+
const account = Account.fromPrivateKey({
|
|
265
|
+
privateKey: new Ed25519PrivateKey(stripped),
|
|
266
|
+
});
|
|
267
|
+
return account.accountAddress.toString();
|
|
268
|
+
} catch (err) {
|
|
269
|
+
// The private key may have come from several sources (network.accounts,
|
|
270
|
+
// global accounts, PRIVATE_KEY env, auto-generated testnet key). Keep
|
|
271
|
+
// the hint generic so it never points at the wrong source.
|
|
272
|
+
console.warn(
|
|
273
|
+
`[movehat] Could not derive account address from the resolved private key: ${
|
|
274
|
+
(err as Error).message
|
|
275
|
+
}. Verify the key configured for this network is a valid Ed25519 private key (with or without the "ed25519-priv-" prefix).`
|
|
276
|
+
);
|
|
277
|
+
return "";
|
|
278
|
+
}
|
|
279
|
+
}
|
package/src/core/contract.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type InputViewFunctionData,
|
|
5
5
|
type MoveFunctionId,
|
|
6
6
|
} from "@aptos-labs/ts-sdk";
|
|
7
|
+
import { logger } from "../ui/index.js";
|
|
7
8
|
|
|
8
9
|
export interface TransactionResult {
|
|
9
10
|
hash: string;
|
|
@@ -21,12 +22,17 @@ export class MoveContract {
|
|
|
21
22
|
async call(
|
|
22
23
|
signer: Account,
|
|
23
24
|
functionName: string,
|
|
25
|
+
// any[]: Move entry-function arguments are heterogeneous primitives
|
|
26
|
+
// (u8/u64/string/bool/address/vector) passed through to the Aptos
|
|
27
|
+
// SDK's `functionArguments`, which validates at submit time. A
|
|
28
|
+
// narrower union here would force casts at every call site for
|
|
29
|
+
// little safety gain.
|
|
24
30
|
args: any[] = [],
|
|
25
31
|
typeArgs: string[] = []
|
|
26
32
|
): Promise<TransactionResult> {
|
|
27
33
|
const functionFullName = `${this.moduleAddress}::${this.moduleName}::${functionName}`;
|
|
28
34
|
|
|
29
|
-
|
|
35
|
+
logger.step(`Calling ${functionFullName}...`);
|
|
30
36
|
|
|
31
37
|
const transaction = await this.aptos.transaction.build.simple({
|
|
32
38
|
sender: signer.accountAddress,
|
|
@@ -51,9 +57,10 @@ export class MoveContract {
|
|
|
51
57
|
transactionHash: committedTxn.hash,
|
|
52
58
|
});
|
|
53
59
|
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
logger.success(
|
|
61
|
+
`Transaction ${committedTxn.hash} committed with status: ${response.vm_status}`
|
|
56
62
|
);
|
|
63
|
+
logger.newline();
|
|
57
64
|
|
|
58
65
|
return {
|
|
59
66
|
hash: committedTxn.hash,
|
|
@@ -62,8 +69,10 @@ export class MoveContract {
|
|
|
62
69
|
};
|
|
63
70
|
}
|
|
64
71
|
|
|
65
|
-
async view<T =
|
|
72
|
+
async view<T = unknown>(
|
|
66
73
|
functionName: string,
|
|
74
|
+
// any[]: see `call()` above — Move view-function arguments share
|
|
75
|
+
// the same SDK-validated boundary semantics.
|
|
67
76
|
args: any[] = [],
|
|
68
77
|
typeArgs: string[] = []
|
|
69
78
|
): Promise<T> {
|
package/src/core/deployments.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "fs";
|
|
2
2
|
import { join } from "path";
|
|
3
|
+
import { logger } from "../ui/index.js";
|
|
3
4
|
|
|
4
5
|
export interface DeploymentInfo {
|
|
5
6
|
address: string;
|
|
@@ -7,8 +8,8 @@ export interface DeploymentInfo {
|
|
|
7
8
|
network: string;
|
|
8
9
|
deployer: string;
|
|
9
10
|
timestamp: number;
|
|
10
|
-
txHash?: string;
|
|
11
|
-
blockNumber?: string;
|
|
11
|
+
txHash?: string | undefined;
|
|
12
|
+
blockNumber?: string | undefined;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
/**
|
|
@@ -30,20 +31,21 @@ export function validateSafeName(name: string, type: "network" | "module"): void
|
|
|
30
31
|
);
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
if (
|
|
34
|
+
// Reject hidden-file names first so the error message is specific
|
|
35
|
+
// (otherwise the alphanumeric check below would fire generically).
|
|
36
|
+
if (name.startsWith(".")) {
|
|
36
37
|
throw new Error(
|
|
37
38
|
`Invalid ${type} name: "${name}"\n` +
|
|
38
|
-
`
|
|
39
|
+
`Names cannot start with a dot (.) to prevent hidden file creation.`
|
|
39
40
|
);
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
//
|
|
43
|
-
|
|
43
|
+
// Only allow alphanumeric, hyphens, underscores
|
|
44
|
+
const safePattern = /^[a-zA-Z0-9_-]+$/;
|
|
45
|
+
if (!safePattern.test(name)) {
|
|
44
46
|
throw new Error(
|
|
45
47
|
`Invalid ${type} name: "${name}"\n` +
|
|
46
|
-
`
|
|
48
|
+
`Only alphanumeric characters, hyphens (-), and underscores (_) are allowed.`
|
|
47
49
|
);
|
|
48
50
|
}
|
|
49
51
|
}
|
|
@@ -89,8 +91,8 @@ export function saveDeployment(deployment: DeploymentInfo): void {
|
|
|
89
91
|
|
|
90
92
|
try {
|
|
91
93
|
writeFileSync(filePath, JSON.stringify(deployment, null, 2), "utf-8");
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
logger.success(
|
|
95
|
+
`Deployment saved: deployments/${deployment.network}/${deployment.moduleName}.json`
|
|
94
96
|
);
|
|
95
97
|
} catch (error) {
|
|
96
98
|
console.error(
|