@openparachute/vault 0.4.3 → 0.4.4-rc.11
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/README.md +58 -2
- package/core/src/core.test.ts +116 -0
- package/core/src/mcp.ts +94 -4
- package/core/src/obsidian.ts +55 -177
- package/core/src/portable-md.test.ts +1001 -0
- package/core/src/portable-md.ts +1409 -0
- package/core/src/schema-defaults.ts +19 -1
- package/core/src/store.ts +13 -0
- package/core/src/types.ts +15 -0
- package/package.json +1 -1
- package/src/cli.ts +699 -141
- package/src/doctor.test.ts +7 -6
- package/src/mcp-install-interactive.test.ts +883 -0
- package/src/mcp-install-interactive.ts +412 -0
- package/src/mcp-install.test.ts +957 -5
- package/src/mcp-install.ts +580 -13
- package/src/routes.ts +19 -3
- package/src/vault.test.ts +141 -0
|
@@ -47,7 +47,17 @@ import { Database } from "bun:sqlite";
|
|
|
47
47
|
// ---------------------------------------------------------------------------
|
|
48
48
|
|
|
49
49
|
export interface SchemaField {
|
|
50
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Declared type for the field's metadata value. `"integer"` is distinct
|
|
52
|
+
* from `"number"` only at validation time — JSON has no separate integer
|
|
53
|
+
* type, so a JSON number with zero fractional part (`5`, `5.0`,
|
|
54
|
+
* `Number.isInteger(n) === true`) is accepted as integer and a non-zero
|
|
55
|
+
* fractional value (`5.5`) is rejected. This matches the indexed-fields
|
|
56
|
+
* `"integer"` storage type (TYPE_MAP) and removes the false-positive
|
|
57
|
+
* `type_mismatch` warning that previously fired on every integer-shaped
|
|
58
|
+
* field because the validator had no `"integer"` case. See vault#310.
|
|
59
|
+
*/
|
|
60
|
+
type?: "string" | "number" | "integer" | "boolean" | "array" | "object";
|
|
51
61
|
enum?: string[];
|
|
52
62
|
description?: string;
|
|
53
63
|
}
|
|
@@ -270,6 +280,14 @@ function valueMatchesType(value: unknown, type: SchemaField["type"]): boolean {
|
|
|
270
280
|
return typeof value === "string";
|
|
271
281
|
case "number":
|
|
272
282
|
return typeof value === "number" && Number.isFinite(value);
|
|
283
|
+
case "integer":
|
|
284
|
+
// JSON has no separate integer type — `5.0` and `5` decode to the
|
|
285
|
+
// same JS Number. Accept any finite Number whose fractional part is
|
|
286
|
+
// zero; reject `5.5`, `NaN`, `Infinity`, and non-Number types.
|
|
287
|
+
// vault#310 (Gitcoin Brain drift detector emits JSON for diffs;
|
|
288
|
+
// without this case, every integer-typed field warned
|
|
289
|
+
// `type_mismatch` and buried the real warnings).
|
|
290
|
+
return typeof value === "number" && Number.isInteger(value);
|
|
273
291
|
case "boolean":
|
|
274
292
|
return typeof value === "boolean";
|
|
275
293
|
case "array":
|
package/core/src/store.ts
CHANGED
|
@@ -202,6 +202,19 @@ export class BunSqliteStore implements Store {
|
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
+
async restoreNoteTimestamps(id: string, createdAt: string, updatedAt: string): Promise<void> {
|
|
206
|
+
// Import-only: direct UPDATE so the importer can restore a note's
|
|
207
|
+
// historical `created_at`/`updated_at` from the portable-md export
|
|
208
|
+
// bytes. `updateNote` either bumps `updated_at` to wall-clock-now or
|
|
209
|
+
// (with `skipUpdatedAt: true`) leaves it untouched — neither lets
|
|
210
|
+
// the importer write a specific historical timestamp. Skips hooks
|
|
211
|
+
// by design: this isn't a user-edit, it's a state restoration.
|
|
212
|
+
// See vault#308 PR 2.
|
|
213
|
+
this.db
|
|
214
|
+
.prepare("UPDATE notes SET created_at = ?, updated_at = ? WHERE id = ?")
|
|
215
|
+
.run(createdAt, updatedAt, id);
|
|
216
|
+
}
|
|
217
|
+
|
|
205
218
|
async deleteNote(id: string): Promise<void> {
|
|
206
219
|
// Read before delete so we can invalidate config caches on the way out.
|
|
207
220
|
const existing = noteOps.getNote(this.db, id);
|
package/core/src/types.ts
CHANGED
|
@@ -143,6 +143,21 @@ export interface Store {
|
|
|
143
143
|
getNoteByPath(path: string): Promise<Note | null>;
|
|
144
144
|
getNotes(ids: string[]): Promise<Note[]>;
|
|
145
145
|
updateNote(id: string, updates: { content?: string; append?: string; prepend?: string; path?: string; metadata?: Record<string, unknown>; created_at?: string; skipUpdatedAt?: boolean; if_updated_at?: string }): Promise<Note>;
|
|
146
|
+
/**
|
|
147
|
+
* Set a note's `created_at` and `updated_at` explicitly. Import-only:
|
|
148
|
+
* used by the portable-md round-trip path to restore timestamps from
|
|
149
|
+
* the export bytes. The regular `updateNote` either bumps `updated_at`
|
|
150
|
+
* to wall-clock-now or (with `skipUpdatedAt: true`) leaves it
|
|
151
|
+
* untouched — neither shape lets the importer write a specific
|
|
152
|
+
* historical timestamp. Bypasses hooks. See vault#308 PR 2.
|
|
153
|
+
*/
|
|
154
|
+
restoreNoteTimestamps(id: string, createdAt: string, updatedAt: string): Promise<void>;
|
|
155
|
+
/**
|
|
156
|
+
* Sync wikilinks for every note in the vault. Cheap O(n) walk; used
|
|
157
|
+
* after bulk-imports to rebuild link rows from `[[brackets]]` in
|
|
158
|
+
* content. Returns counts for caller logging.
|
|
159
|
+
*/
|
|
160
|
+
syncAllWikilinks(): Promise<{ synced: number; totalAdded: number; totalRemoved: number }>;
|
|
146
161
|
deleteNote(id: string): Promise<void>;
|
|
147
162
|
queryNotes(opts: QueryOpts): Promise<Note[]>;
|
|
148
163
|
searchNotes(query: string, opts?: { tags?: string[]; limit?: number }): Promise<Note[]>;
|