@hasna/prompts 0.2.0 → 0.2.2

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/dist/cli/index.js CHANGED
@@ -2187,6 +2187,21 @@ function runMigrations(db) {
2187
2187
  name: "003_pinned",
2188
2188
  sql: `ALTER TABLE prompts ADD COLUMN pinned INTEGER NOT NULL DEFAULT 0;`
2189
2189
  },
2190
+ {
2191
+ name: "004_projects",
2192
+ sql: `
2193
+ CREATE TABLE IF NOT EXISTS projects (
2194
+ id TEXT PRIMARY KEY,
2195
+ name TEXT NOT NULL UNIQUE,
2196
+ slug TEXT NOT NULL UNIQUE,
2197
+ description TEXT,
2198
+ path TEXT,
2199
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
2200
+ );
2201
+ ALTER TABLE prompts ADD COLUMN project_id TEXT REFERENCES projects(id) ON DELETE SET NULL;
2202
+ CREATE INDEX IF NOT EXISTS idx_prompts_project_id ON prompts(project_id);
2203
+ `
2204
+ },
2190
2205
  {
2191
2206
  name: "002_fts5",
2192
2207
  sql: `
@@ -2227,6 +2242,24 @@ function runMigrations(db) {
2227
2242
  db.run("INSERT INTO _migrations (name) VALUES (?)", [migration.name]);
2228
2243
  }
2229
2244
  }
2245
+ function resolveProject(db, idOrSlug) {
2246
+ const byId = db.query("SELECT id FROM projects WHERE id = ?").get(idOrSlug);
2247
+ if (byId)
2248
+ return byId.id;
2249
+ const bySlug = db.query("SELECT id FROM projects WHERE slug = ?").get(idOrSlug);
2250
+ if (bySlug)
2251
+ return bySlug.id;
2252
+ const byName = db.query("SELECT id FROM projects WHERE lower(name) = ?").get(idOrSlug.toLowerCase());
2253
+ if (byName)
2254
+ return byName.id;
2255
+ const byPrefix = db.query("SELECT id FROM projects WHERE id LIKE ? LIMIT 2").all(`${idOrSlug}%`);
2256
+ if (byPrefix.length === 1 && byPrefix[0])
2257
+ return byPrefix[0].id;
2258
+ const bySlugPrefix = db.query("SELECT id FROM projects WHERE slug LIKE ? LIMIT 2").all(`${idOrSlug}%`);
2259
+ if (bySlugPrefix.length === 1 && bySlugPrefix[0])
2260
+ return bySlugPrefix[0].id;
2261
+ return null;
2262
+ }
2230
2263
  function hasFts(db) {
2231
2264
  return db.query("SELECT 1 FROM sqlite_master WHERE type='table' AND name='prompts_fts'").get() !== null;
2232
2265
  }
@@ -2266,25 +2299,24 @@ function uniqueSlug(baseSlug) {
2266
2299
  }
2267
2300
  return slug;
2268
2301
  }
2302
+ var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
2303
+ function nanoid(len) {
2304
+ let id = "";
2305
+ for (let i = 0;i < len; i++) {
2306
+ id += CHARS[Math.floor(Math.random() * CHARS.length)];
2307
+ }
2308
+ return id;
2309
+ }
2269
2310
  function generatePromptId() {
2270
2311
  const db = getDatabase();
2271
- const row = db.query("SELECT id FROM prompts ORDER BY rowid DESC LIMIT 1").get();
2272
- let next = 1;
2273
- if (row) {
2274
- const match = row.id.match(/PRMT-(\d+)/);
2275
- if (match && match[1]) {
2276
- next = parseInt(match[1], 10) + 1;
2277
- }
2278
- }
2279
- return `PRMT-${String(next).padStart(5, "0")}`;
2312
+ let id;
2313
+ do {
2314
+ id = `prmt-${nanoid(8)}`;
2315
+ } while (db.query("SELECT 1 FROM prompts WHERE id = ?").get(id));
2316
+ return id;
2280
2317
  }
2281
2318
  function generateId(prefix) {
2282
- const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
2283
- let id = prefix + "-";
2284
- for (let i = 0;i < 8; i++) {
2285
- id += chars[Math.floor(Math.random() * chars.length)];
2286
- }
2287
- return id;
2319
+ return `${prefix}-${nanoid(8)}`;
2288
2320
  }
2289
2321
 
2290
2322
  // src/db/collections.ts
@@ -2436,6 +2468,12 @@ class DuplicateSlugError extends Error {
2436
2468
  this.name = "DuplicateSlugError";
2437
2469
  }
2438
2470
  }
2471
+ class ProjectNotFoundError extends Error {
2472
+ constructor(id) {
2473
+ super(`Project not found: ${id}`);
2474
+ this.name = "ProjectNotFoundError";
2475
+ }
2476
+ }
2439
2477
 
2440
2478
  // src/db/prompts.ts
2441
2479
  function rowToPrompt(row) {
@@ -2450,6 +2488,7 @@ function rowToPrompt(row) {
2450
2488
  tags: JSON.parse(row["tags"] || "[]"),
2451
2489
  variables: JSON.parse(row["variables"] || "[]"),
2452
2490
  pinned: Boolean(row["pinned"]),
2491
+ project_id: row["project_id"] ?? null,
2453
2492
  is_template: Boolean(row["is_template"]),
2454
2493
  source: row["source"],
2455
2494
  version: row["version"],
@@ -2473,11 +2512,12 @@ function createPrompt(input) {
2473
2512
  ensureCollection(collection);
2474
2513
  const tags = JSON.stringify(input.tags || []);
2475
2514
  const source = input.source || "manual";
2515
+ const project_id = input.project_id ?? null;
2476
2516
  const vars = extractVariables(input.body);
2477
2517
  const variables = JSON.stringify(vars.map((v) => ({ name: v, required: true })));
2478
2518
  const is_template = vars.length > 0 ? 1 : 0;
2479
- db.run(`INSERT INTO prompts (id, name, slug, title, body, description, collection, tags, variables, is_template, source)
2480
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [id, name, slug, input.title, input.body, input.description ?? null, collection, tags, variables, is_template, source]);
2519
+ db.run(`INSERT INTO prompts (id, name, slug, title, body, description, collection, tags, variables, is_template, source, project_id)
2520
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [id, name, slug, input.title, input.body, input.description ?? null, collection, tags, variables, is_template, source, project_id]);
2481
2521
  db.run(`INSERT INTO prompt_versions (id, prompt_id, body, version, changed_by)
2482
2522
  VALUES (?, ?, ?, 1, ?)`, [generateId("VER"), id, input.body, input.changed_by ?? null]);
2483
2523
  return getPrompt(id);
@@ -2521,10 +2561,16 @@ function listPrompts(filter = {}) {
2521
2561
  params.push(`%"${tag}"%`);
2522
2562
  }
2523
2563
  }
2564
+ let orderBy = "pinned DESC, use_count DESC, updated_at DESC";
2565
+ if (filter.project_id !== undefined && filter.project_id !== null) {
2566
+ conditions.push("(project_id = ? OR project_id IS NULL)");
2567
+ params.push(filter.project_id);
2568
+ orderBy = `(CASE WHEN project_id = '${filter.project_id}' THEN 0 ELSE 1 END), pinned DESC, use_count DESC, updated_at DESC`;
2569
+ }
2524
2570
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
2525
2571
  const limit = filter.limit ?? 100;
2526
2572
  const offset = filter.offset ?? 0;
2527
- const rows = db.query(`SELECT * FROM prompts ${where} ORDER BY pinned DESC, use_count DESC, updated_at DESC LIMIT ? OFFSET ?`).all(...params, limit, offset);
2573
+ const rows = db.query(`SELECT * FROM prompts ${where} ORDER BY ${orderBy} LIMIT ? OFFSET ?`).all(...params, limit, offset);
2528
2574
  return rows.map(rowToPrompt);
2529
2575
  }
2530
2576
  function updatePrompt(idOrSlug, input) {
@@ -2657,6 +2703,52 @@ function restoreVersion(promptId, version, changedBy) {
2657
2703
  VALUES (?, ?, ?, ?, ?)`, [generateId("VER"), promptId, ver.body, newVersion, changedBy ?? null]);
