flingit 0.0.63 → 0.0.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +9 -5
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/workflow.d.ts +51 -0
- package/dist/cli/commands/workflow.d.ts.map +1 -0
- package/dist/cli/commands/workflow.js +479 -0
- package/dist/cli/commands/workflow.js.map +1 -0
- package/dist/cli/deploy/bundler.d.ts.map +1 -1
- package/dist/cli/deploy/bundler.js +17 -1
- package/dist/cli/deploy/bundler.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime/entry.d.ts +7 -0
- package/dist/runtime/entry.d.ts.map +1 -1
- package/dist/runtime/entry.js +71 -2
- package/dist/runtime/entry.js.map +1 -1
- package/dist/types/workflow.d.ts +82 -0
- package/dist/types/workflow.d.ts.map +1 -0
- package/dist/types/workflow.js +8 -0
- package/dist/types/workflow.js.map +1 -0
- package/dist/worker-runtime/d1-event-store.d.ts +22 -0
- package/dist/worker-runtime/d1-event-store.d.ts.map +1 -0
- package/dist/worker-runtime/d1-event-store.js +227 -0
- package/dist/worker-runtime/d1-event-store.js.map +1 -0
- package/dist/worker-runtime/entry-extract.d.ts.map +1 -1
- package/dist/worker-runtime/entry-extract.js +6 -3
- package/dist/worker-runtime/entry-extract.js.map +1 -1
- package/dist/worker-runtime/entry.d.ts.map +1 -1
- package/dist/worker-runtime/entry.js +105 -3
- package/dist/worker-runtime/entry.js.map +1 -1
- package/dist/worker-runtime/index.d.ts +2 -0
- package/dist/worker-runtime/index.d.ts.map +1 -1
- package/dist/worker-runtime/index.js +5 -0
- package/dist/worker-runtime/index.js.map +1 -1
- package/dist/workflow/runtime.d.ts +56 -0
- package/dist/workflow/runtime.d.ts.map +1 -0
- package/dist/workflow/runtime.js +450 -0
- package/dist/workflow/runtime.js.map +1 -0
- package/node_modules/@glideapps/ts-necessities/LICENSE +21 -0
- package/node_modules/@glideapps/ts-necessities/README.md +16 -0
- package/node_modules/@glideapps/ts-necessities/dist/branded-strings.d.ts +39 -0
- package/node_modules/@glideapps/ts-necessities/dist/default-map.d.ts +53 -0
- package/node_modules/@glideapps/ts-necessities/dist/index.d.mts +113 -0
- package/node_modules/@glideapps/ts-necessities/dist/index.d.ts +113 -0
- package/node_modules/@glideapps/ts-necessities/dist/index.js +237 -0
- package/node_modules/@glideapps/ts-necessities/dist/index.mjs +189 -0
- package/node_modules/@glideapps/ts-necessities/package.json +52 -0
- package/node_modules/@rollup/rollup-linux-x64-gnu/README.md +3 -0
- package/node_modules/@rollup/rollup-linux-x64-gnu/package.json +25 -0
- package/node_modules/@rollup/rollup-linux-x64-gnu/rollup.linux-x64-gnu.node +0 -0
- package/node_modules/base64-js/LICENSE +21 -0
- package/node_modules/base64-js/README.md +34 -0
- package/node_modules/base64-js/base64js.min.js +1 -0
- package/node_modules/base64-js/index.d.ts +3 -0
- package/node_modules/base64-js/index.js +150 -0
- package/node_modules/base64-js/package.json +47 -0
- package/node_modules/better-sqlite3/LICENSE +21 -0
- package/node_modules/better-sqlite3/README.md +99 -0
- package/node_modules/better-sqlite3/binding.gyp +38 -0
- package/node_modules/better-sqlite3/deps/common.gypi +68 -0
- package/node_modules/better-sqlite3/deps/copy.js +31 -0
- package/node_modules/better-sqlite3/deps/defines.gypi +41 -0
- package/node_modules/better-sqlite3/deps/download.sh +122 -0
- package/node_modules/better-sqlite3/deps/patches/1208.patch +15 -0
- package/node_modules/better-sqlite3/deps/sqlite3/sqlite3.c +265994 -0
- package/node_modules/better-sqlite3/deps/sqlite3/sqlite3.h +13968 -0
- package/node_modules/better-sqlite3/deps/sqlite3/sqlite3ext.h +730 -0
- package/node_modules/better-sqlite3/deps/sqlite3.gyp +80 -0
- package/node_modules/better-sqlite3/deps/test_extension.c +21 -0
- package/node_modules/better-sqlite3/lib/database.js +90 -0
- package/node_modules/better-sqlite3/lib/index.js +3 -0
- package/node_modules/better-sqlite3/lib/methods/aggregate.js +43 -0
- package/node_modules/better-sqlite3/lib/methods/backup.js +67 -0
- package/node_modules/better-sqlite3/lib/methods/function.js +31 -0
- package/node_modules/better-sqlite3/lib/methods/inspect.js +7 -0
- package/node_modules/better-sqlite3/lib/methods/pragma.js +12 -0
- package/node_modules/better-sqlite3/lib/methods/serialize.js +16 -0
- package/node_modules/better-sqlite3/lib/methods/table.js +189 -0
- package/node_modules/better-sqlite3/lib/methods/transaction.js +78 -0
- package/node_modules/better-sqlite3/lib/methods/wrappers.js +54 -0
- package/node_modules/better-sqlite3/lib/sqlite-error.js +20 -0
- package/node_modules/better-sqlite3/lib/util.js +12 -0
- package/node_modules/better-sqlite3/package.json +59 -0
- package/node_modules/better-sqlite3/src/addon.cpp +47 -0
- package/node_modules/better-sqlite3/src/better_sqlite3.cpp +74 -0
- package/node_modules/better-sqlite3/src/objects/backup.cpp +120 -0
- package/node_modules/better-sqlite3/src/objects/backup.hpp +36 -0
- package/node_modules/better-sqlite3/src/objects/database.cpp +417 -0
- package/node_modules/better-sqlite3/src/objects/database.hpp +103 -0
- package/node_modules/better-sqlite3/src/objects/statement-iterator.cpp +113 -0
- package/node_modules/better-sqlite3/src/objects/statement-iterator.hpp +50 -0
- package/node_modules/better-sqlite3/src/objects/statement.cpp +383 -0
- package/node_modules/better-sqlite3/src/objects/statement.hpp +58 -0
- package/node_modules/better-sqlite3/src/util/bind-map.cpp +73 -0
- package/node_modules/better-sqlite3/src/util/binder.cpp +193 -0
- package/node_modules/better-sqlite3/src/util/constants.cpp +172 -0
- package/node_modules/better-sqlite3/src/util/custom-aggregate.cpp +121 -0
- package/node_modules/better-sqlite3/src/util/custom-function.cpp +59 -0
- package/node_modules/better-sqlite3/src/util/custom-table.cpp +409 -0
- package/node_modules/better-sqlite3/src/util/data-converter.cpp +17 -0
- package/node_modules/better-sqlite3/src/util/data.cpp +194 -0
- package/node_modules/better-sqlite3/src/util/helpers.cpp +109 -0
- package/node_modules/better-sqlite3/src/util/macros.cpp +83 -0
- package/node_modules/better-sqlite3/src/util/query-macros.cpp +71 -0
- package/node_modules/better-sqlite3/src/util/row-builder.cpp +49 -0
- package/node_modules/bindings/LICENSE.md +22 -0
- package/node_modules/bindings/README.md +98 -0
- package/node_modules/bindings/bindings.js +221 -0
- package/node_modules/bindings/package.json +28 -0
- package/node_modules/bl/.travis.yml +17 -0
- package/node_modules/bl/BufferList.js +396 -0
- package/node_modules/bl/LICENSE.md +13 -0
- package/node_modules/bl/README.md +247 -0
- package/node_modules/bl/bl.js +84 -0
- package/node_modules/bl/package.json +37 -0
- package/node_modules/bl/test/convert.js +21 -0
- package/node_modules/bl/test/indexOf.js +492 -0
- package/node_modules/bl/test/isBufferList.js +32 -0
- package/node_modules/bl/test/test.js +869 -0
- package/node_modules/buffer/AUTHORS.md +70 -0
- package/node_modules/buffer/LICENSE +21 -0
- package/node_modules/buffer/README.md +410 -0
- package/node_modules/buffer/index.d.ts +186 -0
- package/node_modules/buffer/index.js +1817 -0
- package/node_modules/buffer/package.json +96 -0
- package/node_modules/chownr/LICENSE +15 -0
- package/node_modules/chownr/README.md +3 -0
- package/node_modules/chownr/chownr.js +167 -0
- package/node_modules/chownr/package.json +29 -0
- package/node_modules/decompress-response/index.d.ts +22 -0
- package/node_modules/decompress-response/index.js +58 -0
- package/node_modules/decompress-response/license +9 -0
- package/node_modules/decompress-response/package.json +56 -0
- package/node_modules/decompress-response/readme.md +48 -0
- package/node_modules/deep-extend/LICENSE +20 -0
- package/node_modules/deep-extend/README.md +91 -0
- package/node_modules/deep-extend/index.js +1 -0
- package/node_modules/deep-extend/lib/deep-extend.js +150 -0
- package/node_modules/deep-extend/package.json +62 -0
- package/node_modules/detect-libc/LICENSE +201 -0
- package/node_modules/detect-libc/README.md +163 -0
- package/node_modules/detect-libc/index.d.ts +14 -0
- package/node_modules/detect-libc/lib/detect-libc.js +313 -0
- package/node_modules/detect-libc/lib/elf.js +39 -0
- package/node_modules/detect-libc/lib/filesystem.js +51 -0
- package/node_modules/detect-libc/lib/process.js +24 -0
- package/node_modules/detect-libc/package.json +44 -0
- package/node_modules/determined/LICENSE +18 -0
- package/node_modules/determined/README.md +317 -0
- package/node_modules/determined/dist/index.cjs +370 -0
- package/node_modules/determined/dist/index.d.cts +110 -0
- package/node_modules/determined/dist/index.d.ts +110 -0
- package/node_modules/determined/dist/index.js +332 -0
- package/node_modules/determined/package.json +45 -0
- package/node_modules/end-of-stream/LICENSE +21 -0
- package/node_modules/end-of-stream/README.md +54 -0
- package/node_modules/end-of-stream/index.js +96 -0
- package/node_modules/end-of-stream/package.json +37 -0
- package/node_modules/expand-template/.travis.yml +6 -0
- package/node_modules/expand-template/LICENSE +21 -0
- package/node_modules/expand-template/README.md +43 -0
- package/node_modules/expand-template/index.js +26 -0
- package/node_modules/expand-template/package.json +29 -0
- package/node_modules/expand-template/test.js +67 -0
- package/node_modules/file-uri-to-path/.npmignore +1 -0
- package/node_modules/file-uri-to-path/.travis.yml +30 -0
- package/node_modules/file-uri-to-path/History.md +21 -0
- package/node_modules/file-uri-to-path/LICENSE +20 -0
- package/node_modules/file-uri-to-path/README.md +74 -0
- package/node_modules/file-uri-to-path/index.d.ts +2 -0
- package/node_modules/file-uri-to-path/index.js +66 -0
- package/node_modules/file-uri-to-path/package.json +32 -0
- package/node_modules/file-uri-to-path/test/test.js +24 -0
- package/node_modules/file-uri-to-path/test/tests.json +13 -0
- package/node_modules/flingflow/.nvmrc +1 -0
- package/node_modules/flingflow/AGENTS.md +5 -0
- package/node_modules/flingflow/README.md +679 -0
- package/node_modules/flingflow/SPEC.md +554 -0
- package/node_modules/flingflow/TESTING.md +506 -0
- package/node_modules/flingflow/dist/backoff.d.ts +9 -0
- package/node_modules/flingflow/dist/backoff.js +14 -0
- package/node_modules/flingflow/dist/backoff.js.map +1 -0
- package/node_modules/flingflow/dist/clock.d.ts +13 -0
- package/node_modules/flingflow/dist/clock.js +21 -0
- package/node_modules/flingflow/dist/clock.js.map +1 -0
- package/node_modules/flingflow/dist/context.d.ts +8 -0
- package/node_modules/flingflow/dist/context.js +45 -0
- package/node_modules/flingflow/dist/context.js.map +1 -0
- package/node_modules/flingflow/dist/engine.d.ts +29 -0
- package/node_modules/flingflow/dist/engine.js +306 -0
- package/node_modules/flingflow/dist/engine.js.map +1 -0
- package/node_modules/flingflow/dist/index.d.ts +18 -0
- package/node_modules/flingflow/dist/index.js +14 -0
- package/node_modules/flingflow/dist/index.js.map +1 -0
- package/node_modules/flingflow/dist/recovery.d.ts +16 -0
- package/node_modules/flingflow/dist/recovery.js +118 -0
- package/node_modules/flingflow/dist/recovery.js.map +1 -0
- package/node_modules/flingflow/dist/registry.d.ts +24 -0
- package/node_modules/flingflow/dist/registry.js +29 -0
- package/node_modules/flingflow/dist/registry.js.map +1 -0
- package/node_modules/flingflow/dist/store-memory.d.ts +29 -0
- package/node_modules/flingflow/dist/store-memory.js +349 -0
- package/node_modules/flingflow/dist/store-memory.js.map +1 -0
- package/node_modules/flingflow/dist/store-sqlite.d.ts +30 -0
- package/node_modules/flingflow/dist/store-sqlite.js +400 -0
- package/node_modules/flingflow/dist/store-sqlite.js.map +1 -0
- package/node_modules/flingflow/dist/store.d.ts +39 -0
- package/node_modules/flingflow/dist/store.js +21 -0
- package/node_modules/flingflow/dist/store.js.map +1 -0
- package/node_modules/flingflow/dist/stress.d.ts +1 -0
- package/node_modules/flingflow/dist/stress.js +377 -0
- package/node_modules/flingflow/dist/stress.js.map +1 -0
- package/node_modules/flingflow/dist/transitions.d.ts +14 -0
- package/node_modules/flingflow/dist/transitions.js +28 -0
- package/node_modules/flingflow/dist/transitions.js.map +1 -0
- package/node_modules/flingflow/dist/types.d.ts +114 -0
- package/node_modules/flingflow/dist/types.js +10 -0
- package/node_modules/flingflow/dist/types.js.map +1 -0
- package/node_modules/flingflow/eslint.config.js +94 -0
- package/node_modules/flingflow/package.json +66 -0
- package/node_modules/flingflow/src/backoff.ts +14 -0
- package/node_modules/flingflow/src/clock.ts +29 -0
- package/node_modules/flingflow/src/context.ts +60 -0
- package/node_modules/flingflow/src/engine.ts +367 -0
- package/node_modules/flingflow/src/index.ts +52 -0
- package/node_modules/flingflow/src/recovery.ts +144 -0
- package/node_modules/flingflow/src/registry.ts +52 -0
- package/node_modules/flingflow/src/store-memory.ts +378 -0
- package/node_modules/flingflow/src/store-sqlite.ts +451 -0
- package/node_modules/flingflow/src/store.ts +55 -0
- package/node_modules/flingflow/src/stress.ts +423 -0
- package/node_modules/flingflow/src/transitions.ts +38 -0
- package/node_modules/flingflow/src/types.ts +84 -0
- package/node_modules/flingflow/test/backoff.test.ts +54 -0
- package/node_modules/flingflow/test/context.test.ts +94 -0
- package/node_modules/flingflow/test/engine.test.ts +362 -0
- package/node_modules/flingflow/test/fixtures.ts +58 -0
- package/node_modules/flingflow/test/recovery.test.ts +176 -0
- package/node_modules/flingflow/test/simulation.test.ts +395 -0
- package/node_modules/flingflow/test/store-conformance.ts +344 -0
- package/node_modules/flingflow/test/store-memory.test.ts +8 -0
- package/node_modules/flingflow/test/store-sqlite.test.ts +8 -0
- package/node_modules/flingflow/tsconfig.json +18 -0
- package/node_modules/flingflow/tsconfig.lint.json +5 -0
- package/node_modules/flingflow/tsconfig.typecheck.json +20 -0
- package/node_modules/flingflow/vitest.config.ts +10 -0
- package/node_modules/fs-constants/LICENSE +21 -0
- package/node_modules/fs-constants/README.md +26 -0
- package/node_modules/fs-constants/browser.js +1 -0
- package/node_modules/fs-constants/index.js +1 -0
- package/node_modules/fs-constants/package.json +19 -0
- package/node_modules/github-from-package/.travis.yml +4 -0
- package/node_modules/github-from-package/LICENSE +18 -0
- package/node_modules/github-from-package/example/package.json +8 -0
- package/node_modules/github-from-package/example/url.js +3 -0
- package/node_modules/github-from-package/index.js +17 -0
- package/node_modules/github-from-package/package.json +30 -0
- package/node_modules/github-from-package/readme.markdown +53 -0
- package/node_modules/github-from-package/test/a.json +8 -0
- package/node_modules/github-from-package/test/b.json +5 -0
- package/node_modules/github-from-package/test/c.json +5 -0
- package/node_modules/github-from-package/test/d.json +7 -0
- package/node_modules/github-from-package/test/e.json +5 -0
- package/node_modules/github-from-package/test/url.js +19 -0
- package/node_modules/ieee754/LICENSE +11 -0
- package/node_modules/ieee754/README.md +51 -0
- package/node_modules/ieee754/index.d.ts +10 -0
- package/node_modules/ieee754/index.js +85 -0
- package/node_modules/ieee754/package.json +52 -0
- package/node_modules/inherits/LICENSE +16 -0
- package/node_modules/inherits/README.md +42 -0
- package/node_modules/inherits/inherits.js +9 -0
- package/node_modules/inherits/inherits_browser.js +27 -0
- package/node_modules/inherits/package.json +29 -0
- package/node_modules/ini/LICENSE +15 -0
- package/node_modules/ini/README.md +102 -0
- package/node_modules/ini/ini.js +206 -0
- package/node_modules/ini/package.json +33 -0
- package/node_modules/mimic-response/index.d.ts +17 -0
- package/node_modules/mimic-response/index.js +77 -0
- package/node_modules/mimic-response/license +9 -0
- package/node_modules/mimic-response/package.json +42 -0
- package/node_modules/mimic-response/readme.md +78 -0
- package/node_modules/minimist/.eslintrc +29 -0
- package/node_modules/minimist/.github/FUNDING.yml +12 -0
- package/node_modules/minimist/.nycrc +14 -0
- package/node_modules/minimist/CHANGELOG.md +298 -0
- package/node_modules/minimist/LICENSE +18 -0
- package/node_modules/minimist/README.md +121 -0
- package/node_modules/minimist/example/parse.js +4 -0
- package/node_modules/minimist/index.js +263 -0
- package/node_modules/minimist/package.json +75 -0
- package/node_modules/minimist/test/all_bool.js +34 -0
- package/node_modules/minimist/test/bool.js +177 -0
- package/node_modules/minimist/test/dash.js +43 -0
- package/node_modules/minimist/test/default_bool.js +37 -0
- package/node_modules/minimist/test/dotted.js +24 -0
- package/node_modules/minimist/test/kv_short.js +32 -0
- package/node_modules/minimist/test/long.js +33 -0
- package/node_modules/minimist/test/num.js +38 -0
- package/node_modules/minimist/test/parse.js +209 -0
- package/node_modules/minimist/test/parse_modified.js +11 -0
- package/node_modules/minimist/test/proto.js +64 -0
- package/node_modules/minimist/test/short.js +69 -0
- package/node_modules/minimist/test/stop_early.js +17 -0
- package/node_modules/minimist/test/unknown.js +104 -0
- package/node_modules/minimist/test/whitespace.js +10 -0
- package/node_modules/mkdirp-classic/LICENSE +21 -0
- package/node_modules/mkdirp-classic/README.md +18 -0
- package/node_modules/mkdirp-classic/index.js +98 -0
- package/node_modules/mkdirp-classic/package.json +18 -0
- package/node_modules/napi-build-utils/.github/workflows/run-npm-tests.yml +31 -0
- package/node_modules/napi-build-utils/LICENSE +21 -0
- package/node_modules/napi-build-utils/README.md +52 -0
- package/node_modules/napi-build-utils/index.js +214 -0
- package/node_modules/napi-build-utils/index.md +0 -0
- package/node_modules/napi-build-utils/package.json +42 -0
- package/node_modules/neverthrow/LICENSE +22 -0
- package/node_modules/neverthrow/README.md +1683 -0
- package/node_modules/neverthrow/dist/index.cjs.js +510 -0
- package/node_modules/neverthrow/dist/index.d.ts +408 -0
- package/node_modules/neverthrow/dist/index.es.js +497 -0
- package/node_modules/neverthrow/package.json +64 -0
- package/node_modules/node-abi/LICENSE +21 -0
- package/node_modules/node-abi/README.md +54 -0
- package/node_modules/node-abi/abi_registry.json +425 -0
- package/node_modules/node-abi/index.js +179 -0
- package/node_modules/node-abi/package.json +45 -0
- package/node_modules/once/LICENSE +15 -0
- package/node_modules/once/README.md +79 -0
- package/node_modules/once/once.js +42 -0
- package/node_modules/once/package.json +33 -0
- package/node_modules/prebuild-install/CHANGELOG.md +131 -0
- package/node_modules/prebuild-install/CONTRIBUTING.md +6 -0
- package/node_modules/prebuild-install/LICENSE +21 -0
- package/node_modules/prebuild-install/README.md +163 -0
- package/node_modules/prebuild-install/asset.js +44 -0
- package/node_modules/prebuild-install/bin.js +78 -0
- package/node_modules/prebuild-install/download.js +142 -0
- package/node_modules/prebuild-install/error.js +14 -0
- package/node_modules/prebuild-install/help.txt +16 -0
- package/node_modules/prebuild-install/index.js +1 -0
- package/node_modules/prebuild-install/log.js +33 -0
- package/node_modules/prebuild-install/package.json +67 -0
- package/node_modules/prebuild-install/proxy.js +35 -0
- package/node_modules/prebuild-install/rc.js +64 -0
- package/node_modules/prebuild-install/util.js +143 -0
- package/node_modules/pump/.github/FUNDING.yml +2 -0
- package/node_modules/pump/.travis.yml +5 -0
- package/node_modules/pump/LICENSE +21 -0
- package/node_modules/pump/README.md +74 -0
- package/node_modules/pump/SECURITY.md +5 -0
- package/node_modules/pump/index.js +86 -0
- package/node_modules/pump/package.json +24 -0
- package/node_modules/pump/test-browser.js +66 -0
- package/node_modules/pump/test-node.js +53 -0
- package/node_modules/rc/LICENSE.APACHE2 +15 -0
- package/node_modules/rc/LICENSE.BSD +26 -0
- package/node_modules/rc/LICENSE.MIT +24 -0
- package/node_modules/rc/README.md +227 -0
- package/node_modules/rc/browser.js +7 -0
- package/node_modules/rc/cli.js +4 -0
- package/node_modules/rc/index.js +53 -0
- package/node_modules/rc/lib/utils.js +104 -0
- package/node_modules/rc/package.json +29 -0
- package/node_modules/rc/test/ini.js +16 -0
- package/node_modules/rc/test/nested-env-vars.js +50 -0
- package/node_modules/rc/test/test.js +59 -0
- package/node_modules/readable-stream/CONTRIBUTING.md +38 -0
- package/node_modules/readable-stream/GOVERNANCE.md +136 -0
- package/node_modules/readable-stream/LICENSE +47 -0
- package/node_modules/readable-stream/README.md +106 -0
- package/node_modules/readable-stream/errors-browser.js +127 -0
- package/node_modules/readable-stream/errors.js +116 -0
- package/node_modules/readable-stream/experimentalWarning.js +17 -0
- package/node_modules/readable-stream/lib/_stream_duplex.js +126 -0
- package/node_modules/readable-stream/lib/_stream_passthrough.js +37 -0
- package/node_modules/readable-stream/lib/_stream_readable.js +1027 -0
- package/node_modules/readable-stream/lib/_stream_transform.js +190 -0
- package/node_modules/readable-stream/lib/_stream_writable.js +641 -0
- package/node_modules/readable-stream/lib/internal/streams/async_iterator.js +180 -0
- package/node_modules/readable-stream/lib/internal/streams/buffer_list.js +183 -0
- package/node_modules/readable-stream/lib/internal/streams/destroy.js +96 -0
- package/node_modules/readable-stream/lib/internal/streams/end-of-stream.js +86 -0
- package/node_modules/readable-stream/lib/internal/streams/from-browser.js +3 -0
- package/node_modules/readable-stream/lib/internal/streams/from.js +52 -0
- package/node_modules/readable-stream/lib/internal/streams/pipeline.js +86 -0
- package/node_modules/readable-stream/lib/internal/streams/state.js +22 -0
- package/node_modules/readable-stream/lib/internal/streams/stream-browser.js +1 -0
- package/node_modules/readable-stream/lib/internal/streams/stream.js +1 -0
- package/node_modules/readable-stream/package.json +68 -0
- package/node_modules/readable-stream/readable-browser.js +9 -0
- package/node_modules/readable-stream/readable.js +16 -0
- package/node_modules/safe-buffer/LICENSE +21 -0
- package/node_modules/safe-buffer/README.md +584 -0
- package/node_modules/safe-buffer/index.d.ts +187 -0
- package/node_modules/safe-buffer/index.js +65 -0
- package/node_modules/safe-buffer/package.json +51 -0
- package/node_modules/semver/LICENSE +15 -0
- package/node_modules/semver/README.md +664 -0
- package/node_modules/semver/bin/semver.js +191 -0
- package/node_modules/semver/classes/comparator.js +143 -0
- package/node_modules/semver/classes/index.js +7 -0
- package/node_modules/semver/classes/range.js +557 -0
- package/node_modules/semver/classes/semver.js +333 -0
- package/node_modules/semver/functions/clean.js +8 -0
- package/node_modules/semver/functions/cmp.js +54 -0
- package/node_modules/semver/functions/coerce.js +62 -0
- package/node_modules/semver/functions/compare-build.js +9 -0
- package/node_modules/semver/functions/compare-loose.js +5 -0
- package/node_modules/semver/functions/compare.js +7 -0
- package/node_modules/semver/functions/diff.js +60 -0
- package/node_modules/semver/functions/eq.js +5 -0
- package/node_modules/semver/functions/gt.js +5 -0
- package/node_modules/semver/functions/gte.js +5 -0
- package/node_modules/semver/functions/inc.js +21 -0
- package/node_modules/semver/functions/lt.js +5 -0
- package/node_modules/semver/functions/lte.js +5 -0
- package/node_modules/semver/functions/major.js +5 -0
- package/node_modules/semver/functions/minor.js +5 -0
- package/node_modules/semver/functions/neq.js +5 -0
- package/node_modules/semver/functions/parse.js +18 -0
- package/node_modules/semver/functions/patch.js +5 -0
- package/node_modules/semver/functions/prerelease.js +8 -0
- package/node_modules/semver/functions/rcompare.js +5 -0
- package/node_modules/semver/functions/rsort.js +5 -0
- package/node_modules/semver/functions/satisfies.js +12 -0
- package/node_modules/semver/functions/sort.js +5 -0
- package/node_modules/semver/functions/valid.js +8 -0
- package/node_modules/semver/index.js +91 -0
- package/node_modules/semver/internal/constants.js +37 -0
- package/node_modules/semver/internal/debug.js +11 -0
- package/node_modules/semver/internal/identifiers.js +29 -0
- package/node_modules/semver/internal/lrucache.js +42 -0
- package/node_modules/semver/internal/parse-options.js +17 -0
- package/node_modules/semver/internal/re.js +223 -0
- package/node_modules/semver/package.json +78 -0
- package/node_modules/semver/preload.js +4 -0
- package/node_modules/semver/range.bnf +16 -0
- package/node_modules/semver/ranges/gtr.js +6 -0
- package/node_modules/semver/ranges/intersects.js +9 -0
- package/node_modules/semver/ranges/ltr.js +6 -0
- package/node_modules/semver/ranges/max-satisfying.js +27 -0
- package/node_modules/semver/ranges/min-satisfying.js +26 -0
- package/node_modules/semver/ranges/min-version.js +63 -0
- package/node_modules/semver/ranges/outside.js +82 -0
- package/node_modules/semver/ranges/simplify.js +49 -0
- package/node_modules/semver/ranges/subset.js +249 -0
- package/node_modules/semver/ranges/to-comparators.js +10 -0
- package/node_modules/semver/ranges/valid.js +13 -0
- package/node_modules/simple-concat/.travis.yml +3 -0
- package/node_modules/simple-concat/LICENSE +20 -0
- package/node_modules/simple-concat/README.md +44 -0
- package/node_modules/simple-concat/index.js +15 -0
- package/node_modules/simple-concat/package.json +47 -0
- package/node_modules/simple-concat/test/basic.js +41 -0
- package/node_modules/simple-get/.github/dependabot.yml +15 -0
- package/node_modules/simple-get/.github/workflows/ci.yml +23 -0
- package/node_modules/simple-get/LICENSE +20 -0
- package/node_modules/simple-get/README.md +333 -0
- package/node_modules/simple-get/index.js +108 -0
- package/node_modules/simple-get/package.json +67 -0
- package/node_modules/string_decoder/LICENSE +48 -0
- package/node_modules/string_decoder/README.md +47 -0
- package/node_modules/string_decoder/lib/string_decoder.js +296 -0
- package/node_modules/string_decoder/package.json +34 -0
- package/node_modules/strip-json-comments/index.js +70 -0
- package/node_modules/strip-json-comments/license +21 -0
- package/node_modules/strip-json-comments/package.json +42 -0
- package/node_modules/strip-json-comments/readme.md +64 -0
- package/node_modules/tar-fs/.travis.yml +6 -0
- package/node_modules/tar-fs/LICENSE +21 -0
- package/node_modules/tar-fs/README.md +165 -0
- package/node_modules/tar-fs/index.js +363 -0
- package/node_modules/tar-fs/package.json +41 -0
- package/node_modules/tar-fs/test/fixtures/a/hello.txt +1 -0
- package/node_modules/tar-fs/test/fixtures/b/a/test.txt +1 -0
- package/node_modules/tar-fs/test/fixtures/d/file1 +0 -0
- package/node_modules/tar-fs/test/fixtures/d/file2 +0 -0
- package/node_modules/tar-fs/test/fixtures/d/sub-dir/file5 +0 -0
- package/node_modules/tar-fs/test/fixtures/d/sub-files/file3 +0 -0
- package/node_modules/tar-fs/test/fixtures/d/sub-files/file4 +0 -0
- package/node_modules/tar-fs/test/fixtures/e/directory/.ignore +0 -0
- package/node_modules/tar-fs/test/fixtures/e/file +0 -0
- package/node_modules/tar-fs/test/fixtures/invalid.tar +0 -0
- package/node_modules/tar-fs/test/index.js +346 -0
- package/node_modules/tar-stream/LICENSE +21 -0
- package/node_modules/tar-stream/README.md +168 -0
- package/node_modules/tar-stream/extract.js +257 -0
- package/node_modules/tar-stream/headers.js +295 -0
- package/node_modules/tar-stream/index.js +2 -0
- package/node_modules/tar-stream/pack.js +255 -0
- package/node_modules/tar-stream/package.json +58 -0
- package/node_modules/tar-stream/sandbox.js +11 -0
- package/node_modules/tunnel-agent/LICENSE +55 -0
- package/node_modules/tunnel-agent/README.md +4 -0
- package/node_modules/tunnel-agent/index.js +244 -0
- package/node_modules/tunnel-agent/package.json +22 -0
- package/node_modules/util-deprecate/History.md +16 -0
- package/node_modules/util-deprecate/LICENSE +24 -0
- package/node_modules/util-deprecate/README.md +53 -0
- package/node_modules/util-deprecate/browser.js +67 -0
- package/node_modules/util-deprecate/node.js +6 -0
- package/node_modules/util-deprecate/package.json +27 -0
- package/node_modules/wrappy/LICENSE +15 -0
- package/node_modules/wrappy/README.md +36 -0
- package/node_modules/wrappy/package.json +29 -0
- package/node_modules/wrappy/wrappy.js +33 -0
- package/package.json +12 -2
- package/templates/default/dot-claude/skills/fling/.hash +1 -1
- package/templates/default/dot-claude/skills/fling/SKILL.md +56 -29
- package/templates/default/dot-claude/skills/fling/references/WORKFLOWS.md +368 -0
|
@@ -0,0 +1,679 @@
|
|
|
1
|
+
# flingflow
|
|
2
|
+
|
|
3
|
+
A durable execution engine using explicit continuations and event sourcing. Workflows are functions that receive the current step and return a continuation describing what to do next. All state is persisted as an append-only event log in SQLite.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npm install
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import {
|
|
15
|
+
Engine,
|
|
16
|
+
MemoryEventStore,
|
|
17
|
+
WorkflowRegistry,
|
|
18
|
+
type Ctx,
|
|
19
|
+
type Continuation,
|
|
20
|
+
} from "flingflow";
|
|
21
|
+
import { NoSimulationTask } from "determined";
|
|
22
|
+
|
|
23
|
+
const noSim = new NoSimulationTask("app", false);
|
|
24
|
+
|
|
25
|
+
// 1. Define a workflow
|
|
26
|
+
const registry = new WorkflowRegistry();
|
|
27
|
+
registry.register({
|
|
28
|
+
name: "onboarding",
|
|
29
|
+
fn: async (ctx: Ctx): Promise<Continuation> => {
|
|
30
|
+
switch (ctx.step) {
|
|
31
|
+
case "start": {
|
|
32
|
+
const input = await ctx.get("input");
|
|
33
|
+
const user = await getUser(input.userId);
|
|
34
|
+
ctx.set("user", user);
|
|
35
|
+
return { step: "send-email" };
|
|
36
|
+
}
|
|
37
|
+
case "send-email": {
|
|
38
|
+
const user = await ctx.get("user");
|
|
39
|
+
await sendWelcomeEmail(user.email);
|
|
40
|
+
return { done: true, result: { sent: true } };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// 2. Create the engine
|
|
47
|
+
const store = new MemoryEventStore();
|
|
48
|
+
const engine = new Engine({ store, registry });
|
|
49
|
+
(await engine.initialize())._unsafeUnwrap();
|
|
50
|
+
|
|
51
|
+
// 3. Run a workflow
|
|
52
|
+
const runId = (await engine.createWorkflow("onboarding-wf", "onboarding", { userId: 42 }, noSim))._unsafeUnwrap();
|
|
53
|
+
(await engine.runToCompletion(runId, noSim))._unsafeUnwrap();
|
|
54
|
+
|
|
55
|
+
// 4. Inspect the event log
|
|
56
|
+
const events = (await store.getAllEvents(runId, noSim))._unsafeUnwrap();
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Design
|
|
60
|
+
|
|
61
|
+
### Explicit Continuations
|
|
62
|
+
|
|
63
|
+
Each workflow step is a fresh function invocation. The function receives a `Ctx` with the current step name and a scratchpad for passing data between steps. The original input is available via `ctx.get()` (it is written to the scratchpad at workflow creation). It returns a `Continuation` that either names the next step or marks the workflow as done.
|
|
64
|
+
|
|
65
|
+
There are no determinism constraints — each step can call `Math.random()`, `Date.now()`, fetch live data, whatever it wants.
|
|
66
|
+
|
|
67
|
+
### Dual IDs
|
|
68
|
+
|
|
69
|
+
Each workflow has two distinct IDs:
|
|
70
|
+
|
|
71
|
+
- **Workflow ID** — user-provided logical identity. Only one active run per workflow ID at a time.
|
|
72
|
+
- **Run ID** — system-generated UUID, globally unique across all runs.
|
|
73
|
+
|
|
74
|
+
This allows workflows to be restarted (new run ID) while preserving the logical identity (same workflow ID). The `appendIfNoActiveWorkflow` store method enforces the uniqueness constraint atomically.
|
|
75
|
+
|
|
76
|
+
### Event Sourcing
|
|
77
|
+
|
|
78
|
+
All state is stored as an immutable, append-only event log. The current state of a workflow is derived from its last event. Concurrent workers coordinate via optimistic concurrency: the unique constraint on `(run_id, seq)` ensures exactly one writer wins per sequence number.
|
|
79
|
+
|
|
80
|
+
### Error Handling
|
|
81
|
+
|
|
82
|
+
Framework code never throws. All errors are returned as `neverthrow` `Result` values. Workflow functions throw (caught immediately by the engine). The only exceptions are programming errors (e.g., duplicate workflow registration).
|
|
83
|
+
|
|
84
|
+
### State Machine
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
workflow_created → step_started → step_completed → step_started → ... → workflow_completed
|
|
88
|
+
→ step_failed → step_started (retry)
|
|
89
|
+
→ workflow_failed (max attempts / non-retryable)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Valid transitions:
|
|
93
|
+
|
|
94
|
+
| Last Event | Can Be Followed By |
|
|
95
|
+
|---|---|
|
|
96
|
+
| `workflow_created` | `step_started` |
|
|
97
|
+
| `step_started` | `step_completed`, `step_failed` |
|
|
98
|
+
| `step_completed` (has `next_step`) | `step_started` |
|
|
99
|
+
| `step_completed` (no `next_step`) | `workflow_completed` |
|
|
100
|
+
| `step_failed` (retryable, under max) | `step_started` |
|
|
101
|
+
| `step_failed` (not retryable or at max) | `workflow_failed` |
|
|
102
|
+
| `workflow_completed` | *(terminal)* |
|
|
103
|
+
| `workflow_failed` | *(terminal)* |
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## API Reference
|
|
108
|
+
|
|
109
|
+
### Types
|
|
110
|
+
|
|
111
|
+
#### `Continuation`
|
|
112
|
+
|
|
113
|
+
Returned by workflow functions to describe what happens next.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
type Continuation =
|
|
117
|
+
| { step: string } // continue to next step
|
|
118
|
+
| { done: true; result: unknown } // workflow complete
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
#### `Ctx`
|
|
122
|
+
|
|
123
|
+
The context object passed to every workflow step invocation.
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
type Ctx = {
|
|
127
|
+
workflowId: string; // user-provided logical workflow identity
|
|
128
|
+
runId: string; // system-generated unique run ID
|
|
129
|
+
step: string; // current step name
|
|
130
|
+
sim: SimulationTask; // simulation task for failpoints/checkpoints
|
|
131
|
+
get(key: string): Promise<unknown>; // read from scratchpad
|
|
132
|
+
set(key: string, value: unknown): void; // buffer a write to scratchpad
|
|
133
|
+
};
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- `get()` checks pending (buffered) writes first, then falls back to persisted scratchpad values. Returns `undefined` for missing keys.
|
|
137
|
+
- `set()` buffers a write in memory. Buffered writes are persisted atomically when the step completes successfully. If the step fails, all buffered writes are discarded.
|
|
138
|
+
- `sim` is the `SimulationTask` from the `determined` package. Workflow functions can pass it to external services for failpoint injection during simulation testing.
|
|
139
|
+
|
|
140
|
+
#### `WorkflowFn`
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
type WorkflowFn = (ctx: Ctx) => Promise<Continuation>;
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
A workflow function. Receives the context for the current step and returns a continuation. Typically implemented as a `switch` on `ctx.step`.
|
|
147
|
+
|
|
148
|
+
#### `WorkflowEvent`
|
|
149
|
+
|
|
150
|
+
A discriminated union over `event_type`. Every event has:
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
{
|
|
154
|
+
run_id: string; // system-generated unique run ID
|
|
155
|
+
workflow_id: string; // user-provided logical workflow identity
|
|
156
|
+
seq: number; // sequence number (0-based, ascending)
|
|
157
|
+
event_type: string; // discriminant
|
|
158
|
+
payload: ...; // typed per event_type
|
|
159
|
+
created_at: number; // epoch ms from the injected Clock
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Event types and their payloads:
|
|
164
|
+
|
|
165
|
+
| `event_type` | Payload Type |
|
|
166
|
+
|---|---|
|
|
167
|
+
| `"workflow_created"` | `{ workflowName: string; writes: Record<string, unknown>; config: { maxAttempts, initialBackoffMS, backoffMultiplier, maxBackoffMS, stepTimeoutMS } }` |
|
|
168
|
+
| `"step_started"` | `{ step: string; attempt: number }` |
|
|
169
|
+
| `"step_completed"` | `{ step: string; writes: Record<string, unknown>; next_step?: string }` |
|
|
170
|
+
| `"step_failed"` | `{ step: string; attempt: number; reason: string; retryable: boolean }` |
|
|
171
|
+
| `"workflow_completed"` | `{ result: unknown }` |
|
|
172
|
+
| `"workflow_failed"` | `{ reason: string; cause: WorkflowFailureCause }` |
|
|
173
|
+
|
|
174
|
+
#### `ClaimResult`
|
|
175
|
+
|
|
176
|
+
Returned by `Engine.claimStep()` when a step is successfully claimed.
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
type ClaimResult = {
|
|
180
|
+
workflowId: string; // user-provided workflow ID
|
|
181
|
+
runId: string; // system-generated run ID
|
|
182
|
+
workflowName: string; // name of the registered workflow definition
|
|
183
|
+
step: string; // step name to execute
|
|
184
|
+
attempt: number; // attempt number (1-based)
|
|
185
|
+
seq: number; // sequence number of the step_started event
|
|
186
|
+
};
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
### `WorkflowRegistry`
|
|
192
|
+
|
|
193
|
+
Stores workflow definitions by name. Duplicate registration throws.
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
import { WorkflowRegistry } from "flingflow";
|
|
197
|
+
|
|
198
|
+
const registry = new WorkflowRegistry();
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
#### `registry.register(def)`
|
|
202
|
+
|
|
203
|
+
Register a workflow definition. Throws if `name` is already registered.
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
registry.register({
|
|
207
|
+
name: string; // unique workflow name
|
|
208
|
+
fn: WorkflowFn; // the workflow function
|
|
209
|
+
maxAttempts?: number; // max attempts per step (default: 5)
|
|
210
|
+
initialBackoffMS?: number; // delay after first failure in ms (default: 1000)
|
|
211
|
+
backoffMultiplier?: number; // exponential multiplier (default: 2)
|
|
212
|
+
maxBackoffMS?: number; // backoff cap in ms (default: 60000)
|
|
213
|
+
stepTimeoutMS?: number; // step timeout in ms (default: 300000)
|
|
214
|
+
});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
#### `registry.get(name): WorkflowDefinition | undefined`
|
|
218
|
+
|
|
219
|
+
Look up a workflow by name. Returns `undefined` if not registered.
|
|
220
|
+
|
|
221
|
+
#### `registry.has(name): boolean`
|
|
222
|
+
|
|
223
|
+
Check if a workflow name is registered.
|
|
224
|
+
|
|
225
|
+
#### `WorkflowDefinition`
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
interface WorkflowDefinition {
|
|
229
|
+
name: string;
|
|
230
|
+
fn: WorkflowFn;
|
|
231
|
+
maxAttempts: number; // always populated (default: 5)
|
|
232
|
+
initialBackoffMS: number; // always populated (default: 1000)
|
|
233
|
+
backoffMultiplier: number; // always populated (default: 2)
|
|
234
|
+
maxBackoffMS: number; // always populated (default: 60000)
|
|
235
|
+
stepTimeoutMS: number; // always populated (default: 300000)
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
### `EventStore` Interface
|
|
242
|
+
|
|
243
|
+
The persistence abstraction. All methods accept a `SimulationTask` for failpoint injection. Mutation methods return `Result` types; read methods return `Result` wrapping the data or an error.
|
|
244
|
+
|
|
245
|
+
Event payloads are stored as JSON. This means `undefined` values are silently dropped, `Date` objects become strings, `NaN`/`Infinity` become `null`, and `bigint` values will throw. Keep payloads to JSON-safe primitive types and plain objects/arrays.
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
interface EventStore {
|
|
249
|
+
initialize(): Promise<Result<void, Error>>;
|
|
250
|
+
append(event: WorkflowEvent, sim: SimulationTask): Promise<Result<void, AppendError>>;
|
|
251
|
+
appendBatch(events: WorkflowEvent[], sim: SimulationTask): Promise<Result<void, AppendError>>;
|
|
252
|
+
appendIfNoActiveWorkflow(workflowId: string, event: WorkflowEvent, sim: SimulationTask): Promise<Result<void, AppendIfNoActiveError>>;
|
|
253
|
+
getLastEvent(runId: string, sim: SimulationTask): Promise<Result<WorkflowEvent | null, Error>>;
|
|
254
|
+
getEvent(runId: string, seq: number, sim: SimulationTask): Promise<Result<WorkflowEvent | null, Error>>;
|
|
255
|
+
getCompletedEvents(runId: string, sim: SimulationTask): Promise<Result<WorkflowEvent[], Error>>;
|
|
256
|
+
getAllEvents(runId: string, sim: SimulationTask): Promise<Result<WorkflowEvent[], Error>>;
|
|
257
|
+
getActiveWorkflows(sim: SimulationTask): Promise<Result<WorkflowEvent[], Error>>;
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
#### `initialize()`
|
|
262
|
+
|
|
263
|
+
Create tables/indexes. Must be called before any other method. Returns `Result<void, Error>`.
|
|
264
|
+
|
|
265
|
+
#### `append(event, sim)`
|
|
266
|
+
|
|
267
|
+
Insert a single event. Returns `UniqueConstraintError` if `(run_id, seq)` already exists, or `WorkflowIdMismatchError` if the event's `workflow_id` doesn't match existing events for that `run_id`.
|
|
268
|
+
|
|
269
|
+
#### `appendBatch(events, sim)`
|
|
270
|
+
|
|
271
|
+
Insert multiple events atomically. If any event conflicts, the entire batch is rolled back. No partial inserts.
|
|
272
|
+
|
|
273
|
+
#### `appendIfNoActiveWorkflow(workflowId, event, sim)`
|
|
274
|
+
|
|
275
|
+
Atomically check that no active (non-terminal) run exists for the given `workflowId`, then insert the event. Returns `WorkflowAlreadyActiveError` if an active run exists.
|
|
276
|
+
|
|
277
|
+
#### `getLastEvent(runId, sim)`
|
|
278
|
+
|
|
279
|
+
Return the event with the highest `seq` for the given run, or `null` if the run doesn't exist.
|
|
280
|
+
|
|
281
|
+
#### `getEvent(runId, seq, sim)`
|
|
282
|
+
|
|
283
|
+
Return a specific event by `(run_id, seq)`, or `null` if not found.
|
|
284
|
+
|
|
285
|
+
#### `getCompletedEvents(runId, sim)`
|
|
286
|
+
|
|
287
|
+
Return all `step_completed` events for the run, ordered by `seq DESC` (newest first). Used to reconstruct the scratchpad.
|
|
288
|
+
|
|
289
|
+
#### `getAllEvents(runId, sim)`
|
|
290
|
+
|
|
291
|
+
Return all events for the run, ordered by `seq ASC`.
|
|
292
|
+
|
|
293
|
+
#### `getActiveWorkflows(sim)`
|
|
294
|
+
|
|
295
|
+
Return the last event for every run whose last event is not `workflow_completed` or `workflow_failed`. Used by recovery to find stuck or timed-out workflows.
|
|
296
|
+
|
|
297
|
+
#### Error Types
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
class UniqueConstraintError extends Error {
|
|
301
|
+
constructor(runId: string, seq: number);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
class WorkflowAlreadyActiveError extends Error {
|
|
305
|
+
public readonly activeRunId: string;
|
|
306
|
+
constructor(workflowId: string, activeRunId: string);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
class WorkflowIdMismatchError extends Error {
|
|
310
|
+
constructor(runId: string, expected: string, got: string);
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
### `MemoryEventStore`
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
import { MemoryEventStore } from "flingflow";
|
|
320
|
+
|
|
321
|
+
const store = new MemoryEventStore();
|
|
322
|
+
(await store.initialize())._unsafeUnwrap();
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
An in-memory `EventStore` backed by `Map<string, Map<number, string>>`. All payloads are JSON-serialized and deserialized on storage and retrieval to match SQLite behavior and catch serialization bugs early.
|
|
326
|
+
|
|
327
|
+
Suitable for tests and development. Data is lost when the process exits.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
### `SqliteEventStore`
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
import { SqliteEventStore } from "flingflow";
|
|
335
|
+
|
|
336
|
+
// File-based SQLite
|
|
337
|
+
const store = new SqliteEventStore("/path/to/db.sqlite");
|
|
338
|
+
|
|
339
|
+
// In-memory SQLite
|
|
340
|
+
const store = new SqliteEventStore(":memory:");
|
|
341
|
+
|
|
342
|
+
// Bring your own better-sqlite3 Database instance
|
|
343
|
+
import Database from "better-sqlite3";
|
|
344
|
+
const db = new Database(":memory:");
|
|
345
|
+
const store = new SqliteEventStore(db);
|
|
346
|
+
|
|
347
|
+
(await store.initialize())._unsafeUnwrap();
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
A `better-sqlite3`-backed `EventStore`. Uses WAL journal mode for better concurrent read performance.
|
|
351
|
+
|
|
352
|
+
Schema:
|
|
353
|
+
|
|
354
|
+
```sql
|
|
355
|
+
CREATE TABLE workflow_events (
|
|
356
|
+
run_id TEXT NOT NULL,
|
|
357
|
+
workflow_id TEXT NOT NULL,
|
|
358
|
+
seq INTEGER NOT NULL,
|
|
359
|
+
event_type TEXT NOT NULL,
|
|
360
|
+
payload TEXT NOT NULL,
|
|
361
|
+
created_at INTEGER NOT NULL,
|
|
362
|
+
PRIMARY KEY (run_id, seq)
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
CREATE INDEX idx_workflow_events_last
|
|
366
|
+
ON workflow_events(run_id, seq DESC);
|
|
367
|
+
|
|
368
|
+
CREATE INDEX idx_workflow_events_workflow
|
|
369
|
+
ON workflow_events(workflow_id);
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
#### `store.close()`
|
|
373
|
+
|
|
374
|
+
Close the underlying SQLite database connection. Only available on `SqliteEventStore`, not on the `EventStore` interface.
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
### `Engine`
|
|
379
|
+
|
|
380
|
+
The core orchestrator. Creates workflows, claims steps, executes workflow functions, and persists results. All methods return `Result` types — the engine never throws.
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
import { Engine } from "flingflow";
|
|
384
|
+
|
|
385
|
+
const engine = new Engine({
|
|
386
|
+
store: EventStore; // required
|
|
387
|
+
registry: WorkflowRegistry; // required
|
|
388
|
+
clock?: Clock; // default: SystemClock
|
|
389
|
+
generateId?: () => string; // default: crypto.randomUUID()
|
|
390
|
+
});
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
#### `engine.initialize()`
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
await engine.initialize(): Promise<Result<void, Error>>
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
Delegates to `store.initialize()`. Call once at startup.
|
|
400
|
+
|
|
401
|
+
#### `engine.createWorkflow(workflowId, name, writes, sim)`
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
await engine.createWorkflow(
|
|
405
|
+
workflowId: string,
|
|
406
|
+
name: string,
|
|
407
|
+
writes: Record<string, unknown>,
|
|
408
|
+
sim: SimulationTask,
|
|
409
|
+
): Promise<Result<string, CreateWorkflowError>> // returns runId on success
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
Records a `workflow_created` event at `seq=0` with the provided `writes` as the initial scratchpad. Returns the system-generated `runId`. Does **not** start the first step — the caller drives execution via `executeStep` or `runToCompletion`.
|
|
413
|
+
|
|
414
|
+
Returns `UnknownWorkflowError` if `name` is not registered. Returns `WorkflowAlreadyActiveError` if an active run already exists for this `workflowId`.
|
|
415
|
+
|
|
416
|
+
Simulation checkpoints: before and after the store append.
|
|
417
|
+
|
|
418
|
+
#### `engine.claimStep(runId, sim)`
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
await engine.claimStep(
|
|
422
|
+
runId: string,
|
|
423
|
+
sim: SimulationTask,
|
|
424
|
+
): Promise<Result<ClaimResult | null, Error>>
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Reads the last event, computes the next transition using `resolveTransition`, and attempts to insert `step_started`:
|
|
428
|
+
|
|
429
|
+
- **`start_step`**: inserts `step_started`, returns a `ClaimResult`.
|
|
430
|
+
- **`none`**: returns `null` (step in progress or workflow is terminal).
|
|
431
|
+
- **`complete_workflow`** / **`fail_workflow`**: returns an invariant-violation error (these transitions are unreachable — terminal events are always written atomically with the preceding step event).
|
|
432
|
+
|
|
433
|
+
If the `step_started` insert fails with `UniqueConstraintError` (another worker won the race), the error is propagated — `executeStep` handles it as contention.
|
|
434
|
+
|
|
435
|
+
Simulation checkpoints: after reading the last event, after the step_started append.
|
|
436
|
+
|
|
437
|
+
#### `engine.executeStep(runId, sim)`
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
await engine.executeStep(
|
|
441
|
+
runId: string,
|
|
442
|
+
sim: SimulationTask,
|
|
443
|
+
): Promise<Result<boolean, Error>>
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
Claims a step, builds the context, runs the workflow function, and commits the result. This is the main single-step execution primitive.
|
|
447
|
+
|
|
448
|
+
On success: commits `step_completed` (and `workflow_completed` if done) atomically via `appendBatch`.
|
|
449
|
+
|
|
450
|
+
On failure (workflow function throws):
|
|
451
|
+
- If the error is a `NonRetryableError`, records `step_failed` with `retryable: false`.
|
|
452
|
+
- Otherwise, records `step_failed` with `retryable: true`.
|
|
453
|
+
- If the failure is terminal (non-retryable or at max attempts), writes `step_failed` + `workflow_failed` atomically via `appendBatch`.
|
|
454
|
+
|
|
455
|
+
Returns `true` if a step was claimed and executed (even if the step itself failed), or if contention occurred (another worker claimed the step — the workflow is still active). Returns `false` if nothing was claimable (workflow is done or no pending transitions).
|
|
456
|
+
|
|
457
|
+
`UniqueConstraintError` from any store operation (claim contention, recovery overlap) is handled internally and returned as `ok(true)`.
|
|
458
|
+
|
|
459
|
+
Simulation failpoints: before and after the workflow function call, before the commit append.
|
|
460
|
+
|
|
461
|
+
#### `engine.runToCompletion(runId, sim)`
|
|
462
|
+
|
|
463
|
+
```typescript
|
|
464
|
+
await engine.runToCompletion(
|
|
465
|
+
runId: string,
|
|
466
|
+
sim: SimulationTask,
|
|
467
|
+
): Promise<Result<void, Error>>
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
Calls `executeStep` in a loop until it returns `false`. Drives a workflow from its current state to a terminal state (`workflow_completed` or `workflow_failed`).
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
### `runRecovery(config, sim)`
|
|
475
|
+
|
|
476
|
+
Scans for stuck and timed-out workflows and takes corrective action.
|
|
477
|
+
|
|
478
|
+
```typescript
|
|
479
|
+
import { runRecovery } from "flingflow";
|
|
480
|
+
|
|
481
|
+
const result = await runRecovery({
|
|
482
|
+
store: EventStore;
|
|
483
|
+
registry: WorkflowRegistry;
|
|
484
|
+
clock: Clock;
|
|
485
|
+
}, sim: SimulationTask);
|
|
486
|
+
|
|
487
|
+
const recovered: RecoveryResult[] = result._unsafeUnwrap();
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
Returns an array of `RecoveryResult` objects describing what was found:
|
|
491
|
+
|
|
492
|
+
```typescript
|
|
493
|
+
interface RecoveryResult {
|
|
494
|
+
runId: string;
|
|
495
|
+
reason: RecoveryReason;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
type RecoveryReason =
|
|
499
|
+
| "timeout" // step_started exceeded stepTimeoutMS
|
|
500
|
+
| "stuck_created" // workflow_created but no step ever started
|
|
501
|
+
| "stuck_completed" // step_completed but next step never claimed
|
|
502
|
+
| "stuck_failed" // step_failed (retryable) but retry never started
|
|
503
|
+
| "stuck_terminal"; // step should have been finalized but wasn't
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
Recovery logic for each active (non-terminal) workflow:
|
|
507
|
+
|
|
508
|
+
| Last Event State | Action |
|
|
509
|
+
|---|---|
|
|
510
|
+
| `step_started` and elapsed >= `stepTimeoutMS` | Appends `step_failed` with `reason: "timeout"`, `retryable: true`. If at max attempts, also appends `workflow_failed` atomically. |
|
|
511
|
+
| `step_started` and not timed out | Skipped (still in progress) |
|
|
512
|
+
| `workflow_created`, `step_completed`, `step_failed` (retryable) | Reported as stuck (caller should drive via `executeStep`) |
|
|
513
|
+
|
|
514
|
+
Simulation checkpoints: before `getActiveWorkflows`, per workflow.
|
|
515
|
+
|
|
516
|
+
Typical usage pattern:
|
|
517
|
+
|
|
518
|
+
```typescript
|
|
519
|
+
const result = await runRecovery({ store, registry, clock }, noSim);
|
|
520
|
+
if (result.isOk()) {
|
|
521
|
+
for (const r of result.value) {
|
|
522
|
+
await engine.executeStep(r.runId, noSim);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
---
|
|
528
|
+
|
|
529
|
+
### `Clock`
|
|
530
|
+
|
|
531
|
+
```typescript
|
|
532
|
+
interface Clock {
|
|
533
|
+
now(): number; // epoch ms
|
|
534
|
+
}
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
All `created_at` timestamps on events are set explicitly from `clock.now()`. No SQLite defaults.
|
|
538
|
+
|
|
539
|
+
#### `SystemClock`
|
|
540
|
+
|
|
541
|
+
```typescript
|
|
542
|
+
import { SystemClock } from "flingflow";
|
|
543
|
+
const clock = new SystemClock();
|
|
544
|
+
clock.now(); // Date.now()
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
Uses `Date.now()`. The default clock for `Engine`.
|
|
548
|
+
|
|
549
|
+
#### `ManualClock`
|
|
550
|
+
|
|
551
|
+
```typescript
|
|
552
|
+
import { ManualClock } from "flingflow";
|
|
553
|
+
|
|
554
|
+
const clock = new ManualClock(1000); // initial time: 1000ms
|
|
555
|
+
clock.now(); // 1000
|
|
556
|
+
clock.advance(500); // now() returns 1500
|
|
557
|
+
clock.set(9999); // now() returns 9999
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
For testing. Lets you control time to test timeout and recovery logic.
|
|
561
|
+
|
|
562
|
+
---
|
|
563
|
+
|
|
564
|
+
### `resolveTransition(lastEvent, maxAttempts)`
|
|
565
|
+
|
|
566
|
+
```typescript
|
|
567
|
+
import { resolveTransition } from "flingflow";
|
|
568
|
+
|
|
569
|
+
const result: TransitionResult = resolveTransition(lastEvent, maxAttempts);
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
The centralized state machine transition function. Used internally by both `Engine.claimStep` and `runRecovery`. Exported for custom orchestration or testing.
|
|
573
|
+
|
|
574
|
+
```typescript
|
|
575
|
+
type TransitionResult =
|
|
576
|
+
| { action: "start_step"; step: string; attempt: number }
|
|
577
|
+
| { action: "complete_workflow" }
|
|
578
|
+
| { action: "fail_workflow"; reason: string }
|
|
579
|
+
| { action: "none" };
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
| Input (`lastEvent.event_type`) | Output |
|
|
583
|
+
|---|---|
|
|
584
|
+
| `workflow_created` | `{ action: "start_step", step: "start", attempt: 1 }` |
|
|
585
|
+
| `step_completed` with `next_step` | `{ action: "start_step", step: next_step, attempt: 1 }` |
|
|
586
|
+
| `step_completed` without `next_step` | `{ action: "complete_workflow" }` |
|
|
587
|
+
| `step_failed`, retryable, `attempt < maxAttempts` | `{ action: "start_step", step, attempt: attempt + 1 }` |
|
|
588
|
+
| `step_failed`, retryable, `attempt >= maxAttempts` | `{ action: "fail_workflow", reason: "max attempts (N) exceeded: ..." }` |
|
|
589
|
+
| `step_failed`, non-retryable | `{ action: "fail_workflow", reason: "..." }` |
|
|
590
|
+
| `step_started`, `workflow_completed`, `workflow_failed` | `{ action: "none" }` |
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
594
|
+
### `buildContext(store, runId, workflowId, step, sim)`
|
|
595
|
+
|
|
596
|
+
```typescript
|
|
597
|
+
import { buildContext } from "flingflow";
|
|
598
|
+
|
|
599
|
+
const result = await buildContext(store, runId, workflowId, step, sim);
|
|
600
|
+
const { ctx, getPendingWrites } = result._unsafeUnwrap();
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
Constructs a `Ctx` for a step execution. Eagerly loads the full scratchpad by scanning the `workflow_created` event's `writes` and all `step_completed` events (newest-first, first match per key wins).
|
|
604
|
+
|
|
605
|
+
Returns a `Result` containing:
|
|
606
|
+
- `ctx` — the `Ctx` object to pass to the workflow function.
|
|
607
|
+
- `getPendingWrites()` — returns a snapshot of all buffered `ctx.set()` calls as `Record<string, unknown>`. Used by the engine to persist writes on step completion.
|
|
608
|
+
|
|
609
|
+
---
|
|
610
|
+
|
|
611
|
+
### Failure Handling
|
|
612
|
+
|
|
613
|
+
#### Retryable Failures (default)
|
|
614
|
+
|
|
615
|
+
Any `Error` thrown by a workflow function is recorded as `step_failed` with `retryable: true`. The engine retries with exponential backoff up to `maxAttempts` (default: 5). Backoff formula: attempt 1 = no delay, attempt N delay = min(initialBackoffMS * backoffMultiplier^(N-2), maxBackoffMS).
|
|
616
|
+
|
|
617
|
+
#### Non-Retryable Failures
|
|
618
|
+
|
|
619
|
+
Import `NonRetryableError` from flingflow and throw it:
|
|
620
|
+
|
|
621
|
+
```typescript
|
|
622
|
+
import { NonRetryableError } from "flingflow";
|
|
623
|
+
|
|
624
|
+
throw new NonRetryableError("invalid input");
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
The engine records `step_failed` with `retryable: false` and immediately writes `workflow_failed` atomically in the same batch.
|
|
628
|
+
|
|
629
|
+
#### Max Attempts Exceeded
|
|
630
|
+
|
|
631
|
+
When a retryable step failure occurs at `attempt >= maxAttempts`, the engine writes `step_failed` + `workflow_failed` atomically via `appendBatch` with reason `"max attempts (N) exceeded: <last error>"`.
|
|
632
|
+
|
|
633
|
+
---
|
|
634
|
+
|
|
635
|
+
### Simulation Testing
|
|
636
|
+
|
|
637
|
+
The engine integrates with the [`determined`](https://www.npmjs.com/package/determined) package for deterministic simulation testing. Every engine and store method accepts a `SimulationTask` parameter.
|
|
638
|
+
|
|
639
|
+
- **Checkpoints** (`sim.checkpoint()`): placed at I/O boundaries (before/after store reads/writes). Lets `determined` interleave concurrent workers at these points.
|
|
640
|
+
- **Failpoints** (`sim.failpoint()`): placed around workflow function calls and commit operations. Lets `determined` inject failures to test crash recovery.
|
|
641
|
+
|
|
642
|
+
In production, pass a `NoSimulationTask`. In tests, use `SimulationImpl.runTasks()` to run multiple concurrent workers with controlled interleaving.
|
|
643
|
+
|
|
644
|
+
```typescript
|
|
645
|
+
import { SimulationImpl, SimpleEntropySource, type TaskSpec } from "determined";
|
|
646
|
+
|
|
647
|
+
const sim = new SimulationImpl(logger, new SimpleEntropySource(), 0.3);
|
|
648
|
+
|
|
649
|
+
await sim.runTasks([
|
|
650
|
+
{ name: "worker-1", f: async (task) => { await engine.executeStep(runId, task); } },
|
|
651
|
+
{ name: "worker-2", f: async (task) => { await engine.executeStep(runId, task); } },
|
|
652
|
+
] as const);
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
---
|
|
656
|
+
|
|
657
|
+
## File Structure
|
|
658
|
+
|
|
659
|
+
```
|
|
660
|
+
src/
|
|
661
|
+
types.ts — Core types, discriminated union WorkflowEvent, NonRetryableError, re-exports from determined
|
|
662
|
+
clock.ts — Clock interface, SystemClock, ManualClock
|
|
663
|
+
transitions.ts — resolveTransition() state machine helper
|
|
664
|
+
store.ts — EventStore interface, error types (UniqueConstraintError, WorkflowAlreadyActiveError, WorkflowIdMismatchError)
|
|
665
|
+
store-memory.ts — In-memory EventStore (JSON round-trips payloads)
|
|
666
|
+
store-sqlite.ts — better-sqlite3 EventStore
|
|
667
|
+
context.ts — buildContext(): scratchpad loading + buffered writes
|
|
668
|
+
registry.ts — WorkflowRegistry + WorkflowDefinition
|
|
669
|
+
engine.ts — Engine class: createWorkflow, claimStep, executeStep, runToCompletion
|
|
670
|
+
recovery.ts — runRecovery(): timeout detection, stuck workflow recovery
|
|
671
|
+
index.ts — Barrel exports
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
## Spec Deviations
|
|
675
|
+
|
|
676
|
+
- `workflow_created` payload includes `workflowName` (not in SPEC) — needed to look up the workflow function from the registry. It also includes `config` with the retry/backoff configuration sealed at creation time.
|
|
677
|
+
- `created_at` stored as epoch ms integer (not DATETIME string) — always set from `clock.now()`, never from SQLite defaults.
|
|
678
|
+
- `EventStore` has `getEvent(runId, seq)` — avoids fetching all events when only event 0 is needed.
|
|
679
|
+
- `createWorkflow` does **not** auto-kick the first step (SPEC's trigger endpoint does) — keeps the engine pure and testable; the caller drives execution.
|