@safeurl/sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0 (2026-03-27)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * **ts:** rename package to @safeurl/sdk and add publish config
9
+
10
+ ### Features
11
+
12
+ * centralize openapi fetch and generation ([8779ab4](https://github.com/gnoverse/safeurl-sdk/commit/8779ab469bdbdc2790909812a4702c2d49f66569))
13
+ * initial typescript sdk generation ([4dd77e4](https://github.com/gnoverse/safeurl-sdk/commit/4dd77e45aa1554b2fa5d9b7f2043a6e0f35f69b6))
14
+ * smoke tests, release-please, and @safeurl/sdk package rename ([9af2b58](https://github.com/gnoverse/safeurl-sdk/commit/9af2b585bbb4dbee2245dfecb812ca8da41669dd))
15
+ * **ts:** rename package to @safeurl/sdk and add publish config ([2862f12](https://github.com/gnoverse/safeurl-sdk/commit/2862f121998b215149108d2f589cbe648d00bc2a))
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **smoke:** clean up test keys and disable cache ([6afed44](https://github.com/gnoverse/safeurl-sdk/commit/6afed4467d7639c0cc49e5df3e5a96705a65a300))
package/CLAUDE.md ADDED
@@ -0,0 +1,111 @@
1
+ ---
2
+ description: Use Bun instead of Node.js, npm, pnpm, or vite.
3
+ globs: "*.ts, *.tsx, *.html, *.css, *.js, *.jsx, package.json"
4
+ alwaysApply: false
5
+ ---
6
+
7
+ Default to using Bun instead of Node.js.
8
+
9
+ - Use `bun <file>` instead of `node <file>` or `ts-node <file>`
10
+ - Use `bun test` instead of `jest` or `vitest`
11
+ - Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
12
+ - Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
13
+ - Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
14
+ - Use `bunx <package> <command>` instead of `npx <package> <command>`
15
+ - Bun automatically loads .env, so don't use dotenv.
16
+
17
+ ## APIs
18
+
19
+ - `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
20
+ - `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
21
+ - `Bun.redis` for Redis. Don't use `ioredis`.
22
+ - `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
23
+ - `WebSocket` is built-in. Don't use `ws`.
24
+ - Prefer `Bun.file` over `node:fs`'s readFile/writeFile
25
+ - Bun.$`ls` instead of execa.
26
+
27
+ ## Testing
28
+
29
+ Use `bun test` to run tests.
30
+
31
+ ```ts#index.test.ts
32
+ import { test, expect } from "bun:test";
33
+
34
+ test("hello world", () => {
35
+ expect(1).toBe(1);
36
+ });
37
+ ```
38
+
39
+ ## Frontend
40
+
41
+ Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.
42
+
43
+ Server:
44
+
45
+ ```ts#index.ts
46
+ import index from "./index.html"
47
+
48
+ Bun.serve({
49
+ routes: {
50
+ "/": index,
51
+ "/api/users/:id": {
52
+ GET: (req) => {
53
+ return new Response(JSON.stringify({ id: req.params.id }));
54
+ },
55
+ },
56
+ },
57
+ // optional websocket support
58
+ websocket: {
59
+ open: (ws) => {
60
+ ws.send("Hello, world!");
61
+ },
62
+ message: (ws, message) => {
63
+ ws.send(message);
64
+ },
65
+ close: (ws) => {
66
+ // handle close
67
+ }
68
+ },
69
+ development: {
70
+ hmr: true,
71
+ console: true,
72
+ }
73
+ })
74
+ ```
75
+
76
+ HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.
77
+
78
+ ```html#index.html
79
+ <html>
80
+ <body>
81
+ <h1>Hello, world!</h1>
82
+ <script type="module" src="./frontend.tsx"></script>
83
+ </body>
84
+ </html>
85
+ ```
86
+
87
+ With the following `frontend.tsx`:
88
+
89
+ ```tsx#frontend.tsx
90
+ import React from "react";
91
+ import { createRoot } from "react-dom/client";
92
+
93
+ // import .css files directly and it works
94
+ import './index.css';
95
+
96
+ const root = createRoot(document.body);
97
+
98
+ export default function Frontend() {
99
+ return <h1>Hello, world!</h1>;
100
+ }
101
+
102
+ root.render(<Frontend />);
103
+ ```
104
+
105
+ Then, run index.ts
106
+
107
+ ```sh
108
+ bun --hot ./index.ts
109
+ ```
110
+
111
+ For more information, read the Bun API docs in `node_modules/bun-types/docs/**.mdx`.
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # ts
2
+
3
+ To install dependencies:
4
+
5
+ ```bash
6
+ bun install
7
+ ```
8
+
9
+ To run:
10
+
11
+ ```bash
12
+ bun run index.ts
13
+ ```
14
+
15
+ This project was created using `bun init` in bun v1.3.10. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
package/bun.lock ADDED
@@ -0,0 +1,140 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "configVersion": 1,
4
+ "workspaces": {
5
+ "": {
6
+ "name": "ts",
7
+ "dependencies": {
8
+ "@hey-api/client-fetch": "^0.13.1",
9
+ },
10
+ "devDependencies": {
11
+ "@hey-api/openapi-ts": "^0.94.4",
12
+ "@types/bun": "latest",
13
+ },
14
+ "peerDependencies": {
15
+ "typescript": "^6.0.2",
16
+ },
17
+ },
18
+ },
19
+ "packages": {
20
+ "@hey-api/client-fetch": ["@hey-api/client-fetch@0.13.1", "", { "peerDependencies": { "@hey-api/openapi-ts": "< 2" } }, "sha512-29jBRYNdxVGlx5oewFgOrkulZckpIpBIRHth3uHFn1PrL2ucMy52FvWOY3U3dVx2go1Z3kUmMi6lr07iOpUqqA=="],
21
+
22
+ "@hey-api/codegen-core": ["@hey-api/codegen-core@0.7.4", "", { "dependencies": { "@hey-api/types": "0.1.4", "ansi-colors": "4.1.3", "c12": "3.3.3", "color-support": "1.1.3" } }, "sha512-DGd9yeSQzflOWO3Y5mt1GRXkXH9O/yIMgbxPjwLI3jwu/3nAjoXXD26lEeFb6tclYlg0JAqTIs5d930G/qxHeA=="],
23
+
24
+ "@hey-api/json-schema-ref-parser": ["@hey-api/json-schema-ref-parser@1.3.1", "", { "dependencies": { "@jsdevtools/ono": "7.1.3", "@types/json-schema": "7.0.15", "js-yaml": "4.1.1" } }, "sha512-7atnpUkT8TyUPHYPLk91j/GyaqMuwTEHanLOe50Dlx0EEvNuQqFD52Yjg8x4KU0UFL1mWlyhE+sUE/wAtQ1N2A=="],
25
+
26
+ "@hey-api/openapi-ts": ["@hey-api/openapi-ts@0.94.4", "", { "dependencies": { "@hey-api/codegen-core": "0.7.4", "@hey-api/json-schema-ref-parser": "1.3.1", "@hey-api/shared": "0.2.5", "@hey-api/types": "0.1.4", "ansi-colors": "4.1.3", "color-support": "1.1.3", "commander": "14.0.3", "get-tsconfig": "4.13.6" }, "peerDependencies": { "typescript": ">=5.5.3 || 6.0.1-rc" }, "bin": { "openapi-ts": "bin/run.js" } }, "sha512-943f7wlLAQ0KHVx8CeD3xYJzBsCRQYtr+lgMYrAdfV48j32loqsqiMAM4fsMxvSO7mkz0lqcJkIb+YZIXO8Ubg=="],
27
+
28
+ "@hey-api/shared": ["@hey-api/shared@0.2.5", "", { "dependencies": { "@hey-api/codegen-core": "0.7.4", "@hey-api/json-schema-ref-parser": "1.3.1", "@hey-api/types": "0.1.4", "ansi-colors": "4.1.3", "cross-spawn": "7.0.6", "open": "11.0.0", "semver": "7.7.3" } }, "sha512-NS57dHXxhwBtenPWAzljA0I493ZxzjcZZtr8KFr8SsLboofdjcAbVRFAfOQ0iv2JMhOe9oyiWEEc1QOJ/9WWaw=="],
29
+
30
+ "@hey-api/types": ["@hey-api/types@0.1.4", "", {}, "sha512-thWfawrDIP7wSI9ioT13I5soaaqB5vAPIiZmgD8PbeEVKNrkonc0N/Sjj97ezl7oQgusZmaNphGdMKipPO6IBg=="],
31
+
32
+ "@jsdevtools/ono": ["@jsdevtools/ono@7.1.3", "", {}, "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="],
33
+
34
+ "@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="],
35
+
36
+ "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
37
+
38
+ "@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
39
+
40
+ "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="],
41
+
42
+ "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
43
+
44
+ "bun-types": ["bun-types@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="],
45
+
46
+ "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
47
+
48
+ "c12": ["c12@3.3.3", "", { "dependencies": { "chokidar": "^5.0.0", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^17.2.3", "exsolve": "^1.0.8", "giget": "^2.0.0", "jiti": "^2.6.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.0.0", "pkg-types": "^2.3.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "*" }, "optionalPeers": ["magicast"] }, "sha512-750hTRvgBy5kcMNPdh95Qo+XUBeGo8C7nsKSmedDmaQI+E0r82DwHeM6vBewDe4rGFbnxoa4V9pw+sPh5+Iz8Q=="],
49
+
50
+ "chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="],
51
+
52
+ "citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="],
53
+
54
+ "color-support": ["color-support@1.1.3", "", { "bin": { "color-support": "bin.js" } }, "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="],
55
+
56
+ "commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="],
57
+
58
+ "confbox": ["confbox@0.2.4", "", {}, "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ=="],
59
+
60
+ "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="],
61
+
62
+ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
63
+
64
+ "default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="],
65
+
66
+ "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="],
67
+
68
+ "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="],
69
+
70
+ "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="],
71
+
72
+ "destr": ["destr@2.0.5", "", {}, "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="],
73
+
74
+ "dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="],
75
+
76
+ "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="],
77
+
78
+ "get-tsconfig": ["get-tsconfig@4.13.6", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw=="],
79
+
80
+ "giget": ["giget@2.0.0", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "defu": "^6.1.4", "node-fetch-native": "^1.6.6", "nypm": "^0.6.0", "pathe": "^2.0.3" }, "bin": { "giget": "dist/cli.mjs" } }, "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA=="],
81
+
82
+ "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
83
+
84
+ "is-in-ssh": ["is-in-ssh@1.0.0", "", {}, "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw=="],
85
+
86
+ "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="],
87
+
88
+ "is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="],
89
+
90
+ "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
91
+
92
+ "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
93
+
94
+ "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
95
+
96
+ "node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="],
97
+
98
+ "nypm": ["nypm@0.6.5", "", { "dependencies": { "citty": "^0.2.0", "pathe": "^2.0.3", "tinyexec": "^1.0.2" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ=="],
99
+
100
+ "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="],
101
+
102
+ "open": ["open@11.0.0", "", { "dependencies": { "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", "powershell-utils": "^0.1.0", "wsl-utils": "^0.3.0" } }, "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw=="],
103
+
104
+ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
105
+
106
+ "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
107
+
108
+ "perfect-debounce": ["perfect-debounce@2.1.0", "", {}, "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g=="],
109
+
110
+ "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="],
111
+
112
+ "powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="],
113
+
114
+ "rc9": ["rc9@2.1.2", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" } }, "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg=="],
115
+
116
+ "readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="],
117
+
118
+ "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
119
+
120
+ "run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="],
121
+
122
+ "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
123
+
124
+ "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
125
+
126
+ "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
127
+
128
+ "tinyexec": ["tinyexec@1.0.4", "", {}, "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw=="],
129
+
130
+ "typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="],
131
+
132
+ "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
133
+
134
+ "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
135
+
136
+ "wsl-utils": ["wsl-utils@0.3.1", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg=="],
137
+
138
+ "nypm/citty": ["citty@0.2.1", "", {}, "sha512-kEV95lFBhQgtogAPlQfJJ0WGVSokvLr/UEoFPiKKOXF7pl98HfUVUD0ejsuTCld/9xH9vogSywZ5KqHzXrZpqg=="],
139
+ }
140
+ }
package/index.ts ADDED
@@ -0,0 +1 @@
1
+ console.log("Hello via Bun!");
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@safeurl/sdk",
3
+ "version": "1.0.0",
4
+ "description": "SafeURL TypeScript SDK",
5
+ "main": "index.ts",
6
+ "type": "module",
7
+ "scripts": {
8
+ "test": "bun test",
9
+ "test:smoke": "bun test tests/sdk-smoke.test.ts"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/gnoverse/safeurl-sdk.git",
14
+ "directory": "ts"
15
+ },
16
+ "devDependencies": {
17
+ "@hey-api/openapi-ts": "^0.94.4",
18
+ "@types/bun": "latest"
19
+ },
20
+ "peerDependencies": {
21
+ "typescript": "^6.0.2"
22
+ },
23
+ "dependencies": {
24
+ "@hey-api/client-fetch": "^0.13.1"
25
+ },
26
+ "publishConfig": {
27
+ "access": "public"
28
+ }
29
+ }
@@ -0,0 +1,290 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+
3
+ import { createSseClient } from '../core/serverSentEvents.gen';
4
+ import type { HttpMethod } from '../core/types.gen';
5
+ import { getValidRequestBody } from '../core/utils.gen';
6
+ import type { Client, Config, RequestOptions, ResolvedRequestOptions } from './types.gen';
7
+ import {
8
+ buildUrl,
9
+ createConfig,
10
+ createInterceptors,
11
+ getParseAs,
12
+ mergeConfigs,
13
+ mergeHeaders,
14
+ setAuthParams,
15
+ } from './utils.gen';
16
+
17
+ type ReqInit = Omit<RequestInit, 'body' | 'headers'> & {
18
+ body?: any;
19
+ headers: ReturnType<typeof mergeHeaders>;
20
+ };
21
+
22
+ export const createClient = (config: Config = {}): Client => {
23
+ let _config = mergeConfigs(createConfig(), config);
24
+
25
+ const getConfig = (): Config => ({ ..._config });
26
+
27
+ const setConfig = (config: Config): Config => {
28
+ _config = mergeConfigs(_config, config);
29
+ return getConfig();
30
+ };
31
+
32
+ const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>();
33
+
34
+ const beforeRequest = async (options: RequestOptions) => {
35
+ const opts = {
36
+ ..._config,
37
+ ...options,
38
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
39
+ headers: mergeHeaders(_config.headers, options.headers),
40
+ serializedBody: undefined as string | undefined,
41
+ };
42
+
43
+ if (opts.security) {
44
+ await setAuthParams({
45
+ ...opts,
46
+ security: opts.security,
47
+ });
48
+ }
49
+
50
+ if (opts.requestValidator) {
51
+ await opts.requestValidator(opts);
52
+ }
53
+
54
+ if (opts.body !== undefined && opts.bodySerializer) {
55
+ opts.serializedBody = opts.bodySerializer(opts.body) as string | undefined;
56
+ }
57
+
58
+ // remove Content-Type header if body is empty to avoid sending invalid requests
59
+ if (opts.body === undefined || opts.serializedBody === '') {
60
+ opts.headers.delete('Content-Type');
61
+ }
62
+
63
+ const url = buildUrl(opts);
64
+
65
+ return { opts, url };
66
+ };
67
+
68
+ const request: Client['request'] = async (options) => {
69
+ // @ts-expect-error
70
+ const { opts, url } = await beforeRequest(options);
71
+ const requestInit: ReqInit = {
72
+ redirect: 'follow',
73
+ ...opts,
74
+ body: getValidRequestBody(opts),
75
+ };
76
+
77
+ let request = new Request(url, requestInit);
78
+
79
+ for (const fn of interceptors.request.fns) {
80
+ if (fn) {
81
+ request = await fn(request, opts);
82
+ }
83
+ }
84
+
85
+ // fetch must be assigned here, otherwise it would throw the error:
86
+ // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
87
+ const _fetch = opts.fetch!;
88
+ let response: Response;
89
+
90
+ try {
91
+ response = await _fetch(request);
92
+ } catch (error) {
93
+ // Handle fetch exceptions (AbortError, network errors, etc.)
94
+ let finalError = error;
95
+
96
+ for (const fn of interceptors.error.fns) {
97
+ if (fn) {
98
+ finalError = (await fn(error, undefined as any, request, opts)) as unknown;
99
+ }
100
+ }
101
+
102
+ finalError = finalError || ({} as unknown);
103
+
104
+ if (opts.throwOnError) {
105
+ throw finalError;
106
+ }
107
+
108
+ // Return error response
109
+ return opts.responseStyle === 'data'
110
+ ? undefined
111
+ : {
112
+ error: finalError,
113
+ request,
114
+ response: undefined as any,
115
+ };
116
+ }
117
+
118
+ for (const fn of interceptors.response.fns) {
119
+ if (fn) {
120
+ response = await fn(response, request, opts);
121
+ }
122
+ }
123
+
124
+ const result = {
125
+ request,
126
+ response,
127
+ };
128
+
129
+ if (response.ok) {
130
+ const parseAs =
131
+ (opts.parseAs === 'auto'
132
+ ? getParseAs(response.headers.get('Content-Type'))
133
+ : opts.parseAs) ?? 'json';
134
+
135
+ if (response.status === 204 || response.headers.get('Content-Length') === '0') {
136
+ let emptyData: any;
137
+ switch (parseAs) {
138
+ case 'arrayBuffer':
139
+ case 'blob':
140
+ case 'text':
141
+ emptyData = await response[parseAs]();
142
+ break;
143
+ case 'formData':
144
+ emptyData = new FormData();
145
+ break;
146
+ case 'stream':
147
+ emptyData = response.body;
148
+ break;
149
+ case 'json':
150
+ default:
151
+ emptyData = {};
152
+ break;
153
+ }
154
+ return opts.responseStyle === 'data'
155
+ ? emptyData
156
+ : {
157
+ data: emptyData,
158
+ ...result,
159
+ };
160
+ }
161
+
162
+ let data: any;
163
+ switch (parseAs) {
164
+ case 'arrayBuffer':
165
+ case 'blob':
166
+ case 'formData':
167
+ case 'text':
168
+ data = await response[parseAs]();
169
+ break;
170
+ case 'json': {
171
+ // Some servers return 200 with no Content-Length and empty body.
172
+ // response.json() would throw; read as text and parse if non-empty.
173
+ const text = await response.text();
174
+ data = text ? JSON.parse(text) : {};
175
+ break;
176
+ }
177
+ case 'stream':
178
+ return opts.responseStyle === 'data'
179
+ ? response.body
180
+ : {
181
+ data: response.body,
182
+ ...result,
183
+ };
184
+ }
185
+
186
+ if (parseAs === 'json') {
187
+ if (opts.responseValidator) {
188
+ await opts.responseValidator(data);
189
+ }
190
+
191
+ if (opts.responseTransformer) {
192
+ data = await opts.responseTransformer(data);
193
+ }
194
+ }
195
+
196
+ return opts.responseStyle === 'data'
197
+ ? data
198
+ : {
199
+ data,
200
+ ...result,
201
+ };
202
+ }
203
+
204
+ const textError = await response.text();
205
+ let jsonError: unknown;
206
+
207
+ try {
208
+ jsonError = JSON.parse(textError);
209
+ } catch {
210
+ // noop
211
+ }
212
+
213
+ const error = jsonError ?? textError;
214
+ let finalError = error;
215
+
216
+ for (const fn of interceptors.error.fns) {
217
+ if (fn) {
218
+ finalError = (await fn(error, response, request, opts)) as string;
219
+ }
220
+ }
221
+
222
+ finalError = finalError || ({} as string);
223
+
224
+ if (opts.throwOnError) {
225
+ throw finalError;
226
+ }
227
+
228
+ // TODO: we probably want to return error and improve types
229
+ return opts.responseStyle === 'data'
230
+ ? undefined
231
+ : {
232
+ error: finalError,
233
+ ...result,
234
+ };
235
+ };
236
+
237
+ const makeMethodFn = (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>
238
+ request({ ...options, method });
239
+
240
+ const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
241
+ const { opts, url } = await beforeRequest(options);
242
+ return createSseClient({
243
+ ...opts,
244
+ body: opts.body as BodyInit | null | undefined,
245
+ headers: opts.headers as unknown as Record<string, string>,
246
+ method,
247
+ onRequest: async (url, init) => {
248
+ let request = new Request(url, init);
249
+ for (const fn of interceptors.request.fns) {
250
+ if (fn) {
251
+ request = await fn(request, opts);
252
+ }
253
+ }
254
+ return request;
255
+ },
256
+ serializedBody: getValidRequestBody(opts) as BodyInit | null | undefined,
257
+ url,
258
+ });
259
+ };
260
+
261
+ const _buildUrl: Client['buildUrl'] = (options) => buildUrl({ ..._config, ...options });
262
+
263
+ return {
264
+ buildUrl: _buildUrl,
265
+ connect: makeMethodFn('CONNECT'),
266
+ delete: makeMethodFn('DELETE'),
267
+ get: makeMethodFn('GET'),
268
+ getConfig,
269
+ head: makeMethodFn('HEAD'),
270
+ interceptors,
271
+ options: makeMethodFn('OPTIONS'),
272
+ patch: makeMethodFn('PATCH'),
273
+ post: makeMethodFn('POST'),
274
+ put: makeMethodFn('PUT'),
275
+ request,
276
+ setConfig,
277
+ sse: {
278
+ connect: makeSseFn('CONNECT'),
279
+ delete: makeSseFn('DELETE'),
280
+ get: makeSseFn('GET'),
281
+ head: makeSseFn('HEAD'),
282
+ options: makeSseFn('OPTIONS'),
283
+ patch: makeSseFn('PATCH'),
284
+ post: makeSseFn('POST'),
285
+ put: makeSseFn('PUT'),
286
+ trace: makeSseFn('TRACE'),
287
+ },
288
+ trace: makeMethodFn('TRACE'),
289
+ } as Client;
290
+ };
@@ -0,0 +1,25 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+
3
+ export type { Auth } from '../core/auth.gen';
4
+ export type { QuerySerializerOptions } from '../core/bodySerializer.gen';
5
+ export {
6
+ formDataBodySerializer,
7
+ jsonBodySerializer,
8
+ urlSearchParamsBodySerializer,
9
+ } from '../core/bodySerializer.gen';
10
+ export { buildClientParams } from '../core/params.gen';
11
+ export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen';
12
+ export { createClient } from './client.gen';
13
+ export type {
14
+ Client,
15
+ ClientOptions,
16
+ Config,
17
+ CreateClientConfig,
18
+ Options,
19
+ RequestOptions,
20
+ RequestResult,
21
+ ResolvedRequestOptions,
22
+ ResponseStyle,
23
+ TDataShape,
24
+ } from './types.gen';
25
+ export { createConfig, mergeHeaders } from './utils.gen';