2658
2704
  }
2659
2705
 
2706
+ // src/db/projects.ts
2707
+ function rowToProject(row, promptCount) {
2708
+ return {
2709
+ id: row["id"],
2710
+ name: row["name"],
2711
+ slug: row["slug"],
2712
+ description: row["description"] ?? null,
2713
+ path: row["path"] ?? null,
2714
+ prompt_count: promptCount,
2715
+ created_at: row["created_at"]
2716
+ };
2717
+ }
2718
+ function createProject(input) {
2719
+ const db = getDatabase();
2720
+ const id = generateId("proj");
2721
+ const slug = generateSlug(input.name);
2722
+ db.run(`INSERT INTO projects (id, name, slug, description, path) VALUES (?, ?, ?, ?, ?)`, [id, input.name, slug, input.description ?? null, input.path ?? null]);
2723
+ return getProject(id);
2724
+ }
2725
+ function getProject(idOrSlug) {
2726
+ const db = getDatabase();
2727
+ const id = resolveProject(db, idOrSlug);
2728
+ if (!id)
2729
+ return null;
2730
+ const row = db.query("SELECT * FROM projects WHERE id = ?").get(id);
2731
+ if (!row)
2732
+ return null;
2733
+ const countRow = db.query("SELECT COUNT(*) as n FROM prompts WHERE project_id = ?").get(id);
2734
+ return rowToProject(row, countRow.n);
2735
+ }
2736
+ function listProjects() {
2737
+ const db = getDatabase();
2738
+ const rows = db.query("SELECT * FROM projects ORDER BY name ASC").all();
2739
+ return rows.map((row) => {
2740
+ const countRow = db.query("SELECT COUNT(*) as n FROM prompts WHERE project_id = ?").get(row["id"]);
2741
+ return rowToProject(row, countRow.n);
2742
+ });
2743
+ }
2744
+ function deleteProject(idOrSlug) {
2745
+ const db = getDatabase();
2746
+ const id = resolveProject(db, idOrSlug);
2747
+ if (!id)
2748
+ throw new ProjectNotFoundError(idOrSlug);
2749
+ db.run("DELETE FROM projects WHERE id = ?", [id]);
2750
+ }
2751
+
2660
2752
  // src/lib/search.ts
