diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9feece3..b50d663 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,3 +29,28 @@ jobs: working-directory: starter-vite-tsc - run: pnpm build working-directory: starter-vite-tsc + + node-scripts: + strategy: + matrix: + node-version: [16, 18, 20] + os: [ubuntu-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - uses: pnpm/action-setup@v2 + with: + version: 8 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'pnpm' + - run: pnpm install + working-directory: node-scripts + - run: pnpm tsc + working-directory: node-scripts + - run: pnpm tsx src/fs-write-file.ts + working-directory: node-scripts + - run: pnpm tsx src/async-promises.ts + working-directory: node-scripts diff --git a/.vscode/operators.code-snippets b/.vscode/operators.code-snippets new file mode 100644 index 0000000..1048c7b --- /dev/null +++ b/.vscode/operators.code-snippets @@ -0,0 +1,22 @@ +{ + "Effect Gen Function": { + "prefix": "egen", + "body": ["Effect.gen(function* ($) {\n\t$0\n})"], + "description": "Effect generator FUnction with $ input" + }, + "Gen Function": { + "prefix": "gen", + "body": ["function* ($) {}"], + "description": "Generator FUnction with $ input" + }, + "Gen Yield * tmp": { + "prefix": "yy", + "body": ["yield* $($0)"], + "description": "Yield generator calling $()" + }, + "Gen Yield *": { + "prefix": "!", + "body": ["yield* $($0)"], + "description": "Yield generator calling $()" + } +} diff --git a/flake.nix b/flake.nix index 11b948e..b317b14 100644 --- a/flake.nix +++ b/flake.nix @@ -16,6 +16,7 @@ { devShell = with pkgs; pkgs.mkShell { buildInputs = [ + act nodejs_20 corepack ]; diff --git a/node-scripts/src/async-promises.ts b/node-scripts/src/async-promises.ts new file mode 100644 index 0000000..72373d8 --- /dev/null +++ b/node-scripts/src/async-promises.ts @@ -0,0 +1,51 @@ +import * as Node from '@effect/platform-node/Runtime' +import { Cause, Duration, Effect } from 'effect' +import { TaggedClass } from 'effect/Data' + +// --- HELPERS --- + +const getMagicNumber = async () => { + await sleep(200) + + return 42 +} + +const throwSomeError = async () => { + throw new Error('some error') +} + +const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) + +class MyCustomError extends TaggedClass('MyCustomError')<{ readonly cause: unknown }> {} + +const someEffect = Effect.succeed(69).pipe(Effect.delay(Duration.seconds(0.5))) + +const someAsyncFnRunningAnEffect = async () => { + const result = await Effect.runPromise(someEffect) + + return result +} + +// --- MAIN --- + +const main = Effect.gen(function* ($) { + // calling a async function/promise from Effect + const result1 = yield* $(Effect.promise(() => getMagicNumber())) + + console.log('Got result 1:', result1) + + // calling a async function/promise from Effect (with error handling) + const result2 = yield* $( + Effect.tryPromise({ try: () => throwSomeError(), catch: (cause) => new MyCustomError({ cause }) }), + Effect.catchTag('MyCustomError', (error) => Effect.succeed(`Got error: ${error.cause}`)), + ) + + console.log('Got result 2:', result2) + + // calling an Effect from an async function/promise + const result3 = yield* $(Effect.promise(() => someAsyncFnRunningAnEffect())) + + console.log('Got result 3:', result3) +}) + +Node.runMain(main.pipe(Effect.tapErrorCause((_) => Effect.log(Cause.pretty(_))))) diff --git a/node-scripts/tsconfig.json b/node-scripts/tsconfig.json new file mode 100644 index 0000000..867e1e9 --- /dev/null +++ b/node-scripts/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "noEmit": true, + "module": "Node16", + "moduleResolution": "Node16", + "strict": true, + "plugins": [{ "name": "@effect/language-service" }], + }, + "include": ["src/**/*.ts"] +}