@velum-labs/routekit-registry 0.9.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/LICENSE +201 -0
- package/README.md +8 -0
- package/dist/generated/data.d.ts +430 -0
- package/dist/generated/data.js +629 -0
- package/dist/index.d.ts +155 -0
- package/dist/index.js +109 -0
- package/dist/test/registry.test.d.ts +1 -0
- package/dist/test/registry.test.js +75 -0
- package/package.json +40 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed accessors over RouteKit's generated neutral registry data.
|
|
3
|
+
*
|
|
4
|
+
* Provider/auth metadata, model catalogs, capabilities, pricing, and local
|
|
5
|
+
* model data are generated from spec/registry. Product-specific identities and
|
|
6
|
+
* panel presets are deliberately excluded.
|
|
7
|
+
*/
|
|
8
|
+
import { REGISTRY } from "./generated/data.js";
|
|
9
|
+
export { REGISTRY };
|
|
10
|
+
export type ProviderAuthStyle = "bearer" | "x-api-key" | "x-goog-api-key";
|
|
11
|
+
export type ProviderKeyProbe = {
|
|
12
|
+
path: string;
|
|
13
|
+
auth: ProviderAuthStyle;
|
|
14
|
+
extraHeaders?: Record<string, string>;
|
|
15
|
+
invalidStatuses: readonly number[];
|
|
16
|
+
};
|
|
17
|
+
export type ProviderDiscovery = {
|
|
18
|
+
path: string;
|
|
19
|
+
auth: ProviderAuthStyle;
|
|
20
|
+
extraHeaders?: Record<string, string>;
|
|
21
|
+
responseShape: ProviderDiscoveryResponseShape;
|
|
22
|
+
pickerDefaultSource?: "live" | "curated";
|
|
23
|
+
};
|
|
24
|
+
export type ProviderDiscoveryResponseShape = "openai" | "anthropic" | "google" | "codex";
|
|
25
|
+
export type ProviderWireProtocol = "openai" | "anthropic" | "google" | "codex";
|
|
26
|
+
export type ProviderWire = {
|
|
27
|
+
protocol: ProviderWireProtocol;
|
|
28
|
+
basePath: string;
|
|
29
|
+
};
|
|
30
|
+
export type ProviderInfo = {
|
|
31
|
+
baseUrl?: string;
|
|
32
|
+
keyEnv?: string;
|
|
33
|
+
authTokenEnv?: string;
|
|
34
|
+
baseUrlEnv?: string;
|
|
35
|
+
credentialEnvNames?: readonly string[];
|
|
36
|
+
apiCompatibility?: string;
|
|
37
|
+
attributionHeaders?: Record<string, string>;
|
|
38
|
+
keyProbe?: ProviderKeyProbe;
|
|
39
|
+
discovery?: ProviderDiscovery;
|
|
40
|
+
wire?: ProviderWire;
|
|
41
|
+
};
|
|
42
|
+
export declare const PROVIDERS: Readonly<Record<string, ProviderInfo>>;
|
|
43
|
+
export declare function providerDefaultBaseUrl(provider: string): string | undefined;
|
|
44
|
+
export declare function defaultKeyEnv(provider: string): string | undefined;
|
|
45
|
+
export declare function providerKeyProbe(provider: string): ProviderKeyProbe | undefined;
|
|
46
|
+
export declare function providerDiscovery(provider: string): ProviderDiscovery | undefined;
|
|
47
|
+
export type SubscriptionMode = "claude-code" | "codex";
|
|
48
|
+
export type SubscriptionOAuthInfo = {
|
|
49
|
+
tokenEndpoint: string;
|
|
50
|
+
clientId: string;
|
|
51
|
+
usageEndpoint: string;
|
|
52
|
+
profileEndpoint?: string;
|
|
53
|
+
usagePathFallback?: string;
|
|
54
|
+
};
|
|
55
|
+
export type SubscriptionRateLimitInfo = {
|
|
56
|
+
headerPrefix: string;
|
|
57
|
+
activeLimitHeader?: string;
|
|
58
|
+
retryAfterHeader: string;
|
|
59
|
+
};
|
|
60
|
+
export type SubscriptionAdminInfo = {
|
|
61
|
+
keyEnv: string;
|
|
62
|
+
usageEndpoint: string;
|
|
63
|
+
costEndpoint: string;
|
|
64
|
+
};
|
|
65
|
+
export type SubscriptionInfo = {
|
|
66
|
+
provider: string;
|
|
67
|
+
credentialsPath: string;
|
|
68
|
+
accountsDirectory: string;
|
|
69
|
+
keychainService?: string;
|
|
70
|
+
configPath?: string;
|
|
71
|
+
modelsCachePath?: string;
|
|
72
|
+
authFileName?: string;
|
|
73
|
+
defaultModel: string;
|
|
74
|
+
wire: ProviderWire;
|
|
75
|
+
discovery: {
|
|
76
|
+
path: string;
|
|
77
|
+
responseShape: ProviderDiscoveryResponseShape;
|
|
78
|
+
clientVersion?: string;
|
|
79
|
+
cacheFallback?: boolean;
|
|
80
|
+
extraHeaders?: Record<string, string>;
|
|
81
|
+
};
|
|
82
|
+
oauthBetaHeader?: string;
|
|
83
|
+
spoofSystemPrompt?: string;
|
|
84
|
+
defaultInstructions?: string;
|
|
85
|
+
defaultHeaders?: Record<string, string>;
|
|
86
|
+
requestDefaults?: {
|
|
87
|
+
stream?: boolean;
|
|
88
|
+
store?: boolean;
|
|
89
|
+
omitSampling?: boolean;
|
|
90
|
+
};
|
|
91
|
+
oauth: SubscriptionOAuthInfo;
|
|
92
|
+
rateLimit: SubscriptionRateLimitInfo;
|
|
93
|
+
admin: SubscriptionAdminInfo;
|
|
94
|
+
overrideEnv?: Record<string, readonly string[]>;
|
|
95
|
+
};
|
|
96
|
+
export declare const SUBSCRIPTIONS: Readonly<Record<SubscriptionMode, SubscriptionInfo>>;
|
|
97
|
+
export declare function subscriptionInfo(mode: SubscriptionMode): SubscriptionInfo;
|
|
98
|
+
export declare function providerForAuthMode(mode: SubscriptionMode): string;
|
|
99
|
+
export type AccountConnector = "native" | "cliproxy";
|
|
100
|
+
export type AccountConnectorInfo = {
|
|
101
|
+
connector: AccountConnector;
|
|
102
|
+
/** CLIProxyAPI login flag (cliproxy-backed kinds only). */
|
|
103
|
+
cliproxyLoginFlag?: string;
|
|
104
|
+
/** CLIProxyAPI auth-store `type` values that classify as this kind. */
|
|
105
|
+
cliproxyAuthTypes?: readonly string[];
|
|
106
|
+
/** ToS restriction: reverse-engineered upstream, personal/local use only. */
|
|
107
|
+
localOnly?: boolean;
|
|
108
|
+
aliases?: readonly string[];
|
|
109
|
+
};
|
|
110
|
+
export declare const ACCOUNT_CONNECTORS: Readonly<Record<string, AccountConnectorInfo>>;
|
|
111
|
+
/** Canonical account kinds known to the neutral registry (not a support contract). */
|
|
112
|
+
export declare function accountKinds(): readonly string[];
|
|
113
|
+
/** Canonical registry kinds plus their aliases (not necessarily public CLI choices). */
|
|
114
|
+
export declare function accountKindChoices(): readonly string[];
|
|
115
|
+
/**
|
|
116
|
+
* Resolve a user-supplied account kind (canonical name or alias) to its
|
|
117
|
+
* canonical kind and connector metadata.
|
|
118
|
+
*/
|
|
119
|
+
export declare function resolveAccountConnector(value: string): {
|
|
120
|
+
kind: string;
|
|
121
|
+
info: AccountConnectorInfo;
|
|
122
|
+
} | undefined;
|
|
123
|
+
/** Classify a CLIProxyAPI auth-store `type` value back to a canonical kind. */
|
|
124
|
+
export declare function accountKindForCliproxyAuthType(type: string): string | undefined;
|
|
125
|
+
export declare const DEFAULT_REASONING_MODEL: string;
|
|
126
|
+
export declare function catalogDefaultModel(choice: string): string | undefined;
|
|
127
|
+
export declare function curatedModels(choice: string): readonly string[];
|
|
128
|
+
export declare function smokeModelForTool(tool: string): string | undefined;
|
|
129
|
+
export declare function samplingOverridesForModel(model: string): Readonly<Record<string, number>>;
|
|
130
|
+
export declare function chatTemplateKwargsForModel(model: string): Readonly<Record<string, boolean>> | undefined;
|
|
131
|
+
export type RegistryModelPricing = {
|
|
132
|
+
inputPer1mTokens: number;
|
|
133
|
+
outputPer1mTokens: number;
|
|
134
|
+
};
|
|
135
|
+
export declare const PRICING_ALIASES: Readonly<Record<string, string>>;
|
|
136
|
+
export declare const DEFAULT_MODEL_PRICING: Readonly<Record<string, RegistryModelPricing>>;
|
|
137
|
+
export type LocalModelRole = "general" | "coder";
|
|
138
|
+
export type LocalCatalogModel = {
|
|
139
|
+
repo: string;
|
|
140
|
+
label: string;
|
|
141
|
+
params: string;
|
|
142
|
+
quant: string;
|
|
143
|
+
sizeGB: number;
|
|
144
|
+
minRamGB: number;
|
|
145
|
+
blurb: string;
|
|
146
|
+
role: LocalModelRole;
|
|
147
|
+
};
|
|
148
|
+
export declare const LOCAL_CATALOG_ENTRIES: readonly LocalCatalogModel[];
|
|
149
|
+
export type PreferredLocalModel = {
|
|
150
|
+
id: string;
|
|
151
|
+
repo: string;
|
|
152
|
+
};
|
|
153
|
+
export declare const PREFERRED_LOCAL_MODELS: readonly PreferredLocalModel[];
|
|
154
|
+
export declare const GATEWAY_DEFAULT_MLX_MODEL: string;
|
|
155
|
+
export declare const LOCAL_PROBE_MODEL: string;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed accessors over RouteKit's generated neutral registry data.
|
|
3
|
+
*
|
|
4
|
+
* Provider/auth metadata, model catalogs, capabilities, pricing, and local
|
|
5
|
+
* model data are generated from spec/registry. Product-specific identities and
|
|
6
|
+
* panel presets are deliberately excluded.
|
|
7
|
+
*/
|
|
8
|
+
import { REGISTRY } from "./generated/data.js";
|
|
9
|
+
export { REGISTRY };
|
|
10
|
+
export const PROVIDERS = REGISTRY.providers;
|
|
11
|
+
export function providerDefaultBaseUrl(provider) {
|
|
12
|
+
return PROVIDERS[provider]?.baseUrl;
|
|
13
|
+
}
|
|
14
|
+
export function defaultKeyEnv(provider) {
|
|
15
|
+
return PROVIDERS[provider]?.keyEnv;
|
|
16
|
+
}
|
|
17
|
+
export function providerKeyProbe(provider) {
|
|
18
|
+
return PROVIDERS[provider]?.keyProbe;
|
|
19
|
+
}
|
|
20
|
+
export function providerDiscovery(provider) {
|
|
21
|
+
return PROVIDERS[provider]?.discovery;
|
|
22
|
+
}
|
|
23
|
+
export const SUBSCRIPTIONS = REGISTRY.subscriptions;
|
|
24
|
+
export function subscriptionInfo(mode) {
|
|
25
|
+
return SUBSCRIPTIONS[mode];
|
|
26
|
+
}
|
|
27
|
+
export function providerForAuthMode(mode) {
|
|
28
|
+
return SUBSCRIPTIONS[mode].provider;
|
|
29
|
+
}
|
|
30
|
+
export const ACCOUNT_CONNECTORS = REGISTRY.connectors;
|
|
31
|
+
/** Canonical account kinds known to the neutral registry (not a support contract). */
|
|
32
|
+
export function accountKinds() {
|
|
33
|
+
return Object.keys(ACCOUNT_CONNECTORS);
|
|
34
|
+
}
|
|
35
|
+
/** Canonical registry kinds plus their aliases (not necessarily public CLI choices). */
|
|
36
|
+
export function accountKindChoices() {
|
|
37
|
+
return [
|
|
38
|
+
...accountKinds(),
|
|
39
|
+
...Object.values(ACCOUNT_CONNECTORS).flatMap((info) => info.aliases ?? [])
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Resolve a user-supplied account kind (canonical name or alias) to its
|
|
44
|
+
* canonical kind and connector metadata.
|
|
45
|
+
*/
|
|
46
|
+
export function resolveAccountConnector(value) {
|
|
47
|
+
const direct = ACCOUNT_CONNECTORS[value];
|
|
48
|
+
if (direct !== undefined)
|
|
49
|
+
return { kind: value, info: direct };
|
|
50
|
+
for (const [kind, info] of Object.entries(ACCOUNT_CONNECTORS)) {
|
|
51
|
+
if (info.aliases?.includes(value) === true)
|
|
52
|
+
return { kind, info };
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
/** Classify a CLIProxyAPI auth-store `type` value back to a canonical kind. */
|
|
57
|
+
export function accountKindForCliproxyAuthType(type) {
|
|
58
|
+
for (const [kind, info] of Object.entries(ACCOUNT_CONNECTORS)) {
|
|
59
|
+
if (info.cliproxyAuthTypes?.includes(type) === true)
|
|
60
|
+
return kind;
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
export const DEFAULT_REASONING_MODEL = REGISTRY.modelCatalog.defaultReasoningModel;
|
|
65
|
+
export function catalogDefaultModel(choice) {
|
|
66
|
+
return REGISTRY.modelCatalog.defaultModelByAuthChoice[choice];
|
|
67
|
+
}
|
|
68
|
+
export function curatedModels(choice) {
|
|
69
|
+
return REGISTRY.modelCatalog.curated[choice] ?? [];
|
|
70
|
+
}
|
|
71
|
+
export function smokeModelForTool(tool) {
|
|
72
|
+
return REGISTRY.modelCatalog.smokeModels[tool];
|
|
73
|
+
}
|
|
74
|
+
function familyMatches(family, loweredModel) {
|
|
75
|
+
if (!family.requires.every((needle) => loweredModel.includes(needle)))
|
|
76
|
+
return false;
|
|
77
|
+
if (family.anyOf !== undefined && !family.anyOf.some((needle) => loweredModel.includes(needle))) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
export function samplingOverridesForModel(model) {
|
|
83
|
+
const lowered = model.toLowerCase();
|
|
84
|
+
const families = REGISTRY.modelCapabilities.samplingFamilies;
|
|
85
|
+
for (const family of families) {
|
|
86
|
+
if (familyMatches(family, lowered))
|
|
87
|
+
return family.overrides;
|
|
88
|
+
}
|
|
89
|
+
return {};
|
|
90
|
+
}
|
|
91
|
+
export function chatTemplateKwargsForModel(model) {
|
|
92
|
+
const lowered = model.toLowerCase();
|
|
93
|
+
const families = REGISTRY.modelCapabilities.chatTemplateFamilies;
|
|
94
|
+
for (const family of families) {
|
|
95
|
+
if (familyMatches(family, lowered))
|
|
96
|
+
return family.chatTemplateKwargs;
|
|
97
|
+
}
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
export const PRICING_ALIASES = (REGISTRY.pricing.aliases ?? {});
|
|
101
|
+
export const DEFAULT_MODEL_PRICING = {
|
|
102
|
+
...REGISTRY.pricing.models,
|
|
103
|
+
...REGISTRY.pricing.manualOverrides
|
|
104
|
+
};
|
|
105
|
+
export const LOCAL_CATALOG_ENTRIES = REGISTRY.localCatalog
|
|
106
|
+
.entries;
|
|
107
|
+
export const PREFERRED_LOCAL_MODELS = REGISTRY.localCatalog.preferred;
|
|
108
|
+
export const GATEWAY_DEFAULT_MLX_MODEL = REGISTRY.localCatalog.gatewayDefaultModel;
|
|
109
|
+
export const LOCAL_PROBE_MODEL = REGISTRY.localCatalog.probeModel;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { test } from "node:test";
|
|
4
|
+
import { ACCOUNT_CONNECTORS, DEFAULT_MODEL_PRICING, GATEWAY_DEFAULT_MLX_MODEL, LOCAL_CATALOG_ENTRIES, LOCAL_PROBE_MODEL, PREFERRED_LOCAL_MODELS, REGISTRY, accountKindChoices, accountKindForCliproxyAuthType, providerDiscovery, resolveAccountConnector } from "../index.js";
|
|
5
|
+
test("neutral generated registry excludes product and panel data", () => {
|
|
6
|
+
assert.equal("fusion" in REGISTRY, false);
|
|
7
|
+
assert.equal("defaultCloudPanel" in REGISTRY.modelCatalog, false);
|
|
8
|
+
assert.equal("benchmarkPanels" in REGISTRY.modelCatalog, false);
|
|
9
|
+
const generatedSource = readFileSync(new URL("../../src/generated/data.ts", import.meta.url), "utf8");
|
|
10
|
+
assert.doesNotMatch(generatedSource, /fusionkit/i);
|
|
11
|
+
});
|
|
12
|
+
test("local catalog defaults reference valid catalog metadata", () => {
|
|
13
|
+
const repos = new Set(LOCAL_CATALOG_ENTRIES.map((entry) => entry.repo));
|
|
14
|
+
assert.ok(repos.has(LOCAL_PROBE_MODEL));
|
|
15
|
+
for (const preferred of PREFERRED_LOCAL_MODELS) {
|
|
16
|
+
assert.ok(repos.has(preferred.repo), `${preferred.id} must reference a local catalog entry`);
|
|
17
|
+
}
|
|
18
|
+
assert.ok(GATEWAY_DEFAULT_MLX_MODEL.length > 0);
|
|
19
|
+
});
|
|
20
|
+
test("neutral pricing and provider metadata remain available", () => {
|
|
21
|
+
assert.deepEqual(DEFAULT_MODEL_PRICING["gpt-5.5"], {
|
|
22
|
+
inputPer1mTokens: 1.25,
|
|
23
|
+
outputPer1mTokens: 10
|
|
24
|
+
});
|
|
25
|
+
const discovery = providerDiscovery("openrouter");
|
|
26
|
+
assert.equal(discovery?.path, "/v1/models");
|
|
27
|
+
assert.equal(discovery?.pickerDefaultSource, "curated");
|
|
28
|
+
assert.equal(REGISTRY.providers.openai.wire.protocol, "openai");
|
|
29
|
+
assert.equal(REGISTRY.providers.anthropic.wire.protocol, "anthropic");
|
|
30
|
+
assert.equal(REGISTRY.providers.google.wire.protocol, "google");
|
|
31
|
+
assert.equal(REGISTRY.providers.codex.discovery.responseShape, "codex");
|
|
32
|
+
assert.equal(REGISTRY.subscriptions["claude-code"].discovery.path, "/v1/models");
|
|
33
|
+
assert.equal(REGISTRY.subscriptions.codex.discovery.cacheFallback, true);
|
|
34
|
+
assert.equal(REGISTRY.providers.openrouter.attributionHeaders["X-Title"], "RouteKit");
|
|
35
|
+
assert.equal(REGISTRY.providers.openrouter.discovery.extraHeaders["X-Title"], "RouteKit");
|
|
36
|
+
assert.equal(REGISTRY.subscriptions.codex.defaultHeaders.originator, "routekit");
|
|
37
|
+
});
|
|
38
|
+
test("account connector map resolves canonical kinds, aliases, and auth types", () => {
|
|
39
|
+
// Native subscription kinds stay native; every native kind has full
|
|
40
|
+
// subscription metadata in the subscriptions section.
|
|
41
|
+
for (const [kind, info] of Object.entries(ACCOUNT_CONNECTORS)) {
|
|
42
|
+
if (info.connector === "native") {
|
|
43
|
+
assert.ok(kind in REGISTRY.subscriptions, `${kind} needs subscription metadata`);
|
|
44
|
+
assert.equal(info.localOnly, undefined);
|
|
45
|
+
assert.equal(info.cliproxyLoginFlag, undefined);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
assert.equal(info.connector, "cliproxy");
|
|
49
|
+
assert.ok(info.cliproxyLoginFlag?.startsWith("-"), `${kind} needs a login flag`);
|
|
50
|
+
assert.equal(info.localOnly, true, `${kind} is ToS-restricted to local use`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
assert.deepEqual(resolveAccountConnector("claude"), {
|
|
54
|
+
kind: "claude-code",
|
|
55
|
+
info: ACCOUNT_CONNECTORS["claude-code"]
|
|
56
|
+
});
|
|
57
|
+
assert.deepEqual(resolveAccountConnector("antigravity"), {
|
|
58
|
+
kind: "gemini",
|
|
59
|
+
info: ACCOUNT_CONNECTORS.gemini
|
|
60
|
+
});
|
|
61
|
+
assert.equal(resolveAccountConnector("unknown-kind"), undefined);
|
|
62
|
+
assert.equal(accountKindForCliproxyAuthType("antigravity"), "gemini");
|
|
63
|
+
assert.equal(accountKindForCliproxyAuthType("xai"), "grok");
|
|
64
|
+
assert.equal(accountKindForCliproxyAuthType("vertex"), undefined);
|
|
65
|
+
assert.deepEqual(accountKindChoices(), [
|
|
66
|
+
"claude-code",
|
|
67
|
+
"codex",
|
|
68
|
+
"gemini",
|
|
69
|
+
"grok",
|
|
70
|
+
"kimi",
|
|
71
|
+
"claude",
|
|
72
|
+
"antigravity",
|
|
73
|
+
"xai"
|
|
74
|
+
]);
|
|
75
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@velum-labs/routekit-registry",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "0.9.0",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/velum-labs/handoffkit.git",
|
|
8
|
+
"directory": "packages/routekit-registry"
|
|
9
|
+
},
|
|
10
|
+
"description": "Product-neutral provider, subscription, model catalog, capability, pricing, and local model registry data.",
|
|
11
|
+
"license": "Apache-2.0",
|
|
12
|
+
"type": "module",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"registry": "https://registry.npmjs.org",
|
|
25
|
+
"access": "public",
|
|
26
|
+
"provenance": true
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"routekit",
|
|
30
|
+
"llm",
|
|
31
|
+
"registry",
|
|
32
|
+
"providers",
|
|
33
|
+
"models"
|
|
34
|
+
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc -b",
|
|
37
|
+
"clean": "tsc -b --clean",
|
|
38
|
+
"test": "node --test \"dist/test/*.test.js\""
|
|
39
|
+
}
|
|
40
|
+
}
|