mirror of
https://github.com/Blah-IM/typescript-core.git
synced 2025-06-23 08:21:11 +00:00
refactor: Switch to Node-based package structure
- unbuild for building npm packages - vitest for testing - remove dependency on deno
This commit is contained in:
parent
7f4d6ce3f3
commit
1962ecb298
45 changed files with 2293 additions and 525 deletions
33
.github/workflows/deno.yml
vendored
33
.github/workflows/deno.yml
vendored
|
@ -1,33 +0,0 @@
|
|||
name: Deno
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
branches: ["main"]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Setup repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Deno
|
||||
uses: denoland/setup-deno@v2
|
||||
with:
|
||||
deno-version: v2.x
|
||||
|
||||
# Uncomment this step to verify the use of 'deno fmt' on each commit.
|
||||
# - name: Verify formatting
|
||||
# run: deno fmt --check
|
||||
|
||||
- name: Run linter
|
||||
run: deno lint
|
||||
|
||||
- name: Run tests
|
||||
run: deno test -A
|
33
.github/workflows/publish.yml
vendored
33
.github/workflows/publish.yml
vendored
|
@ -1,36 +1,35 @@
|
|||
name: Publish on JSR & npm
|
||||
name: Test & Publish on JSR & npm
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [Deno]
|
||||
types: [completed]
|
||||
branches: [main]
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
publish:
|
||||
testAndPublish:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write # The OIDC ID token is used for authentication with JSR.
|
||||
steps:
|
||||
- name: Setup Deno
|
||||
uses: denoland/setup-deno@v2
|
||||
with:
|
||||
deno-version: v2.x
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22.x"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
- name: Build & test npm package
|
||||
run: deno task build:npm
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Build & Test
|
||||
run: pnpm build && pnpm test
|
||||
|
||||
- name: Publish to JSR
|
||||
run: npx jsr publish
|
||||
run: pnpm dlx jsr publish
|
||||
- name: Publish to npm
|
||||
run: |
|
||||
cd npm
|
||||
npx is-published@0.2.0 || npm publish --provenance --access public
|
||||
run: pnpm dlx is-published@0.2.0 || pnpm publish --provenance --access public
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1 +1 @@
|
|||
npm
|
||||
node_modules
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
{
|
||||
"lsp": {
|
||||
"deno": {
|
||||
"settings": {
|
||||
"deno": {
|
||||
"enable": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"languages": {
|
||||
"TypeScript": {
|
||||
"language_servers": [
|
||||
"deno",
|
||||
"!typescript-language-server",
|
||||
"!vtsls",
|
||||
"!eslint"
|
||||
],
|
||||
"formatter": "language_server"
|
||||
},
|
||||
"TSX": {
|
||||
"language_servers": [
|
||||
"deno",
|
||||
"!typescript-language-server",
|
||||
"!vtsls",
|
||||
"!eslint"
|
||||
],
|
||||
"formatter": "language_server"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,6 @@
|
|||
// Static tasks configuration.
|
||||
//
|
||||
// Example:
|
||||
[
|
||||
{
|
||||
"label": "Deno Test",
|
||||
"command": "deno test -A"
|
||||
},
|
||||
{
|
||||
"label": "Deno Test - Watch",
|
||||
"command": "deno test -A --watch"
|
||||
"label": "Test",
|
||||
"command": "pnpm test"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
import z from "zod";
|
||||
import type { BlahSignedPayload } from "./mod.ts";
|
||||
import {
|
||||
type BlahPayloadSignee,
|
||||
blahPayloadSigneeSchemaOf,
|
||||
blahSignedPayloadSchemaOf,
|
||||
} from "./signedPayload.ts";
|
||||
import { assertTypeMatchesZodSchema } from "../test/utils.ts";
|
||||
|
||||
const testPayloadSchema = z.object({
|
||||
foo: z.string(),
|
||||
});
|
||||
type TestPayload = z.infer<typeof testPayloadSchema>;
|
||||
|
||||
Deno.test("type BlahPayloadSignee is accurate", () => {
|
||||
assertTypeMatchesZodSchema<BlahPayloadSignee<TestPayload>>(
|
||||
blahPayloadSigneeSchemaOf(testPayloadSchema),
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test("type BlahSignedPayload is accurate", () => {
|
||||
assertTypeMatchesZodSchema<BlahSignedPayload<TestPayload>>(
|
||||
blahSignedPayloadSchemaOf(testPayloadSchema),
|
||||
);
|
||||
});
|
31
deno.json
31
deno.json
|
@ -1,31 +0,0 @@
|
|||
{
|
||||
"name": "@blah/core",
|
||||
"version": "0.8.3",
|
||||
"exports": {
|
||||
"./crypto": "./crypto/mod.ts",
|
||||
"./identity": "./identity/mod.ts",
|
||||
"./richText": "./richText/mod.ts"
|
||||
},
|
||||
"imports": {
|
||||
"@deno/dnt": "jsr:@deno/dnt@^0.42.1",
|
||||
"@std/expect": "jsr:@std/expect@^1.0.16",
|
||||
"@std/testing": "jsr:@std/testing@^1.0.12",
|
||||
"zod": "npm:zod@^3.25.7"
|
||||
},
|
||||
"tasks": {
|
||||
"build:npm": "deno run -A ./scripts/build_npm.ts"
|
||||
},
|
||||
"publish": {
|
||||
"include": ["LICENSE", "README.md", "crypto", "identity", "richText"],
|
||||
"exclude": ["**/*.test.ts"]
|
||||
},
|
||||
"test": {
|
||||
"exclude": ["npm/"]
|
||||
},
|
||||
"lint": {
|
||||
"exclude": ["npm/"]
|
||||
},
|
||||
"fmt": {
|
||||
"exclude": ["npm/"]
|
||||
}
|
||||
}
|
221
deno.lock
generated
221
deno.lock
generated
|
@ -1,221 +0,0 @@
|
|||
{
|
||||
"version": "5",
|
||||
"specifiers": {
|
||||
"jsr:@david/code-block-writer@^13.0.2": "13.0.3",
|
||||
"jsr:@deno/cache-dir@0.20": "0.20.1",
|
||||
"jsr:@deno/dnt@~0.42.1": "0.42.1",
|
||||
"jsr:@deno/graph@0.86": "0.86.9",
|
||||
"jsr:@std/assert@^1.0.13": "1.0.13",
|
||||
"jsr:@std/assert@^1.0.5": "1.0.5",
|
||||
"jsr:@std/async@^1.0.13": "1.0.13",
|
||||
"jsr:@std/bytes@^1.0.5": "1.0.6",
|
||||
"jsr:@std/data-structures@^1.0.8": "1.0.8",
|
||||
"jsr:@std/expect@^1.0.16": "1.0.16",
|
||||
"jsr:@std/fmt@1": "1.0.8",
|
||||
"jsr:@std/fmt@^1.0.3": "1.0.8",
|
||||
"jsr:@std/fs@1": "1.0.17",
|
||||
"jsr:@std/fs@^1.0.17": "1.0.17",
|
||||
"jsr:@std/fs@^1.0.4": "1.0.4",
|
||||
"jsr:@std/fs@^1.0.5": "1.0.6",
|
||||
"jsr:@std/fs@^1.0.6": "1.0.17",
|
||||
"jsr:@std/fs@^1.0.9": "1.0.13",
|
||||
"jsr:@std/internal@^1.0.3": "1.0.3",
|
||||
"jsr:@std/internal@^1.0.6": "1.0.7",
|
||||
"jsr:@std/internal@^1.0.7": "1.0.7",
|
||||
"jsr:@std/io@0.225": "0.225.2",
|
||||
"jsr:@std/path@1": "1.0.9",
|
||||
"jsr:@std/path@^1.0.4": "1.0.6",
|
||||
"jsr:@std/path@^1.0.6": "1.0.6",
|
||||
"jsr:@std/path@^1.0.8": "1.0.9",
|
||||
"jsr:@std/path@^1.0.9": "1.0.9",
|
||||
"jsr:@std/testing@^1.0.12": "1.0.12",
|
||||
"jsr:@ts-morph/bootstrap@0.25": "0.25.0",
|
||||
"jsr:@ts-morph/common@0.25": "0.25.0",
|
||||
"npm:zod@^3.25.7": "3.25.7"
|
||||
},
|
||||
"jsr": {
|
||||
"@david/code-block-writer@13.0.2": {
|
||||
"integrity": "14dd3baaafa3a2dea8bf7dfbcddeccaa13e583da2d21d666c01dc6d681cd74ad"
|
||||
},
|
||||
"@david/code-block-writer@13.0.3": {
|
||||
"integrity": "f98c77d320f5957899a61bfb7a9bead7c6d83ad1515daee92dbacc861e13bb7f"
|
||||
},
|
||||
"@deno/cache-dir@0.20.1": {
|
||||
"integrity": "dc4f3add14307f3ff3b712441ea4acabcbfc9a13f67c5adc78c3aac16ac5e2a0",
|
||||
"dependencies": [
|
||||
"jsr:@deno/graph",
|
||||
"jsr:@std/fmt@^1.0.3",
|
||||
"jsr:@std/fs@^1.0.6",
|
||||
"jsr:@std/io",
|
||||
"jsr:@std/path@^1.0.8"
|
||||
]
|
||||
},
|
||||
"@deno/dnt@0.42.1": {
|
||||
"integrity": "85322b38eb40d4e8c5216d62536152c35b1bda9dc47c8c60860610397b960223",
|
||||
"dependencies": [
|
||||
"jsr:@david/code-block-writer",
|
||||
"jsr:@deno/cache-dir",
|
||||
"jsr:@std/fmt@1",
|
||||
"jsr:@std/fs@1",
|
||||
"jsr:@std/path@1",
|
||||
"jsr:@ts-morph/bootstrap"
|
||||
]
|
||||
},
|
||||
"@deno/graph@0.86.9": {
|
||||
"integrity": "c4f353a695bcc5246c099602977dabc6534eacea9999a35a8cb24e807192e6a1"
|
||||
},
|
||||
"@std/assert@1.0.5": {
|
||||
"integrity": "e37da8e4033490ce613eec4ac1d78dba1faf5b02a3f6c573a28f15365b9b440f",
|
||||
"dependencies": [
|
||||
"jsr:@std/internal@^1.0.3"
|
||||
]
|
||||
},
|
||||
"@std/assert@1.0.12": {
|
||||
"integrity": "08009f0926dda9cbd8bef3a35d3b6a4b964b0ab5c3e140a4e0351fbf34af5b9a",
|
||||
"dependencies": [
|
||||
"jsr:@std/internal@^1.0.6"
|
||||
]
|
||||
},
|
||||
"@std/assert@1.0.13": {
|
||||
"integrity": "ae0d31e41919b12c656c742b22522c32fb26ed0cba32975cb0de2a273cb68b29",
|
||||
"dependencies": [
|
||||
"jsr:@std/internal@^1.0.6"
|
||||
]
|
||||
},
|
||||
"@std/async@1.0.13": {
|
||||
"integrity": "1d76ca5d324aef249908f7f7fe0d39aaf53198e5420604a59ab5c035adc97c96"
|
||||
},
|
||||
"@std/bytes@1.0.6": {
|
||||
"integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a"
|
||||
},
|
||||
"@std/data-structures@1.0.8": {
|
||||
"integrity": "2fb7219247e044c8fcd51341788547575653c82ae2c759ff209e0263ba7d9b66"
|
||||
},
|
||||
"@std/expect@1.0.3": {
|
||||
"integrity": "d9cbd03323ef7feafd1e969ed85d5edb04ebbd9937b0fe7a52d5ff53be8e913a",
|
||||
"dependencies": [
|
||||
"jsr:@std/assert@^1.0.5",
|
||||
"jsr:@std/internal@^1.0.3"
|
||||
]
|
||||
},
|
||||
"@std/expect@1.0.16": {
|
||||
"integrity": "ceeef6dda21f256a5f0f083fcc0eaca175428b523359a9b1d9b3a1df11cc7391",
|
||||
"dependencies": [
|
||||
"jsr:@std/assert@^1.0.13",
|
||||
"jsr:@std/internal@^1.0.7"
|
||||
]
|
||||
},
|
||||
"@std/fmt@1.0.2": {
|
||||
"integrity": "87e9dfcdd3ca7c066e0c3c657c1f987c82888eb8103a3a3baa62684ffeb0f7a7"
|
||||
},
|
||||
"@std/fmt@1.0.5": {
|
||||
"integrity": "0cfab43364bc36650d83c425cd6d99910fc20c4576631149f0f987eddede1a4d"
|
||||
},
|
||||
"@std/fmt@1.0.8": {
|
||||
"integrity": "71e1fc498787e4434d213647a6e43e794af4fd393ef8f52062246e06f7e372b7"
|
||||
},
|
||||
"@std/fs@1.0.3": {
|
||||
"integrity": "3cb839b1360b0a42d8b367c3093bfe4071798e6694fa44cf1963e04a8edba4fe",
|
||||
"dependencies": [
|
||||
"jsr:@std/path@^1.0.4"
|
||||
]
|
||||
},
|
||||
"@std/fs@1.0.4": {
|
||||
"integrity": "2907d32d8d1d9e540588fd5fe0ec21ee638134bd51df327ad4e443aaef07123c",
|
||||
"dependencies": [
|
||||
"jsr:@std/path@^1.0.6"
|
||||
]
|
||||
},
|
||||
"@std/fs@1.0.6": {
|
||||
"integrity": "42b56e1e41b75583a21d5a37f6a6a27de9f510bcd36c0c85791d685ca0b85fa2",
|
||||
"dependencies": [
|
||||
"jsr:@std/path@^1.0.8"
|
||||
]
|
||||
},
|
||||
"@std/fs@1.0.13": {
|
||||
"integrity": "756d3ff0ade91c9e72b228e8012b6ff00c3d4a4ac9c642c4dac083536bf6c605",
|
||||
"dependencies": [
|
||||
"jsr:@std/path@^1.0.8"
|
||||
]
|
||||
},
|
||||
"@std/fs@1.0.17": {
|
||||
"integrity": "1c00c632677c1158988ef7a004cb16137f870aafdb8163b9dce86ec652f3952b",
|
||||
"dependencies": [
|
||||
"jsr:@std/path@^1.0.9"
|
||||
]
|
||||
},
|
||||
"@std/internal@1.0.3": {
|
||||
"integrity": "208e9b94a3d5649bd880e9ca38b885ab7651ab5b5303a56ed25de4755fb7b11e"
|
||||
},
|
||||
"@std/internal@1.0.7": {
|
||||
"integrity": "39eeb5265190a7bc5d5591c9ff019490bd1f2c3907c044a11b0d545796158a0f"
|
||||
},
|
||||
"@std/io@0.225.2": {
|
||||
"integrity": "3c740cd4ee4c082e6cfc86458f47e2ab7cb353dc6234d5e9b1f91a2de5f4d6c7",
|
||||
"dependencies": [
|
||||
"jsr:@std/bytes"
|
||||
]
|
||||
},
|
||||
"@std/path@1.0.6": {
|
||||
"integrity": "ab2c55f902b380cf28e0eec501b4906e4c1960d13f00e11cfbcd21de15f18fed"
|
||||
},
|
||||
"@std/path@1.0.8": {
|
||||
"integrity": "548fa456bb6a04d3c1a1e7477986b6cffbce95102d0bb447c67c4ee70e0364be"
|
||||
},
|
||||
"@std/path@1.0.9": {
|
||||
"integrity": "260a49f11edd3db93dd38350bf9cd1b4d1366afa98e81b86167b4e3dd750129e"
|
||||
},
|
||||
"@std/testing@1.0.12": {
|
||||
"integrity": "fec973a45ccc62c540fb89296199051fee142409138fd6e3eae409366bcd4720",
|
||||
"dependencies": [
|
||||
"jsr:@std/assert@^1.0.13",
|
||||
"jsr:@std/async",
|
||||
"jsr:@std/data-structures",
|
||||
"jsr:@std/fs@^1.0.17",
|
||||
"jsr:@std/internal@^1.0.7",
|
||||
"jsr:@std/path@^1.0.9"
|
||||
]
|
||||
},
|
||||
"@ts-morph/bootstrap@0.25.0": {
|
||||
"integrity": "3cd33ee80ac0aab8e5d2660c639a02187f0c8abfe454636ce86c00eb7e8407db",
|
||||
"dependencies": [
|
||||
"jsr:@ts-morph/common"
|
||||
]
|
||||
},
|
||||
"@ts-morph/common@0.25.0": {
|
||||
"integrity": "e3ed1771e2fb61fbc3d2cb39ebbc4f89cd686d6d9bc6d91a71372be055ac1967",
|
||||
"dependencies": [
|
||||
"jsr:@std/fs@1",
|
||||
"jsr:@std/path@1"
|
||||
]
|
||||
}
|
||||
},
|
||||
"npm": {
|
||||
"zod@3.25.7": {
|
||||
"integrity": "sha512-YGdT1cVRmKkOg6Sq7vY7IkxdphySKnXhaUmFI4r4FcuFVNgpCb9tZfNwXbT6BPjD5oz0nubFsoo9pIqKrDcCvg=="
|
||||
}
|
||||
},
|
||||
"remote": {
|
||||
"https://deno.land/x/zod@v3.23.8/ZodError.ts": "528da200fbe995157b9ae91498b103c4ef482217a5c086249507ac850bd78f52",
|
||||
"https://deno.land/x/zod@v3.23.8/errors.ts": "5285922d2be9700cc0c70c95e4858952b07ae193aa0224be3cbd5cd5567eabef",
|
||||
"https://deno.land/x/zod@v3.23.8/external.ts": "a6cfbd61e9e097d5f42f8a7ed6f92f93f51ff927d29c9fbaec04f03cbce130fe",
|
||||
"https://deno.land/x/zod@v3.23.8/helpers/enumUtil.ts": "54efc393cc9860e687d8b81ff52e980def00fa67377ad0bf8b3104f8a5bf698c",
|
||||
"https://deno.land/x/zod@v3.23.8/helpers/errorUtil.ts": "7a77328240be7b847af6de9189963bd9f79cab32bbc61502a9db4fe6683e2ea7",
|
||||
"https://deno.land/x/zod@v3.23.8/helpers/parseUtil.ts": "c14814d167cc286972b6e094df88d7d982572a08424b7cd50f862036b6fcaa77",
|
||||
"https://deno.land/x/zod@v3.23.8/helpers/partialUtil.ts": "998c2fe79795257d4d1cf10361e74492f3b7d852f61057c7c08ac0a46488b7e7",
|
||||
"https://deno.land/x/zod@v3.23.8/helpers/typeAliases.ts": "0fda31a063c6736fc3cf9090dd94865c811dfff4f3cb8707b932bf937c6f2c3e",
|
||||
"https://deno.land/x/zod@v3.23.8/helpers/util.ts": "30c273131661ca5dc973f2cfb196fa23caf3a43e224cdde7a683b72e101a31fc",
|
||||
"https://deno.land/x/zod@v3.23.8/index.ts": "d27aabd973613985574bc31f39e45cb5d856aa122ef094a9f38a463b8ef1a268",
|
||||
"https://deno.land/x/zod@v3.23.8/locales/en.ts": "a7a25cd23563ccb5e0eed214d9b31846305ddbcdb9c5c8f508b108943366ab4c",
|
||||
"https://deno.land/x/zod@v3.23.8/mod.ts": "ec6e2b1255c1a350b80188f97bd0a6bac45801bb46fc48f50b9763aa66046039",
|
||||
"https://deno.land/x/zod@v3.23.8/types.ts": "1b172c90782b1eaa837100ebb6abd726d79d6c1ec336350c8e851e0fd706bf5c"
|
||||
},
|
||||
"workspace": {
|
||||
"dependencies": [
|
||||
"jsr:@deno/dnt@~0.42.1",
|
||||
"jsr:@std/expect@^1.0.16",
|
||||
"jsr:@std/testing@^1.0.12",
|
||||
"npm:zod@^3.25.7"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
import { type BlahActKeyRecord, blahActKeyRecordSchema } from "./actKey.ts";
|
||||
import { assertTypeMatchesZodSchema } from "../test/utils.ts";
|
||||
|
||||
Deno.test("type BlahActKeyRecord is accurate", () => {
|
||||
assertTypeMatchesZodSchema<BlahActKeyRecord>(blahActKeyRecordSchema);
|
||||
});
|
11
jsr.json
Normal file
11
jsr.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"name": "@blah/core",
|
||||
"version": "0.9.0",
|
||||
"exports": {
|
||||
"./crypto": "./src/crypto/mod.ts",
|
||||
"./identity": "./src/identity/mod.ts",
|
||||
"./richText": "./src/richText/mod.ts"
|
||||
},
|
||||
"include": ["LICENSE", "README.md", "src"],
|
||||
"exclude": ["**/*.test.ts"]
|
||||
}
|
48
package.json
Normal file
48
package.json
Normal file
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"name": "@blah-im/core",
|
||||
"version": "0.9.0",
|
||||
"description": "Core logic & types for Blah IM.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Blah-IM/typescript-core.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Blah-IM/typescript-core/issues"
|
||||
},
|
||||
"exports": {
|
||||
"./crypto": {
|
||||
"import": "./dist/crypto/mod.mjs",
|
||||
"require": "./dist/crypto/mod.cjs",
|
||||
"types": "./dist/crypto/mod.d.ts"
|
||||
},
|
||||
"./identity": {
|
||||
"import": "./dist/identity/mod.mjs",
|
||||
"require": "./dist/identity/mod.cjs",
|
||||
"types": "./dist/identity/mod.d.ts"
|
||||
},
|
||||
"./richText": {
|
||||
"import": "./dist/richText/mod.mjs",
|
||||
"require": "./dist/richText/mod.cjs",
|
||||
"types": "./dist/richText/mod.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"LICENSE",
|
||||
"README.md"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "vitest --typecheck",
|
||||
"build": "unbuild"
|
||||
},
|
||||
"dependencies": {
|
||||
"zod": "^3.25.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jsr": "^0.13.4",
|
||||
"unbuild": "^3.5.0",
|
||||
"vitest": "^3.1.4"
|
||||
},
|
||||
"packageManager": "pnpm@10.11.0"
|
||||
}
|
2045
pnpm-lock.yaml
generated
Normal file
2045
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load diff
2
pnpm-workspace.yaml
Normal file
2
pnpm-workspace.yaml
Normal file
|
@ -0,0 +1,2 @@
|
|||
onlyBuiltDependencies:
|
||||
- esbuild
|
|
@ -1,8 +0,0 @@
|
|||
import { assertTypeMatchesZodSchema } from "../test/utils.ts";
|
||||
import { type BlahRichText, blahRichTextSchema } from "./richText.ts";
|
||||
|
||||
Deno.test("type BlahRichText is accurate", () => {
|
||||
assertTypeMatchesZodSchema<BlahRichText>(
|
||||
blahRichTextSchema,
|
||||
);
|
||||
});
|
|
@ -1,8 +0,0 @@
|
|||
import { assertTypeMatchesZodSchema } from "../test/utils.ts";
|
||||
import { type BlahRichTextSpan, blahRichTextSpanSchema } from "./span.ts";
|
||||
|
||||
Deno.test("type BlahRichTextSpan is accurate", () => {
|
||||
assertTypeMatchesZodSchema<BlahRichTextSpan>(
|
||||
blahRichTextSpanSchema,
|
||||
);
|
||||
});
|
|
@ -1,43 +0,0 @@
|
|||
import { build, emptyDir } from "@deno/dnt";
|
||||
import denoJson from "../deno.json" with { type: "json" };
|
||||
|
||||
await emptyDir("./npm");
|
||||
|
||||
await build({
|
||||
entryPoints: [
|
||||
{ name: "./crypto", path: "crypto/mod.ts" },
|
||||
{ name: "./identity", path: "identity/mod.ts" },
|
||||
{ name: "./richText", path: "richText/mod.ts" },
|
||||
],
|
||||
outDir: "./npm",
|
||||
importMap: "deno.json",
|
||||
compilerOptions: {
|
||||
lib: ["ESNext", "DOM"],
|
||||
},
|
||||
shims: {
|
||||
deno: {
|
||||
test: "dev",
|
||||
},
|
||||
crypto: false,
|
||||
webSocket: true,
|
||||
},
|
||||
package: {
|
||||
// package.json properties
|
||||
name: "@blah-im/core",
|
||||
version: denoJson.version,
|
||||
description: "Core logic & types for Blah IM.",
|
||||
license: "MIT",
|
||||
repository: {
|
||||
type: "git",
|
||||
url: "git+https://github.com/Blah-IM/typescript-core.git",
|
||||
},
|
||||
bugs: {
|
||||
url: "https://github.com/Blah-IM/typescript-core/issues",
|
||||
},
|
||||
},
|
||||
postBuild() {
|
||||
// steps to run after building and before running the tests
|
||||
Deno.copyFileSync("LICENSE", "npm/LICENSE");
|
||||
Deno.copyFileSync("README.md", "npm/README.md");
|
||||
},
|
||||
});
|
|
@ -1,20 +1,21 @@
|
|||
import { expect } from "@std/expect";
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import { BlahKeyPair } from "./mod.ts";
|
||||
|
||||
let keypair: BlahKeyPair;
|
||||
|
||||
Deno.test("generate keypair", async () => {
|
||||
test("generate keypair", async () => {
|
||||
keypair = await BlahKeyPair.generate();
|
||||
});
|
||||
|
||||
Deno.test("encode & decode keypair", async () => {
|
||||
test("encode & decode keypair", async () => {
|
||||
const encoded = await keypair.encode();
|
||||
const decoded = await BlahKeyPair.fromEncoded(encoded);
|
||||
|
||||
expect(decoded.id).toBe(keypair.id);
|
||||
});
|
||||
|
||||
Deno.test("encode & decode keypair w/ password", async () => {
|
||||
test("encode & decode keypair w/ password", async () => {
|
||||
const password = "password";
|
||||
const encoded = await keypair.encode(password);
|
||||
const decoded = await BlahKeyPair.fromEncoded(encoded, password);
|
|
@ -1,4 +1,5 @@
|
|||
import { expect } from "@std/expect";
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import { BlahKeyPair } from "./keypair.ts";
|
||||
import { z } from "zod";
|
||||
import { BlahPublicKey } from "./publicKey.ts";
|
||||
|
@ -6,19 +7,17 @@ import type { SignOrVerifyOptions } from "./signAndVerify.ts";
|
|||
|
||||
let keypair: BlahKeyPair;
|
||||
|
||||
Deno.test("sign & verify payload", async () => {
|
||||
test("sign & verify payload", async () => {
|
||||
keypair = await BlahKeyPair.generate();
|
||||
|
||||
const payload = { foo: "bar", baz: 123 };
|
||||
const signedPayload = await keypair.signPayload(payload);
|
||||
const verifiedPayload = await keypair.publicKey.verifyPayload(
|
||||
signedPayload,
|
||||
);
|
||||
const verifiedPayload = await keypair.publicKey.verifyPayload(signedPayload);
|
||||
|
||||
expect(verifiedPayload).toEqual(payload);
|
||||
});
|
||||
|
||||
Deno.test("sign and verify with POW", async () => {
|
||||
test("sign and verify with POW", async () => {
|
||||
const payload = { foo: "bar-pow", baz: 123 };
|
||||
const options: SignOrVerifyOptions = { powDifficulty: 1 };
|
||||
const signedPayload = await keypair.signPayload(payload, options);
|
||||
|
@ -30,59 +29,58 @@ Deno.test("sign and verify with POW", async () => {
|
|||
expect(verifiedPayload).toEqual(payload);
|
||||
});
|
||||
|
||||
Deno.test("sign and verify with unmet POW", async () => {
|
||||
test("sign and verify with unmet POW", async () => {
|
||||
const payload = { foo: "bar", baz: 123 };
|
||||
const signedPayload = await keypair.signPayload(payload, {
|
||||
powDifficulty: 1,
|
||||
});
|
||||
|
||||
await expect(keypair.publicKey.verifyPayload(
|
||||
signedPayload,
|
||||
{ powDifficulty: 6 },
|
||||
)).rejects.toMatch(/proof-of-work/);
|
||||
await expect(
|
||||
keypair.publicKey.verifyPayload(signedPayload, { powDifficulty: 6 }),
|
||||
).rejects.toThrowError(/proof-of-work/);
|
||||
});
|
||||
|
||||
Deno.test("parse and verify payload", async () => {
|
||||
const payloadSchema = z.object({
|
||||
foo: z.string(),
|
||||
baz: z.number(),
|
||||
}).strict();
|
||||
test("parse and verify payload", async () => {
|
||||
const payloadSchema = z
|
||||
.object({
|
||||
foo: z.string(),
|
||||
baz: z.number(),
|
||||
})
|
||||
.strict();
|
||||
const payload = { foo: "bar", baz: 123 };
|
||||
const signedPayload = await keypair.signPayload(payload);
|
||||
const { payload: verifiedPayload, key } = await BlahPublicKey
|
||||
.parseAndVerifyPayload(
|
||||
payloadSchema,
|
||||
signedPayload,
|
||||
);
|
||||
const { payload: verifiedPayload, key } =
|
||||
await BlahPublicKey.parseAndVerifyPayload(payloadSchema, signedPayload);
|
||||
|
||||
expect(verifiedPayload).toEqual(payload);
|
||||
expect(key.id).toBe(keypair.id);
|
||||
});
|
||||
|
||||
Deno.test("parse and verify corrupted payload", async () => {
|
||||
const payloadSchema = z.object({
|
||||
foo: z.string(),
|
||||
baz: z.number(),
|
||||
}).strict();
|
||||
test("parse and verify corrupted payload", async () => {
|
||||
const payloadSchema = z
|
||||
.object({
|
||||
foo: z.string(),
|
||||
baz: z.number(),
|
||||
})
|
||||
.strict();
|
||||
const payload = { foo: "bar", baz: 123, qux: "quux" };
|
||||
const signedPayload = await keypair.signPayload(payload);
|
||||
|
||||
await expect(BlahPublicKey
|
||||
.parseAndVerifyPayload(
|
||||
payloadSchema,
|
||||
signedPayload,
|
||||
)).rejects.toMatch(/unrecognized/);
|
||||
await expect(
|
||||
BlahPublicKey.parseAndVerifyPayload(payloadSchema, signedPayload),
|
||||
).rejects.toThrowError(/unrecognized/);
|
||||
});
|
||||
|
||||
Deno.test("sign & verify payload with wrong keypair", async () => {
|
||||
test("sign & verify payload with wrong keypair", async () => {
|
||||
const keypair2 = await BlahKeyPair.generate();
|
||||
const payload = { foo: "bar", baz: 123 };
|
||||
const signedPayload = await keypair.signPayload(payload);
|
||||
expect(keypair2.publicKey.verifyPayload(signedPayload))
|
||||
.rejects.toMatch(/sign/);
|
||||
await expect(
|
||||
keypair2.publicKey.verifyPayload(signedPayload),
|
||||
).rejects.toThrowError(/sign/);
|
||||
});
|
||||
|
||||
Deno.test("sign & verify payload with wrong key order but should still work", async () => {
|
||||
test("sign & verify payload with wrong key order but should still work", async () => {
|
||||
const payload = { foo: "bar", baz: 123 };
|
||||
const signedPayload = await keypair.signPayload(payload);
|
||||
const signedPayload2 = {
|
||||
|
@ -95,8 +93,6 @@ Deno.test("sign & verify payload with wrong key order but should still work", as
|
|||
timestamp: signedPayload.signee.timestamp,
|
||||
},
|
||||
};
|
||||
const verifiedPayload = await keypair.publicKey.verifyPayload(
|
||||
signedPayload2,
|
||||
);
|
||||
const verifiedPayload = await keypair.publicKey.verifyPayload(signedPayload2);
|
||||
expect(verifiedPayload).toEqual(payload);
|
||||
});
|
28
src/crypto/signedPayload.test.ts
Normal file
28
src/crypto/signedPayload.test.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { expectTypeOf, test } from "vitest";
|
||||
|
||||
import z from "zod";
|
||||
import type { BlahSignedPayload } from "./mod.ts";
|
||||
import {
|
||||
type BlahPayloadSignee,
|
||||
blahPayloadSigneeSchemaOf,
|
||||
blahSignedPayloadSchemaOf,
|
||||
} from "./signedPayload.ts";
|
||||
|
||||
const testPayloadSchema = z.object({
|
||||
foo: z.string(),
|
||||
});
|
||||
type TestPayload = z.infer<typeof testPayloadSchema>;
|
||||
|
||||
test("BlahPayloadSignee typed correctly", () => {
|
||||
const signeeSchema = blahPayloadSigneeSchemaOf(testPayloadSchema);
|
||||
expectTypeOf<z.infer<typeof signeeSchema>>().toEqualTypeOf<
|
||||
BlahPayloadSignee<TestPayload>
|
||||
>();
|
||||
});
|
||||
|
||||
test("BlahSignedPayload typed correctly", () => {
|
||||
const signedPayloadSchema = blahSignedPayloadSchemaOf(testPayloadSchema);
|
||||
expectTypeOf<z.infer<typeof signedPayloadSchema>>().toEqualTypeOf<
|
||||
BlahSignedPayload<TestPayload>
|
||||
>();
|
||||
});
|
10
src/identity/actKey.test.ts
Normal file
10
src/identity/actKey.test.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { expectTypeOf, test } from "vitest";
|
||||
|
||||
import { type BlahActKeyRecord, blahActKeyRecordSchema } from "./actKey.ts";
|
||||
import z from "zod";
|
||||
|
||||
test("BlahActKeyRecord typed correctly", () => {
|
||||
expectTypeOf<
|
||||
z.infer<typeof blahActKeyRecordSchema>
|
||||
>().toEqualTypeOf<BlahActKeyRecord>();
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import { expect } from "@std/expect";
|
||||
import { expect, test } from "vitest";
|
||||
import { BlahKeyPair, type BlahSignedPayload } from "../crypto/mod.ts";
|
||||
import { BlahIdentity } from "./identity.ts";
|
||||
import type { BlahIdentityDescription, BlahProfile } from "./mod.ts";
|
||||
|
@ -17,17 +17,17 @@ let identity: BlahIdentity;
|
|||
let identityDesc: BlahIdentityDescription;
|
||||
let identityFromFile: BlahIdentity;
|
||||
|
||||
Deno.test("create identity", async () => {
|
||||
test("create identity", async () => {
|
||||
idKeyPair = await BlahKeyPair.generate();
|
||||
actKeyPair = await BlahKeyPair.generate();
|
||||
identity = await BlahIdentity.create(idKeyPair, actKeyPair, profile);
|
||||
});
|
||||
|
||||
Deno.test("generate identity description", () => {
|
||||
test("generate identity description", () => {
|
||||
identityDesc = identity.generateIdentityDescription();
|
||||
});
|
||||
|
||||
Deno.test("created identity act key signed correctly", async () => {
|
||||
test("created identity act key signed correctly", async () => {
|
||||
const record = await identity.idPublicKey.verifyPayload(
|
||||
identityDesc.act_keys[0],
|
||||
);
|
||||
|
@ -37,7 +37,7 @@ Deno.test("created identity act key signed correctly", async () => {
|
|||
expect(record.act_key).toBe(actKeyPair.id);
|
||||
});
|
||||
|
||||
Deno.test("created identity profile signed correctly", async () => {
|
||||
test("created identity profile signed correctly", async () => {
|
||||
const record = await actKeyPair.publicKey.verifyPayload(
|
||||
identityDesc.profile,
|
||||
{ identityKeyId: identityDesc.id_key },
|
||||
|
@ -49,26 +49,29 @@ Deno.test("created identity profile signed correctly", async () => {
|
|||
expect(record.id_urls).toEqual(["https://localhost"]);
|
||||
});
|
||||
|
||||
Deno.test("parse identity description", async () => {
|
||||
test("parse identity description", async () => {
|
||||
identityFromFile = await BlahIdentity.fromIdentityDescription(identityDesc);
|
||||
expect(identityFromFile.idPublicKey.id).toBe(idKeyPair.id);
|
||||
expect(identityFromFile.actKeys[0].publicKey.id).toBe(actKeyPair.id);
|
||||
expect(identityFromFile.profileSigValid).toBe(true);
|
||||
});
|
||||
|
||||
Deno.test("identity description profile sigs are properly verfied", async () => {
|
||||
test("identity description profile sigs are properly verfied", async () => {
|
||||
const identityDescWithProfileInvalidProfileSig: BlahIdentityDescription = {
|
||||
...identityDesc,
|
||||
profile: { ...identityDesc.profile, sig: "_ obviously not a valid sig _" },
|
||||
profile: {
|
||||
...identityDesc.profile,
|
||||
sig: "_ obviously not a valid sig _",
|
||||
},
|
||||
};
|
||||
const identityWithProfileInvalidProfileSig = await BlahIdentity
|
||||
.fromIdentityDescription(
|
||||
const identityWithProfileInvalidProfileSig =
|
||||
await BlahIdentity.fromIdentityDescription(
|
||||
identityDescWithProfileInvalidProfileSig,
|
||||
);
|
||||
expect(identityWithProfileInvalidProfileSig.profileSigValid).toBe(false);
|
||||
});
|
||||
|
||||
Deno.test("identity description profile must be signed with correct id_key", async () => {
|
||||
test("identity description profile must be signed with correct id_key", async () => {
|
||||
const rawProfile: BlahProfile = identityDesc.profile.signee.payload;
|
||||
const profileSignedWithActKeyAsIdKey: BlahSignedPayload<BlahProfile> =
|
||||
await actKeyPair.signPayload(rawProfile);
|
||||
|
@ -76,12 +79,13 @@ Deno.test("identity description profile must be signed with correct id_key", asy
|
|||
...identityDesc,
|
||||
profile: profileSignedWithActKeyAsIdKey,
|
||||
};
|
||||
const identityWithWrongIdKey = await BlahIdentity
|
||||
.fromIdentityDescription(identityDescWithWrongIdKey);
|
||||
const identityWithWrongIdKey = await BlahIdentity.fromIdentityDescription(
|
||||
identityDescWithWrongIdKey,
|
||||
);
|
||||
expect(identityWithWrongIdKey.profileSigValid).toBe(false);
|
||||
});
|
||||
|
||||
Deno.test("identity description act key sigs are properly verfied", async () => {
|
||||
test("identity description act key sigs are properly verfied", async () => {
|
||||
const identityDescWithActKeyInvalidActKeySig: BlahIdentityDescription = {
|
||||
...identityDesc,
|
||||
act_keys: [
|
||||
|
@ -91,14 +95,14 @@ Deno.test("identity description act key sigs are properly verfied", async () =>
|
|||
},
|
||||
],
|
||||
};
|
||||
const identityWithActKeyInvalidActKeySig = await BlahIdentity
|
||||
.fromIdentityDescription(
|
||||
const identityWithActKeyInvalidActKeySig =
|
||||
await BlahIdentity.fromIdentityDescription(
|
||||
identityDescWithActKeyInvalidActKeySig,
|
||||
);
|
||||
expect(identityWithActKeyInvalidActKeySig.actKeys[0].isSigValid).toBe(false);
|
||||
});
|
||||
|
||||
Deno.test("add a second act key", async () => {
|
||||
test("add a second act key", async () => {
|
||||
const actKeyPair2 = await BlahKeyPair.generate();
|
||||
await identity.addActKey(actKeyPair2, { comment: "test" });
|
||||
identityDesc = identity.generateIdentityDescription();
|
||||
|
@ -113,7 +117,7 @@ Deno.test("add a second act key", async () => {
|
|||
expect(record.act_key).toBe(actKeyPair2.id);
|
||||
});
|
||||
|
||||
Deno.test("update first act key", async () => {
|
||||
test("update first act key", async () => {
|
||||
await identity.updateActKey(actKeyPair.id, { comment: "test2" });
|
||||
identityDesc = identity.generateIdentityDescription();
|
||||
|
||||
|
@ -124,13 +128,13 @@ Deno.test("update first act key", async () => {
|
|||
expect(record.comment).toBe("test2");
|
||||
});
|
||||
|
||||
Deno.test("act key properly expires", async () => {
|
||||
test("act key properly expires", async () => {
|
||||
expect(identity.actKeys[0].isExpired).toBe(false);
|
||||
await identity.updateActKey(actKeyPair.id, { expiresAt: new Date(10000) });
|
||||
expect(identity.actKeys[0].isExpired).toBe(true);
|
||||
});
|
||||
|
||||
Deno.test("update profile", async () => {
|
||||
test("update profile", async () => {
|
||||
const newProfile: BlahProfile = {
|
||||
typ: "profile",
|
||||
name: "Shibo Lyu",
|
||||
|
@ -144,7 +148,8 @@ Deno.test("update profile", async () => {
|
|||
expect(identityDesc.profile.signee.payload).toEqual(newProfile);
|
||||
});
|
||||
|
||||
Deno.test("throw when try writing to identity without id key pair", () => {
|
||||
expect(identityFromFile.updateActKey(actKeyPair.id, { comment: "test2" }))
|
||||
.rejects.toMatch(/key pair/i);
|
||||
test("throw when try writing to identity without id key pair", async () => {
|
||||
await expect(
|
||||
identityFromFile.updateActKey(actKeyPair.id, { comment: "test2" }),
|
||||
).rejects.toThrowError(/key pair/i);
|
||||
});
|
|
@ -1,19 +1,20 @@
|
|||
import { expect, test, expectTypeOf } from "vitest";
|
||||
|
||||
import {
|
||||
type BlahIdentityDescription,
|
||||
blahIdentityDescriptionSchema,
|
||||
getIdentityDescriptionFileURL,
|
||||
identityDescriptionFilePath,
|
||||
} from "./identityDescription.ts";
|
||||
import { assertTypeMatchesZodSchema } from "../test/utils.ts";
|
||||
import { expect } from "@std/expect";
|
||||
import { z } from "zod";
|
||||
|
||||
Deno.test("type BlahIdentityDescription is accurate", () => {
|
||||
assertTypeMatchesZodSchema<BlahIdentityDescription>(
|
||||
blahIdentityDescriptionSchema,
|
||||
);
|
||||
test("BlahIdentityDescription typed correctly", () => {
|
||||
expectTypeOf<
|
||||
z.infer<typeof blahIdentityDescriptionSchema>
|
||||
>().toEqualTypeOf<BlahIdentityDescription>();
|
||||
});
|
||||
|
||||
Deno.test("getIdentityDescriptionFileURL", () => {
|
||||
test("getIdentityDescriptionFileURL", () => {
|
||||
expect(getIdentityDescriptionFileURL("https://lao.sb")).toBe(
|
||||
"https://lao.sb" + identityDescriptionFilePath,
|
||||
);
|
||||
|
@ -22,6 +23,7 @@ Deno.test("getIdentityDescriptionFileURL", () => {
|
|||
"https://test.lao.sb" + identityDescriptionFilePath,
|
||||
);
|
||||
|
||||
expect(() => getIdentityDescriptionFileURL("https://trailing-slash.lao.sb/"))
|
||||
.toThrow();
|
||||
expect(() =>
|
||||
getIdentityDescriptionFileURL("https://trailing-slash.lao.sb/"),
|
||||
).toThrow();
|
||||
});
|
|
@ -1,22 +1,25 @@
|
|||
import { expect, test, expectTypeOf } from "vitest";
|
||||
|
||||
import z from "zod";
|
||||
import {
|
||||
type BlahProfile,
|
||||
blahProfileSchema,
|
||||
validateIDURLFormat,
|
||||
} from "./profile.ts";
|
||||
import { assertTypeMatchesZodSchema } from "../test/utils.ts";
|
||||
import { expect } from "@std/expect";
|
||||
|
||||
Deno.test("type BlahProfile is accurate", () => {
|
||||
assertTypeMatchesZodSchema<BlahProfile>(blahProfileSchema);
|
||||
test("BlahProfile typed correctly", () => {
|
||||
expectTypeOf<
|
||||
z.infer<typeof blahProfileSchema>
|
||||
>().toEqualTypeOf<BlahProfile>();
|
||||
});
|
||||
|
||||
Deno.test("ID URL format - valid", () => {
|
||||
test("ID URL format - valid", () => {
|
||||
expect(validateIDURLFormat("https://lao.sb")).toBe(true);
|
||||
expect(validateIDURLFormat("https://test.lao.sb")).toBe(true);
|
||||
expect(validateIDURLFormat("https://🧧.lao.sb")).toBe(true);
|
||||
});
|
||||
|
||||
Deno.test("ID URL format - invalid", () => {
|
||||
test("ID URL format - invalid", () => {
|
||||
// Must be valid URL
|
||||
expect(validateIDURLFormat("lao.sb")).toBe(false);
|
||||
// No trailing slash
|
10
src/richText/richText.test.ts
Normal file
10
src/richText/richText.test.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { expectTypeOf, test } from "vitest";
|
||||
|
||||
import { type BlahRichText, blahRichTextSchema } from "./richText.ts";
|
||||
import z from "zod";
|
||||
|
||||
test("BlahRichText typed correctly", () => {
|
||||
expectTypeOf<
|
||||
z.input<typeof blahRichTextSchema>
|
||||
>().toEqualTypeOf<BlahRichText>();
|
||||
});
|
10
src/richText/span.test.ts
Normal file
10
src/richText/span.test.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { expectTypeOf, test } from "vitest";
|
||||
|
||||
import { type BlahRichTextSpan, blahRichTextSpanSchema } from "./span.ts";
|
||||
import z from "zod";
|
||||
|
||||
test("BlahRichTextSpan typed correctly", () => {
|
||||
expectTypeOf<BlahRichTextSpan>().toEqualTypeOf<
|
||||
z.input<typeof blahRichTextSpanSchema>
|
||||
>();
|
||||
});
|
|
@ -1,8 +1,9 @@
|
|||
import { expect } from "@std/expect";
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import type { BlahRichText } from "./mod.ts";
|
||||
import { toPlainText } from "./toPlainText.ts";
|
||||
|
||||
Deno.test("toPlainText", () => {
|
||||
test("toPlainText", () => {
|
||||
const richText: BlahRichText = ["hello ", ["world", { b: true }]];
|
||||
expect(toPlainText(richText)).toBe("hello world");
|
||||
});
|
|
@ -1,10 +0,0 @@
|
|||
import { assertType, type IsExact } from "@std/testing/types";
|
||||
import type { z } from "zod";
|
||||
|
||||
export function assertTypeMatchesZodSchema<T>(
|
||||
schema: z.ZodTypeAny,
|
||||
) {
|
||||
assertType<IsExact<T, z.infer<typeof schema>>>(
|
||||
true as IsExact<T, z.infer<typeof schema>>,
|
||||
);
|
||||
}
|
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "Preserve",
|
||||
"moduleResolution": "Bundler",
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"skipLibCheck": true,
|
||||
"allowJs": false,
|
||||
"strict": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"isolatedModules": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
"noImplicitOverride": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
Loading…
Add table
Reference in a new issue