2661
2753
  function rowToSearchResult(row, snippet) {
2662
2754
  return {
@@ -2671,6 +2763,7 @@ function rowToSearchResult(row, snippet) {
2671
2763
  tags: JSON.parse(row["tags"] || "[]"),
2672
2764
  variables: JSON.parse(row["variables"] || "[]"),
2673
2765
  pinned: Boolean(row["pinned"]),
2766
+ project_id: row["project_id"] ?? null,
2674
2767
  is_template: Boolean(row["is_template"]),
2675
2768
  source: row["source"],
2676
2769
  version: row["version"],
@@ -2714,6 +2807,10 @@ function searchPrompts(query, filter = {}) {
2714
2807
  for (const tag of filter.tags)
2715
2808
  params.push(`%"${tag}"%`);
2716
2809
  }
2810
+ if (filter.project_id !== undefined && filter.project_id !== null) {
2811
+ conditions.push("(p.project_id = ? OR p.project_id IS NULL)");
2812
+ params.push(filter.project_id);
2813
+ }
2717
2814
  const where = conditions.length > 0 ? `AND ${conditions.join(" AND ")}` : "";
2718
2815
  const limit = filter.limit ?? 50;
2719
2816
  const offset = filter.offset ?? 0;
@@ -2807,10 +2904,17 @@ function lintAll(prompts) {
2807
2904
  // src/cli/index.tsx
2808
2905
  var require2 = createRequire(import.meta.url);
2809
2906
  var pkg = require2("../../package.json");
2810
- var program2 = new Command().name("prompts").version(pkg.version).description("Reusable prompt library \u2014 save, search, render prompts from any AI session").option("--json", "Output as JSON");
2907
+ var program2 = new Command().name("prompts").version(pkg.version).description("Reusable prompt library \u2014 save, search, render prompts from any AI session").option("--json", "Output as JSON").option("--project <name>", "Active project (name, slug, or ID) for scoped operations");
2811
2908
  function isJson() {
2812
2909
  return Boolean(program2.opts()["json"]);
2813
2910
  }
2911
+ function getActiveProjectId() {
2912
+ const projectName = program2.opts()["project"] ?? process.env["PROMPTS_PROJECT"];
2913
+ if (!projectName)
2914
+ return null;
2915
+ const db = getDatabase();
2916
+ return resolveProject(db, projectName);
2917
+ }
2814
2918
  function output(data) {
2815
2919
  if (isJson()) {
2816
2920
  console.log(JSON.stringify(data, null, 2));
@@ -2847,6 +2951,7 @@ program2.command("save <title>").description("Save a new prompt (or update exist
2847
2951
  }
2848
2952
  if (!body)
2849
2953
  handleError("No body provided. Use --body, --file, or pipe via stdin.");
2954
+ const project_id = getActiveProjectId();
2850
2955
  const { prompt, created, duplicate_warning } = upsertPrompt({
2851
2956
  title,
2852
2957
  body,
@@ -2855,7 +2960,8 @@ program2.command("save <title>").description("Save a new prompt (or update exist
2855
2960
  collection: opts["collection"],
2856
2961
  tags: opts["tags"] ? opts["tags"].split(",").map((t) => t.trim()) : [],
2857
2962
  source: opts["source"] || "manual",
2858
- changed_by: opts["agent"]
2963
+ changed_by: opts["agent"],
2964
+ project_id
2859
2965
  }, Boolean(opts["force"]));
2860
2966
  if (duplicate_warning && !isJson()) {
2861
2967
  console.warn(chalk.yellow(`Warning: ${duplicate_warning}`));
@@ -2900,11 +3006,13 @@ program2.command("get <id>").description("Get prompt details without incrementin
2900
3006
  });
2901
3007
  program2.command("list").description("List prompts").option("-c, --collection <name>", "Filter by collection").option("-t, --tags <tags>", "Filter by tags (comma-separated)").option("--templates", "Show only templates").option("--recent", "Sort by recently used").option("-n, --limit <n>", "Max results", "50").action((opts) => {
2902
3008
  try {
3009
+ const project_id = getActiveProjectId();
2903
3010
  let prompts = listPrompts({
2904
3011
  collection: opts["collection"],
2905
3012
  tags: opts["tags"] ? opts["tags"].split(",").map((t) => t.trim()) : undefined,
2906
3013
  is_template: opts["templates"] ? true : undefined,
2907
- limit: parseInt(opts["limit"]) || 50
3014
+ limit: parseInt(opts["limit"]) || 50,
3015
+ ...project_id !== null ? { project_id } : {}
2908
3016
  });
2909
3017
  if (opts["recent"]) {
2910
3018
  prompts = prompts.filter((p) => p.last_used_at !== null).sort((a, b) => (b.last_used_at ?? "").localeCompare(a.last_used_at ?? ""));
@@ -2925,10 +3033,12 @@ ${prompts.length} prompt(s)`));
2925
3033
  });
2926
3034
  program2.command("search <query>").description("Full-text search across prompts (FTS5)").option("-c, --collection <name>").option("-t, --tags <tags>").option("-n, --limit <n>", "Max results", "20").action((query, opts) => {
2927
3035
  try {
3036
+ const project_id = getActiveProjectId();
2928
3037
  const results = searchPrompts(query, {
2929
3038
  collection: opts["collection"],
2930
3039
  tags: opts["tags"] ? opts["tags"].split(",").map((t) => t.trim()) : undefined,
2931
- limit: parseInt(opts["limit"] ?? "20") || 20
3040
+ limit: parseInt(opts["limit"] ?? "20") || 20,
3041
+ ...project_id !== null ? { project_id } : {}
2932
3042
  });
2933
3043
  if (isJson()) {
2934
3044
  output(results);
@@ -3317,4 +3427,77 @@ program2.command("copy <id>").description("Copy prompt body to clipboard and inc
3317
3427
  handleError(e);
3318
3428
  }
3319
3429
  });
3430
+ var projectCmd = program2.command("project").description("Manage projects");
3431
+ projectCmd.command("create <name>").description("Create a new project").option("-d, --description <desc>", "Short description").option("--path <path>", "Filesystem path this project maps to").action((name, opts) => {
3432
+ try {
3433
+ const project = createProject({ name, description: opts["description"], path: opts["path"] });
3434
+ if (isJson())
3435
+ output(project);
3436
+ else {
3437
+ console.log(`${chalk.green("Created")} project ${chalk.bold(project.name)} \u2014 ${chalk.gray(project.slug)}`);
3438
+ if (project.description)
3439
+ console.log(chalk.gray(` ${project.description}`));
3440
+ }
3441
+ } catch (e) {
3442
+ handleError(e);
3443
+ }
3444
+ });
3445
+ projectCmd.command("list").description("List all projects").action(() => {
3446
+ try {
3447
+ const projects = listProjects();
3448
+ if (isJson()) {
3449
+ output(projects);
3450
+ return;
3451
+ }
3452
+ if (projects.length === 0) {
3453
+ console.log(chalk.gray("No projects."));
3454
+ return;
3455
+ }
3456
+ for (const p of projects) {
3457
+ console.log(`${chalk.bold(p.name)} ${chalk.gray(p.slug)} ${chalk.cyan(`${p.prompt_count} prompt(s)`)}`);
3458
+ if (p.description)
3459
+ console.log(chalk.gray(` ${p.description}`));
3460
+ }
3461
+ } catch (e) {
3462
+ handleError(e);
3463
+ }
3464
+ });
3465
+ projectCmd.command("get <id>").description("Get project details").action((id) => {
3466
+ try {
3467
+ const project = getProject(id);
3468
+ if (!project)
3469
+ handleError(`Project not found: ${id}`);
3470
+ output(isJson() ? project : `${chalk.bold(project.name)} ${chalk.gray(project.slug)} ${chalk.cyan(`${project.prompt_count} prompt(s)`)}`);
3471
+ } catch (e) {
3472
+ handleError(e);
3473
+ }
3474
+ });
3475
+ projectCmd.command("delete <id>").description("Delete a project (prompts become global)").option("-y, --yes", "Skip confirmation").action(async (id, opts) => {
3476
+ try {
3477
+ const project = getProject(id);
3478
+ if (!project)
3479
+ handleError(`Project not found: ${id}`);
3480
+ if (!opts.yes && !isJson()) {
3481
+ const { createInterface } = await import("readline");
3482
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
3483
+ await new Promise((resolve) => {
3484
+ rl.question(chalk.yellow(`Delete project "${project.name}"? Prompts will become global. [y/N] `), (ans) => {
3485
+ rl.close();
3486
+ if (ans.toLowerCase() !== "y") {
3487
+ console.log("Cancelled.");
3488
+ process.exit(0);
3489
+ }
3490
+ resolve();
3491
+ });
3492
+ });
3493
+ }
3494
+ deleteProject(id);
3495
+ if (isJson())
3496
+ output({ deleted: true, id: project.id });
3497
+ else
3498
+ console.log(chalk.red(`Deleted project ${project.name}`));
3499
+ } catch (e) {
3500
+ handleError(e);
3501
+ }
3502
+ });
3320
3503
  program2.parse();
@@ -3,6 +3,7 @@ export declare function getDbPath(): string;
3
3
  export declare function getDatabase(): Database;
4
4
  export declare function closeDatabase(): void;
5
5
  export declare function resetDatabase(): void;
6
+ export declare function resolveProject(db: Database, idOrSlug: string): string | null;
6
7
  export declare function hasFts(db: Database): boolean;
7
8
  export declare function resolvePrompt(db: Database, idOrSlug: string): string | null;
8
9
  //# sourceMappingURL=database.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAMrC,wBAAgB,SAAS,IAAI,MAAM,CAsBlC;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAmBtC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAKpC;AAGD,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAsHD,wBAAgB,MAAM,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAM5C;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkC3E"}
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAMrC,wBAAgB,SAAS,IAAI,MAAM,CAsBlC;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAmBtC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAKpC;AAGD,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAqID,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA0B5E;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAM5C;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkC3E"}
@@ -0,0 +1,10 @@
1
+ import type { Project } from "../types/index.js";
2
+ export declare function createProject(input: {
3
+ name: string;
4
+ description?: string;
5
+ path?: string;
6
+ }): Project;
7
+ export declare function getProject(idOrSlug: string): Project | null;
8
+ export declare function listProjects(): Project[];
9
+ export declare function deleteProject(idOrSlug: string): void;
10
+ //# sourceMappingURL=projects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/db/projects.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAehD,wBAAgB,aAAa,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAWnG;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAU3D;AAED,wBAAgB,YAAY,IAAI,OAAO,EAAE,CAOxC;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAKpD"}
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/db/prompts.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,MAAM,EACN,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EAGlB,MAAM,mBAAmB,CAAA;AA0B1B,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAyC7D;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOzD;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAItD;AAED,wBAAgB,WAAW,CAAC,MAAM,GAAE,iBAAsB,GAAG,MAAM,EAAE,CAmCpE;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,MAAM,CA8C/E;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAInD;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQlD;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAKnE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,EAAE,KAAK,UAAQ,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE,CA6BtI;AAED,wBAAgB,cAAc;;;;;YAOJ,MAAM;cAAQ,MAAM;cAAQ,MAAM;eAAS,MAAM;mBAAa,MAAM;;;YAGpE,MAAM;cAAQ,MAAM;cAAQ,MAAM;eAAS,MAAM;sBAAgB,MAAM;;;oBAG/D,MAAM;eAAS,MAAM;;;gBAGzB,MAAM;eAAS,MAAM;;EAGlD"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/db/prompts.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,MAAM,EACN,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EAGlB,MAAM,mBAAmB,CAAA;AA2B1B,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CA0C7D;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOzD;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAItD;AAED,wBAAgB,WAAW,CAAC,MAAM,GAAE,iBAAsB,GAAG,MAAM,EAAE,CA4CpE;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,MAAM,CA8C/E;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAInD;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQlD;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAKnE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,EAAE,KAAK,UAAQ,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE,CA6BtI;AAED,wBAAgB,cAAc;;;;;YAOJ,MAAM;cAAQ,MAAM;cAAQ,MAAM;eAAS,MAAM;mBAAa,MAAM;;;YAGpE,MAAM;cAAQ,MAAM;cAAQ,MAAM;eAAS,MAAM;sBAAgB,MAAM;;;oBAG/D,MAAM;eAAS,MAAM;;;gBAGzB,MAAM;eAAS,MAAM;;EAGlD"}
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export { listVersions, getVersion, restoreVersion } from "./db/versions.js";
3
3
  export { listCollections, getCollection, ensureCollection, movePrompt } from "./db/collections.js";
4
4
  export { registerAgent, listAgents } from "./db/agents.js";
5
5
  export { getDatabase, getDbPath } from "./db/database.js";
6
+ export { createProject, getProject, listProjects, deleteProject } from "./db/projects.js";
6
7
  export { searchPrompts, findSimilar } from "./lib/search.js";
7
8
  export { extractVariables, extractVariableInfo, renderTemplate, validateVars } from "./lib/template.js";
8
9
  export type { VariableInfo } from "./lib/template.js";
@@ -10,6 +11,6 @@ export { importFromJson, exportToJson } from "./lib/importer.js";
10
11
  export { findDuplicates } from "./lib/duplicates.js";
11
12
  export type { DuplicateMatch } from "./lib/duplicates.js";
12
13
  export { generateSlug, uniqueSlug, generatePromptId } from "./lib/ids.js";
13
- export type { Prompt, PromptVersion, Collection, Agent, TemplateVariable, PromptSource, CreatePromptInput, UpdatePromptInput, ListPromptsFilter, SearchResult, RenderResult, PromptStats, } from "./types/index.js";
14
- export { PromptNotFoundError, VersionConflictError, DuplicateSlugError, TemplateRenderError, } from "./types/index.js";
14
+ export type { Prompt, PromptVersion, Collection, Agent, Project, TemplateVariable, PromptSource, CreatePromptInput, UpdatePromptInput, ListPromptsFilter, SearchResult, RenderResult, PromptStats, } from "./types/index.js";
15
+ export { PromptNotFoundError, VersionConflictError, DuplicateSlugError, TemplateRenderError, ProjectNotFoundError, } from "./types/index.js";
15
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AACrK,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAC3E,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAClG,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAGzD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAG5D,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACvG,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGrD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAGzD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAGzE,YAAY,EACV,MAAM,EACN,aAAa,EACb,UAAU,EACV,KAAK,EACL,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AACrK,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAC3E,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAClG,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAGzF,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAG5D,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACvG,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGrD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAGzD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAGzE,YAAY,EACV,MAAM,EACN,aAAa,EACb,UAAU,EACV,KAAK,EACL,OAAO,EACP,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,kBAAkB,CAAA"}
package/dist/index.js CHANGED
@@ -113,6 +113,21 @@ function runMigrations(db) {
113
113
  name: "003_pinned",
114
114
  sql: `ALTER TABLE prompts ADD COLUMN pinned INTEGER NOT NULL DEFAULT 0;`
115
115
  },
116
+ {
117
+ name: "004_projects",
118
+ sql: `
119
+ CREATE TABLE IF NOT EXISTS projects (
120
+ id TEXT PRIMARY KEY,
121
+ name TEXT NOT NULL UNIQUE,
122
+ slug TEXT NOT NULL UNIQUE,
123
+ description TEXT,
124
+ path TEXT,
125
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
126
+ );
127
+ ALTER TABLE prompts ADD COLUMN project_id TEXT REFERENCES projects(id) ON DELETE SET NULL;
128
+ CREATE INDEX IF NOT EXISTS idx_prompts_project_id ON prompts(project_id);
129
+ `
130
+ },
116
131
  {
117
132
  name: "002_fts5",
118
133
  sql: `
@@ -153,6 +168,24 @@ function runMigrations(db) {
153
168
  db.run("INSERT INTO _migrations (name) VALUES (?)", [migration.name]);
154
169
  }
155
170
  }
171
+ function resolveProject(db, idOrSlug) {
172
+ const byId = db.query("SELECT id FROM projects WHERE id = ?").get(idOrSlug);
173
+ if (byId)
174
+ return byId.id;
175
+ const bySlug = db.query("SELECT id FROM projects WHERE slug = ?").get(idOrSlug);
176
+ if (bySlug)
177
+ return bySlug.id;
178
+ const byName = db.query("SELECT id FROM projects WHERE lower(name) = ?").get(idOrSlug.toLowerCase());
179
+ if (byName)
180
+ return byName.id;
181
+ const byPrefix = db.query("SELECT id FROM projects WHERE id LIKE ? LIMIT 2").all(`${idOrSlug}%`);
182
+ if (byPrefix.length === 1 && byPrefix[0])
183
+ return byPrefix[0].id;
184
+ const bySlugPrefix = db.query("SELECT id FROM projects WHERE slug LIKE ? LIMIT 2").all(`${idOrSlug}%`);
185
+ if (bySlugPrefix.length === 1 && bySlugPrefix[0])
186
+ return bySlugPrefix[0].id;
187
+ return null;
188
+ }
156
189
  function hasFts(db) {
157
190
  return db.query("SELECT 1 FROM sqlite_master WHERE type='table' AND name='prompts_fts'").get() !== null;
158
191
  }
@@ -192,25 +225,24 @@ function uniqueSlug(baseSlug) {
192
225
  }
193
226
  return slug;
194
227
  }
228
+ var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
229
+ function nanoid(len) {
230
+ let id = "";
231
+ for (let i = 0;i < len; i++) {
232
+ id += CHARS[Math.floor(Math.random() * CHARS.length)];
233
+ }
234
+ return id;
235
+ }
195
236
  function generatePromptId() {
196
237
  const db = getDatabase();
197
- const row = db.query("SELECT id FROM prompts ORDER BY rowid DESC LIMIT 1").get();
198
- let next = 1;
199
- if (row) {
200
- const match = row.id.match(/PRMT-(\d+)/);
201
- if (match && match[1]) {
202
- next = parseInt(match[1], 10) + 1;
203
- }
204
- }
205
- return `PRMT-${String(next).padStart(5, "0")}`;
238
+ let id;
239
+ do {
240
+ id = `prmt-${nanoid(8)}`;
241
+ } while (db.query("SELECT 1 FROM prompts WHERE id = ?").get(id));
242
+ return id;
206
243
  }
207
244
  function generateId(prefix) {
208
- const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
209
- let id = prefix + "-";
210
- for (let i = 0;i < 8; i++) {
211
- id += chars[Math.floor(Math.random() * chars.length)];
212
- }
213
- return id;
245
+ return `${prefix}-${nanoid(8)}`;
214
246
  }
215
247
 
216
248
  // src/db/collections.ts
@@ -379,6 +411,13 @@ class TemplateRenderError extends Error {
379
411
  }
380
412
  }
381
413
 
414
+ class ProjectNotFoundError extends Error {
415
+ constructor(id) {
416
+ super(`Project not found: ${id}`);
417
+ this.name = "ProjectNotFoundError";
418
+ }
419
+ }
420
+
382
421
  // src/db/prompts.ts
383
422
  function rowToPrompt(row) {
384
423
  return {
@@ -392,6 +431,7 @@ function rowToPrompt(row) {
392
431
  tags: JSON.parse(row["tags"] || "[]"),
393
432
  variables: JSON.parse(row["variables"] || "[]"),
394
433
  pinned: Boolean(row["pinned"]),
434
+ project_id: row["project_id"] ?? null,
395
435
  is_template: Boolean(row["is_template"]),
396
436
  source: row["source"],
397
437
  version: row["version"],
@@ -415,11 +455,12 @@ function createPrompt(input) {
415
455
  ensureCollection(collection);
416
456
  const tags = JSON.stringify(input.tags || []);
417
457
  const source = input.source || "manual";
458
+ const project_id = input.project_id ?? null;
418
459
  const vars = extractVariables(input.body);
419
460
  const variables = JSON.stringify(vars.map((v) => ({ name: v, required: true })));
420
461
  const is_template = vars.length > 0 ? 1 : 0;
421
- db.run(`INSERT INTO prompts (id, name, slug, title, body, description, collection, tags, variables, is_template, source)
422
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [id, name, slug, input.title, input.body, input.description ?? null, collection, tags, variables, is_template, source]);
462
+ db.run(`INSERT INTO prompts (id, name, slug, title, body, description, collection, tags, variables, is_template, source, project_id)
463
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [id, name, slug, input.title, input.body, input.description ?? null, collection, tags, variables, is_template, source, project_id]);
423
464
  db.run(`INSERT INTO prompt_versions (id, prompt_id, body, version, changed_by)
424
465
  VALUES (?, ?, ?, 1, ?)`, [generateId("VER"), id, input.body, input.changed_by ?? null]);
425
466
  return getPrompt(id);
@@ -463,10 +504,16 @@ function listPrompts(filter = {}) {
463
504
  params.push(`%"${tag}"%`);
464
505
  }
465
506
  }
507
+ let orderBy = "pinned DESC, use_count DESC, updated_at DESC";
508
+ if (filter.project_id !== undefined && filter.project_id !== null) {
509
+ conditions.push("(project_id = ? OR project_id IS NULL)");
510
+ params.push(filter.project_id);
511
+ orderBy = `(CASE WHEN project_id = '${filter.project_id}' THEN 0 ELSE 1 END), pinned DESC, use_count DESC, updated_at DESC`;
512
+ }
466
513
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
467
514
  const limit = filter.limit ?? 100;
468
515
  const offset = filter.offset ?? 0;
469
- const rows = db.query(`SELECT * FROM prompts ${where} ORDER BY pinned DESC, use_count DESC, updated_at DESC LIMIT ? OFFSET ?`).all(...params, limit, offset);
516
+ const rows = db.query(`SELECT * FROM prompts ${where} ORDER BY ${orderBy} LIMIT ? OFFSET ?`).all(...params, limit, offset);
470
517
  return rows.map(rowToPrompt);
471
518
  }
472
519
  function updatePrompt(idOrSlug, input) {
@@ -626,6 +673,51 @@ function listAgents() {
626
673
  const rows = db.query("SELECT * FROM agents ORDER BY last_seen_at DESC").all();
627
674
  return rows.map(rowToAgent);
628
675
  }
676
+ // src/db/projects.ts
677
+ function rowToProject(row, promptCount) {
678
+ return {
679
+ id: row["id"],
680
+ name: row["name"],
681
+ slug: row["slug"],
682
+ description: row["description"] ?? null,
683
+ path: row["path"] ?? null,
684
+ prompt_count: promptCount,
685
+ created_at: row["created_at"]
686
+ };
687
+ }
688
+ function createProject(input) {
689
+ const db = getDatabase();
690
+ const id = generateId("proj");
691
+ const slug = generateSlug(input.name);
692
+ db.run(`INSERT INTO projects (id, name, slug, description, path) VALUES (?, ?, ?, ?, ?)`, [id, input.name, slug, input.description ?? null, input.path ?? null]);
693
+ return getProject(id);
694
+ }
695
+ function getProject(idOrSlug) {
696
+ const db = getDatabase();
697
+ const id = resolveProject(db, idOrSlug);
698
+ if (!id)
699
+ return null;
700
+ const row = db.query("SELECT * FROM projects WHERE id = ?").get(id);
701
+ if (!row)
702
+ return null;
703
+ const countRow = db.query("SELECT COUNT(*) as n FROM prompts WHERE project_id = ?").get(id);
704
+ return rowToProject(row, countRow.n);
705
+ }
706
+ function listProjects() {
707
+ const db = getDatabase();
708
+ const rows = db.query("SELECT * FROM projects ORDER BY name ASC").all();
709
+ return rows.map((row) => {
710
+ const countRow = db.query("SELECT COUNT(*) as n FROM prompts WHERE project_id = ?").get(row["id"]);
711
+ return rowToProject(row, countRow.n);
712
+ });
713
+ }
714
+ function deleteProject(idOrSlug) {
715
+ const db = getDatabase();
716
+ const id = resolveProject(db, idOrSlug);
717
+ if (!id)
718
+ throw new ProjectNotFoundError(idOrSlug);
719
+ db.run("DELETE FROM projects WHERE id = ?", [id]);
720
+ }
629
721
  // src/lib/search.ts
630
722
  function rowToSearchResult(row, snippet) {
631
723
  return {
@@ -640,6 +732,7 @@ function rowToSearchResult(row, snippet) {
640
732
  tags: JSON.parse(row["tags"] || "[]"),
641
733
  variables: JSON.parse(row["variables"] || "[]"),
642
734
  pinned: Boolean(row["pinned"]),
735
+ project_id: row["project_id"] ?? null,
643
736
  is_template: Boolean(row["is_template"]),
644
737
  source: row["source"],
645
738
  version: row["version"],
@@ -683,6 +776,10 @@ function searchPrompts(query, filter = {}) {
683
776
  for (const tag of filter.tags)
684
777
  params.push(`%"${tag}"%`);
685
778
  }
779
+ if (filter.project_id !== undefined && filter.project_id !== null) {
780
+ conditions.push("(p.project_id = ? OR p.project_id IS NULL)");
781
+ params.push(filter.project_id);
782
+ }
686
783
  const where = conditions.length > 0 ? `AND ${conditions.join(" AND ")}` : "";
687
784
  const limit = filter.limit ?? 50;
688
785
  const offset = filter.offset ?? 0;
@@ -772,12 +869,14 @@ export {
772
869
  movePrompt,
773
870
  listVersions,
774
871
  listPrompts,
872
+ listProjects,
775
873
  listCollections,
776
874
  listAgents,
777
875
  importFromJson,
778
876
  getVersion,
779
877
  getPromptStats,
780
878
  getPrompt,
879
+ getProject,
781
880
  getDbPath,
782
881
  getDatabase,
783
882
  getCollection,
@@ -790,9 +889,12 @@ export {
790
889
  exportToJson,
791
890
  ensureCollection,
792
891
  deletePrompt,
892
+ deleteProject,
793
893
  createPrompt,
894
+ createProject,
794
895
  VersionConflictError,
795
896
  TemplateRenderError,
796
897
  PromptNotFoundError,
898
+ ProjectNotFoundError,
797
899
  DuplicateSlugError
798
900
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../../src/lib/ids.ts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQlD;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CASnD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAezC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOjD"}
1
+ {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../../src/lib/ids.ts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQlD;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CASnD;AAYD,wBAAgB,gBAAgB,IAAI,MAAM,CAOzC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD"}
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAuCxE,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,IAAI,CAAC,iBAAiB,EAAE,GAAG,CAAM,GACxC,YAAY,EAAE,CAoEhB;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,YAAY,EAAE,CAmCvE"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAwCxE,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,IAAI,CAAC,iBAAiB,EAAE,GAAG,CAAM,GACxC,YAAY,EAAE,CAwEhB;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,YAAY,EAAE,CAmCvE"}