@jchat/runtime 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,120 @@
1
+ JChat Runtime License Agreement
2
+ Version 1.0 - July 29, 2026
3
+
4
+ Copyright (c) 2026 Md. Jabarullah. All rights reserved.
5
+
6
+ This agreement governs the @jchat/runtime software package (the "Runtime"). The Runtime is
7
+ proprietary software made publicly downloadable only to support authorized JChat deployments.
8
+ Public availability, including availability through the npm public registry, does not make the
9
+ Runtime open-source software and does not grant any rights except those stated below.
10
+
11
+ 1. Definitions
12
+
13
+ "JChat" means the JChat software product and services published by Md. Jabarullah.
14
+
15
+ "Vendor License" means a valid standard, extended, or vendor-issued development license for JChat
16
+ obtained from JChat Hub, Envato Market, Codester, or another channel expressly authorized by the
17
+ copyright owner.
18
+
19
+ "Authorized Deployment" means a JChat installation that complies with its Vendor License,
20
+ including its domain, installation, environment, and usage restrictions.
21
+
22
+ "You" means the individual or legal entity that owns a Vendor License or is acting for its
23
+ authorized license holder.
24
+
25
+ 2. Limited License Grant
26
+
27
+ Subject to continued compliance with this agreement and the applicable Vendor License, you receive
28
+ a limited, non-exclusive, non-transferable except as expressly allowed by Section 2(d),
29
+ non-sublicensable, and revocable license to:
30
+
31
+ a. download the Runtime from npm or another distribution channel authorized by JChat;
32
+
33
+ b. install and execute the Runtime solely as an unmodified dependency of an Authorized Deployment;
34
+
35
+ c. make reasonable technical copies required for private package caches, continuous integration,
36
+ Docker or other deployment images, staging environments, disaster recovery, and backups for the
37
+ Authorized Deployment; and
38
+
39
+ d. provide those copies to a client only as an integral part of an end product and only when that
40
+ transfer is permitted by the applicable Vendor License.
41
+
42
+ A vendor-issued development license may additionally authorize local development use according to
43
+ the conditions encoded in that license. No right is granted to use the Runtime independently from
44
+ JChat or without a valid Vendor License.
45
+
46
+ 3. Restrictions
47
+
48
+ Except where applicable law does not permit a restriction, you must not:
49
+
50
+ a. sell, rent, sublicense, republish, publicly mirror, or distribute the Runtime as a standalone or
51
+ reusable package;
52
+
53
+ b. modify, adapt, translate, or create derivative works of the Runtime;
54
+
55
+ c. reverse engineer, decompile, disassemble, or otherwise attempt to discover non-public source
56
+ code or implementation details;
57
+
58
+ d. remove or alter copyright, license, attribution, integrity, entitlement, or ownership notices;
59
+
60
+ e. bypass, disable, interfere with, or misrepresent activation, entitlement, domain, installation,
61
+ signature, integrity, or registry verification;
62
+
63
+ f. use the Runtime to build, enable, or operate an unlicensed JChat deployment; or
64
+
65
+ g. use the Runtime as a component of a competing standalone product or licensing system.
66
+
67
+ Internal caches and deployment artifacts allowed by Section 2 are not prohibited redistribution,
68
+ provided they remain access-controlled and are used only for the Authorized Deployment.
69
+
70
+ 4. Ownership
71
+
72
+ The Runtime is licensed, not sold. JChat and its licensors retain all title, copyright, patent,
73
+ trade-secret, and other intellectual-property rights in the Runtime. No implied license is granted.
74
+
75
+ 5. Third-Party Software
76
+
77
+ Third-party components, if any, remain governed by their respective licenses. This agreement does
78
+ not reduce rights granted under a third-party license.
79
+
80
+ 6. Updates, Services, and Vendor License Terms
81
+
82
+ This agreement does not promise updates, support, availability, or continued registry access.
83
+ Purchase, activation, installation, replacement, and service terms remain governed by the
84
+ applicable Vendor License and written JChat terms. If those terms conflict with this agreement for
85
+ the Runtime, the more specific written terms supplied by JChat control.
86
+
87
+ 7. Term and Termination
88
+
89
+ This agreement remains effective while you comply with it and maintain the required Vendor License.
90
+ It terminates automatically when the Vendor License expires or is revoked, or when you materially
91
+ breach this agreement. On termination, you must stop using the Runtime and remove all copies except
92
+ copies retained solely where applicable law requires archival retention.
93
+
94
+ Sections 3, 4, 5, 8, 9, and 10 survive termination.
95
+
96
+ 8. Disclaimer of Warranty
97
+
98
+ TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE RUNTIME IS PROVIDED "AS IS" AND "AS
99
+ AVAILABLE", WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER EXPRESS, IMPLIED, OR STATUTORY,
100
+ INCLUDING WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR
101
+ PURPOSE, ACCURACY, OR RELIABILITY.
102
+
103
+ 9. Limitation of Liability
104
+
105
+ TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, JCHAT, MD. JABARULLAH, AND THEIR SUPPLIERS WILL
106
+ NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, CONSEQUENTIAL, OR PUNITIVE DAMAGES,
107
+ OR FOR LOSS OF DATA, PROFITS, REVENUE, BUSINESS, OR GOODWILL, ARISING FROM OR RELATED TO THE
108
+ RUNTIME, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
109
+
110
+ 10. General
111
+
112
+ The governing law, venue, and dispute terms stated in the applicable Vendor License or written
113
+ JChat purchase terms apply to this agreement. If any provision is unenforceable, it will be limited
114
+ to the minimum extent necessary, and the remaining provisions will continue in effect. A waiver
115
+ must be in writing and applies only to the specific instance waived.
116
+
117
+ The JChat name, logos, and related marks are not licensed except for truthful identification of
118
+ compatible products and services.
119
+
120
+ For permissions outside this agreement, contact JChat through https://jchat.com.
@@ -0,0 +1,137 @@
1
+ //#region src/domain.d.ts
2
+ type Plan = "standard" | "extended";
3
+ type RoutingMode = "path" | "subdomain";
4
+ type DomainScope = "current-host" | "parent-domain";
5
+ type NormalizedDomain = {
6
+ host: string;
7
+ isLocalhost: boolean;
8
+ };
9
+ /** Normalize the host used for instance binding; ports and www are not significant. */
10
+ declare function normalizeDomain(value: string): NormalizedDomain;
11
+ declare function isPublicDomain(value: string): boolean;
12
+ declare function isAllowedConfiguredDomain(value: string): boolean;
13
+ declare function resolveActivationDomain(host: string, plan: Plan, routingMode: RoutingMode, domainScope?: DomainScope): string;
14
+ //#endregion
15
+ //#region src/audit.d.ts
16
+ type AuditEvent = "check_success" | "check_unreachable" | "check_rejected";
17
+ declare function recordAudit(event: AuditEvent, details: {
18
+ domain?: string;
19
+ installationId?: string;
20
+ reference?: string;
21
+ }, filePath?: string): Promise<void>;
22
+ //#endregion
23
+ //#region src/check.d.ts
24
+ type CheckResult = {
25
+ status: "valid";
26
+ token: string;
27
+ } | {
28
+ status: "unreachable-fallback";
29
+ token: string;
30
+ error: string;
31
+ } | {
32
+ status: "invalid";
33
+ error: string;
34
+ reference: string;
35
+ };
36
+ type RegistryProvider = "envato" | "jchat";
37
+ type RegistryRoutingMode = "path" | "subdomain";
38
+ type ActivationInput = {
39
+ purchaseCode: string;
40
+ domain: string;
41
+ siteSlug?: string;
42
+ domainScope?: "current-host" | "parent-domain";
43
+ provider: RegistryProvider;
44
+ routingMode: RegistryRoutingMode;
45
+ installationId: string;
46
+ installationPublicKey: string;
47
+ machineFingerprint: string;
48
+ registryEndpoint?: string;
49
+ fetchImpl?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
50
+ };
51
+ type ActivationResult = {
52
+ success: true;
53
+ buyer: string;
54
+ token: string;
55
+ domain: string;
56
+ } | {
57
+ success: false;
58
+ message: string;
59
+ };
60
+ declare function activateRegistry(input: ActivationInput): Promise<ActivationResult>;
61
+ type CheckInput = {
62
+ token: string;
63
+ domain: string;
64
+ routingMode: RegistryRoutingMode;
65
+ installationId: string;
66
+ machineFingerprint: string;
67
+ registryEndpoint?: string;
68
+ runtimeOptions?: RuntimeOptions;
69
+ auditPath?: string;
70
+ fetchImpl?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
71
+ localTokenValidator?: (token: string, domain: string, installationId: string, machineFingerprint: string) => boolean;
72
+ };
73
+ declare function checkRegistry(input: CheckInput): Promise<CheckResult>;
74
+ //#endregion
75
+ //#region src/state.d.ts
76
+ type LocalState = {
77
+ version: 1;
78
+ installationId: string;
79
+ privateKeyPem: string;
80
+ publicKeyPem: string;
81
+ machineFingerprint: string;
82
+ instanceToken: string;
83
+ lastSuccessfulCheckAt?: string;
84
+ };
85
+ declare const DEFAULT_STATE_PATH: string;
86
+ declare function createMachineFingerprint(): string;
87
+ declare function createIdentity(machineFingerprint?: string): {
88
+ installationId: `${string}-${string}-${string}-${string}-${string}`;
89
+ machineFingerprint: string;
90
+ privateKeyPem: string;
91
+ publicKeyPem: string;
92
+ };
93
+ declare function readTokenSync(filePath?: string): string;
94
+ declare function readState(filePath?: string): Promise<LocalState | null>;
95
+ declare function writeState(state: LocalState, filePath?: string): Promise<void>;
96
+ declare function acquireProcessLock(statePath?: string): Promise<() => Promise<void>>;
97
+ //#endregion
98
+ //#region src/runtime.d.ts
99
+ type RuntimeStatus$1 = "valid" | "unreachable-fallback" | "invalid" | "unavailable";
100
+ declare function registerInvalidationHandler(handler: () => void): void;
101
+ declare function setRuntimeStatus(status: RuntimeStatus$1, reference?: string): void;
102
+ declare function getRuntimeStatus(): {
103
+ status: RuntimeStatus$1;
104
+ reference: string;
105
+ };
106
+ declare function isApplicationDisabled(): boolean;
107
+ //#endregion
108
+ //#region src/index.d.ts
109
+ type PurchaseProvider = "envato" | "jchat";
110
+ type RuntimeEnvironment = "production" | "development";
111
+ type ConfigPayload = {
112
+ iss: string;
113
+ aud: string;
114
+ licenseId: string;
115
+ domain: string;
116
+ buyer: string;
117
+ installationId: string;
118
+ machineFingerprint: string;
119
+ plan: Plan;
120
+ entitlements: string[];
121
+ purchaseProvider: PurchaseProvider;
122
+ environment: RuntimeEnvironment;
123
+ routingMode: RoutingMode;
124
+ iat: number;
125
+ };
126
+ type RuntimeOptions = {
127
+ publicKeyPem: string;
128
+ issuer?: string;
129
+ audience?: string;
130
+ };
131
+ type RuntimeStatus = "valid" | "unreachable-fallback" | "invalid" | "unavailable";
132
+ declare function parsePayload(token: string): ConfigPayload | null;
133
+ declare function verifySignature(token: string, currentDomain: string, options: RuntimeOptions): boolean;
134
+ declare function verifyEntitlement(token: string, currentDomain: string, installationId: string, machineFingerprint: string, options: RuntimeOptions): boolean;
135
+ declare function hasEntitlement(token: string, currentDomain: string, entitlement: string, options: RuntimeOptions): boolean;
136
+ //#endregion
137
+ export { ActivationInput, ActivationResult, AuditEvent, CheckInput, CheckResult, ConfigPayload, DEFAULT_STATE_PATH, DomainScope, LocalState, NormalizedDomain, Plan, PurchaseProvider, RegistryProvider, RegistryRoutingMode, RoutingMode, RuntimeEnvironment, RuntimeOptions, RuntimeStatus, acquireProcessLock, activateRegistry, checkRegistry, createIdentity, createMachineFingerprint, getRuntimeStatus, hasEntitlement, isAllowedConfiguredDomain, isApplicationDisabled, isPublicDomain, normalizeDomain, parsePayload, readState, readTokenSync, recordAudit, registerInvalidationHandler, resolveActivationDomain, setRuntimeStatus, verifyEntitlement, verifySignature, writeState };
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ import e from"node:crypto";import t from"node:net";import n from"node:fs/promises";import r from"node:path";import i from"node:fs";import a from"node:os";const o=new Set([`localhost`,`127.0.0.1`,`::1`]),s=[`.local`,`.test`,`.invalid`,`.example`];function c(e){let t=e.trim();if(!t)throw Error(`Instance domain is required`);let n=new URL(t.includes(`://`)?t:`https://${t}`).hostname.toLowerCase().replace(/\.$/,``),r=n===`www.localhost`?`localhost`:n.replace(/^www\./,``);if(!r||r.includes(`@`)||/\s/.test(r))throw Error(`Invalid instance domain`);return{host:r,isLocalhost:o.has(r)}}function l(e){let{host:n,isLocalhost:r}=c(e);return!r&&t.isIP(n)===0&&n.includes(`.`)&&!s.some(e=>n.endsWith(e))}function u(e){try{return c(e).isLocalhost||l(e)}catch{return!1}}function d(e){let{host:n,isLocalhost:r}=c(e);if(r||t.isIP(n)!==0)return null;let i=n.split(`.`);if(i.length<=2)return n;let a=new Set([`co`,`com`,`org`,`net`,`gov`,`edu`,`ac`,`sch`]),o=i.at(-1)??``,s=i.at(-2)??``;return a.has(s)&&o.length===2&&i.length>=3?i.slice(-3).join(`.`):i.slice(-2).join(`.`)}function f(e,t,n,r=`current-host`){let i=c(e).host;return n===`subdomain`&&t===`extended`&&r===`parent-domain`?d(i)??i:i}function p(e){if(e)return e.length<=8?`redacted`:`${e.slice(0,4)}…${e.slice(-4)}`}async function m(e,t,i=r.resolve(process.cwd(),`data/license-events.log`)){await n.mkdir(r.dirname(i),{recursive:!0});let a=JSON.stringify({at:new Date().toISOString(),event:e,domain:p(t.domain),installationId:p(t.installationId),reference:p(t.reference)});await n.appendFile(i,`${a}\n`,`utf8`)}let h=`unavailable`,g=`startup`,_;function v(e){_=e}function y(t,n=e.randomUUID()){h=t,g=n,t===`invalid`&&_?.()}function b(){return{status:h,reference:g}}function x(){return h===`invalid`}const S=Buffer.from(`aHR0cDovL2xvY2FsaG9zdDo0MDAw`,`base64`).toString(`utf8`);async function C(e){try{let t=await(e.fetchImpl??fetch)(`${e.registryEndpoint??S}/api/activate`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({purchaseCode:e.purchaseCode,domain:c(e.domain).host,siteSlug:e.siteSlug,domainScope:e.domainScope,provider:e.provider,routingMode:e.routingMode,installationId:e.installationId,installationPublicKey:e.installationPublicKey,machineFingerprint:e.machineFingerprint})}),n=await t.json();return t.ok===!1||!n.success||!n.token?{success:!1,message:n.message??`This license is already active on another domain. Please deactivate it first.`}:{success:!0,buyer:n.buyer??`Customer`,token:n.token,domain:n.domain??c(e.domain).host}}catch{return{success:!1,message:`Failed to connect to the central registry. Please try again later.`}}}async function w(t){let n=t.fetchImpl??fetch,r=t.localTokenValidator??((e,n,r,i)=>t.runtimeOptions?z(e,n,r,i,t.runtimeOptions):!1),i=(n,r)=>{let i=e.randomUUID();return y(`invalid`,i),m(`check_rejected`,{domain:n,reference:i},t.auditPath),{status:`invalid`,error:r,reference:i}},a=e=>{let n=c(t.domain).host;return r(t.token,n,t.installationId,t.machineFingerprint)?(y(`unreachable-fallback`),m(`check_unreachable`,{domain:n},t.auditPath),{status:`unreachable-fallback`,token:t.token,error:e}):i(n,`Local license validation failed.`)};try{let e=c(t.domain).host,r=await n(`${t.registryEndpoint??S}/api/check`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({token:t.token,domain:e,routingMode:t.routingMode,installationId:t.installationId,machineFingerprint:t.machineFingerprint})});if(!r.ok)return r.status>=500?a(`HTTP ${r.status}`):i(e,`License rejected by jchat service.`);let o=await r.json();if(!o.success||!o.token||!(t.runtimeOptions&&z(o.token,e,t.installationId,t.machineFingerprint,t.runtimeOptions))&&!t.localTokenValidator||t.localTokenValidator&&!t.localTokenValidator(o.token,e,t.installationId,t.machineFingerprint))return i(e,`License rejected by jchat service.`);let s=L(o.token);return!s||s.installationId!==t.installationId||s.machineFingerprint!==t.machineFingerprint||s.routingMode!==t.routingMode?i(e,`License binding rejected by jchat service.`):(y(`valid`),m(`check_success`,{domain:e},t.auditPath),{status:`valid`,token:o.token})}catch{return a(`License service unreachable.`)}}const T=r.resolve(process.cwd(),`data/instance.json`);function E(){return e.createHash(`sha256`).update([a.hostname(),a.platform(),a.arch()].join(`|`)).digest(`hex`)}function D(t=E()){let n=e.generateKeyPairSync(`ed25519`);return{installationId:e.randomUUID(),machineFingerprint:t,privateKeyPem:n.privateKey.export({type:`pkcs8`,format:`pem`}).toString(),publicKeyPem:n.publicKey.export({type:`spki`,format:`pem`}).toString()}}function O(e=T){try{if(!i.existsSync(e))return``;let t=i.readFileSync(e,`utf8`);return JSON.parse(t)?.instanceToken??``}catch{return``}}async function k(e=T){try{let t=JSON.parse(await Bun.file(e).text());if(!t||typeof t!=`object`)return null;let n=t;return n.version!==1||typeof n.installationId!=`string`||!n.installationId||typeof n.privateKeyPem!=`string`||!n.privateKeyPem||typeof n.publicKeyPem!=`string`||!n.publicKeyPem||typeof n.machineFingerprint!=`string`||!n.machineFingerprint||typeof n.instanceToken!=`string`||!n.instanceToken||n.lastSuccessfulCheckAt!==void 0&&(typeof n.lastSuccessfulCheckAt!=`string`||!n.lastSuccessfulCheckAt)?null:n}catch{return null}}async function A(t,i=T){let a=r.dirname(i);await n.mkdir(a,{recursive:!0});let o=`${i}.${process.pid}.${e.randomUUID()}.tmp`;await Bun.write(o,`${JSON.stringify(t,null,2)}\n`),await n.rename(o,i)}async function j(e=T){let t=`${e}.lock`;await n.mkdir(r.dirname(t),{recursive:!0});let i;try{i=await n.open(t,`wx`)}catch(e){if(!(e instanceof Error)||!(`code`in e)||e.code!==`EEXIST`)throw e;let r=Number.parseInt(await Bun.file(t).text().catch(()=>``),10),a=!1;if(Number.isInteger(r)&&r>0)try{process.kill(r,0),a=!0}catch{a=!1}if(a)throw Error(`Another JChat process already owns the license lock`);await n.rm(t,{force:!0}),i=await n.open(t,`wx`)}return await i.writeFile(`${process.pid}\n`),async()=>{await i.close(),await n.rm(t,{force:!0})}}function M(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function N(e){return typeof e==`string`&&e.trim().length>0}function P(e){if(!e)return null;try{return JSON.parse(Buffer.from(e,`base64url`).toString(`utf8`))}catch{return null}}function F(e){let t=e.split(`.`);if(t.length!==3)return null;let n=P(t[0]);return!M(n)||n.alg!==`RS256`||n.typ!==`JWT`?null:{alg:`RS256`,typ:`JWT`}}function I(e){if(!M(e))return null;let{iss:t,aud:n,licenseId:r,domain:i,buyer:a,installationId:o,machineFingerprint:s,plan:u,entitlements:d,purchaseProvider:f,environment:p,routingMode:m,iat:h}=e;if(!N(t)||!N(n)||!N(r)||!N(i)||!N(a)||!N(o)||!N(s)||u!==`standard`&&u!==`extended`||!Array.isArray(d)||!d.every(N)||f!==`envato`&&f!==`jchat`||p!==`production`&&p!==`development`||m!==`path`&&m!==`subdomain`||typeof h!=`number`||!Number.isSafeInteger(h)||h<0)return null;let g;try{g=c(i)}catch{return null}if(p===`development`&&!g.isLocalhost||p===`production`&&!l(i))return null;let _=d.includes(`site.create.multi`);return u===`extended`&&!_||u===`standard`&&_?null:{iss:t,aud:n,licenseId:r,domain:i,buyer:a,installationId:o,machineFingerprint:s,plan:u,entitlements:d,purchaseProvider:f,environment:p,routingMode:m,iat:h}}function L(e){let t=e.split(`.`);return t.length!==3||!t.every(Boolean)||!F(e)?null:I(P(t[1]))}function R(t,n,r){if(!t||t===`YOUR_LICENSE_KEY_PLACEHOLDER`)return!1;try{let i=t.split(`.`);if(i.length!==3||!F(t))return!1;let a=L(t);if(!a||a.iss!==(r.issuer??`https://license.jchat.local`)||a.aud!==(r.audience??`jchat-chat`)||c(a.domain).host!==c(n).host)return!1;let o=Buffer.from(`${i[0]}.${i[1]}`),s=Buffer.from(i[2].replace(/-/g,`+`).replace(/_/g,`/`),`base64`);return e.verify(`sha256`,o,r.publicKeyPem,s)}catch{return!1}}function z(e,t,n,r,i){if(!R(e,t,i))return!1;let a=L(e);return a?a.installationId===n&&a.machineFingerprint===r:!1}function B(e,t,n,r){return R(e,t,r)?L(e)?.entitlements?.includes(n)??!1:!1}export{T as DEFAULT_STATE_PATH,j as acquireProcessLock,C as activateRegistry,w as checkRegistry,D as createIdentity,E as createMachineFingerprint,b as getRuntimeStatus,B as hasEntitlement,u as isAllowedConfiguredDomain,x as isApplicationDisabled,l as isPublicDomain,c as normalizeDomain,L as parsePayload,k as readState,O as readTokenSync,m as recordAudit,v as registerInvalidationHandler,f as resolveActivationDomain,y as setRuntimeStatus,z as verifyEntitlement,R as verifySignature,A as writeState};
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@jchat/runtime",
3
+ "version": "0.0.1",
4
+ "private": false,
5
+ "description": "Runtime support package for JChat deployments.",
6
+ "license": "SEE LICENSE IN LICENSE",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/mjjabarullah/jchat.git",
10
+ "directory": "packages/runtime"
11
+ },
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "type": "module",
16
+ "main": "./dist/index.mjs",
17
+ "types": "./dist/index.d.mts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.mts",
21
+ "import": "./dist/index.mjs"
22
+ }
23
+ },
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "scripts": {
28
+ "build": "tsdown",
29
+ "lint": "oxlint . --config=../../oxlint.json",
30
+ "format": "oxfmt . --write",
31
+ "typecheck": "tsc --noEmit",
32
+ "test": "bun --config ./bunfig.toml test",
33
+ "prepack": "bun run build"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^26.1.1",
37
+ "bun-types": "^1.3.14",
38
+ "tsdown": "^0.22.14",
39
+ "typescript": "^7.0.2"
40
+ }
41
+ }