@ulpi/cli 0.1.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 +21 -0
- package/README.md +200 -0
- package/dist/auth-PN7TMQHV-2W4ICG64.js +15 -0
- package/dist/chunk-247GVVKK.js +2259 -0
- package/dist/chunk-2CLNOKPA.js +793 -0
- package/dist/chunk-2HEE5OKX.js +79 -0
- package/dist/chunk-2MZER6ND.js +415 -0
- package/dist/chunk-3SBPZRB5.js +772 -0
- package/dist/chunk-4VNS5WPM.js +42 -0
- package/dist/chunk-6JCMYYBT.js +1546 -0
- package/dist/chunk-6OCEY7JY.js +422 -0
- package/dist/chunk-74WVVWJ4.js +375 -0
- package/dist/chunk-7AL4DOEJ.js +131 -0
- package/dist/chunk-7LXY5UVC.js +330 -0
- package/dist/chunk-DBMUNBNB.js +3048 -0
- package/dist/chunk-JWUUVXIV.js +13694 -0
- package/dist/chunk-KIKPIH6N.js +4048 -0
- package/dist/chunk-KLEASXUR.js +70 -0
- package/dist/chunk-MIAQVCFW.js +39 -0
- package/dist/chunk-NNUWU6CV.js +1610 -0
- package/dist/chunk-PKD4ASEM.js +115 -0
- package/dist/chunk-Q4HIY43N.js +4230 -0
- package/dist/chunk-QJ5GSMEC.js +146 -0
- package/dist/chunk-SIAQVRKG.js +2163 -0
- package/dist/chunk-SPOI23SB.js +197 -0
- package/dist/chunk-YM2HV4IA.js +505 -0
- package/dist/codemap-RRJIDBQ5.js +636 -0
- package/dist/config-EGAXXCGL.js +127 -0
- package/dist/dist-6G7JC2RA.js +90 -0
- package/dist/dist-7LHZ65GC.js +418 -0
- package/dist/dist-LZKZFPVX.js +140 -0
- package/dist/dist-R5F4MX3I.js +107 -0
- package/dist/dist-R5ZJ4LX5.js +56 -0
- package/dist/dist-RJGCUS3L.js +87 -0
- package/dist/dist-RKOGLK7R.js +151 -0
- package/dist/dist-W7K4WPAF.js +597 -0
- package/dist/export-import-4A5MWLIA.js +53 -0
- package/dist/history-ATTUKOHO.js +934 -0
- package/dist/index.js +2120 -0
- package/dist/init-AY5C2ZAS.js +393 -0
- package/dist/launchd-LF2QMSKZ.js +148 -0
- package/dist/log-TVTUXAYD.js +75 -0
- package/dist/mcp-installer-NQCGKQ23.js +124 -0
- package/dist/memory-J3G24QHS.js +406 -0
- package/dist/ollama-3XCUZMZT-FYKHW4TZ.js +7 -0
- package/dist/openai-E7G2YAHU-UYY4ZWON.js +8 -0
- package/dist/projects-ATHDD3D6.js +271 -0
- package/dist/review-ADUPV3PN.js +152 -0
- package/dist/rules-E427DKYJ.js +134 -0
- package/dist/server-MOYPE4SM-N7SE2AN7.js +18 -0
- package/dist/server-X5P6WH2M-7K2RY34N.js +11 -0
- package/dist/skills/ulpi-generate-guardian/SKILL.md +511 -0
- package/dist/skills/ulpi-generate-guardian/references/framework-rules.md +692 -0
- package/dist/skills/ulpi-generate-guardian/references/language-rules.md +596 -0
- package/dist/skills-CX73O3IV.js +76 -0
- package/dist/status-4DFHDJMN.js +66 -0
- package/dist/templates/biome.yml +24 -0
- package/dist/templates/conventional-commits.yml +18 -0
- package/dist/templates/django.yml +30 -0
- package/dist/templates/docker.yml +30 -0
- package/dist/templates/eslint.yml +13 -0
- package/dist/templates/express.yml +20 -0
- package/dist/templates/fastapi.yml +23 -0
- package/dist/templates/git-flow.yml +26 -0
- package/dist/templates/github-flow.yml +27 -0
- package/dist/templates/go.yml +33 -0
- package/dist/templates/jest.yml +24 -0
- package/dist/templates/laravel.yml +30 -0
- package/dist/templates/monorepo.yml +26 -0
- package/dist/templates/nestjs.yml +21 -0
- package/dist/templates/nextjs.yml +31 -0
- package/dist/templates/nodejs.yml +33 -0
- package/dist/templates/npm.yml +15 -0
- package/dist/templates/php.yml +25 -0
- package/dist/templates/pnpm.yml +15 -0
- package/dist/templates/prettier.yml +23 -0
- package/dist/templates/prisma.yml +21 -0
- package/dist/templates/python.yml +33 -0
- package/dist/templates/quality-of-life.yml +111 -0
- package/dist/templates/ruby.yml +25 -0
- package/dist/templates/rust.yml +34 -0
- package/dist/templates/typescript.yml +14 -0
- package/dist/templates/vitest.yml +24 -0
- package/dist/templates/yarn.yml +15 -0
- package/dist/templates-U7T6MARD.js +156 -0
- package/dist/ui-L7UAWXDY.js +167 -0
- package/dist/ui.html +698 -0
- package/dist/ulpi-RMMCUAGP-JCJ273T6.js +161 -0
- package/dist/uninstall-6SW35IK4.js +25 -0
- package/dist/update-M2B4RLGH.js +61 -0
- package/dist/version-checker-ANCS3IHR.js +10 -0
- package/package.json +92 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveApiKey,
|
|
3
|
+
resolveUlpiUrl
|
|
4
|
+
} from "./chunk-7LXY5UVC.js";
|
|
5
|
+
import "./chunk-4VNS5WPM.js";
|
|
6
|
+
|
|
7
|
+
// ../../packages/codemap-engine/dist/ulpi-RMMCUAGP.js
|
|
8
|
+
var MAX_RETRIES = 3;
|
|
9
|
+
var RETRY_BASE_MS = 1e3;
|
|
10
|
+
var BATCH_POLL_INTERVAL_MS = 2e3;
|
|
11
|
+
var UlpiEmbedder = class {
|
|
12
|
+
provider = "ulpi";
|
|
13
|
+
model;
|
|
14
|
+
dimensions;
|
|
15
|
+
supportsBatch = true;
|
|
16
|
+
baseUrl;
|
|
17
|
+
apiKey;
|
|
18
|
+
constructor(model = "code", dimensions = 1024, baseUrl) {
|
|
19
|
+
this.model = model;
|
|
20
|
+
this.dimensions = dimensions;
|
|
21
|
+
this.baseUrl = baseUrl ?? resolveUlpiUrl();
|
|
22
|
+
this.apiKey = resolveApiKey("ulpi");
|
|
23
|
+
}
|
|
24
|
+
get headers() {
|
|
25
|
+
const h = { "Content-Type": "application/json" };
|
|
26
|
+
if (this.apiKey) h["Authorization"] = `Bearer ${this.apiKey}`;
|
|
27
|
+
return h;
|
|
28
|
+
}
|
|
29
|
+
async embed(texts) {
|
|
30
|
+
if (texts.length === 0) return [];
|
|
31
|
+
const body = {
|
|
32
|
+
model: this.model,
|
|
33
|
+
input: texts,
|
|
34
|
+
encoding_format: "float"
|
|
35
|
+
};
|
|
36
|
+
let lastError = null;
|
|
37
|
+
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
38
|
+
try {
|
|
39
|
+
const response = await fetch(`${this.baseUrl}/api/v1/embeddings`, {
|
|
40
|
+
method: "POST",
|
|
41
|
+
headers: this.headers,
|
|
42
|
+
body: JSON.stringify(body)
|
|
43
|
+
});
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
lastError = await this.handleErrorResponse(response);
|
|
46
|
+
if (response.status === 429 || response.status >= 500) {
|
|
47
|
+
await sleep(RETRY_BASE_MS * Math.pow(2, attempt));
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
throw lastError;
|
|
51
|
+
}
|
|
52
|
+
const data = await response.json();
|
|
53
|
+
const sorted = data.data.sort((a, b) => a.index - b.index);
|
|
54
|
+
return sorted.map((item) => item.embedding);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
lastError = this.classifyError(err, attempt);
|
|
57
|
+
if (lastError !== err && attempt < MAX_RETRIES - 1) {
|
|
58
|
+
await sleep(RETRY_BASE_MS * Math.pow(2, attempt));
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
throw lastError;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
throw lastError ?? new Error("ULPI embedding failed after retries");
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Submit all texts as an async batch (up to 10,000).
|
|
68
|
+
* Returns immediately with a batch ID for polling.
|
|
69
|
+
*/
|
|
70
|
+
async submitBatch(texts, webhookUrl) {
|
|
71
|
+
if (texts.length === 0) throw new Error("Cannot submit empty batch");
|
|
72
|
+
const body = {
|
|
73
|
+
model: this.model,
|
|
74
|
+
input: texts
|
|
75
|
+
};
|
|
76
|
+
if (webhookUrl) {
|
|
77
|
+
body.webhook_url = webhookUrl;
|
|
78
|
+
}
|
|
79
|
+
const payload = JSON.stringify(body);
|
|
80
|
+
const totalChars = texts.reduce((sum, t) => sum + t.length, 0);
|
|
81
|
+
const avgChars = Math.round(totalChars / texts.length);
|
|
82
|
+
const maxChars = Math.max(...texts.map((t) => t.length));
|
|
83
|
+
console.error(
|
|
84
|
+
`[ulpi-embedder] submitBatch: ${texts.length} texts, payload=${(payload.length / 1024).toFixed(0)}KB, chars: total=${totalChars} avg=${avgChars} max=${maxChars}, model=${this.model}, url=${this.baseUrl}/api/v1/embeddings/batch`
|
|
85
|
+
);
|
|
86
|
+
const response = await fetch(`${this.baseUrl}/api/v1/embeddings/batch`, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: this.headers,
|
|
89
|
+
body: payload
|
|
90
|
+
});
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
throw await this.handleErrorResponse(response);
|
|
93
|
+
}
|
|
94
|
+
const result = await response.json();
|
|
95
|
+
console.error(`[ulpi-embedder] submitBatch: got batchId=${result.data.id}`);
|
|
96
|
+
return result.data.id;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Poll the status of an async batch.
|
|
100
|
+
* Returns all available results on every poll (cumulative, sorted by index).
|
|
101
|
+
* This enables progressive storage — callers can store partial results
|
|
102
|
+
* as they arrive rather than waiting for full batch completion.
|
|
103
|
+
*/
|
|
104
|
+
async pollBatch(batchId) {
|
|
105
|
+
const response = await fetch(
|
|
106
|
+
`${this.baseUrl}/api/v1/embeddings/batch/${encodeURIComponent(batchId)}`,
|
|
107
|
+
{ headers: this.headers }
|
|
108
|
+
);
|
|
109
|
+
if (!response.ok) {
|
|
110
|
+
throw await this.handleErrorResponse(response);
|
|
111
|
+
}
|
|
112
|
+
const json = await response.json();
|
|
113
|
+
const batch = json.data;
|
|
114
|
+
let results;
|
|
115
|
+
if (json.results?.data && json.results.data.length > 0) {
|
|
116
|
+
const sorted = json.results.data.sort((a, b) => a.index - b.index);
|
|
117
|
+
results = sorted.map((item) => item.embedding);
|
|
118
|
+
}
|
|
119
|
+
const allProcessed = batch.processed_inputs >= batch.total_inputs;
|
|
120
|
+
return {
|
|
121
|
+
id: batch.id,
|
|
122
|
+
status: allProcessed && batch.status !== "failed" ? "completed" : batch.status,
|
|
123
|
+
totalInputs: batch.total_inputs,
|
|
124
|
+
processedInputs: batch.processed_inputs,
|
|
125
|
+
results
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
async handleErrorResponse(response) {
|
|
129
|
+
const errorText = await response.text();
|
|
130
|
+
if (response.status === 401 || response.status === 403) {
|
|
131
|
+
return new Error(
|
|
132
|
+
`Authentication failed (${response.status}). Check your ULPI API key with: ulpi config get ulpi-key`
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
if (response.status === 402) {
|
|
136
|
+
return new Error(
|
|
137
|
+
"Insufficient credits. Visit https://ulpi.io/billing to add credits to your account."
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
return new Error(`ULPI embedding API error (${response.status}): ${errorText.slice(0, 200)}`);
|
|
141
|
+
}
|
|
142
|
+
classifyError(err, _attempt) {
|
|
143
|
+
if (!(err instanceof Error)) return new Error(String(err));
|
|
144
|
+
if (err.message.startsWith("Authentication failed") || err.message.startsWith("Insufficient credits")) {
|
|
145
|
+
throw err;
|
|
146
|
+
}
|
|
147
|
+
if (err.message.includes("fetch") || err.message.includes("ECONNREFUSED")) {
|
|
148
|
+
throw new Error(
|
|
149
|
+
`Cannot connect to ULPI embedding service at ${this.baseUrl}. Check your network connection or configure the URL with: ulpi config set ulpi-url <url>`
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
return err;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
function sleep(ms) {
|
|
156
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
157
|
+
}
|
|
158
|
+
export {
|
|
159
|
+
BATCH_POLL_INTERVAL_MS,
|
|
160
|
+
UlpiEmbedder
|
|
161
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
uninstallHooks
|
|
3
|
+
} from "./chunk-QJ5GSMEC.js";
|
|
4
|
+
import "./chunk-7LXY5UVC.js";
|
|
5
|
+
import "./chunk-4VNS5WPM.js";
|
|
6
|
+
|
|
7
|
+
// src/commands/uninstall.ts
|
|
8
|
+
import chalk from "chalk";
|
|
9
|
+
async function runUninstall(_args, projectDir) {
|
|
10
|
+
console.log(chalk.cyan("Removing hooks..."));
|
|
11
|
+
uninstallHooks(projectDir);
|
|
12
|
+
console.log(chalk.green("\u2713 Hooks removed from .claude/settings.json"));
|
|
13
|
+
try {
|
|
14
|
+
const { isSupported, isLaunchAgentInstalled, uninstallLaunchAgent } = await import("./launchd-LF2QMSKZ.js");
|
|
15
|
+
if (isSupported() && isLaunchAgentInstalled()) {
|
|
16
|
+
uninstallLaunchAgent();
|
|
17
|
+
console.log(chalk.green("\u2713 Removed LaunchAgent for UI server"));
|
|
18
|
+
}
|
|
19
|
+
} catch {
|
|
20
|
+
}
|
|
21
|
+
console.log(chalk.dim("Note: Your guards.yml and session data are preserved."));
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
runUninstall
|
|
25
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import {
|
|
2
|
+
checkForUpdates
|
|
3
|
+
} from "./chunk-PKD4ASEM.js";
|
|
4
|
+
import {
|
|
5
|
+
CLI_BIN_NAME,
|
|
6
|
+
CLI_NPM_PACKAGE
|
|
7
|
+
} from "./chunk-7LXY5UVC.js";
|
|
8
|
+
import "./chunk-4VNS5WPM.js";
|
|
9
|
+
|
|
10
|
+
// src/commands/update.ts
|
|
11
|
+
import chalk from "chalk";
|
|
12
|
+
async function runUpdate(args) {
|
|
13
|
+
const checkOnly = args.includes("--check");
|
|
14
|
+
console.log(chalk.cyan("Checking for updates..."));
|
|
15
|
+
const info = await checkForUpdates();
|
|
16
|
+
console.log(` Current version: ${chalk.bold(info.current)}`);
|
|
17
|
+
console.log(` Latest version: ${chalk.bold(info.latest)}`);
|
|
18
|
+
if (!info.updateAvailable) {
|
|
19
|
+
console.log(chalk.green("\n\u2713 You're on the latest version."));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
console.log(chalk.yellow(`
|
|
23
|
+
\u2B06 Update available: ${info.current} \u2192 ${info.latest}`));
|
|
24
|
+
if (checkOnly) {
|
|
25
|
+
console.log(chalk.dim(`
|
|
26
|
+
Run '${CLI_BIN_NAME} update' to install the update.`));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
console.log(chalk.cyan("\nInstalling update..."));
|
|
30
|
+
try {
|
|
31
|
+
const { execFileSync } = await import("child_process");
|
|
32
|
+
execFileSync("npm", ["update", "-g", CLI_NPM_PACKAGE], {
|
|
33
|
+
stdio: "inherit",
|
|
34
|
+
timeout: 12e4
|
|
35
|
+
});
|
|
36
|
+
console.log(chalk.green(`
|
|
37
|
+
\u2713 Updated to v${info.latest}`));
|
|
38
|
+
try {
|
|
39
|
+
const { isSupported, isLaunchAgentInstalled, needsLegacyMigration, installLaunchAgent, restartLaunchAgent } = await import("./launchd-LF2QMSKZ.js");
|
|
40
|
+
if (isSupported()) {
|
|
41
|
+
if (needsLegacyMigration()) {
|
|
42
|
+
installLaunchAgent();
|
|
43
|
+
console.log(chalk.green("\u2713 Migrated LaunchAgent from com.ulpi.guardian.ui \u2192 com.ulpi.ui"));
|
|
44
|
+
} else if (isLaunchAgentInstalled()) {
|
|
45
|
+
restartLaunchAgent();
|
|
46
|
+
console.log(chalk.green("\u2713 Restarted LaunchAgent with updated binary"));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
} catch (err) {
|
|
52
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
53
|
+
console.error(chalk.red(`
|
|
54
|
+
Update failed: ${message}`));
|
|
55
|
+
console.log(chalk.dim("\nTry manually:"));
|
|
56
|
+
console.log(chalk.dim(` npm update -g ${CLI_NPM_PACKAGE}`));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export {
|
|
60
|
+
runUpdate
|
|
61
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ulpi/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"ulpi": "./dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist/*.js",
|
|
10
|
+
"dist/ui.html",
|
|
11
|
+
"dist/skills/**",
|
|
12
|
+
"dist/templates/**",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@lancedb/lancedb": "^0.16.0",
|
|
17
|
+
"chalk": "^5.4.0",
|
|
18
|
+
"ora": "^8.2.0",
|
|
19
|
+
"tree-sitter-c": "^0.24.1",
|
|
20
|
+
"tree-sitter-cpp": "^0.23.4",
|
|
21
|
+
"tree-sitter-css": "^0.25.0",
|
|
22
|
+
"tree-sitter-dart": "^1.0.0",
|
|
23
|
+
"tree-sitter-go": "^0.25.0",
|
|
24
|
+
"tree-sitter-html": "^0.23.2",
|
|
25
|
+
"tree-sitter-java": "^0.23.5",
|
|
26
|
+
"tree-sitter-javascript": "^0.25.0",
|
|
27
|
+
"tree-sitter-kotlin": "^0.3.8",
|
|
28
|
+
"tree-sitter-lua": "^2.1.3",
|
|
29
|
+
"tree-sitter-php": "^0.24.2",
|
|
30
|
+
"tree-sitter-python": "^0.25.0",
|
|
31
|
+
"tree-sitter-ruby": "^0.23.1",
|
|
32
|
+
"tree-sitter-rust": "^0.24.0",
|
|
33
|
+
"tree-sitter-scala": "^0.24.0",
|
|
34
|
+
"tree-sitter-swift": "^0.7.1",
|
|
35
|
+
"tree-sitter-typescript": "^0.23.2",
|
|
36
|
+
"web-tree-sitter": "^0.26.5",
|
|
37
|
+
"ws": "^8.18.0",
|
|
38
|
+
"yaml": "^2.7.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^25.2.0",
|
|
42
|
+
"@types/ws": "^8.5.0",
|
|
43
|
+
"tsup": "^8.4.0",
|
|
44
|
+
"typescript": "^5.7.0",
|
|
45
|
+
"vitest": "^3.0.0",
|
|
46
|
+
"@ulpi/guards-engine": "0.1.0",
|
|
47
|
+
"@ulpi/contracts": "0.1.0",
|
|
48
|
+
"@ulpi/config": "0.1.0",
|
|
49
|
+
"@ulpi/session-engine": "0.1.0",
|
|
50
|
+
"@ulpi/templates-engine": "0.1.0",
|
|
51
|
+
"@ulpi/notifications-engine": "0.1.0",
|
|
52
|
+
"@ulpi/history-engine": "0.1.0",
|
|
53
|
+
"@ulpi/projects-engine": "0.1.0",
|
|
54
|
+
"@ulpi/review-runtime": "0.1.0",
|
|
55
|
+
"@ulpi/codemap-engine": "0.1.0",
|
|
56
|
+
"@ulpi/review-engine": "0.1.0",
|
|
57
|
+
"@ulpi/api": "0.1.0",
|
|
58
|
+
"@ulpi/memory-mcp": "0.1.0",
|
|
59
|
+
"@ulpi/depgraph-engine": "0.1.0",
|
|
60
|
+
"@ulpi/memory-engine": "0.1.0",
|
|
61
|
+
"@ulpi/stack-engine": "0.1.0",
|
|
62
|
+
"@ulpi/codemap-mcp": "0.1.0"
|
|
63
|
+
},
|
|
64
|
+
"publishConfig": {
|
|
65
|
+
"access": "public"
|
|
66
|
+
},
|
|
67
|
+
"engines": {
|
|
68
|
+
"node": ">=20"
|
|
69
|
+
},
|
|
70
|
+
"repository": {
|
|
71
|
+
"type": "git",
|
|
72
|
+
"url": "https://github.com/ulpi-io/ulpi.git",
|
|
73
|
+
"directory": "apps/cli"
|
|
74
|
+
},
|
|
75
|
+
"keywords": [
|
|
76
|
+
"ai",
|
|
77
|
+
"coding-agent",
|
|
78
|
+
"rules-engine",
|
|
79
|
+
"claude-code",
|
|
80
|
+
"hooks",
|
|
81
|
+
"ulpi",
|
|
82
|
+
"cli"
|
|
83
|
+
],
|
|
84
|
+
"license": "MIT",
|
|
85
|
+
"scripts": {
|
|
86
|
+
"build": "tsup",
|
|
87
|
+
"dev": "tsup src/index.ts --format esm --watch",
|
|
88
|
+
"test": "vitest",
|
|
89
|
+
"clean": "rm -rf dist",
|
|
90
|
+
"lint": "tsc --noEmit"
|
|
91
|
+
}
|
|
92
|
+
}
|