diff --git a/.github/workflows/deno-ci.yml b/.github/workflows/deno-ci.yml index b4c770a..ae13b62 100644 --- a/.github/workflows/deno-ci.yml +++ b/.github/workflows/deno-ci.yml @@ -29,15 +29,16 @@ jobs: with: deno-version: ${{ matrix.deno-version }} - - name: Cache https:// deps + - name: Cache Deno deps uses: actions/cache@v4 with: - path: | - ~/.cache/deno/deps/https - ~/.cache/deno/remote/https + path: ~/.cache/deno key: deno/${{ matrix.deno-version }}-https/v1-${{ github.sha }} restore-keys: deno/${{ matrix.deno-version }}-https/v1- + - name: 'Possibly reset lockfile' + run: deno install || rm deno.lock + - name: Check client/mod.ts if: always() run: time deno check lib/client/mod.ts @@ -56,6 +57,42 @@ jobs: lib/encoding/ lib/extras/ + check-publish: + runs-on: ubuntu-latest + name: Check JSR Publish + + steps: + - uses: actions/checkout@v5 + + - uses: denoland/setup-deno@v2 + with: + deno-version: v2.4 + + - name: Check publish rules + run: deno publish --dry-run --allow-dirty + + publish: + runs-on: ubuntu-latest + name: JSR Publish + needs: + - build + - check-publish + if: github.event_name == 'push' + + permissions: + contents: read + id-token: write + + steps: + - uses: actions/checkout@v5 + + - uses: denoland/setup-deno@v2 + with: + deno-version: v2.4 + + - name: Publish now + run: deno publish + build-web-service: runs-on: ubuntu-latest @@ -78,18 +115,19 @@ jobs: with: deno-version: ${{ matrix.deno-version }} - - name: Cache https:// deps + - name: Cache Deno deps uses: actions/cache@v4 with: - path: | - ~/.cache/deno/deps/https - ~/.cache/deno/remote/https + path: ~/.cache/deno key: deno/${{ matrix.deno-version }}-https/v1-${{ github.sha }} restore-keys: deno/${{ matrix.deno-version }}-https/v1- + - name: 'Possibly reset lockfile' + run: deno install || rm deno.lock + - name: Check generation/deploy/mod.ts if: always() - run: time deno check --allow-import=cdn.skypack.dev,deno.land generation/deploy/mod.ts + run: time deno check generation/deploy/mod.ts validate-codegen: runs-on: ubuntu-latest @@ -116,15 +154,16 @@ jobs: with: deno-version: ${{ matrix.deno-version }} - - name: Cache https:// deps + - name: Cache Deno deps uses: actions/cache@v4 with: - path: | - ~/.cache/deno/deps/https - ~/.cache/deno/remote/https + path: ~/.cache/deno key: deno/${{ matrix.deno-version }}-https/v1-${{ github.sha }} restore-keys: deno/${{ matrix.deno-version }}-https/v1- + - name: 'Possibly reset lockfile' + run: deno install || rm deno.lock + - name: Validate aws-sdk fixtures if: always() run: time deno run -A generation/script/validate-fixtures.ts @@ -156,12 +195,10 @@ jobs: with: deno-version: ${{ matrix.deno-version }} - - name: Cache https:// deps + - name: Cache Deno deps uses: actions/cache@v4 with: - path: | - ~/.cache/deno/deps/https - ~/.cache/deno/remote/https + path: ~/.cache/deno key: deno/${{ matrix.deno-version }}-https/v1-${{ github.sha }} restore-keys: deno/${{ matrix.deno-version }}-https/v1- diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..a52c808 --- /dev/null +++ b/deno.json @@ -0,0 +1,18 @@ +{ + "tasks": { + "deploy:dev": "deno run --watch --allow-env --allow-sys --allow-read --allow-net='[::]:8000,otel.devmode.cloud,api.github.com,raw.githubusercontent.com' generation/deploy/mod.ts" + }, + "workspace": [ + "./generation", + "./lib" + ], + "imports": { + "@cloudydeno/jmespath": "jsr:@cloudydeno/jmespath@^1", + "@cloudydeno/opentelemetry": "jsr:@cloudydeno/opentelemetry@^0.10", + "@std/assert": "jsr:@std/assert@^1", + "@std/cache": "jsr:@std/cache@^0.2", + "@std/csv": "jsr:@std/csv@^1", + "@std/html": "jsr:@std/html@^1", + "@std/path": "jsr:@std/path@^1" + } +} diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..e0f1de7 --- /dev/null +++ b/deno.lock @@ -0,0 +1,220 @@ +{ + "version": "5", + "specifiers": { + "jsr:@cloudydeno/jmespath@1": "1.0.1", + "jsr:@cloudydeno/opentelemetry@0.10": "0.10.3", + "jsr:@cloudydeno/shimmer@1.2.1": "1.2.1", + "jsr:@cloudydeno/stream-observables@^1.4.1": "1.4.1", + "jsr:@sallai/ask@^2.0.2": "2.0.2", + "jsr:@sallai/iro@^1.0.3": "1.0.4", + "jsr:@std/assert@1": "1.0.14", + "jsr:@std/assert@^1.0.14": "1.0.14", + "jsr:@std/async@^1.0.14": "1.0.14", + "jsr:@std/bytes@^1.0.5": "1.0.6", + "jsr:@std/bytes@^1.0.6": "1.0.6", + "jsr:@std/cache@0.2": "0.2.0", + "jsr:@std/cli@^1.0.22": "1.0.22", + "jsr:@std/csv@1": "1.0.6", + "jsr:@std/encoding@1.0.10": "1.0.10", + "jsr:@std/encoding@^1.0.10": "1.0.10", + "jsr:@std/html@1": "1.0.4", + "jsr:@std/internal@^1.0.10": "1.0.10", + "jsr:@std/io@0.225": "0.225.2", + "jsr:@std/path@1": "1.1.2", + "jsr:@std/streams@^1.0.9": "1.0.12", + "jsr:@takker/md5@0.1": "0.1.0", + "jsr:@takker/md5@0.1.0": "0.1.0", + "npm:http-cache-semantics@4.2.0": "4.2.0" + }, + "jsr": { + "@cloudydeno/jmespath@1.0.1": { + "integrity": "de46849bf1dea8819bb2c6f574f2ca7faf25d14c36675407df797cccf76bf354" + }, + "@cloudydeno/opentelemetry@0.10.3": { + "integrity": "a678c8cac0853b6097ad0291274a60baa185a377cb9c34fc2340836c58644345", + "dependencies": [ + "jsr:@cloudydeno/shimmer" + ] + }, + "@cloudydeno/shimmer@1.2.1": { + "integrity": "6d7cf8ba798532a9beb963937977e28e26dbd4e020b38f828a411aaacb34c3b2" + }, + "@cloudydeno/stream-observables@1.4.1": { + "integrity": "555aa3d786fcfd066d096fc943ea47afc688618e95146e615705e981008f57c0" + }, + "@sallai/ask@2.0.2": { + "integrity": "8a1d3cfe5f5a1d4b1e66412c7537f8879b8e70b949076ae9d2e05cff4a82ab42", + "dependencies": [ + "jsr:@sallai/iro", + "jsr:@std/io" + ] + }, + "@sallai/iro@1.0.4": { + "integrity": "e14f39c7b80e80994788a8542b2c4983554fd4bb6d2f2a09471327f9cf37ee36" + }, + "@std/assert@1.0.14": { + "integrity": "68d0d4a43b365abc927f45a9b85c639ea18a9fab96ad92281e493e4ed84abaa4", + "dependencies": [ + "jsr:@std/internal" + ] + }, + "@std/async@1.0.14": { + "integrity": "62e954a418652c704d37563a3e54a37d4cf0268a9dcaeac1660cc652880b5326" + }, + "@std/bytes@1.0.6": { + "integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a" + }, + "@std/cache@0.2.0": { + "integrity": "63a2ccd5a9e7c03e430f7d34dfcfd0d0cfc90731a1eaf8208f4c66e418fc3035" + }, + "@std/cli@1.0.22": { + "integrity": "50d1e4f87887cb8a8afa29b88505ab5081188f5cad3985460c3b471fa49ff21a" + }, + "@std/csv@1.0.6": { + "integrity": "52ef0e62799a0028d278fa04762f17f9bd263fad9a8e7f98c14fbd371d62d9fd", + "dependencies": [ + "jsr:@std/streams" + ] + }, + "@std/encoding@1.0.10": { + "integrity": "8783c6384a2d13abd5e9e87a7ae0520a30e9f56aeeaa3bdf910a3eaaf5c811a1" + }, + "@std/html@1.0.4": { + "integrity": "eff3497c08164e6ada49b7f81a28b5108087033823153d065e3f89467dd3d50e" + }, + "@std/internal@1.0.10": { + "integrity": "e3be62ce42cab0e177c27698e5d9800122f67b766a0bea6ca4867886cbde8cf7" + }, + "@std/io@0.225.2": { + "integrity": "3c740cd4ee4c082e6cfc86458f47e2ab7cb353dc6234d5e9b1f91a2de5f4d6c7", + "dependencies": [ + "jsr:@std/bytes@^1.0.5" + ] + }, + "@std/path@1.1.2": { + "integrity": "c0b13b97dfe06546d5e16bf3966b1cadf92e1cc83e56ba5476ad8b498d9e3038", + "dependencies": [ + "jsr:@std/internal" + ] + }, + "@std/streams@1.0.12": { + "integrity": "ae925fa1dc459b1abf5cbaa28cc5c7b0485853af3b2a384b0dc22d86e59dfbf4", + "dependencies": [ + "jsr:@std/bytes@^1.0.6" + ] + }, + "@takker/md5@0.1.0": { + "integrity": "4c423d8247aadf7bcb1eb83c727bf28c05c21906e916517395d00aa157b6eae0" + } + }, + "npm": { + "http-cache-semantics@4.2.0": { + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==" + } + }, + "redirects": { + "https://esm.sh/shimmer": "https://esm.sh/shimmer@1.2.1" + }, + "remote": { + "https://deno.land/std@0.104.0/_util/assert.ts": "2f868145a042a11d5ad0a3c748dcf580add8a0dbc0e876eaa0026303a5488f58", + "https://deno.land/std@0.104.0/bytes/bytes_list.ts": "a13287edb03f19d27ba4927dec6d6de3e5bd46254cd4aee6f7e5815810122673", + "https://deno.land/std@0.104.0/bytes/mod.ts": "1ae1ccfe98c4b979f12b015982c7444f81fcb921bea7aa215bf37d84f46e1e13", + "https://deno.land/std@0.104.0/fmt/colors.ts": "d2f8355f00a74404668fc5a1e4a92983ce1a9b0a6ac1d40efbd681cb8f519586", + "https://deno.land/std@0.104.0/fs/exists.ts": "b0d2e31654819cc2a8d37df45d6b14686c0cc1d802e9ff09e902a63e98b85a00", + "https://deno.land/std@0.104.0/io/buffer.ts": "3ead6bb11276ebcf093c403f74f67fd2205a515dbbb9061862c468ca56f37cd8", + "https://deno.land/std@0.104.0/io/bufio.ts": "6024117aa37f8d21a116654bd5ca5191d803f6492bbc744e3cee5054d0e900d1", + "https://deno.land/std@0.104.0/io/util.ts": "85c33d61b20fd706acc094fe80d4c8ae618b04abcf3a96ca2b47071842c1c8ac", + "https://deno.land/std@0.104.0/log/handlers.ts": "8c7221a2408b4097e186b018f3f1a18865d20b98761aa1dccaf1ee3d57298355", + "https://deno.land/std@0.104.0/log/levels.ts": "088a883039ece5fa0da5f74bc7688654045ea7cb01bf200b438191a28d728eae", + "https://deno.land/std@0.104.0/log/logger.ts": "6b2dd8cbe6f407100b9becfe61595d7681f8ce3692412fad843de84d617a038e", + "https://deno.land/std@0.104.0/log/mod.ts": "91711789b28803082b1bdfb123d2c9685a7e01767f2e79c0a82706063ad964d8", + "https://deno.land/std@0.104.0/testing/_diff.ts": "5d3693155f561d1a5443ac751ac70aab9f5d67b4819a621d4b96b8a1a1c89620", + "https://deno.land/std@0.104.0/testing/asserts.ts": "e4311d45d956459d4423bc267208fe154b5294989da2ed93257b6a85cae0427e", + "https://deno.land/std@0.160.0/encoding/hex.ts": "4cc5324417cbb4ac9b828453d35aed45b9cc29506fad658f1f138d981ae33795", + "https://deno.land/std@0.160.0/hash/md5.ts": "5df247e8d9e0abeb555ed8ff39d39c0c3240f52847bfb72e363ad582a102527c", + "https://deno.land/std@0.177.0/_util/asserts.ts": "178dfc49a464aee693a7e285567b3d0b555dc805ff490505a8aae34f9cfb1462", + "https://deno.land/std@0.177.0/_util/os.ts": "d932f56d41e4f6a6093d56044e29ce637f8dcc43c5a90af43504a889cf1775e3", + "https://deno.land/std@0.177.0/async/pool.ts": "fd082bd4aaf26445909889435a5c74334c017847842ec035739b4ae637ae8260", + "https://deno.land/std@0.177.0/encoding/base64.ts": "7de04c2f8aeeb41453b09b186480be90f2ff357613b988e99fabb91d2eeceba1", + "https://deno.land/std@0.177.0/flags/mod.ts": "d1cdefa18472ef69858a17df5cf7c98445ed27ac10e1460183081303b0ebc270", + "https://deno.land/std@0.177.0/fmt/colors.ts": "938c5d44d889fb82eff6c358bea8baa7e85950a16c9f6dae3ec3a7a729164471", + "https://deno.land/std@0.177.0/path/_constants.ts": "e49961f6f4f48039c0dfed3c3f93e963ca3d92791c9d478ac5b43183413136e0", + "https://deno.land/std@0.177.0/path/_interface.ts": "6471159dfbbc357e03882c2266d21ef9afdb1e4aa771b0545e90db58a0ba314b", + "https://deno.land/std@0.177.0/path/_util.ts": "d7abb1e0dea065f427b89156e28cdeb32b045870acdf865833ba808a73b576d0", + "https://deno.land/std@0.177.0/path/common.ts": "ee7505ab01fd22de3963b64e46cff31f40de34f9f8de1fff6a1bd2fe79380000", + "https://deno.land/std@0.177.0/path/glob.ts": "d479e0a695621c94d3fd7fe7abd4f9499caf32a8de13f25073451c6ef420a4e1", + "https://deno.land/std@0.177.0/path/mod.ts": "4b83694ac500d7d31b0cdafc927080a53dc0c3027eb2895790fb155082b0d232", + "https://deno.land/std@0.177.0/path/posix.ts": "8b7c67ac338714b30c816079303d0285dd24af6b284f7ad63da5b27372a2c94d", + "https://deno.land/std@0.177.0/path/separator.ts": "0fb679739d0d1d7bf45b68dacfb4ec7563597a902edbaf3c59b50d5bcadd93b1", + "https://deno.land/std@0.177.0/path/win32.ts": "d186344e5583bcbf8b18af416d13d82b35a317116e6460a5a3953508c3de5bba", + "https://deno.land/std@0.177.0/testing/_diff.ts": "1a3c044aedf77647d6cac86b798c6417603361b66b54c53331b312caeb447aea", + "https://deno.land/std@0.177.0/testing/_format.ts": "a69126e8a469009adf4cf2a50af889aca364c349797e63174884a52ff75cf4c7", + "https://deno.land/std@0.177.0/testing/asserts.ts": "984ab0bfb3faeed92ffaa3a6b06536c66811185328c5dd146257c702c41b01ab", + "https://deno.land/x/csv@v0.6.0/deps.ts": "4f538492c176e239c4c394ac59c5d085a0e8ad2b92bb1d13e4ed9e4ec855ecf6", + "https://deno.land/x/csv@v0.6.0/mod.ts": "2a13285c8716257aa5d6b5021d45c74dcb275eaaa46776106ddf78b071cabd88", + "https://deno.land/x/csv@v0.6.0/reader.ts": "b1cc94a85511782e14cb8dde4a5f3f4c16388e1312d32f38535fda1890d46abf", + "https://deno.land/x/csv@v0.6.0/utils.ts": "c12632d89129e115a6cdebec536349f74906b2cac2dae80838b8bc2c659ef9c8", + "https://deno.land/x/csv@v0.6.0/writer.ts": "a1f96922b6d12e5f88b3b4c648527c43361ed22efcac68f5793de032adc569e3", + "https://deno.land/x/html_escape@v1.1.5/escape.ts": "36f6d64ba196de17aec153c977d9581f8ce9df4643e659e4a6575a1a6fe2df47", + "https://deno.land/x/jmespath@v0.2.2/Lexer.ts": "4b99f6b34b92fad32dd43e436c5d2f70e1156d42a2b747a95b2d752196d9ab1b", + "https://deno.land/x/jmespath@v0.2.2/Parser.ts": "63d63c3faede516fdfbeed9e696caa694f835947fc264252506b5fe9db39deea", + "https://deno.land/x/jmespath@v0.2.2/Runtime.ts": "8281cbff7922a795125525bb3ce7f48406ef67d2de9b33e81f5c2a22791def32", + "https://deno.land/x/jmespath@v0.2.2/TreeInterpreter.ts": "ead002e5d78ab248c7c305e564538bc4dd70cc94417398c638f2e2fab5a9e700", + "https://deno.land/x/jmespath@v0.2.2/index.ts": "465015b79aa345287758ba6596301960a9a7e99f6499256be958c3f368ae7c9d", + "https://deno.land/x/jmespath@v0.2.2/utils/index.ts": "975cc174afcfa7b0f38099597a00ba3579b05bbd0d0961aedab5b15c5707ce66", + "https://deno.land/x/lru@1.0.2/mod.ts": "1d44b87c4d40ff33749ae5fd85fe234344e0dace835fdfeb48413edea9461159", + "https://deno.land/x/observability@v0.5.3/instrumentation/auto.ts": "1fe4089151dd951bac44202f81ca86f0e7ef79aa604d30190f9e09da744203f3", + "https://deno.land/x/observability@v0.5.3/instrumentation/deno-kv.ts": "978f8fe388c01ba2b9cfd6cd813df64d17509c76727914a4620e0534d3b6c8f2", + "https://deno.land/x/observability@v0.5.3/instrumentation/deno-run.ts": "3769546406a970f797d3c04ddf9382cf4db3738af3be9a46830c83d71fab36b8", + "https://deno.land/x/observability@v0.5.3/instrumentation/deno-runtime.ts": "dc32e437b348ef3e7f5ba143417ebafa9ca817d7826b3c445a06d2be75ea7599", + "https://deno.land/x/observability@v0.5.3/instrumentation/fetch.ts": "6c79835a146ca079da1766b69fe621f743509e52b0134f26f2d8e66e856df644", + "https://deno.land/x/observability@v0.5.3/instrumentation/http-server.ts": "739f8475d5cb12f6a90248e5a02ec232ca407638449101e569aa68c080d62fd9", + "https://deno.land/x/observability@v0.5.3/opentelemetry/api-logs.js": "353ebfe8415cd4c26c786415a71b8893b60e47ab8a916c0fdfe92e8a27c4eb9d", + "https://deno.land/x/observability@v0.5.3/opentelemetry/api.js": "1987c95d9783d69d197fb1ee9f61f2d1ad0bcb4c471c0bb41fa4086e246e34e6", + "https://deno.land/x/observability@v0.5.3/opentelemetry/core.js": "1f71dd13c17e0e13f95cb227129de941bb7a631e0805b72fb524f75f1f3cddc0", + "https://deno.land/x/observability@v0.5.3/opentelemetry/exporter-metrics-otlp-http.js": "36d862bcc995cc3f746ae9762c64fb98ab3fb03aa92b7e7e9ab62368e0658649", + "https://deno.land/x/observability@v0.5.3/opentelemetry/instrumentation.js": "de19519c35842fa1c024c0df19d9e62513a5c94d6ff13098ae259d7985e2d1e7", + "https://deno.land/x/observability@v0.5.3/opentelemetry/otlp-exporter-base.js": "da986e3a1427d98fa433db7c61bc2d3f2392ae45f00b3e11c2f6fce47ae028d2", + "https://deno.land/x/observability@v0.5.3/opentelemetry/otlp-transformer.js": "3fddbf62ad699c0a4e736cdc2aa2e70c634d076182081676e8d90a8f0eff162b", + "https://deno.land/x/observability@v0.5.3/opentelemetry/resources.js": "1ff53338f820978b71035fd166087fe6ced229849ede713ed2a229016a31073a", + "https://deno.land/x/observability@v0.5.3/opentelemetry/sdk-logs.js": "10f16cd98837f95eccb8c1f650abbfe4418f07aad7bb3a094d21bbb4d8f2b7fd", + "https://deno.land/x/observability@v0.5.3/opentelemetry/sdk-metrics.js": "47890192dcfdf57afe3a7ea9bddb0c59b7c48e6751caca32d17cda74493a6fee", + "https://deno.land/x/observability@v0.5.3/opentelemetry/sdk-trace-base.js": "dd19bc066eea555a447222bc2eab447669059f7383c2c60d419ed88978f79fbb", + "https://deno.land/x/observability@v0.5.3/opentelemetry/semantic-conventions.js": "e4534682aaf9bbf7ff1626de225626a24561b1535f731291c55af21e95f2545e", + "https://deno.land/x/observability@v0.5.3/otel-platform/context-manager.ts": "8ec46d784c3058cc5309de74b32cdad131f5bd68ee34f3b914e2dd0fe5bba514", + "https://deno.land/x/observability@v0.5.3/otel-platform/detectors.ts": "5f477af0adcc31d10cbfdfbcbe874b7eeae10b199c72f8d637eaaec7c47d3dbb", + "https://deno.land/x/observability@v0.5.3/otel-platform/otlp-json-exporters.ts": "a6d11dd6ba200390f15abfbb65d6a4d77d5386f000694324a6fba71a64a3684d", + "https://deno.land/x/observability@v0.5.3/sdk.ts": "37f1f1a34892db40c323db4a53b603029cd127082a082bd3390ccdc0761d122b", + "https://deno.land/x/stream_observables@v1.2/sinks/collect.ts": "8502907955cfbd0a843781134aa742a9081bfa5b580d81959f39033166bd95df", + "https://deno.land/x/stream_observables@v1.2/sources/external.ts": "02d02d06085765a61fc0357c7031cc34eb81e6a873aa1d986e00dff63adcb1a6", + "https://deno.land/x/stream_observables@v1.2/sources/just.ts": "14e7179ce5e02fec65ef7b544b0b820ccc43dded0be2d8cdd0eac22001957572", + "https://deno.land/x/stream_observables@v1.2/transforms/map.ts": "40f9e305a0425d0ee48c17b3268757ce5030cc9c45ba537e0242bd95dfcedd21", + "https://deno.land/x/stream_observables@v1.2/types.ts": "3933df0a0e584ff35a596157834eebf0bc2844d0b96bf3e4349e6fd3c4bd27a6", + "https://esm.sh/shimmer@1.2.1": "81f32087a6dbcf26b1953fe14629caf1b1fe92d1aac3370acb4d33a233680987", + "https://esm.sh/shimmer@1.2.1/denonext/shimmer.mjs": "6b2cc25472ebc0a0627a087fa0ae919121903f9494da796e8ed59c4067651f56" + }, + "workspace": { + "dependencies": [ + "jsr:@cloudydeno/jmespath@1", + "jsr:@cloudydeno/opentelemetry@0.10", + "jsr:@std/assert@1", + "jsr:@std/cache@0.2", + "jsr:@std/csv@1", + "jsr:@std/html@1", + "jsr:@std/path@1" + ], + "members": { + "lib": { + "dependencies": [ + "jsr:@cloudydeno/stream-observables@^1.4.1", + "jsr:@sallai/ask@^2.0.2", + "jsr:@std/assert@^1.0.14", + "jsr:@std/async@^1.0.14", + "jsr:@std/cli@^1.0.22", + "jsr:@std/encoding@^1.0.10", + "jsr:@takker/md5@0.1" + ] + } + } + } +} diff --git a/generation/code-gen.ts b/generation/code-gen.ts index 220fcc4..70b8b63 100644 --- a/generation/code-gen.ts +++ b/generation/code-gen.ts @@ -1,6 +1,6 @@ import type * as Schema from './sdk-schema.ts'; import { ShapeLibrary } from './shape-library.ts'; -import { makeHelperLibrary } from "./helper-library.ts"; +import { HelperLibrary, makeHelperLibrary } from "./helper-library.ts"; import { makeProtocolCodegenFor } from "./protocol.ts"; import { fixupApiSpec, fixupWaitersSpec } from './quirks.ts'; @@ -21,7 +21,10 @@ export default class ServiceCodeGen { useAuthType: boolean; // for aws-api v0.6.0 alwaysReqLists: boolean; // for codegen v0.2 and earlier streamingResponses: boolean; // for codegen v0.3 and earlier - useStdJsr: boolean; + useJsr: boolean; // for codegen v0.4 and earlier + useImportMap: boolean; // for codegen v0.4 and earlier + stdModRoot: string | null; + awsApiRoot: string | null; shapes: ShapeLibrary; constructor(specs: { @@ -43,13 +46,17 @@ export default class ServiceCodeGen { this.docMode = 'none'; } + this.stdModRoot = opts.get('std_mod_root') || null; + this.awsApiRoot = opts.get('aws_api_root') || null; + this.includeOpts = (opts.get('includeOpts') || 'yes') !== 'no'; this.includeJsonRemap = (opts.get('includeJsonRemap') || 'yes') !== 'no'; this.includeClientExtras = (opts.get('includeClientExtras') || 'yes') !== 'no'; this.useAuthType = (opts.get('useAuthType') || 'yes') !== 'no'; this.alwaysReqLists = (opts.get('alwaysReqLists') || 'no') !== 'no'; this.streamingResponses = (opts.get('streamingResponses') || 'yes') !== 'no'; - this.useStdJsr = (opts.get('useStdJsr') || 'yes') !== 'no'; + this.useJsr = (opts.get('useJsr') || 'yes') !== 'no'; + this.useImportMap = (opts.get('useImportMap') || 'yes') !== 'no'; // mutate the specs to fix inaccuracies fixupApiSpec(this.apiSpec); @@ -60,10 +67,25 @@ export default class ServiceCodeGen { this.shapes = ShapeLibrary.fromApiSpec(specs.api); } + private renderHelperString(helpers: HelperLibrary) { + let helperSource = helpers.toSourceString(); + if (this.stdModRoot) { + // TODO: intentionally excluding md5 imports, as it was removed from std later on + helperSource = helperSource.replaceAll(/from "https:\/\/deno.land\/std@[0-9.]+\/([^"]+)/g, (orig, pkg) => pkg.includes('md5') ? orig : `from "${this.stdModRoot}/${pkg}`) + } + if (this.awsApiRoot) { + helperSource = helperSource.replaceAll('@cloudydeno/aws-api', this.awsApiRoot); + } + if (this.useImportMap) { + helperSource = helperSource.replaceAll(/from "jsr:(@[^\/]+\/[^@\/]+)@[^\/"]+/g, (_, x) => `from "${x}`); + } + return helperSource; + } + generateTypescript(namespace: string): string { const helpers = makeHelperLibrary({ isTest: this.isTest, - useStdJsr: this.useStdJsr, + useJsr: this.useJsr, }); const protocol = makeProtocolCodegenFor(this.apiSpec.metadata, this.shapes, helpers, { includeJsonRemap: this.includeJsonRemap, @@ -94,7 +116,7 @@ export default class ServiceCodeGen { return [ `// Autogenerated API client for: ${this.apiSpec.metadata.serviceFullName}`, - helpers.toSourceString(), + this.renderHelperString(helpers), chunks.join('\n'), ].filter(x => x).join('\n\n'); } @@ -102,7 +124,7 @@ export default class ServiceCodeGen { generateModTypescript(namespace: string): string { const helpers = makeHelperLibrary({ isTest: this.isTest, - useStdJsr: this.useStdJsr, + useJsr: this.useJsr, }); const protocol = makeProtocolCodegenFor(this.apiSpec.metadata, this.shapes, helpers, { includeJsonRemap: this.includeJsonRemap, @@ -131,7 +153,7 @@ export default class ServiceCodeGen { return [ `// Autogenerated API client for: ${this.apiSpec.metadata.serviceFullName}`, - helpers.toSourceString(), + this.renderHelperString(helpers), chunks.join('\n'), ].filter(x => x).join('\n\n'); } @@ -139,7 +161,7 @@ export default class ServiceCodeGen { generateStructsTypescript(): string { const helpers = makeHelperLibrary({ isTest: this.isTest, - useStdJsr: this.useStdJsr, + useJsr: this.useJsr, }); const protocol = makeProtocolCodegenFor(this.apiSpec.metadata, this.shapes, helpers, { includeJsonRemap: this.includeJsonRemap, @@ -150,7 +172,7 @@ export default class ServiceCodeGen { return [ `// Autogenerated API structures for: ${this.apiSpec.metadata.serviceFullName}`, - helpers.toSourceString(), + this.renderHelperString(helpers), structCode, ].filter(x => x).join('\n\n'); } diff --git a/generation/deno.json b/generation/deno.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/generation/deno.json @@ -0,0 +1,2 @@ +{ +} diff --git a/generation/deploy/cache-s3.ts b/generation/deploy/cache-s3.ts deleted file mode 100644 index 775339c..0000000 --- a/generation/deploy/cache-s3.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Cache } from "./httpcache/mod.ts"; - -import { S3 } from "./s3-api.ts"; -import { AwsServiceError } from "../../lib/client/common.ts"; - -export function s3Cache( - s3Client: S3, - bucketName: string, - prefix = "", -): Cache { - - function s3Coords(url: string) { - const key = url.replace('://', '/'); - return { - Bucket: bucketName, - Key: prefix + key + '.cache', - }; - } - - return new Cache({ - - async get(url) { - try { - console.log('s3 get', s3Coords(url).Key); - const { Metadata, Body } = await s3Client.getObject(s3Coords(url)); - if (!Metadata['cache-policy']) return undefined; - const BodyBuffer = new Uint8Array(await new Response(Body).arrayBuffer()); - - if (Body && Metadata['cache-policy'] === 'inline') { - const idx = BodyBuffer.indexOf(10); - return { - policy: JSON.parse(new TextDecoder().decode(BodyBuffer.slice(0, idx))), - body: BodyBuffer.slice(idx+1), - }; - } - - return { - policy: JSON.parse(Metadata['cache-policy'] || '{}'), - body: BodyBuffer == null ? new Uint8Array(0) : BodyBuffer, - }; - - } catch (err: unknown) { - if ((err as AwsServiceError).code === 'NoSuchKey') return undefined; - throw err; - } - }, - - async set(url, resp) { - const list = resp.policy.resh['content-type'] ?? []; - const contentType = Array.isArray(list) ? list[0] : list; - console.log('s3 put', s3Coords(url).Key, contentType); - - const policy = JSON.stringify(resp.policy); - if (policy.length > 1800) { - const encodedPolicy = new TextEncoder().encode(policy); - const body = new Uint8Array(encodedPolicy.length + 1 + resp.body.length); - body.set(encodedPolicy, 0); - body.set([10], encodedPolicy.length); - body.set(resp.body, encodedPolicy.length + 1); - - await s3Client.putObject({ - ...s3Coords(url), - Body: body, - ContentType: contentType.startsWith('text/') - ? 'text/x-httpcache' - : 'binary/x-httpcache', - Metadata: { - ['cache-policy']: 'inline', - }, - }); - return; - } - - await s3Client.putObject({ - ...s3Coords(url), - Body: resp.body, - ContentType: contentType, - Metadata: { - ['cache-policy']: JSON.stringify(resp.policy), - }, - }); - }, - - async delete(url) { - await s3Client.deleteObject(s3Coords(url)); - }, - - close() {}, - }); -} diff --git a/generation/deploy/cache.ts b/generation/deploy/cache.ts index cbcc124..9c9b1e0 100644 --- a/generation/deploy/cache.ts +++ b/generation/deploy/cache.ts @@ -1,33 +1,28 @@ -// import { S3 } from "./s3-api.ts"; -// import { ApiFactory } from "../../lib/client/mod.ts"; -import { AsyncTracer, Span } from "./tracer.ts"; +import { LogicTracer, Span } from "./tracer.ts"; -// can maybe replace this whole dep with deno edge cache once it's out of beta import type { Cache } from "./httpcache/mod.ts"; import { inMemoryCache } from "./httpcache/in_memory.ts"; -// import { s3Cache } from "./cache-s3.ts"; -import { platformCache } from "./cache-platform.ts"; - -// const s3Api = new ApiFactory({ -// region: Deno.env.get('HTTPCACHE_S3_REGION') || 'us-east-2', -// }).makeNew(S3); +import { platformCache } from "./httpcache/platform.ts"; const caches: Array = [ inMemoryCache(40), await platformCache(), - // s3Cache(s3Api, Deno.env.get('HTTPCACHE_S3_BUCKET') || 'deno-httpcache'), ]; const cacheLabels = ['in-memory', 'platform', 's3']; -const tracer = new AsyncTracer('cached-fetch'); +const tracer = new LogicTracer({ + name: 'cached-fetch', +}); export async function cachedFetch(mode: 'immutable' | 'mutable', label: string, url: string) { - return await tracer.runAsyncSpan(`fetch ${label}`, { - 'cache.label': label, - 'cache.mode': mode, - }, span => cachedFetchInner(mode, label, url, span)); + return await tracer.asyncSpan(`fetch ${label}`, { + attributes: { + 'cache.label': label, + 'cache.mode': mode, + }, + }, span => cachedFetchInner(mode, url, span!)); } -async function cachedFetchInner(mode: 'immutable' | 'mutable', label: string, url: string, span: Span) { +async function cachedFetchInner(mode: 'immutable' | 'mutable', url: string, span: Span) { for (const [cacheIdx, cache] of caches.entries()) { const cached = await cache.match(url).catch(err => { diff --git a/generation/deploy/generations.ts b/generation/deploy/generations.ts index c44326c..420cd75 100644 --- a/generation/deploy/generations.ts +++ b/generation/deploy/generations.ts @@ -17,7 +17,6 @@ interface CodeGen { export class ModuleGenerator { constructor( - public readonly stdModRoot: string, public readonly sdkVersion: string, public readonly defaults: URLSearchParams, public readonly codegenConstr: (config: ApiSpecsBundle, opts: URLSearchParams) => CodeGen, @@ -42,71 +41,72 @@ export class ModuleGenerator { const codeGen = this.codegenConstr(opts.apiSpecs, fullOptions); return codeGen.generateTypescript(opts.className) - // TODO: intentionally excluding md5 imports, as it was removed from std later on - .replaceAll(/from "https:\/\/deno.land\/std@[0-9.]+\/([^"]+)/g, (orig, pkg) => pkg.includes('md5') ? orig : `from "${this.stdModRoot}/${pkg}`) - .replaceAll('from "../../', `from "${fullOptions.get('aws_api_root')}/`); } } // Newest versions come first export const Generations = new Map([ ['v0.1', new ModuleGenerator( - 'https://deno.land/std@0.95.0', 'v2.895.0', new URLSearchParams([ + ['std_mod_root', 'https://deno.land/std@0.95.0'], ['aws_api_root', 'https://deno.land/x/aws_api@v0.4.0'], - ['useStdJsr', 'no'], + ['useJsr', 'no'], ['includeOpts', 'no'], ['includeJsonRemap', 'no'], ['includeClientExtras', 'no'], ['useAuthType', 'no'], ['alwaysReqLists', 'yes'], ['streamingResponses', 'no'], + ['useImportMap', 'no'], ['docs', 'none'], ]), (config, opts) => new LatestCodeGen(config, opts), )], ['v0.2', new ModuleGenerator( - 'https://deno.land/std@0.105.0', 'v2.971.0', new URLSearchParams([ + ['std_mod_root', 'https://deno.land/std@0.105.0'], ['aws_api_root', 'https://deno.land/x/aws_api@v0.5.0'], - ['useStdJsr', 'no'], + ['useJsr', 'no'], ['includeJsonRemap', 'no'], ['includeClientExtras', 'no'], ['useAuthType', 'no'], ['alwaysReqLists', 'yes'], ['streamingResponses', 'no'], + ['useImportMap', 'no'], ['docs', 'none'], ]), (config, opts) => new LatestCodeGen(config, opts), )], ['v0.3', new ModuleGenerator( - 'https://deno.land/std@0.120.0', 'v2.1060.0', new URLSearchParams([ + ['std_mod_root', 'https://deno.land/std@0.120.0'], ['aws_api_root', 'https://deno.land/x/aws_api@v0.6.0'], - ['useStdJsr', 'no'], + ['useJsr', 'no'], ['streamingResponses', 'no'], + ['useImportMap', 'no'], ['docs', 'short'], ]), (config, opts) => new LatestCodeGen(config, opts), )], ['v0.4', new ModuleGenerator( - 'https://deno.land/std@0.177.0', - 'v2.1323.0', // https://github.com/aws/aws-sdk-js/releases + 'v2.1323.0', new URLSearchParams([ + ['std_mod_root', 'https://deno.land/std@0.177.0'], ['aws_api_root', 'https://deno.land/x/aws_api@v0.8.1'], - ['useStdJsr', 'no'], + ['useJsr', 'no'], + ['useImportMap', 'no'], ['docs', 'short'], ]), (config, opts) => new LatestCodeGen(config, opts), )], ['v0.5', new ModuleGenerator( - 'https://deno.land/std@0.177.0', - 'v2.1692.0', // https://github.com/aws/aws-sdk-js/releases + 'v2.1692.0', // Final version before https://github.com/aws/aws-sdk-js reached EOL new URLSearchParams([ - ['aws_api_root', 'https://deno.land/x/aws_api@v0.8.1'], + ['aws_api_root', 'jsr:@cloudydeno/aws-api@0.9.0'], + ['useImportMap', 'no'], ['docs', 'short'], ]), (config, opts) => new LatestCodeGen(config, opts), diff --git a/generation/deploy/helpers.ts b/generation/deploy/helpers.ts index a57757c..383cc10 100644 --- a/generation/deploy/helpers.ts +++ b/generation/deploy/helpers.ts @@ -5,7 +5,7 @@ export type RouteHandler = (context: { headers: Headers, }) => Response | Promise; -import { escape } from "https://deno.land/x/html_escape@v1.1.5/escape.ts"; +import { escape } from "@std/html/entities"; export { escape }; export function escapeTemplate(strings: TemplateStringsArray, ...inputs: string[]) { return String.raw(strings, ...inputs.map(escape)); diff --git a/generation/deploy/httpcache/in_memory.ts b/generation/deploy/httpcache/in_memory.ts index 280caca..8fd3816 100644 --- a/generation/deploy/httpcache/in_memory.ts +++ b/generation/deploy/httpcache/in_memory.ts @@ -1,11 +1,11 @@ // Downloaded from https://deno.land/x/httpcache@0.1.2/in_memory.ts -import { LRU } from "https://deno.land/x/lru@1.0.2/mod.ts"; +import { LruCache } from "@std/cache/lru-cache"; import { Cache, CachedResponse } from "./mod.ts"; export { Cache }; export function inMemoryCache(capacity: number): Cache { - const lru = new LRU(capacity); + const lru = new LruCache(capacity); return new Cache({ get(url) { return Promise.resolve(lru.get(url)); @@ -15,7 +15,7 @@ export function inMemoryCache(capacity: number): Cache { return Promise.resolve(); }, delete(url) { - lru.remove(url); + lru.delete(url); return Promise.resolve(); }, close() { diff --git a/generation/deploy/cache-platform.ts b/generation/deploy/httpcache/platform.ts similarity index 93% rename from generation/deploy/cache-platform.ts rename to generation/deploy/httpcache/platform.ts index 4583ede..2f972a0 100644 --- a/generation/deploy/cache-platform.ts +++ b/generation/deploy/httpcache/platform.ts @@ -1,5 +1,5 @@ -import { Cache } from "./httpcache/mod.ts"; -import { trace } from "./tracer.ts"; +import { trace } from "@cloudydeno/opentelemetry/pkg/api"; +import { Cache } from "./mod.ts"; // https://docs.deno.com/deploy/manual/edge-cache diff --git a/generation/deploy/routes/service-module.ts b/generation/deploy/routes/service-module.ts index 0bcbd1d..e6518df 100644 --- a/generation/deploy/routes/service-module.ts +++ b/generation/deploy/routes/service-module.ts @@ -226,18 +226,23 @@ function generateApiModule(opts: { `No ${opts.apiId} actions matched the given filter ${opts.options.get('actions')}`); } + headerChunks.push('//'); + headerChunks.push(`// Originally served at ${opts.selfUrl}`); + + const moduleText = opts.generation.buildApi({ + className: opts.module.name, + options: opts.options, + apiSpecs: { + api: opts.spec.normal, + pagers: opts.spec.paginators, + waiters: opts.spec.waiters2, + }, + }); + + headerChunks.unshift(moduleText.slice(0, moduleText.indexOf('\n'))); return [ headerChunks.join('\n'), - `// Originally served at ${opts.selfUrl}`, - opts.generation.buildApi({ - className: opts.module.name, - options: opts.options, - apiSpecs: { - api: opts.spec.normal, - pagers: opts.spec.paginators, - waiters: opts.spec.waiters2, - }, - }), + moduleText.slice(moduleText.indexOf('\n')+1), ].join('\n\n'); } diff --git a/generation/deploy/s3-api.ts b/generation/deploy/s3-api.ts deleted file mode 100644 index e696003..0000000 --- a/generation/deploy/s3-api.ts +++ /dev/null @@ -1,388 +0,0 @@ -// Generation parameters: -// aws-sdk-js definitions from v2.971.0 -// AWS service UID: s3-2006-03-01 -// code generation: v0.3 -// extra options: actions=GetObject%2CPutObject%2CDeleteObject&aws_api_root=..%2F..%2Flib&docs=none -// current time: 2021-12-24T17:46:24.290Z -// skipped 93 out of 96 actions, leaving 3 - -// Originally served at https://aws-api.deno.dev/v0.3/services/s3.ts?actions=GetObject,PutObject,DeleteObject&aws_api_root=../../lib&docs=none - -// Autogenerated API client for: Amazon Simple Storage Service - -import * as Base64 from "https://deno.land/std@0.177.0/encoding/base64.ts"; -import * as HashMd5 from "https://deno.land/std@0.160.0/hash/md5.ts"; -import * as client from "../../lib/client/common.ts"; -import * as cmnP from "../../lib/encoding/common.ts"; -function hashMD5(data: HashMd5.Message): string { - const hasher = new HashMd5.Md5(); - hasher.update(data); - return hasher.toString('base64'); -} -function serializeBlob(input: string | Uint8Array | null | undefined) { - if (input == null) return input; - return Base64.encode(input); -} - -export class S3 { - #client: client.ServiceClient; - constructor(apiFactory: client.ApiFactory) { - this.#client = apiFactory.buildServiceClient(S3.ApiMetadata); - } - - static ApiMetadata: client.ApiMetadata = { - "apiVersion": "2006-03-01", - "checksumFormat": "md5", - "endpointPrefix": "s3", - "protocol": "rest-xml", - "serviceAbbreviation": "Amazon S3", - "serviceFullName": "Amazon Simple Storage Service", - "serviceId": "S3", - "signatureVersion": "s3", - "uid": "s3-2006-03-01" - }; - - async deleteObject( - params: DeleteObjectRequest, - opts: client.RequestOptions = {}, - ): Promise { - const headers = new Headers; - const query = new URLSearchParams; - if (params["MFA"] != null) headers.append("x-amz-mfa", params["MFA"]); - if (params["VersionId"] != null) query.set("versionId", params["VersionId"]?.toString() ?? ""); - if (params["RequestPayer"] != null) headers.append("x-amz-request-payer", params["RequestPayer"]); - if (params["BypassGovernanceRetention"] != null) headers.append("x-amz-bypass-governance-retention", params["BypassGovernanceRetention"]?.toString() ?? ''); - if (params["ExpectedBucketOwner"] != null) headers.append("x-amz-expected-bucket-owner", params["ExpectedBucketOwner"]); - const resp = await this.#client.performRequest({ - opts, headers, query, - action: "DeleteObject", - method: "DELETE", - requestUri: cmnP.encodePath`/${params["Bucket"]}/${params["Key"].split("/")}`, - responseCode: 204, - }); - return { - DeleteMarker: cmnP.readBool(resp.headers.get("x-amz-delete-marker")), - VersionId: resp.headers.get("x-amz-version-id"), - RequestCharged: cmnP.readEnum(resp.headers.get("x-amz-request-charged")), - }; - } - - async getObject( - params: GetObjectRequest, - opts: client.RequestOptions = {}, - ): Promise { - const headers = new Headers; - const query = new URLSearchParams; - if (params["IfMatch"] != null) headers.append("If-Match", params["IfMatch"]); - if (params["IfModifiedSince"] != null) headers.append("If-Modified-Since", cmnP.serializeDate_rfc822(params["IfModifiedSince"]) ?? ""); - if (params["IfNoneMatch"] != null) headers.append("If-None-Match", params["IfNoneMatch"]); - if (params["IfUnmodifiedSince"] != null) headers.append("If-Unmodified-Since", cmnP.serializeDate_rfc822(params["IfUnmodifiedSince"]) ?? ""); - if (params["Range"] != null) headers.append("Range", params["Range"]); - if (params["ResponseCacheControl"] != null) query.set("response-cache-control", params["ResponseCacheControl"]?.toString() ?? ""); - if (params["ResponseContentDisposition"] != null) query.set("response-content-disposition", params["ResponseContentDisposition"]?.toString() ?? ""); - if (params["ResponseContentEncoding"] != null) query.set("response-content-encoding", params["ResponseContentEncoding"]?.toString() ?? ""); - if (params["ResponseContentLanguage"] != null) query.set("response-content-language", params["ResponseContentLanguage"]?.toString() ?? ""); - if (params["ResponseContentType"] != null) query.set("response-content-type", params["ResponseContentType"]?.toString() ?? ""); - if (params["ResponseExpires"] != null) query.set("response-expires", cmnP.serializeDate_rfc822(params["ResponseExpires"]) ?? ""); - if (params["VersionId"] != null) query.set("versionId", params["VersionId"]?.toString() ?? ""); - if (params["SSECustomerAlgorithm"] != null) headers.append("x-amz-server-side-encryption-customer-algorithm", params["SSECustomerAlgorithm"]); - if (params["SSECustomerKey"] != null) headers.append("x-amz-server-side-encryption-customer-key", serializeBlob(params["SSECustomerKey"]) ?? ''); - if (params["SSECustomerKeyMD5"] != null) headers.append("x-amz-server-side-encryption-customer-key-MD5", params["SSECustomerKeyMD5"]); - if (params["RequestPayer"] != null) headers.append("x-amz-request-payer", params["RequestPayer"]); - if (params["PartNumber"] != null) query.set("partNumber", params["PartNumber"]?.toString() ?? ""); - if (params["ExpectedBucketOwner"] != null) headers.append("x-amz-expected-bucket-owner", params["ExpectedBucketOwner"]); - const resp = await this.#client.performRequest({ - opts, headers, query, - action: "GetObject", - method: "GET", - requestUri: cmnP.encodePath`/${params["Bucket"]}/${params["Key"].split("/")}`, - }); - return { - DeleteMarker: cmnP.readBool(resp.headers.get("x-amz-delete-marker")), - AcceptRanges: resp.headers.get("accept-ranges"), - Expiration: resp.headers.get("x-amz-expiration"), - Restore: resp.headers.get("x-amz-restore"), - LastModified: cmnP.readTimestamp(resp.headers.get("Last-Modified")), - ContentLength: cmnP.readNum(resp.headers.get("Content-Length")), - ETag: resp.headers.get("ETag"), - MissingMeta: cmnP.readNum(resp.headers.get("x-amz-missing-meta")), - VersionId: resp.headers.get("x-amz-version-id"), - CacheControl: resp.headers.get("Cache-Control"), - ContentDisposition: resp.headers.get("Content-Disposition"), - ContentEncoding: resp.headers.get("Content-Encoding"), - ContentLanguage: resp.headers.get("Content-Language"), - ContentRange: resp.headers.get("Content-Range"), - ContentType: resp.headers.get("Content-Type"), - Expires: cmnP.readTimestamp(resp.headers.get("Expires")), - WebsiteRedirectLocation: resp.headers.get("x-amz-website-redirect-location"), - ServerSideEncryption: cmnP.readEnum(resp.headers.get("x-amz-server-side-encryption")), - Metadata: cmnP.toJsObj(resp.headers, "x-amz-meta-", v => v), - SSECustomerAlgorithm: resp.headers.get("x-amz-server-side-encryption-customer-algorithm"), - SSECustomerKeyMD5: resp.headers.get("x-amz-server-side-encryption-customer-key-MD5"), - SSEKMSKeyId: resp.headers.get("x-amz-server-side-encryption-aws-kms-key-id"), - BucketKeyEnabled: cmnP.readBool(resp.headers.get("x-amz-server-side-encryption-bucket-key-enabled")), - StorageClass: cmnP.readEnum(resp.headers.get("x-amz-storage-class")), - RequestCharged: cmnP.readEnum(resp.headers.get("x-amz-request-charged")), - ReplicationStatus: cmnP.readEnum(resp.headers.get("x-amz-replication-status")), - PartsCount: cmnP.readNum(resp.headers.get("x-amz-mp-parts-count")), - TagCount: cmnP.readNum(resp.headers.get("x-amz-tagging-count")), - ObjectLockMode: cmnP.readEnum(resp.headers.get("x-amz-object-lock-mode")), - ObjectLockRetainUntilDate: cmnP.readTimestamp(resp.headers.get("x-amz-object-lock-retain-until-date")), - ObjectLockLegalHoldStatus: cmnP.readEnum(resp.headers.get("x-amz-object-lock-legal-hold")), - Body: resp.body, - }; - } - - async putObject( - params: PutObjectRequest, - opts: client.RequestOptions = {}, - ): Promise { - const body = typeof params["Body"] === 'string' ? new TextEncoder().encode(params["Body"]) : params["Body"]; - const headers = new Headers; - if (params["ACL"] != null) headers.append("x-amz-acl", params["ACL"]); - if (params["CacheControl"] != null) headers.append("Cache-Control", params["CacheControl"]); - if (params["ContentDisposition"] != null) headers.append("Content-Disposition", params["ContentDisposition"]); - if (params["ContentEncoding"] != null) headers.append("Content-Encoding", params["ContentEncoding"]); - if (params["ContentLanguage"] != null) headers.append("Content-Language", params["ContentLanguage"]); - if (params["ContentLength"] != null) headers.append("Content-Length", params["ContentLength"]?.toString() ?? ''); - headers.append("Content-MD5", params["ContentMD5"] ?? hashMD5(body ?? '')); - if (params["ContentType"] != null) headers.append("Content-Type", params["ContentType"]); - if (params["Expires"] != null) headers.append("Expires", cmnP.serializeDate_rfc822(params["Expires"]) ?? ""); - if (params["GrantFullControl"] != null) headers.append("x-amz-grant-full-control", params["GrantFullControl"]); - if (params["GrantRead"] != null) headers.append("x-amz-grant-read", params["GrantRead"]); - if (params["GrantReadACP"] != null) headers.append("x-amz-grant-read-acp", params["GrantReadACP"]); - if (params["GrantWriteACP"] != null) headers.append("x-amz-grant-write-acp", params["GrantWriteACP"]); - for (const [key, val] of Object.entries(params["Metadata"] ?? {})) { - headers.append("x-amz-meta-"+key, val ?? ""); - } - if (params["ServerSideEncryption"] != null) headers.append("x-amz-server-side-encryption", params["ServerSideEncryption"]); - if (params["StorageClass"] != null) headers.append("x-amz-storage-class", params["StorageClass"]); - if (params["WebsiteRedirectLocation"] != null) headers.append("x-amz-website-redirect-location", params["WebsiteRedirectLocation"]); - if (params["SSECustomerAlgorithm"] != null) headers.append("x-amz-server-side-encryption-customer-algorithm", params["SSECustomerAlgorithm"]); - if (params["SSECustomerKey"] != null) headers.append("x-amz-server-side-encryption-customer-key", serializeBlob(params["SSECustomerKey"]) ?? ''); - if (params["SSECustomerKeyMD5"] != null) headers.append("x-amz-server-side-encryption-customer-key-MD5", params["SSECustomerKeyMD5"]); - if (params["SSEKMSKeyId"] != null) headers.append("x-amz-server-side-encryption-aws-kms-key-id", params["SSEKMSKeyId"]); - if (params["SSEKMSEncryptionContext"] != null) headers.append("x-amz-server-side-encryption-context", params["SSEKMSEncryptionContext"]); - if (params["BucketKeyEnabled"] != null) headers.append("x-amz-server-side-encryption-bucket-key-enabled", params["BucketKeyEnabled"]?.toString() ?? ''); - if (params["RequestPayer"] != null) headers.append("x-amz-request-payer", params["RequestPayer"]); - if (params["Tagging"] != null) headers.append("x-amz-tagging", params["Tagging"]); - if (params["ObjectLockMode"] != null) headers.append("x-amz-object-lock-mode", params["ObjectLockMode"]); - if (params["ObjectLockRetainUntilDate"] != null) headers.append("x-amz-object-lock-retain-until-date", cmnP.serializeDate_iso8601(params["ObjectLockRetainUntilDate"]) ?? ""); - if (params["ObjectLockLegalHoldStatus"] != null) headers.append("x-amz-object-lock-legal-hold", params["ObjectLockLegalHoldStatus"]); - if (params["ExpectedBucketOwner"] != null) headers.append("x-amz-expected-bucket-owner", params["ExpectedBucketOwner"]); - const resp = await this.#client.performRequest({ - opts, headers, body, - action: "PutObject", - method: "PUT", - requestUri: cmnP.encodePath`/${params["Bucket"]}/${params["Key"].split("/")}`, - }); - await resp.arrayBuffer(); // consume body without use - return { - Expiration: resp.headers.get("x-amz-expiration"), - ETag: resp.headers.get("ETag"), - ServerSideEncryption: cmnP.readEnum(resp.headers.get("x-amz-server-side-encryption")), - VersionId: resp.headers.get("x-amz-version-id"), - SSECustomerAlgorithm: resp.headers.get("x-amz-server-side-encryption-customer-algorithm"), - SSECustomerKeyMD5: resp.headers.get("x-amz-server-side-encryption-customer-key-MD5"), - SSEKMSKeyId: resp.headers.get("x-amz-server-side-encryption-aws-kms-key-id"), - SSEKMSEncryptionContext: resp.headers.get("x-amz-server-side-encryption-context"), - BucketKeyEnabled: cmnP.readBool(resp.headers.get("x-amz-server-side-encryption-bucket-key-enabled")), - RequestCharged: cmnP.readEnum(resp.headers.get("x-amz-request-charged")), - }; - } - - // Resource State Waiters - - // waitForBucketExists() skipped - depends on HeadBucket - // waitForBucketNotExists() skipped - depends on HeadBucket - // waitForObjectExists() skipped - depends on HeadObject - // waitForObjectNotExists() skipped - depends on HeadObject -} - -// refs: 1 - tags: named, input -export interface DeleteObjectRequest { - Bucket: string; - Key: string; - MFA?: string | null; - VersionId?: string | null; - RequestPayer?: RequestPayer | null; - BypassGovernanceRetention?: boolean | null; - ExpectedBucketOwner?: string | null; -} - -// refs: 1 - tags: named, input -export interface GetObjectRequest { - Bucket: string; - IfMatch?: string | null; - IfModifiedSince?: Date | number | null; - IfNoneMatch?: string | null; - IfUnmodifiedSince?: Date | number | null; - Key: string; - Range?: string | null; - ResponseCacheControl?: string | null; - ResponseContentDisposition?: string | null; - ResponseContentEncoding?: string | null; - ResponseContentLanguage?: string | null; - ResponseContentType?: string | null; - ResponseExpires?: Date | number | null; - VersionId?: string | null; - SSECustomerAlgorithm?: string | null; - SSECustomerKey?: Uint8Array | string | null; - SSECustomerKeyMD5?: string | null; - RequestPayer?: RequestPayer | null; - PartNumber?: number | null; - ExpectedBucketOwner?: string | null; -} - -// refs: 1 - tags: named, input -export interface PutObjectRequest { - ACL?: ObjectCannedACL | null; - Body?: Uint8Array | string | null; - Bucket: string; - CacheControl?: string | null; - ContentDisposition?: string | null; - ContentEncoding?: string | null; - ContentLanguage?: string | null; - ContentLength?: number | null; - ContentMD5?: string | null; - ContentType?: string | null; - Expires?: Date | number | null; - GrantFullControl?: string | null; - GrantRead?: string | null; - GrantReadACP?: string | null; - GrantWriteACP?: string | null; - Key: string; - Metadata?: { [key: string]: string | null | undefined } | null; - ServerSideEncryption?: ServerSideEncryption | null; - StorageClass?: StorageClass | null; - WebsiteRedirectLocation?: string | null; - SSECustomerAlgorithm?: string | null; - SSECustomerKey?: Uint8Array | string | null; - SSECustomerKeyMD5?: string | null; - SSEKMSKeyId?: string | null; - SSEKMSEncryptionContext?: string | null; - BucketKeyEnabled?: boolean | null; - RequestPayer?: RequestPayer | null; - Tagging?: string | null; - ObjectLockMode?: ObjectLockMode | null; - ObjectLockRetainUntilDate?: Date | number | null; - ObjectLockLegalHoldStatus?: ObjectLockLegalHoldStatus | null; - ExpectedBucketOwner?: string | null; -} - -// refs: 1 - tags: named, output -export interface DeleteObjectOutput { - DeleteMarker?: boolean | null; - VersionId?: string | null; - RequestCharged?: RequestCharged | null; -} - -// refs: 1 - tags: named, output -export interface GetObjectOutput { - /** To get this stream as a buffer, use `new Response(...).arrayBuffer()` or related functions. */ - Body?: ReadableStream | null; - DeleteMarker?: boolean | null; - AcceptRanges?: string | null; - Expiration?: string | null; - Restore?: string | null; - LastModified?: Date | number | null; - ContentLength?: number | null; - ETag?: string | null; - MissingMeta?: number | null; - VersionId?: string | null; - CacheControl?: string | null; - ContentDisposition?: string | null; - ContentEncoding?: string | null; - ContentLanguage?: string | null; - ContentRange?: string | null; - ContentType?: string | null; - Expires?: Date | number | null; - WebsiteRedirectLocation?: string | null; - ServerSideEncryption?: ServerSideEncryption | null; - Metadata: { [key: string]: string | null | undefined }; - SSECustomerAlgorithm?: string | null; - SSECustomerKeyMD5?: string | null; - SSEKMSKeyId?: string | null; - BucketKeyEnabled?: boolean | null; - StorageClass?: StorageClass | null; - RequestCharged?: RequestCharged | null; - ReplicationStatus?: ReplicationStatus | null; - PartsCount?: number | null; - TagCount?: number | null; - ObjectLockMode?: ObjectLockMode | null; - ObjectLockRetainUntilDate?: Date | number | null; - ObjectLockLegalHoldStatus?: ObjectLockLegalHoldStatus | null; -} - -// refs: 1 - tags: named, output -export interface PutObjectOutput { - Expiration?: string | null; - ETag?: string | null; - ServerSideEncryption?: ServerSideEncryption | null; - VersionId?: string | null; - SSECustomerAlgorithm?: string | null; - SSECustomerKeyMD5?: string | null; - SSEKMSKeyId?: string | null; - SSEKMSEncryptionContext?: string | null; - BucketKeyEnabled?: boolean | null; - RequestCharged?: RequestCharged | null; -} - -// refs: 3 - tags: input, named, enum -export type RequestPayer = -| "requester" -| cmnP.UnexpectedEnumValue; - -// refs: 1 - tags: input, named, enum -export type ObjectCannedACL = -| "private" -| "public-read" -| "public-read-write" -| "authenticated-read" -| "aws-exec-read" -| "bucket-owner-read" -| "bucket-owner-full-control" -| cmnP.UnexpectedEnumValue; - -// refs: 3 - tags: input, named, enum, output -export type ServerSideEncryption = -| "AES256" -| "aws:kms" -| cmnP.UnexpectedEnumValue; - -// refs: 2 - tags: input, named, enum, output -export type StorageClass = -| "STANDARD" -| "REDUCED_REDUNDANCY" -| "STANDARD_IA" -| "ONEZONE_IA" -| "INTELLIGENT_TIERING" -| "GLACIER" -| "DEEP_ARCHIVE" -| "OUTPOSTS" -| cmnP.UnexpectedEnumValue; - -// refs: 2 - tags: input, named, enum, output -export type ObjectLockMode = -| "GOVERNANCE" -| "COMPLIANCE" -| cmnP.UnexpectedEnumValue; - -// refs: 2 - tags: input, named, enum, output -export type ObjectLockLegalHoldStatus = -| "ON" -| "OFF" -| cmnP.UnexpectedEnumValue; - -// refs: 3 - tags: output, named, enum -export type RequestCharged = -| "requester" -| cmnP.UnexpectedEnumValue; - -// refs: 1 - tags: output, named, enum -export type ReplicationStatus = -| "COMPLETE" -| "PENDING" -| "FAILED" -| "REPLICA" -| cmnP.UnexpectedEnumValue; diff --git a/generation/deploy/tracer.ts b/generation/deploy/tracer.ts index 2c6771c..c8c9e2b 100644 --- a/generation/deploy/tracer.ts +++ b/generation/deploy/tracer.ts @@ -1,8 +1,10 @@ -export { httpTracer } from "https://deno.land/x/observability@v0.5.3/instrumentation/http-server.ts"; -import { Attributes, Span, SpanStatusCode, Tracer, trace } from "https://deno.land/x/observability@v0.5.3/opentelemetry/api.js"; -export { trace, type Span }; +export { httpTracer } from "@cloudydeno/opentelemetry/instrumentation/http-server.ts"; -import { DenoTelemetrySdk } from "https://deno.land/x/observability@v0.5.3/sdk.ts"; +import { LogicTracer } from "@cloudydeno/opentelemetry/instrumentation/async.ts"; +import { Attributes, Span, trace } from "@cloudydeno/opentelemetry/pkg/api"; +export { LogicTracer, trace, type Span }; + +import { DenoTelemetrySdk } from "@cloudydeno/opentelemetry/sdk"; new DenoTelemetrySdk({ resourceAttrs: { @@ -10,48 +12,10 @@ new DenoTelemetrySdk({ }, }); -export class AsyncTracer { - tracer: Tracer; - constructor(name: string, version?: string) { - this.tracer = trace.getTracer(name, version); - } - - async runAsyncSpan(name: string, attributes: Attributes, fn: (span: Span) => Promise) { - return await this.tracer.startActiveSpan(name, { - attributes, - }, async span => { - try { - return await fn(span); - } catch (thrown: unknown) { - const err = thrown as Error; - span.setStatus({ - code: SpanStatusCode.ERROR, - message: err.message, - }); - span.recordException(err); - throw err; - } finally { - span.end(); - } - }); - } +const logicWrap = new LogicTracer({ + name: 'logic-wrap', + requireParent: false, +}); +export function runAsyncSpan(name: string, attributes: Attributes, fn: (span: Span) => Promise): Promise { + return logicWrap.asyncSpan(name, { attributes }, span => fn(span!)); } - -const logicWrap = new AsyncTracer('logic-wrap'); -export const runAsyncSpan = logicWrap.runAsyncSpan.bind(logicWrap); - -// deno deploy decorators seem in a weird state for now -// so we don't use this yet - -// export function AsyncSpan< -// Targs extends unknown[], -// Tret, -// >( -// fn: (...args: Targs) => Promise, -// ctx: ClassMethodDecoratorContext, -// ) { -// return function (this: unknown, ...args: Targs) { -// return runAsyncSpan(String(ctx.name), {}, () => -// fn.apply(this, args)); -// }; -// } diff --git a/generation/helper-library.ts b/generation/helper-library.ts index 2d0e400..4519148 100644 --- a/generation/helper-library.ts +++ b/generation/helper-library.ts @@ -158,23 +158,22 @@ export const IdemptTokenMock: Helper = { export function makeHelperLibrary(opts: { isTest: boolean; - useStdJsr: boolean; + useJsr: boolean; }) { const lib = new HelperLibrary(); - // lib.addOptionalDep('Base64', 'https://deno.land/x/base64@v0.2.1/mod.ts'); - lib.addOptionalDep('client', '../../client/common.ts'); + lib.addOptionalDep('client', '@cloudydeno/aws-api/client/common.ts'); - lib.addOptionalDep('cmnP', '../../encoding/common.ts'); - lib.addOptionalDep('jsonP', '../../encoding/json.ts'); - lib.addOptionalDep('qsP', '../../encoding/querystring.ts'); - lib.addOptionalDep('xmlP', '../../encoding/xml.ts'); + lib.addOptionalDep('cmnP', '@cloudydeno/aws-api/encoding/common.ts'); + lib.addOptionalDep('jsonP', '@cloudydeno/aws-api/encoding/json.ts'); + lib.addOptionalDep('qsP', '@cloudydeno/aws-api/encoding/querystring.ts'); + lib.addOptionalDep('xmlP', '@cloudydeno/aws-api/encoding/xml.ts'); lib.addHelper('generateIdemptToken', opts.isTest ? IdemptTokenMock : IdemptToken); - if (opts.useStdJsr) { + if (opts.useJsr) { lib.addHelper('hashMD5', HashMD5JSR); lib.addHelper('serializeBlob', SerializeBlobJSR); diff --git a/generation/jmespath.ts b/generation/jmespath.ts index f354406..5c0d2d5 100644 --- a/generation/jmespath.ts +++ b/generation/jmespath.ts @@ -1,5 +1,4 @@ -import { ASTNode, Token } from 'https://deno.land/x/jmespath@v0.2.2/Lexer.ts'; -import { compile } from 'https://deno.land/x/jmespath@v0.2.2/index.ts'; +import { compile, type ASTNode, Token } from '@cloudydeno/jmespath'; export function compileJMESPath(pathstr: string, rootRef: string): string { return postProcess(compilePath(compile(pathstr), rootRef)); diff --git a/generation/jmespath_test.ts b/generation/jmespath_test.ts index 1bbae7c..b5e4b08 100644 --- a/generation/jmespath_test.ts +++ b/generation/jmespath_test.ts @@ -1,5 +1,5 @@ import { compileJMESPath } from './jmespath.ts'; -import { assertEquals } from "https://deno.land/std@0.177.0/testing/asserts.ts"; +import { assertEquals } from "@std/assert/equals"; const cases: Record = { "EndpointStatus": "resp?.EndpointStatus", diff --git a/generation/script/update-readme.ts b/generation/script/update-readme.ts index 1fce02b..a0582e7 100644 --- a/generation/script/update-readme.ts +++ b/generation/script/update-readme.ts @@ -1,4 +1,4 @@ -import { readCSVObjects } from "https://deno.land/x/csv@v0.6.0/mod.ts"; +import { CsvParseStream } from "@std/csv/parse-stream"; const sdk = JSON.parse(await Deno.readTextFile('aws-sdk-js/package.json')); const header = `All API definitions are current as of [aws-sdk-js \`v${sdk.version}\`](https://github.com/aws/aws-sdk-js/releases/tag/v${sdk.version}).`; @@ -22,18 +22,22 @@ interface ServiceEntry { } const services: ServiceEntry[] = []; -const f = await Deno.open("grid-services.csv"); -for await (const obj of readCSVObjects(f)) { - services.push(obj as unknown as ServiceEntry); +{ + using f = await Deno.open("grid-services.csv", { read: true }); + for await (const obj of f.readable + .pipeThrough(new TextDecoderStream()) + .pipeThrough(new CsvParseStream({ skipFirstRow: true })) + ) { + services.push(obj as unknown as ServiceEntry); + } } -f.close(); services.sort((a, b) => `${a.id}!${a.version}`.localeCompare(`${b.id}!${b.version}`)); const workingSvc = services.filter(x => x.typechecked === 'ok'); -await updateReadme(header); +await updateReadme(); async function updateFile(path: string, contents: string) { const original = await Deno.readTextFile(path); @@ -43,7 +47,7 @@ async function updateFile(path: string, contents: string) { ].join(genBarrier)); } -async function updateReadme(header: string) { +function updateReadme() { const chunks = new Array(); chunks.push(`| Class | Module | Protocol |`); chunks.push(`| --- | --- | --- |`); diff --git a/generation/script/update-services.ts b/generation/script/update-services.ts index fcab342..d1c12ec 100644 --- a/generation/script/update-services.ts +++ b/generation/script/update-services.ts @@ -1,5 +1,7 @@ -import { readCSVObjects, writeCSVObjects } from "https://deno.land/x/csv@v0.6.0/mod.ts"; -import * as path from "https://deno.land/std@0.177.0/path/mod.ts"; +import { CsvParseStream } from "@std/csv/parse-stream"; +import { CsvStringifyStream } from "@std/csv/stringify-stream"; +import { join as joinPath } from "@std/path/join"; + import ServiceCodeGen from '../code-gen.ts'; import type * as Schema from '../sdk-schema.ts'; @@ -20,11 +22,15 @@ interface ServiceEntry { } const services: Record = {}; -const f = await Deno.open("./grid-services.csv"); -for await (const obj of readCSVObjects(f)) { - services[`${obj.service}@${obj.version}`] = obj as unknown as ServiceEntry; +{ + using f = await Deno.open("grid-services.csv", { read: true }); + for await (const obj of f.readable + .pipeThrough(new TextDecoderStream()) + .pipeThrough(new CsvParseStream({ skipFirstRow: true })) + ) { + services[`${obj.service}@${obj.version}`] = obj as unknown as ServiceEntry; + } } -f.close(); const serviceList = JSON.parse(await Deno.readTextFile('./aws-sdk-js/apis/metadata.json')) as Record; for (const [modId, svc] of Object.entries(serviceList)) { @@ -85,20 +91,19 @@ for (const svc of relevantServices.values()) { modPath = await generateApi('aws-sdk-js/apis', uid, svc.namespace, svc.id); svc.generated = 'ok'; } catch (err) { - console.log(`${svc.service}@${svc.version}`, 'build fail:', err.message); + console.log(`${svc.service}@${svc.version}`, 'build fail:', (err as Error).message); svc.generated = 'fail'; continue; } - const cache = Deno.run({ - cmd: ["deno", "cache", modPath], - stderr: 'piped' - }); - const checkOutput = new TextDecoder().decode(await cache.stderrOutput()) - const { code } = await cache.status(); + const cache = await new Deno.Command('deno', { + args: ['cache', modPath], + stderr: 'piped', + }).output(); + const checkOutput = new TextDecoder().decode(cache.stderr); - if (code !== 0) { - console.log(`${svc.service}@${svc.version}`, 'cache fail code', code); + if (!cache.success) { + console.log(`${svc.service}@${svc.version}`, 'cache fail code', cache.code); svc.typechecked = 'fail'; continue; } @@ -109,21 +114,29 @@ for (const svc of relevantServices.values()) { } -const fOut = await Deno.open("./grid-services.csv", { write: true, create: true, truncate: true }); -const asyncObjectsGenerator = async function*() { - for (const service of Object.values(services).sort((a,b) => `${a.service}@${a.version}`.localeCompare(`${b.service}@${b.version}`))) { - yield service as unknown as {[key: string]: string}; +{ + using fOut = await Deno.open("./grid-services.csv", { write: true, create: true, truncate: true }); + const asyncObjectsGenerator = async function*() { + for (const service of Object.values(services).sort((a,b) => `${a.service}@${a.version}`.localeCompare(`${b.service}@${b.version}`))) { + yield service as unknown as {[key: string]: string}; + } } + await ReadableStream + .from(asyncObjectsGenerator()) + .pipeThrough(new CsvStringifyStream({ columns: header })) + .pipeThrough(new TransformStream({ + transform(val, ctlr) { + ctlr.enqueue(val.replaceAll('\r', '')); + }, + })) + .pipeThrough(new TextEncoderStream()) + .pipeTo(fOut.writable); } -await writeCSVObjects(fOut, asyncObjectsGenerator(), { header }); -fOut.close(); - - async function generateApi(apisPath: string, apiUid: string, namespace: string, serviceId: string): Promise { const jsonPath = (suffix: string) => - path.join(apisPath, `${apiUid}.${suffix}.json`); - const maybeReadFile = (path: string): Promise => + joinPath(apisPath, `${apiUid}.${suffix}.json`); + const maybeReadFile = (path: string): Promise => Deno.readTextFile(path).catch(err => { if (err.name === 'NotFound') return null; return Promise.reject(err); @@ -131,18 +144,18 @@ async function generateApi(apisPath: string, apiUid: string, namespace: string, const codeGen = new ServiceCodeGen({ api: JSON.parse(await Deno.readTextFile(jsonPath('normal'))) as Schema.Api, - pagers: JSON.parse(await maybeReadFile(jsonPath('paginators'))) as Schema.Pagination, - waiters: JSON.parse(await maybeReadFile(jsonPath('waiters2'))) as Schema.Waiters, + pagers: JSON.parse(await maybeReadFile(jsonPath('paginators')) ?? 'null') as Schema.Pagination, + waiters: JSON.parse(await maybeReadFile(jsonPath('waiters2')) ?? 'null') as Schema.Waiters, }, opts); const modCode = codeGen.generateModTypescript(namespace); const structsCode = codeGen.generateStructsTypescript(); - const version = apiUid.slice(-10); + // const version = apiUid.slice(-10); // const modName = `${serviceId}@${version}`; console.log('Writing', serviceId); - const modPath = path.join('lib', 'services', serviceId); - await Deno.run({cmd: ['mkdir', '-p', modPath]}).status(); + const modPath = joinPath('lib', 'services', serviceId); + await new Deno.Command('mkdir', {args: ['-p', modPath]}).output(); await Deno.writeTextFile(modPath+'/mod.ts', modCode); await Deno.writeTextFile(modPath+'/structs.ts', structsCode); return modPath+'/mod.ts'; diff --git a/generation/script/validate-fixtures.ts b/generation/script/validate-fixtures.ts index 43e7c8c..f3d0739 100755 --- a/generation/script/validate-fixtures.ts +++ b/generation/script/validate-fixtures.ts @@ -140,9 +140,9 @@ async function generateRun(run: TestRun): Promise { const chunks = new Array(); chunks.push('\n/////////\n'); - chunks.push(`import { assertEquals, assertRejects, assertObjectMatch } from "https://deno.land/std@0.177.0/testing/asserts.ts";`); - chunks.push(`import { wrapServiceClient } from '../../client/client.ts';\n`); - chunks.push(`import { ServiceApiClass, AwsServiceError } from '../../client/common.ts';\n`); + chunks.push(`import { assertEquals, assertRejects, assertObjectMatch } from "@std/assert";`); + chunks.push(`import { wrapServiceClient } from '@cloudydeno/aws-api/client/client.ts';\n`); + chunks.push(`import { ServiceApiClass, AwsServiceError } from '@cloudydeno/aws-api/client/common.ts';\n`); const mockFuncName = run.category === 'input' ? 'checkRequest' : 'mockResponse'; chunks.push(`async function ${mockFuncName}(request: Request, opts: {hostPrefix?: string, urlPath: string}): Promise {`); @@ -229,9 +229,10 @@ for await (const run of allTestRuns) { await generateRun(run); } -const child = await Deno.run({ - cmd: ["deno", "test", testDir], -}).status(); +const child = await new Deno.Command('deno', { + args: ['test', testDir], + stdout: 'inherit', +}).output(); Deno.exit(child.code); // Our comparing doesn't respect different orders, but order is often right so just fudge for now diff --git a/generation/script/validate-services.ts b/generation/script/validate-services.ts index 21b7d2d..c1bb676 100755 --- a/generation/script/validate-services.ts +++ b/generation/script/validate-services.ts @@ -2,9 +2,9 @@ import type * as Schema from '../sdk-schema.ts'; import ServiceCodeGen from '../code-gen.ts'; -import * as path from "https://deno.land/std@0.177.0/path/mod.ts"; +import { join as joinPath } from "@std/path/join"; -const testDir = path.join('lib','testgen','services'); +const testDir = joinPath('lib','testgen','services'); await Deno.mkdir(testDir, { recursive: true }); const serviceList = JSON.parse(await Deno.readTextFile('aws-sdk-js/apis/metadata.json')) as Record; @@ -32,7 +32,7 @@ for await (const entry of Deno.readDir(`./aws-sdk-js/apis`)) { if (!svc) throw new Error(`Missing service for '${service}'`); const jsonPath = (suffix: string) => - path.join('aws-sdk-js/apis', `${uid}.${suffix}.json`); + joinPath('aws-sdk-js/apis', `${uid}.${suffix}.json`); const maybeReadFile = (path: string): Promise => Deno.readTextFile(path).catch(err => { if (err.name === 'NotFound') return null; @@ -46,20 +46,21 @@ for await (const entry of Deno.readDir(`./aws-sdk-js/apis`)) { }, opts); const code = codeGen.generateTypescript(svc.name); - await Deno.writeTextFile(path.join(testDir, `${uid}.ts`), code); + await Deno.writeTextFile(joinPath(testDir, `${uid}.ts`), code); generatedFiles.push(`./${uid}.ts`); } -await Deno.writeTextFile(path.join(testDir, 'mod.ts'), generatedFiles +await Deno.writeTextFile(joinPath(testDir, 'mod.ts'), generatedFiles .map(x => `import {} from ${JSON.stringify(x)}`) .join('\n')); const cacheStart = Date.now(); -const child = await Deno.run({ - cmd: ["deno", "cache", path.join(testDir, 'mod.ts')], -}).status(); +const child = await new Deno.Command('deno', { + args: ['cache', joinPath(testDir, 'mod.ts')], + stderr: 'inherit', +}).output(); const cacheEnd = Date.now(); console.log('Cached in', Math.round((cacheEnd - cacheStart) / 1000), 'seconds'); Deno.exit(child.code); diff --git a/grid-services.csv b/grid-services.csv index 667d8b7..c0c5120 100644 --- a/grid-services.csv +++ b/grid-services.csv @@ -12,4 +12,4 @@ s3,2006-03-01,Amazon Simple Storage Service,s3,S3,rest-xml,ok,ok sesv2,2019-09-27,Amazon Simple Email Service,sesv2,SESV2,rest-json,ok,ok sns,2010-03-31,Amazon Simple Notification Service,sns,SNS,query,ok,ok sqs,2012-11-05,Amazon Simple Queue Service,sqs,SQS,query,ok,ok -sts,2011-06-15,AWS Security Token Service,sts,STS,query,ok,ok \ No newline at end of file +sts,2011-06-15,AWS Security Token Service,sts,STS,query,ok,ok diff --git a/lib/README.md b/lib/README.md index 1ed9eca..3e3a32f 100644 --- a/lib/README.md +++ b/lib/README.md @@ -23,8 +23,8 @@ and then use it to construct a client for the AWS service API you want to use. A bare-bones example from `demo.ts`: ```typescript -import { ApiFactory } from 'https://deno.land/x/aws_api/client/mod.ts'; -import { STS } from 'https://deno.land/x/aws_api/services/sts/mod.ts'; +import { ApiFactory } from '@cloudydeno/aws-api/client'; +import { STS } from '@cloudydeno/aws-api/services/sts'; // Create a service client for AWS Security Token Service const sts = new ApiFactory().makeNew(STS); @@ -85,7 +85,7 @@ For other services, or to cut down on dependency size by selecting the available you can import from [the /x/aws_api Web Service][webservice]: ```typescript -import { ApiFactory } from 'https://deno.land/x/aws_api/client/mod.ts'; +import { ApiFactory } from '@cloudydeno/aws-api/client'; import { Pricing } from 'https://aws-api.deno.dev/latest/services/pricing.ts'; const pricing = new ApiFactory().makeNew(Pricing); @@ -120,7 +120,7 @@ const ec2_europe = new ApiFactory({ ## Changelog -* `TBD` on `TBD`: minor adjustments for Deno 2 type compatibility +* `v0.9.0` on `2025-09-15`: Migrate to JSR packaging and imports, targetting Deno 2+ * `v0.8.1` on `2023-02-26`: hotfixes in extras files * `v0.8.0` on `2023-02-26`: codegen `v0.4` * Use Deno's `/std@0.177.0` (except for MD5). diff --git a/lib/client/api-factory.ts b/lib/client/api-factory.ts new file mode 100644 index 0000000..0dd3ee1 --- /dev/null +++ b/lib/client/api-factory.ts @@ -0,0 +1,34 @@ +import { + Credentials, CredentialsProvider, + DefaultCredentialsProvider, +} from "./credentials.ts"; +import { + EndpointResolver, + AwsEndpointResolver, + FixedBaseEndpointResolver, +} from "./endpoints.ts"; +import { + BaseApiFactory, +} from "./client.ts"; +import type { + ServiceClientExtras, +} from "./common.ts"; + +export class ApiFactory extends BaseApiFactory { + constructor(opts: { + credentialProvider?: CredentialsProvider, + credentials?: Credentials, + region?: string; + fixedEndpoint?: string; + endpointResolver?: EndpointResolver, + extras?: ServiceClientExtras; + }={}) { + super({ + credentialProvider: DefaultCredentialsProvider, + endpointResolver: (typeof opts.fixedEndpoint == 'string') + ? new FixedBaseEndpointResolver(opts.fixedEndpoint) + : new AwsEndpointResolver(), + ...opts, + }); + } +} diff --git a/lib/client/client.ts b/lib/client/client.ts index c418522..1a7abe1 100644 --- a/lib/client/client.ts +++ b/lib/client/client.ts @@ -109,13 +109,13 @@ export class BaseApiFactory implements ApiFactory { return wrapServiceClient(apiMetadata, signingFetcher); } - async ensureCredentialsAvailable() { + async ensureCredentialsAvailable(): Promise { const creds = await this.#credentials.getCredentials(); if (creds.awsAccessKeyId) return; throw new Error(`Empty credentials were returned successfully (somehow?)`); } - async determineCurrentRegion() { + async determineCurrentRegion(): Promise { if (this.#region != null) return this.#region; const credentials = await this.#credentials.getCredentials(); return credentials.region ?? throwMissingRegion(); diff --git a/lib/client/client_test.ts b/lib/client/client_test.ts index e3146c5..35f590c 100644 --- a/lib/client/client_test.ts +++ b/lib/client/client_test.ts @@ -1,4 +1,6 @@ -import { assertRejects, assertObjectMatch } from "https://deno.land/std@0.177.0/testing/asserts.ts"; +import { assertObjectMatch } from "@std/assert/object-match"; +import { assertRejects } from "@std/assert/rejects"; + import { BaseApiFactory, handleErrorResponse } from "./client.ts"; import { AwsServiceError } from "./mod.ts"; diff --git a/lib/client/common.ts b/lib/client/common.ts index 8616160..96b2c4c 100644 --- a/lib/client/common.ts +++ b/lib/client/common.ts @@ -56,7 +56,7 @@ export interface ApiRequestConfig { opts?: RequestOptions; } -export function getRequestId(headers: Headers) { +export function getRequestId(headers: Headers): string | null { return headers.get('x-amzn-requestid') ?? headers.get('x-amz-request-id'); } @@ -151,7 +151,7 @@ export class AwsServiceError extends Error { } } - get originalMessage() { + get originalMessage(): string | null | undefined { return this.internal.Message; } } @@ -163,19 +163,19 @@ const hmacSha256Alg = { name: 'HMAC', hash: { name: 'SHA-256' } }; const encoder = new TextEncoder(); /** Generate SHA-256 hash of a string with an HMAC byte-buffer key */ -export async function hmacSha256(key: Uint8Array, body: string) { +export async function hmacSha256(key: Uint8Array, body: string): Promise { const cryptoKey = await crypto.subtle.importKey('raw', key, hmacSha256Alg, false, ['sign']); const buffer = await crypto.subtle.sign('HMAC', cryptoKey, encoder.encode(body)); return new Uint8Array(buffer); } /** Generate SHA-256 hash of a byte-buffer */ -export async function hashSha256(content: Uint8Array) { +export async function hashSha256(content: Uint8Array): Promise { const buffer = await crypto.subtle.digest('SHA-256', content); return new Uint8Array(buffer); } /** Return a hex representation of a byte-buffer */ -export function bytesAsHex(buffer: Uint8Array) { +export function bytesAsHex(buffer: Uint8Array): string { return [...buffer].map(x => x.toString(16).padStart(2, '0')).join(''); } diff --git a/lib/client/credentials.ts b/lib/client/credentials.ts index 7c09453..c715270 100644 --- a/lib/client/credentials.ts +++ b/lib/client/credentials.ts @@ -47,7 +47,7 @@ export class CredentialsProviderChain implements CredentialsProvider { } } -export const DefaultCredentialsProvider +export const DefaultCredentialsProvider: CredentialsProviderChain = new CredentialsProviderChain([ () => new EnvironmentCredentials('AWS'), () => new EnvironmentCredentials('AMAZON'), diff --git a/lib/client/credentials_test.ts b/lib/client/credentials_test.ts index 151fe07..15edb5f 100644 --- a/lib/client/credentials_test.ts +++ b/lib/client/credentials_test.ts @@ -1,5 +1,5 @@ import { SharedIniFileCredentials } from './credentials.ts'; -import { assertEquals } from "https://deno.land/std@0.177.0/testing/asserts.ts"; +import { assertEquals } from "@std/assert/equals"; Deno.test('basic ini file', async () => { const credential = new SharedIniFileCredentials({ diff --git a/lib/client/endpoints_test.ts b/lib/client/endpoints_test.ts index 2e24ad7..a077761 100644 --- a/lib/client/endpoints_test.ts +++ b/lib/client/endpoints_test.ts @@ -1,8 +1,10 @@ -import { assertEquals, assertThrows } from "https://deno.land/std@0.177.0/testing/asserts.ts"; +import { assertEquals } from "@std/assert/equals"; +import { assertThrows } from "@std/assert/throws"; + import type { ApiMetadata } from "./common.ts"; import { AwsEndpointResolver, FixedBaseEndpointResolver, S3CompatibleEndpointResolver } from "./endpoints.ts"; -Deno.test('aws ec2 / use aws china partition', async () => { +Deno.test('aws ec2 / use aws china partition', () => { const resolver = new AwsEndpointResolver(); assertEquals(resolver.resolveUrl({ @@ -12,7 +14,7 @@ Deno.test('aws ec2 / use aws china partition', async () => { }).url.toString(), 'https://ec2.cn-none-1.amazonaws.com.cn/path'); }); -Deno.test('aws ec2 / use aws iso partition', async () => { +Deno.test('aws ec2 / use aws iso partition', () => { const resolver = new AwsEndpointResolver(); assertEquals(resolver.resolveUrl({ @@ -22,7 +24,7 @@ Deno.test('aws ec2 / use aws iso partition', async () => { }).url.toString(), 'https://ec2.us-iso-none-1.c2s.ic.gov/path'); }); -Deno.test('aws ec2 / opportunistic dualstack', async () => { +Deno.test('aws ec2 / opportunistic dualstack', () => { const resolver = new AwsEndpointResolver(); assertEquals(resolver.resolveUrl({ @@ -38,7 +40,7 @@ Deno.test('aws ec2 / opportunistic dualstack', async () => { }).url.toString(), 'https://ec2.na-none-1.amazonaws.com/path'); }); -Deno.test('aws ec2 / allow disabling dualstack', async () => { +Deno.test('aws ec2 / allow disabling dualstack', () => { const resolver = new AwsEndpointResolver({ upgradeEndpoints: false, }); @@ -50,7 +52,7 @@ Deno.test('aws ec2 / allow disabling dualstack', async () => { }).url.toString(), 'https://ec2.us-east-2.amazonaws.com/path'); }); -Deno.test('aws lambda / opportunistic dualstack', async () => { +Deno.test('aws lambda / opportunistic dualstack', () => { assertEquals(new AwsEndpointResolver().resolveUrl({ requestPath: '/path', region: 'us-east-2', @@ -58,7 +60,7 @@ Deno.test('aws lambda / opportunistic dualstack', async () => { }).url.toString(), 'https://lambda.us-east-2.api.aws/path'); }); -Deno.test('aws lambda / no dualstack in govcloud', async () => { +Deno.test('aws lambda / no dualstack in govcloud', () => { assertEquals(new AwsEndpointResolver().resolveUrl({ requestPath: '/path', region: 'us-gov-east-1', @@ -66,7 +68,7 @@ Deno.test('aws lambda / no dualstack in govcloud', async () => { }).url.toString(), 'https://lambda.us-gov-east-1.amazonaws.com/path'); }); -Deno.test('aws lambda / china endpoint', async () => { +Deno.test('aws lambda / china endpoint', () => { assertEquals(new AwsEndpointResolver().resolveUrl({ requestPath: '/path', region: 'cn-north-1', @@ -74,7 +76,7 @@ Deno.test('aws lambda / china endpoint', async () => { }).url.toString(), 'https://lambda.cn-north-1.api.amazonwebservices.com.cn/path'); }); -Deno.test('aws s3 / upgrades to host style routing', async () => { +Deno.test('aws s3 / upgrades to host style routing', () => { const resolver = new AwsEndpointResolver(); assertEquals(resolver.resolveUrl({ @@ -108,7 +110,7 @@ Deno.test('aws s3 / upgrades to host style routing', async () => { }).url.toString(), 'https://s3.dualstack.region.amazonaws.com/?query'); }); -Deno.test('aws s3 / does not upgrade buckets with dots', async () => { +Deno.test('aws s3 / does not upgrade buckets with dots', () => { const resolver = new AwsEndpointResolver(); assertEquals(resolver.resolveUrl({ @@ -118,7 +120,7 @@ Deno.test('aws s3 / does not upgrade buckets with dots', async () => { }).url.toString(), 'https://s3.dualstack.us-east-2.amazonaws.com/dotted.bucket/key'); }); -Deno.test('aws sts / uses global endpoint by default', async () => { +Deno.test('aws sts / uses global endpoint by default', () => { const resolver = new AwsEndpointResolver(); const endpoint = resolver.resolveUrl({ @@ -131,7 +133,7 @@ Deno.test('aws sts / uses global endpoint by default', async () => { assertEquals(endpoint.signingRegion, 'us-east-1'); }); -Deno.test('aws sts / can use regional endpoint by request', async () => { +Deno.test('aws sts / can use regional endpoint by request', () => { const resolver = new AwsEndpointResolver({ forceRegional: true, }); @@ -146,7 +148,7 @@ Deno.test('aws sts / can use regional endpoint by request', async () => { assertEquals(endpoint.signingRegion, 'eu-west-1'); }); -Deno.test('aws chime / non-standard global endpoint', async () => { +Deno.test('aws chime / non-standard global endpoint', () => { const resolver = new AwsEndpointResolver(); const endpoint = resolver.resolveUrl({ @@ -209,7 +211,7 @@ const apiMetadata: Record = { -Deno.test('s3 compat / basic assembly', async () => { +Deno.test('s3 compat / basic assembly', () => { const resolver = new S3CompatibleEndpointResolver('vendor.tld'); assertEquals(resolver.resolveUrl({ @@ -219,7 +221,7 @@ Deno.test('s3 compat / basic assembly', async () => { }).url.toString(), 'https://us-east-2.vendor.tld/'); }); -Deno.test('s3 compat / virtual host upgrade', async () => { +Deno.test('s3 compat / virtual host upgrade', () => { const resolver = new S3CompatibleEndpointResolver('vendor.tld'); assertEquals(resolver.resolveUrl({ @@ -235,13 +237,13 @@ Deno.test('s3 compat / virtual host upgrade', async () => { }).url.toString(), 'https://us-east-2.vendor.tld/dotted.bucket/key'); }); -Deno.test('s3 compat / validation', async () => { +Deno.test('s3 compat / validation', () => { assertThrows(() => { new S3CompatibleEndpointResolver('http://localhost'); }, Error, 'must be a naked domain name'); }); -Deno.test('s3 compat / refuse non-S3', async () => { +Deno.test('s3 compat / refuse non-S3', () => { const resolver = new S3CompatibleEndpointResolver('vendor.tld'); assertThrows(() => { @@ -255,7 +257,7 @@ Deno.test('s3 compat / refuse non-S3', async () => { -Deno.test('fixed base / basic assembly', async () => { +Deno.test('fixed base / basic assembly', () => { const resolver = new FixedBaseEndpointResolver('http://localhost:9000'); assertEquals(resolver.resolveUrl({ @@ -265,7 +267,7 @@ Deno.test('fixed base / basic assembly', async () => { }).url.toString(), 'http://localhost:9000/path'); }); -Deno.test('fixed base / validation', async () => { +Deno.test('fixed base / validation', () => { assertThrows(() => { new FixedBaseEndpointResolver('localhost'); }, Error, 'must be a full URL'); diff --git a/lib/client/ini.ts b/lib/client/ini.ts index 874b75b..1d6ce24 100644 --- a/lib/client/ini.ts +++ b/lib/client/ini.ts @@ -7,7 +7,7 @@ export const DEFAULT_SECTION = Symbol.for('ini default section'); * Decode the given ini-style formatted document into a nested object. * @param str ini-style document */ -export function decode (str: string) { +export function decode (str: string): Record> { const out: Record> = { [DEFAULT_SECTION]: {}, }; diff --git a/lib/client/instance-metadata.ts b/lib/client/instance-metadata.ts index 8f469e0..4b8a92e 100644 --- a/lib/client/instance-metadata.ts +++ b/lib/client/instance-metadata.ts @@ -51,7 +51,7 @@ export class IMDSv2 { tokenTtlSeconds: number; cachedToken: string | null = null; - async getToken() { + async getToken(): Promise { if (this.cachedToken) return this.cachedToken; // Fetch fresh token const [newToken, expireAfterMillis] = await this.fetchNewToken(); @@ -88,7 +88,7 @@ export class IMDSv2 { async performRequest( method: 'GET' | 'HEAD' | 'PUT' = 'GET', path = 'meta-data/', - ) { + ): Promise { return await this.#performRawRequest({ method, path, timeoutMs: this.apiTimeoutMs, diff --git a/lib/client/mod.ts b/lib/client/mod.ts index ef51b52..dceb737 100644 --- a/lib/client/mod.ts +++ b/lib/client/mod.ts @@ -23,39 +23,6 @@ export { TokenFileWebIdentityCredentials, } from "./credentials.ts"; -// --- - -import { - Credentials, CredentialsProvider, - DefaultCredentialsProvider, -} from "./credentials.ts"; -import { - EndpointResolver, - AwsEndpointResolver, - FixedBaseEndpointResolver, -} from "./endpoints.ts"; -import { - BaseApiFactory, -} from "./client.ts"; -import type { - ServiceClientExtras, -} from "./common.ts"; - -export class ApiFactory extends BaseApiFactory { - constructor(opts: { - credentialProvider?: CredentialsProvider, - credentials?: Credentials, - region?: string; - fixedEndpoint?: string; - endpointResolver?: EndpointResolver, - extras?: ServiceClientExtras; - }={}) { - super({ - credentialProvider: DefaultCredentialsProvider, - endpointResolver: (typeof opts.fixedEndpoint == 'string') - ? new FixedBaseEndpointResolver(opts.fixedEndpoint) - : new AwsEndpointResolver(), - ...opts, - }); - } -} +export { + ApiFactory, +} from "./api-factory.ts"; diff --git a/lib/client/signing.ts b/lib/client/signing.ts index 935002c..54e670e 100644 --- a/lib/client/signing.ts +++ b/lib/client/signing.ts @@ -135,7 +135,7 @@ export class AWSSignerV4 implements Signer { expiresIn?: number, signTime?: Date, }, - ) { + ): Promise { const url = new URL(props.url); const date = props.signTime ?? new Date(); const algorithm = "AWS4-HMAC-SHA256"; @@ -171,7 +171,7 @@ export async function getSignatureKey( dateStamp: string, region: string, service: string, -) { +): Promise { const keyBytes = encoder.encode(key); const paddedKey = new Uint8Array(4 + keyBytes.byteLength); paddedKey.set(AWS4, 0); @@ -184,7 +184,10 @@ export async function getSignatureKey( return mac; }; -export function canonicalizeRequest(method: string, url: string, headers: Headers, payloadHash: string) { +export function canonicalizeRequest(method: string, url: string, headers: Headers, payloadHash: string): { + signedHeaders: string; + request: string; +} { const { pathname, searchParams } = new URL(url); searchParams.sort(); const canonicalQuerystring = searchParams.toString(); diff --git a/lib/client/signing_test.ts b/lib/client/signing_test.ts index 2ac19a3..f9664f5 100644 --- a/lib/client/signing_test.ts +++ b/lib/client/signing_test.ts @@ -1,4 +1,6 @@ -import { assertEquals, assertObjectMatch } from "https://deno.land/std@0.177.0/testing/asserts.ts"; +import { assertEquals } from "@std/assert/equals"; +import { assertObjectMatch } from "@std/assert/object-match"; + import { bytesAsHex } from "./common.ts"; import { canonicalizeRequest, getSignatureKey, AWSSignerV4 } from "./signing.ts"; @@ -7,7 +9,7 @@ Deno.test('getSignatureKey', async () => { assertEquals(bytesAsHex(hash), 'b0bee7c7725547d1f3a029762a16795f2800b544c27e72b2a5727e3c06f040ce'); }); -Deno.test('canonicalizeRequest no attributes', async () => { +Deno.test('canonicalizeRequest no attributes', () => { assertObjectMatch(canonicalizeRequest( 'GET', 'https://example/', new Headers(), @@ -18,7 +20,7 @@ Deno.test('canonicalizeRequest no attributes', async () => { }); }) -Deno.test('canonicalizeRequest with attributes', async () => { +Deno.test('canonicalizeRequest with attributes', () => { assertObjectMatch(canonicalizeRequest( 'GET', 'https://example/hello-world?b=1&a=1', new Headers({ diff --git a/lib/deno.json b/lib/deno.json new file mode 100644 index 0000000..372a966 --- /dev/null +++ b/lib/deno.json @@ -0,0 +1,52 @@ +{ + "name": "@cloudydeno/aws-api", + "version": "0.9.0", + "license": "Apache-2.0", + "imports": { + "@cloudydeno/stream-observables": "jsr:@cloudydeno/stream-observables@^1.4.1", + "@sallai/ask": "jsr:@sallai/ask@^2.0.2", + "@std/assert": "jsr:@std/assert@^1.0.14", + "@std/async": "jsr:@std/async@^1.0.14", + "@std/cli": "jsr:@std/cli@^1.0.22", + "@std/encoding": "jsr:@std/encoding@^1.0.10", + "@takker/md5": "jsr:@takker/md5@^0.1.0" + }, + "exports": { + "./client/api-factory.ts": "./client/api-factory.ts", + "./client/client.ts": "./client/client.ts", + "./client/common.ts": "./client/common.ts", + "./client/credentials.ts": "./client/credentials.ts", + "./client/endpoints.ts": "./client/endpoints.ts", + "./client/ini.ts": "./client/ini.ts", + "./client/instance-metadata.ts": "./client/instance-metadata.ts", + "./client": "./client/mod.ts", + "./client/mod.ts": "./client/mod.ts", + "./client/signing.ts": "./client/signing.ts", + "./encoding/common.ts": "./encoding/common.ts", + "./encoding/json.ts": "./encoding/json.ts", + "./encoding/querystring.ts": "./encoding/querystring.ts", + "./encoding/xml.ts": "./encoding/xml.ts", + "./extras/s3-presign.ts": "./extras/s3-presign.ts", + "./extras/s3-upload.ts": "./extras/s3-upload.ts", + "./services/cloudwatch": "./services/cloudwatch/mod.ts", + "./services/dynamodb": "./services/dynamodb/mod.ts", + "./services/ecr": "./services/ecr/mod.ts", + "./services/kinesis": "./services/kinesis/mod.ts", + "./services/kms": "./services/kms/mod.ts", + "./services/lambda": "./services/lambda/mod.ts", + "./services/route53": "./services/route53/mod.ts", + "./services/s3": "./services/s3/mod.ts", + "./services/sesv2": "./services/sesv2/mod.ts", + "./services/sns": "./services/sns/mod.ts", + "./services/sqs": "./services/sqs/mod.ts", + "./services/sts": "./services/sts/mod.ts" + }, + "publish": { + "exclude": [ + "examples", + "demo.ts", + "demo-codegen.ts", + ".github" + ] + } +} diff --git a/lib/encoding/common.ts b/lib/encoding/common.ts index 3283687..fd15a9f 100644 --- a/lib/encoding/common.ts +++ b/lib/encoding/common.ts @@ -38,26 +38,26 @@ export function readBool(raw: string | null | undefined): boolean | null | undef } -export function serializeDate_unixTimestamp(input: Date | number | null | undefined) { +export function serializeDate_unixTimestamp(input: Date | number | null | undefined): number | null | undefined { if (input == null) return input; const date = typeof input === 'number' ? new Date(input*1000) : input; return Math.floor(date.valueOf() / 1000); } -export function serializeDate_iso8601(input: Date | number | null | undefined) { +export function serializeDate_iso8601(input: Date | number | null | undefined): string | null | undefined { if (input == null) return input; const date = typeof input === 'number' ? new Date(input*1000) : input; return date.toISOString().replace(/\.000Z$/, 'Z'); } -export function serializeDate_rfc822(input: Date | number | null | undefined) { +export function serializeDate_rfc822(input: Date | number | null | undefined): string | null | undefined { if (input == null) return input; const date = typeof input === 'number' ? new Date(input*1000) : input; return date.toUTCString(); } -export function readTimestamp(str: string | null | undefined) { +export function readTimestamp(str: string | null | undefined): Date | null | undefined { if (str == null) return str; const date = (str?.includes('T')) @@ -70,7 +70,7 @@ export function readTimestamp(str: string | null | undefined) { return date; } -export function readReqTimestamp(str: string | null | undefined) { +export function readReqTimestamp(str: string | null | undefined): Date { if (str == null) throw new Error(`Expected timestamp from server. TODO: better error reporting`); const date = (str?.includes('T')) @@ -104,7 +104,7 @@ export function toJsObj( // Functions used in fixture testing -export function testTransformJsObj(obj: {[key: string]: any}) { +export function testTransformJsObj(obj: {[key: string]: any}): {[key: string]: any} { const res: {[key: string]: any} = Object.create(null); for (const [key, val] of Object.entries(obj)) { res[key] = testTransformJsVal(val); diff --git a/lib/encoding/querystring.ts b/lib/encoding/querystring.ts index 0203206..f088080 100644 --- a/lib/encoding/querystring.ts +++ b/lib/encoding/querystring.ts @@ -10,7 +10,7 @@ export function appendMap(body: URLSearchParams, prefix: string, raw: {[k:str entryPrefix: string; appender?: (body: URLSearchParams, prefix: string, val: T) => void; encoder?: (val: T) => string; -}) { +}): void { const entries = Object.entries(raw ?? {}); if (entries.length === 0) { return body.append(prefix, ''); @@ -35,7 +35,7 @@ export function appendList(body: URLSearchParams, prefix: string, raw: T[], { entryPrefix: string; appender?: (body: URLSearchParams, prefix: string, val: T) => void; encoder?: (val: T) => string; -}) { +}): void { const entries = raw ?? []; if (entries.length === 0) { return body.append(prefix, ''); diff --git a/lib/encoding/xml.ts b/lib/encoding/xml.ts index bfb9c01..53b5c8a 100644 --- a/lib/encoding/xml.ts +++ b/lib/encoding/xml.ts @@ -265,13 +265,13 @@ const CHAR_S_INDEX: Record = { "&": "&", }; -export function encodeXmlEntities(str: string) { +export function encodeXmlEntities(str: string): string { return str.replace(/<|>|"|'|&/g, function(s) { return CHAR_S_INDEX[s]; }); } -export function decodeXmlEntities(str: string) { +export function decodeXmlEntities(str: string): string { return str.replace(/&#?[0-9a-zA-Z]+;?/g, function(s) { if (s.charAt(1) === "#") { const code = s.charAt(2).toLowerCase() === "x" diff --git a/lib/encoding/xml_test.ts b/lib/encoding/xml_test.ts index d49e7ca..8da12a6 100644 --- a/lib/encoding/xml_test.ts +++ b/lib/encoding/xml_test.ts @@ -1,4 +1,5 @@ -import { assertEquals } from 'https://deno.land/std@0.177.0/testing/asserts.ts'; +import { assertEquals } from "@std/assert/equals"; + import * as xmlP from './xml.ts'; // import type * as SQS from '../generated/sqs@2012-11-05.ts'; diff --git a/lib/examples/sqs-redriver.ts b/lib/examples/sqs-redriver.ts index 8c7ca54..0e26670 100755 --- a/lib/examples/sqs-redriver.ts +++ b/lib/examples/sqs-redriver.ts @@ -6,10 +6,10 @@ import { SQS } from '../services/sqs/mod.ts'; const sqs = new ApiFactory().makeNew(SQS); // we'll be taking input -import { parse as parseFlags } from "https://deno.land/std@0.177.0/flags/mod.ts"; -import Ask from 'https://deno.land/x/ask@1.0.6/mod.ts'; +import { parseArgs } from "@std/cli"; +import { Ask } from '@sallai/ask'; -let { dlq, target, automatic } = parseFlags(Deno.args, { +let { dlq, target, automatic } = parseArgs(Deno.args, { string: ['dlq', 'target'], boolean: ['automatic'], default: { automatic: false }, diff --git a/lib/extras/s3-presign.ts b/lib/extras/s3-presign.ts index b208aba..589ba36 100644 --- a/lib/extras/s3-presign.ts +++ b/lib/extras/s3-presign.ts @@ -1,5 +1,5 @@ -import { type Credentials, DefaultCredentialsProvider, getDefaultRegion } from "../client/credentials.ts"; -import { AWSSignerV4 } from "../client/signing.ts"; +import { type Credentials, DefaultCredentialsProvider, getDefaultRegion } from "@cloudydeno/aws-api/client/credentials.ts"; +import { AWSSignerV4 } from "@cloudydeno/aws-api/client/signing.ts"; export interface GetSignedUrlOptions { bucket: string; diff --git a/lib/extras/s3-presign_test.ts b/lib/extras/s3-presign_test.ts index 57c1838..7c806e2 100644 --- a/lib/extras/s3-presign_test.ts +++ b/lib/extras/s3-presign_test.ts @@ -1,4 +1,4 @@ -import { assertEquals } from "https://deno.land/std@0.177.0/testing/asserts.ts"; +import { assertEquals } from "@std/assert/equals"; import { getPresignedUrl } from "./s3-presign.ts"; const date = new Date('Fri, 24 May 2013 00:00:00 GMT') diff --git a/lib/extras/s3-upload.ts b/lib/extras/s3-upload.ts index 5df107b..1203671 100644 --- a/lib/extras/s3-upload.ts +++ b/lib/extras/s3-upload.ts @@ -1,6 +1,6 @@ -import { pooledMap } from "https://deno.land/std@0.177.0/async/pool.ts"; +import { pooledMap } from "@std/async/pool"; -import { +import type { PutObjectRequest, PutObjectOutput, CreateMultipartUploadRequest, CreateMultipartUploadOutput, UploadPartRequest, UploadPartOutput, @@ -32,41 +32,42 @@ export async function managedUpload( partSize?: number; leavePartsOnError?: boolean; }, -) { +): Promise { let uploadId: string | null = null; - try { - const queueSize = config?.queueSize ?? 4; - const partSize = config?.partSize ?? (5*1024*1024); - let startUploadCall: Promise | null = null; - async function uploadSegment(part: UploadPart) { - if (part.seqNumber == 1 && part.isFinal) { - // fast path: if object is smaller than partSize, simply upload in one go - const response = await s3.putObject({...params, Body: part.payload}); - return { putObject: response }; - } - if (!uploadId) { - // Only want to call createMultipartUpload once - if (!startUploadCall) { - startUploadCall = s3.createMultipartUpload(params).then(x => x.UploadId ?? ''); - } - uploadId = await startUploadCall; - } - if (!uploadId) throw new Error(`No S3 multipart UploadId received from server`); + const queueSize = config?.queueSize ?? 4; + const partSize = config?.partSize ?? (5*1024*1024); - const partResp = await s3.uploadPart({ - ...params, - UploadId: uploadId, - PartNumber: part.seqNumber, - Body: part.payload, - }); - if (!partResp.ETag) throw new Error(`No S3 multipart segment ETag received from server`); - return { uploadPart: { - ETag: partResp.ETag, - PartNumber: part.seqNumber, - }}; + let startUploadCall: Promise | null = null; + async function uploadSegment(part: UploadPart) { + if (part.seqNumber == 1 && part.isFinal) { + // fast path: if object is smaller than partSize, simply upload in one go + const response = await s3.putObject({...params, Body: part.payload}); + return { putObject: response }; + } + if (!uploadId) { + // Only want to call createMultipartUpload once + if (!startUploadCall) { + startUploadCall = s3.createMultipartUpload(params).then(x => x.UploadId ?? ''); + } + uploadId = await startUploadCall; } + if (!uploadId) throw new Error(`No S3 multipart UploadId received from server`); + const partResp = await s3.uploadPart({ + ...params, + UploadId: uploadId, + PartNumber: part.seqNumber, + Body: part.payload, + }); + if (!partResp.ETag) throw new Error(`No S3 multipart segment ETag received from server`); + return { uploadPart: { + ETag: partResp.ETag, + PartNumber: part.seqNumber, + }}; + } + + try { // Actually process the stream and do the transfers const segments = params.Body.pipeThrough(newPartSegmenter(partSize)); const partEtags = new Array(); @@ -110,7 +111,7 @@ interface UploadPart { payload: Uint8Array; isFinal: boolean; } -export function newPartSegmenter(partSize: number) { +export function newPartSegmenter(partSize: number): TransformStream { let currentPart = new Uint8Array(partSize); let byteOffset = 0; let nextPartNum = 1; diff --git a/lib/extras/s3-upload_test.ts b/lib/extras/s3-upload_test.ts index a434358..bfb228f 100644 --- a/lib/extras/s3-upload_test.ts +++ b/lib/extras/s3-upload_test.ts @@ -1,7 +1,7 @@ -import { just } from "https://deno.land/x/stream_observables@v1.2/sources/just.ts"; -import { collect } from "https://deno.land/x/stream_observables@v1.2/sinks/collect.ts"; -import { map } from "https://deno.land/x/stream_observables@v1.2/transforms/map.ts"; -import { assertEquals } from "https://deno.land/std@0.177.0/testing/asserts.ts"; +import { just } from "@cloudydeno/stream-observables/sources/just.ts"; +import { collect } from "@cloudydeno/stream-observables/sinks/collect.ts"; +import { map } from "@cloudydeno/stream-observables/transforms/map.ts"; +import { assertEquals } from "@std/assert/equals"; import { newPartSegmenter } from "./s3-upload.ts"; diff --git a/lib/services/cloudwatch/mod.ts b/lib/services/cloudwatch/mod.ts index 57b8210..910d543 100644 --- a/lib/services/cloudwatch/mod.ts +++ b/lib/services/cloudwatch/mod.ts @@ -1,10 +1,10 @@ // Autogenerated API client for: Amazon CloudWatch export * from "./structs.ts"; -import * as Base64 from "jsr:@std/encoding@1.0.10/base64"; -import * as client from "../../client/common.ts"; -import * as qsP from "../../encoding/querystring.ts"; -import * as xmlP from "../../encoding/xml.ts"; +import * as Base64 from "@std/encoding/base64"; +import * as client from "@cloudydeno/aws-api/client/common.ts"; +import * as qsP from "@cloudydeno/aws-api/encoding/querystring.ts"; +import * as xmlP from "@cloudydeno/aws-api/encoding/xml.ts"; import type * as s from "./structs.ts"; function parseBlob(input: string | null | undefined) { if (input == null) return input; diff --git a/lib/services/cloudwatch/structs.ts b/lib/services/cloudwatch/structs.ts index 91687b3..a3e8352 100644 --- a/lib/services/cloudwatch/structs.ts +++ b/lib/services/cloudwatch/structs.ts @@ -1,6 +1,6 @@ // Autogenerated API structures for: Amazon CloudWatch -import * as cmnP from "../../encoding/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; // refs: 1 - tags: named, input export interface DeleteAlarmsInput { diff --git a/lib/services/dynamodb/mod.ts b/lib/services/dynamodb/mod.ts index e5617fe..8b4aafc 100644 --- a/lib/services/dynamodb/mod.ts +++ b/lib/services/dynamodb/mod.ts @@ -1,10 +1,10 @@ // Autogenerated API client for: Amazon DynamoDB export * from "./structs.ts"; -import * as Base64 from "jsr:@std/encoding@1.0.10/base64"; -import * as client from "../../client/common.ts"; -import * as cmnP from "../../encoding/common.ts"; -import * as jsonP from "../../encoding/json.ts"; +import * as Base64 from "@std/encoding/base64"; +import * as client from "@cloudydeno/aws-api/client/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; +import * as jsonP from "@cloudydeno/aws-api/encoding/json.ts"; import type * as s from "./structs.ts"; function generateIdemptToken() { return crypto.randomUUID(); diff --git a/lib/services/dynamodb/structs.ts b/lib/services/dynamodb/structs.ts index a9e0a7f..9fe62a0 100644 --- a/lib/services/dynamodb/structs.ts +++ b/lib/services/dynamodb/structs.ts @@ -1,6 +1,6 @@ // Autogenerated API structures for: Amazon DynamoDB -import * as cmnP from "../../encoding/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; // refs: 1 - tags: named, input export interface BatchExecuteStatementInput { diff --git a/lib/services/ecr/mod.ts b/lib/services/ecr/mod.ts index 6689d4c..48fe0b0 100644 --- a/lib/services/ecr/mod.ts +++ b/lib/services/ecr/mod.ts @@ -1,10 +1,10 @@ // Autogenerated API client for: Amazon EC2 Container Registry export * from "./structs.ts"; -import * as Base64 from "jsr:@std/encoding@1.0.10/base64"; -import * as client from "../../client/common.ts"; -import * as cmnP from "../../encoding/common.ts"; -import * as jsonP from "../../encoding/json.ts"; +import * as Base64 from "@std/encoding/base64"; +import * as client from "@cloudydeno/aws-api/client/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; +import * as jsonP from "@cloudydeno/aws-api/encoding/json.ts"; import type * as s from "./structs.ts"; function serializeBlob(input: string | Uint8Array | null | undefined) { if (input == null) return input; diff --git a/lib/services/ecr/structs.ts b/lib/services/ecr/structs.ts index 606b736..1bae845 100644 --- a/lib/services/ecr/structs.ts +++ b/lib/services/ecr/structs.ts @@ -1,6 +1,6 @@ // Autogenerated API structures for: Amazon EC2 Container Registry -import * as cmnP from "../../encoding/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; // refs: 1 - tags: named, input export interface BatchCheckLayerAvailabilityRequest { diff --git a/lib/services/kinesis/mod.ts b/lib/services/kinesis/mod.ts index b877c69..979c97b 100644 --- a/lib/services/kinesis/mod.ts +++ b/lib/services/kinesis/mod.ts @@ -1,10 +1,10 @@ // Autogenerated API client for: Amazon Kinesis export * from "./structs.ts"; -import * as Base64 from "jsr:@std/encoding@1.0.10/base64"; -import * as client from "../../client/common.ts"; -import * as cmnP from "../../encoding/common.ts"; -import * as jsonP from "../../encoding/json.ts"; +import * as Base64 from "@std/encoding/base64"; +import * as client from "@cloudydeno/aws-api/client/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; +import * as jsonP from "@cloudydeno/aws-api/encoding/json.ts"; import type * as s from "./structs.ts"; function serializeBlob(input: string | Uint8Array | null | undefined) { if (input == null) return input; diff --git a/lib/services/kinesis/structs.ts b/lib/services/kinesis/structs.ts index 1be41e5..8d91002 100644 --- a/lib/services/kinesis/structs.ts +++ b/lib/services/kinesis/structs.ts @@ -1,6 +1,6 @@ // Autogenerated API structures for: Amazon Kinesis -import * as cmnP from "../../encoding/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; // refs: 1 - tags: named, input export interface AddTagsToStreamInput { diff --git a/lib/services/kms/mod.ts b/lib/services/kms/mod.ts index 0bd5106..7e15408 100644 --- a/lib/services/kms/mod.ts +++ b/lib/services/kms/mod.ts @@ -1,10 +1,10 @@ // Autogenerated API client for: AWS Key Management Service export * from "./structs.ts"; -import * as Base64 from "jsr:@std/encoding@1.0.10/base64"; -import * as client from "../../client/common.ts"; -import * as cmnP from "../../encoding/common.ts"; -import * as jsonP from "../../encoding/json.ts"; +import * as Base64 from "@std/encoding/base64"; +import * as client from "@cloudydeno/aws-api/client/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; +import * as jsonP from "@cloudydeno/aws-api/encoding/json.ts"; import type * as s from "./structs.ts"; function serializeBlob(input: string | Uint8Array | null | undefined) { if (input == null) return input; diff --git a/lib/services/kms/structs.ts b/lib/services/kms/structs.ts index 72e0768..4ae2e20 100644 --- a/lib/services/kms/structs.ts +++ b/lib/services/kms/structs.ts @@ -1,6 +1,6 @@ // Autogenerated API structures for: AWS Key Management Service -import * as cmnP from "../../encoding/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; // refs: 1 - tags: named, input export interface CancelKeyDeletionRequest { diff --git a/lib/services/lambda/mod.ts b/lib/services/lambda/mod.ts index 54f82c8..59a07c1 100644 --- a/lib/services/lambda/mod.ts +++ b/lib/services/lambda/mod.ts @@ -1,10 +1,10 @@ // Autogenerated API client for: AWS Lambda export * from "./structs.ts"; -import * as Base64 from "jsr:@std/encoding@1.0.10/base64"; -import * as client from "../../client/common.ts"; -import * as cmnP from "../../encoding/common.ts"; -import * as jsonP from "../../encoding/json.ts"; +import * as Base64 from "@std/encoding/base64"; +import * as client from "@cloudydeno/aws-api/client/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; +import * as jsonP from "@cloudydeno/aws-api/encoding/json.ts"; import type * as s from "./structs.ts"; function serializeBlob(input: string | Uint8Array | null | undefined) { if (input == null) return input; diff --git a/lib/services/lambda/structs.ts b/lib/services/lambda/structs.ts index a228396..afaf7bf 100644 --- a/lib/services/lambda/structs.ts +++ b/lib/services/lambda/structs.ts @@ -1,6 +1,6 @@ // Autogenerated API structures for: AWS Lambda -import * as cmnP from "../../encoding/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; // refs: 1 - tags: named, input export interface AddLayerVersionPermissionRequest { diff --git a/lib/services/route53/mod.ts b/lib/services/route53/mod.ts index 96d6939..55dfe0e 100644 --- a/lib/services/route53/mod.ts +++ b/lib/services/route53/mod.ts @@ -1,9 +1,9 @@ // Autogenerated API client for: Amazon Route 53 export * from "./structs.ts"; -import * as client from "../../client/common.ts"; -import * as cmnP from "../../encoding/common.ts"; -import * as xmlP from "../../encoding/xml.ts"; +import * as client from "@cloudydeno/aws-api/client/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; +import * as xmlP from "@cloudydeno/aws-api/encoding/xml.ts"; import type * as s from "./structs.ts"; export class Route53 { diff --git a/lib/services/route53/structs.ts b/lib/services/route53/structs.ts index ec7c8fd..537a2c8 100644 --- a/lib/services/route53/structs.ts +++ b/lib/services/route53/structs.ts @@ -1,6 +1,6 @@ // Autogenerated API structures for: Amazon Route 53 -import * as cmnP from "../../encoding/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; // refs: 1 - tags: named, input export interface ActivateKeySigningKeyRequest { diff --git a/lib/services/s3/mod.ts b/lib/services/s3/mod.ts index 767aacd..b4eeda6 100644 --- a/lib/services/s3/mod.ts +++ b/lib/services/s3/mod.ts @@ -1,11 +1,11 @@ // Autogenerated API client for: Amazon Simple Storage Service export * from "./structs.ts"; -import * as Base64 from "jsr:@std/encoding@1.0.10/base64"; -import * as HashMd5 from "jsr:@takker/md5@0.1.0"; -import * as client from "../../client/common.ts"; -import * as cmnP from "../../encoding/common.ts"; -import * as xmlP from "../../encoding/xml.ts"; +import * as Base64 from "@std/encoding/base64"; +import * as HashMd5 from "@takker/md5"; +import * as client from "@cloudydeno/aws-api/client/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; +import * as xmlP from "@cloudydeno/aws-api/encoding/xml.ts"; import type * as s from "./structs.ts"; function hashMD5(data: BufferSource | string): string { const hashed = HashMd5.md5(data); diff --git a/lib/services/s3/structs.ts b/lib/services/s3/structs.ts index cc6ee48..b95456b 100644 --- a/lib/services/s3/structs.ts +++ b/lib/services/s3/structs.ts @@ -1,6 +1,6 @@ // Autogenerated API structures for: Amazon Simple Storage Service -import * as cmnP from "../../encoding/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; // refs: 1 - tags: named, input export interface AbortMultipartUploadRequest { diff --git a/lib/services/sesv2/mod.ts b/lib/services/sesv2/mod.ts index d9f19a3..484a0f4 100644 --- a/lib/services/sesv2/mod.ts +++ b/lib/services/sesv2/mod.ts @@ -1,10 +1,10 @@ // Autogenerated API client for: Amazon Simple Email Service export * from "./structs.ts"; -import * as Base64 from "jsr:@std/encoding@1.0.10/base64"; -import * as client from "../../client/common.ts"; -import * as cmnP from "../../encoding/common.ts"; -import * as jsonP from "../../encoding/json.ts"; +import * as Base64 from "@std/encoding/base64"; +import * as client from "@cloudydeno/aws-api/client/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; +import * as jsonP from "@cloudydeno/aws-api/encoding/json.ts"; import type * as s from "./structs.ts"; function serializeBlob(input: string | Uint8Array | null | undefined) { if (input == null) return input; diff --git a/lib/services/sesv2/structs.ts b/lib/services/sesv2/structs.ts index b557c3d..51d42f9 100644 --- a/lib/services/sesv2/structs.ts +++ b/lib/services/sesv2/structs.ts @@ -1,6 +1,6 @@ // Autogenerated API structures for: Amazon Simple Email Service -import * as cmnP from "../../encoding/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; // refs: 1 - tags: named, input export interface BatchGetMetricDataRequest { diff --git a/lib/services/sns/mod.ts b/lib/services/sns/mod.ts index 9c344cd..e517a33 100644 --- a/lib/services/sns/mod.ts +++ b/lib/services/sns/mod.ts @@ -1,10 +1,10 @@ // Autogenerated API client for: Amazon Simple Notification Service export * from "./structs.ts"; -import * as Base64 from "jsr:@std/encoding@1.0.10/base64"; -import * as client from "../../client/common.ts"; -import * as qsP from "../../encoding/querystring.ts"; -import * as xmlP from "../../encoding/xml.ts"; +import * as Base64 from "@std/encoding/base64"; +import * as client from "@cloudydeno/aws-api/client/common.ts"; +import * as qsP from "@cloudydeno/aws-api/encoding/querystring.ts"; +import * as xmlP from "@cloudydeno/aws-api/encoding/xml.ts"; import type * as s from "./structs.ts"; function serializeBlob(input: string | Uint8Array | null | undefined) { if (input == null) return input; diff --git a/lib/services/sns/structs.ts b/lib/services/sns/structs.ts index c35b2c2..89bd729 100644 --- a/lib/services/sns/structs.ts +++ b/lib/services/sns/structs.ts @@ -1,6 +1,6 @@ // Autogenerated API structures for: Amazon Simple Notification Service -import * as cmnP from "../../encoding/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; // refs: 1 - tags: named, input export interface AddPermissionInput { diff --git a/lib/services/sqs/mod.ts b/lib/services/sqs/mod.ts index 07ed1c9..c118403 100644 --- a/lib/services/sqs/mod.ts +++ b/lib/services/sqs/mod.ts @@ -1,10 +1,10 @@ // Autogenerated API client for: Amazon Simple Queue Service export * from "./structs.ts"; -import * as Base64 from "jsr:@std/encoding@1.0.10/base64"; -import * as client from "../../client/common.ts"; -import * as cmnP from "../../encoding/common.ts"; -import * as jsonP from "../../encoding/json.ts"; +import * as Base64 from "@std/encoding/base64"; +import * as client from "@cloudydeno/aws-api/client/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; +import * as jsonP from "@cloudydeno/aws-api/encoding/json.ts"; import type * as s from "./structs.ts"; function serializeBlob(input: string | Uint8Array | null | undefined) { if (input == null) return input; diff --git a/lib/services/sqs/structs.ts b/lib/services/sqs/structs.ts index c47b535..113346c 100644 --- a/lib/services/sqs/structs.ts +++ b/lib/services/sqs/structs.ts @@ -1,6 +1,6 @@ // Autogenerated API structures for: Amazon Simple Queue Service -import * as cmnP from "../../encoding/common.ts"; +import * as cmnP from "@cloudydeno/aws-api/encoding/common.ts"; // refs: 1 - tags: named, input export interface AddPermissionRequest { diff --git a/lib/services/sts/mod.ts b/lib/services/sts/mod.ts index aeb0bab..e5799b5 100644 --- a/lib/services/sts/mod.ts +++ b/lib/services/sts/mod.ts @@ -1,9 +1,9 @@ // Autogenerated API client for: AWS Security Token Service export * from "./structs.ts"; -import * as client from "../../client/common.ts"; -import * as qsP from "../../encoding/querystring.ts"; -import * as xmlP from "../../encoding/xml.ts"; +import * as client from "@cloudydeno/aws-api/client/common.ts"; +import * as qsP from "@cloudydeno/aws-api/encoding/querystring.ts"; +import * as xmlP from "@cloudydeno/aws-api/encoding/xml.ts"; import type * as s from "./structs.ts"; export class STS {