@lapis-notes/api 0.1.3 → 0.2.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/CHANGELOG.md +304 -13
- package/README.md +19 -0
- package/dist/__tests__/fixtures/indexed-mutations.json +6862 -0
- package/dist/__tests__/fixtures/memory-storage.json +309 -0
- package/dist/__tests__/fixtures/native-facade-contract.json +3224 -0
- package/dist/__tests__/fixtures/projection-query.json +195 -0
- package/dist/__tests__/fixtures/projection-values.json +60 -0
- package/dist/__tests__/fixtures/search-preparation.json +1513 -0
- package/dist/__tests__/fixtures/search-retrieval.json +15409 -0
- package/dist/__tests__/fixtures/search-semantic-model.json +3691 -0
- package/dist/__tests__/fixtures/search-semantic-retrieval.json +6603 -0
- package/dist/__tests__/fixtures/search-storage.json +409 -0
- package/dist/__tests__/fixtures/task-projection.json +428 -0
- package/dist/__tests__/indexed-mutation-support.js +262 -0
- package/dist/__tests__/projection-query-support.js +40 -0
- package/dist/__tests__/search-retrieval-support.js +47 -0
- package/dist/app-database-host.d.ts +1 -0
- package/dist/app-shell-plugin-persistence.d.ts +3 -2
- package/dist/app-shell-plugin-persistence.js +37 -3
- package/dist/cache.svelte.d.ts +8 -1
- package/dist/cache.svelte.js +103 -5
- package/dist/command.svelte.js +29 -2
- package/dist/components/editor/editor.css +4 -0
- package/dist/components/editor/editor.svelte +24 -11
- package/dist/components/editor/embedded-editor-surface.js +3 -1
- package/dist/components/editor/inline-title-alignment.d.ts +3 -0
- package/dist/components/editor/inline-title-alignment.js +57 -0
- package/dist/configuration.svelte.d.ts +270 -206
- package/dist/configuration.svelte.js +161 -86
- package/dist/context.svelte.d.ts +23 -3
- package/dist/context.svelte.js +68 -30
- package/dist/diagnostics.d.ts +8 -0
- package/dist/diagnostics.js +6 -0
- package/dist/editor-save-context.d.ts +35 -0
- package/dist/editor-save-context.js +132 -0
- package/dist/editor-view-registry.d.ts +10 -0
- package/dist/editor-view-registry.js +44 -4
- package/dist/editor.svelte.d.ts +19 -1
- package/dist/editor.svelte.js +528 -55
- package/dist/embed-registry.d.ts +10 -0
- package/dist/embed-registry.js +15 -0
- package/dist/file-editing-failures.d.ts +2 -0
- package/dist/file-editing-failures.js +29 -0
- package/dist/file-editing-native-issues.d.ts +19 -0
- package/dist/file-editing-native-issues.js +65 -0
- package/dist/file-editing-sessions.d.ts +76 -0
- package/dist/file-editing-sessions.js +367 -0
- package/dist/file-manager.d.ts +9 -1
- package/dist/file-manager.js +45 -3
- package/dist/file-state-store.d.ts +5 -0
- package/dist/file-state-store.js +34 -0
- package/dist/file-text-conflicts.d.ts +25 -0
- package/dist/file-text-conflicts.js +35 -0
- package/dist/file-text-mutation.d.ts +13 -0
- package/dist/file-text-mutation.js +100 -0
- package/dist/file-text-persistence.d.ts +36 -0
- package/dist/file-text-persistence.js +234 -0
- package/dist/file-text-state-writer.d.ts +34 -0
- package/dist/file-text-state-writer.js +183 -0
- package/dist/files-configuration.d.ts +20 -0
- package/dist/files-configuration.js +47 -0
- package/dist/generated/plugin-host-modules.schema.generated.d.ts +114 -34
- package/dist/generated/plugin-host-modules.schema.generated.js +132 -34
- package/dist/glob.d.ts +3 -0
- package/dist/glob.js +2 -1
- package/dist/icons/changes.d.ts +3 -0
- package/dist/icons/changes.js +16 -0
- package/dist/icons/index.d.ts +5 -1
- package/dist/icons/index.js +44 -3
- package/dist/icons/registry.d.ts +35 -0
- package/dist/icons/registry.js +154 -0
- package/dist/icons/safe-svg.d.ts +2 -0
- package/dist/icons/safe-svg.js +44 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +4 -1
- package/dist/lapis-extension.d.ts +6 -2
- package/dist/lapis-extension.js +2 -0
- package/dist/metadata-store.d.ts +23 -0
- package/dist/metadata-store.js +1 -0
- package/dist/metadata.svelte.js +45 -2
- package/dist/native-background-indexing.d.ts +48 -0
- package/dist/native-background-indexing.js +208 -0
- package/dist/native-database-protocol.d.ts +29 -0
- package/dist/native-database-protocol.js +1 -0
- package/dist/native-editing-intent-lease.d.ts +17 -0
- package/dist/native-editing-intent-lease.js +188 -0
- package/dist/native-editing-intents-protocol.d.ts +70 -0
- package/dist/native-editing-intents-protocol.js +1 -0
- package/dist/native-editing-intents.d.ts +8 -0
- package/dist/native-editing-intents.js +1 -0
- package/dist/native-editing-problems.d.ts +3 -0
- package/dist/native-editing-problems.js +180 -0
- package/dist/native-editing-recovery.d.ts +24 -0
- package/dist/native-editing-recovery.js +198 -0
- package/dist/native-editing-session.d.ts +51 -0
- package/dist/native-editing-session.js +251 -0
- package/dist/native-history-index-protocol.d.ts +80 -0
- package/dist/native-history-index-protocol.js +1 -0
- package/dist/native-history-index.d.ts +6 -0
- package/dist/native-history-index.js +1 -0
- package/dist/native-indexing-protocol.d.ts +63 -0
- package/dist/native-indexing-protocol.js +1 -0
- package/dist/native-participant-protocol.d.ts +67 -0
- package/dist/native-participant-protocol.js +3 -0
- package/dist/native-queue-protocol.d.ts +73 -0
- package/dist/native-queue-protocol.js +3 -0
- package/dist/native-tasks-protocol.d.ts +264 -0
- package/dist/native-tasks-protocol.js +1 -0
- package/dist/native-tasks.d.ts +35 -0
- package/dist/native-tasks.js +79 -0
- package/dist/native-turn-protocol.d.ts +81 -0
- package/dist/native-turn-protocol.js +1 -0
- package/dist/native-turns.d.ts +29 -0
- package/dist/native-turns.js +2 -0
- package/dist/plugin-asset-server.js +3 -2
- package/dist/plugin-dependency-resolver.d.ts +1 -1
- package/dist/plugin-distribution/compatibility.d.ts +1 -1
- package/dist/plugin-distribution/compatibility.js +10 -5
- package/dist/plugin-distribution/installed-plugin-state.js +2 -1
- package/dist/plugin-distribution/installer.d.ts +6 -0
- package/dist/plugin-distribution/installer.js +90 -37
- package/dist/plugin-distribution/manager.d.ts +4 -1
- package/dist/plugin-distribution/manager.js +12 -5
- package/dist/plugin-distribution/registry-cache.js +2 -1
- package/dist/plugin-distribution/registry-source-state.js +2 -1
- package/dist/plugin-distribution/schemas.d.ts +26 -8
- package/dist/plugin-distribution/schemas.js +2 -1
- package/dist/plugin-distribution/types.d.ts +4 -0
- package/dist/plugin-manager.d.ts +21 -5
- package/dist/plugin-manager.js +228 -64
- package/dist/plugin-runtime-entry.d.ts +1 -1
- package/dist/plugin-runtime-entry.js +16 -0
- package/dist/plugin.d.ts +19 -3
- package/dist/plugin.js +110 -44
- package/dist/registry-schema/catalog-v1.d.ts +60 -9
- package/dist/registry-schema/catalog-v1.js +2 -1
- package/dist/registry-schema/catalog-v2.d.ts +60 -9
- package/dist/registry-schema/catalog-v2.js +1 -1
- package/dist/search-result-provider.d.ts +95 -0
- package/dist/search-result-provider.js +42 -0
- package/dist/status-bar.svelte.d.ts +26 -20
- package/dist/status-bar.svelte.js +1 -0
- package/dist/storage/app-database.d.ts +9 -23
- package/dist/storage/app-database.js +41 -34
- package/dist/storage/desktop-native.d.ts +5 -3
- package/dist/storage/desktop-native.js +59 -6
- package/dist/storage/directory-watcher.d.ts +27 -0
- package/dist/storage/directory-watcher.js +201 -0
- package/dist/storage/fs.d.ts +14 -27
- package/dist/storage/fs.js +2 -168
- package/dist/storage/index-projection.js +33 -15
- package/dist/storage/memory-vault-adapter.d.ts +2 -0
- package/dist/storage/memory-vault-adapter.js +14 -1
- package/dist/storage/path.d.ts +6 -2
- package/dist/storage/path.js +8 -2
- package/dist/storage/projection-query-candidates.d.ts +3 -0
- package/dist/storage/projection-query-candidates.js +69 -0
- package/dist/storage/remote-app-database.d.ts +2 -2
- package/dist/storage/remote-app-database.js +1 -1
- package/dist/storage/runtime.d.ts +3 -0
- package/dist/storage/runtime.js +3 -0
- package/dist/storage/search-embedding-record.d.ts +3 -0
- package/dist/storage/search-embedding-record.js +18 -0
- package/dist/storage/turso-app-database.d.ts +2 -0
- package/dist/storage/turso-app-database.js +67 -30
- package/dist/storage/vault-listing.d.ts +3 -0
- package/dist/storage/vault-listing.js +36 -0
- package/dist/storage/vault-reconciliation.d.ts +19 -0
- package/dist/storage/vault-reconciliation.js +137 -0
- package/dist/storage/vault-session.d.ts +8 -0
- package/dist/storage/vault-session.js +10 -2
- package/dist/storage/vault.svelte.d.ts +53 -4
- package/dist/storage/vault.svelte.js +223 -87
- package/dist/sync-editor-flush.d.ts +6 -0
- package/dist/sync-editor-flush.js +22 -0
- package/dist/sync-host-local.d.ts +15 -0
- package/dist/sync-host-local.js +228 -0
- package/dist/sync-host-security.d.ts +24 -9
- package/dist/sync-host-security.js +47 -14
- package/dist/sync-host.d.ts +33 -4
- package/dist/sync-host.js +160 -10
- package/dist/sync-repository.d.ts +106 -0
- package/dist/sync-repository.js +18 -0
- package/dist/vault-change-views.d.ts +4 -0
- package/dist/vault-change-views.js +43 -0
- package/dist/vault-changes.d.ts +37 -0
- package/dist/vault-changes.js +228 -0
- package/dist/view.svelte.d.ts +182 -149
- package/dist/view.svelte.js +39 -21
- package/dist/workspace-close-guard.d.ts +3 -0
- package/dist/workspace-close-guard.js +35 -0
- package/dist/workspace-host-internal.js +10 -2
- package/dist/workspace-layout-normalizer.d.ts +4 -2
- package/dist/workspace-layout-normalizer.js +5 -5
- package/dist/workspace-view-document.d.ts +3 -0
- package/dist/workspace-view-document.js +12 -0
- package/dist/workspace.svelte.d.ts +13 -2
- package/dist/workspace.svelte.js +371 -82
- package/package.json +61 -8
package/dist/storage/fs.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { EventDispatcher } from "../events";
|
|
2
1
|
import type { Vault } from "./vault.svelte";
|
|
3
2
|
interface FileProperties {
|
|
4
3
|
/**
|
|
@@ -90,6 +89,7 @@ export type WatchOptions = {
|
|
|
90
89
|
interval?: number;
|
|
91
90
|
};
|
|
92
91
|
export interface ChangeEvent {
|
|
92
|
+
previousPath?: string;
|
|
93
93
|
type: "create" | "modify" | "delete";
|
|
94
94
|
path: string;
|
|
95
95
|
}
|
|
@@ -99,7 +99,9 @@ export interface WatchErrorEvent {
|
|
|
99
99
|
error: unknown;
|
|
100
100
|
}
|
|
101
101
|
export interface NativeWatchSubscription {
|
|
102
|
-
|
|
102
|
+
/** Resolves after native registration and its initial snapshot complete. */
|
|
103
|
+
readonly ready?: Promise<void>;
|
|
104
|
+
close(): void | Promise<void>;
|
|
103
105
|
}
|
|
104
106
|
export interface NativeWatchAdapter {
|
|
105
107
|
watch(path: string | string[], options: WatchOptions, listener: (event: ChangeEvent | WatchErrorEvent) => void): NativeWatchSubscription | void;
|
|
@@ -140,6 +142,8 @@ export interface DataAdapter {
|
|
|
140
142
|
trashLocal(normalizedPath: string): Promise<void>;
|
|
141
143
|
}
|
|
142
144
|
export interface VaultAdapterCapabilities {
|
|
145
|
+
exclusiveCreate?: boolean;
|
|
146
|
+
conditionalTextWrite?: boolean;
|
|
143
147
|
persistent: boolean;
|
|
144
148
|
userVisibleFiles: boolean;
|
|
145
149
|
requiresPermission: boolean;
|
|
@@ -155,6 +159,13 @@ export interface VaultAdapterCapabilities {
|
|
|
155
159
|
*/
|
|
156
160
|
export interface VaultAdapter extends DataAdapter {
|
|
157
161
|
getCapabilities?(): Partial<VaultAdapterCapabilities>;
|
|
162
|
+
/** Publish new complete bytes without replacing an existing destination. */
|
|
163
|
+
writeExclusive?(normalizedPath: string, data: string | ArrayBuffer, options?: DataWriteOptions): Promise<void>;
|
|
164
|
+
/**
|
|
165
|
+
* Reject when the file no longer has these exact contents (null means
|
|
166
|
+
* absent).
|
|
167
|
+
*/
|
|
168
|
+
writeTextIfUnchanged?(normalizedPath: string, data: string, expected: string | null, options?: DataWriteOptions): Promise<void>;
|
|
158
169
|
openRead?(normalizedPath: string): Promise<VaultReadHandle>;
|
|
159
170
|
atomicWrite?(normalizedPath: string, source: ReadableStream<Uint8Array>, options?: AtomicDataWriteOptions): Promise<void>;
|
|
160
171
|
}
|
|
@@ -165,30 +176,7 @@ export interface AsyncResourceAdapter {
|
|
|
165
176
|
getResourceUrl(normalizedPath: string): Promise<string>;
|
|
166
177
|
revokeResourceUrl?(url: string): void;
|
|
167
178
|
}
|
|
168
|
-
export
|
|
169
|
-
error: [{
|
|
170
|
-
error: unknown;
|
|
171
|
-
path: string;
|
|
172
|
-
}];
|
|
173
|
-
all: [event: ChangeEvent | WatchErrorEvent];
|
|
174
|
-
create: [path: string];
|
|
175
|
-
modify: [path: string];
|
|
176
|
-
delete: [path: string];
|
|
177
|
-
}> {
|
|
178
|
-
readonly adapter: DataAdapter;
|
|
179
|
-
readonly pollingInterval: number;
|
|
180
|
-
private watchers;
|
|
181
|
-
constructor(adapter: DataAdapter, pollingInterval?: number);
|
|
182
|
-
watch(path: string | string[], options?: WatchOptions): {
|
|
183
|
-
close: () => void;
|
|
184
|
-
} | undefined;
|
|
185
|
-
unwatch(path: string): void;
|
|
186
|
-
close(): void;
|
|
187
|
-
private takeSnapshot;
|
|
188
|
-
private toEventPath;
|
|
189
|
-
private checkForChanges;
|
|
190
|
-
private diffSnapshot;
|
|
191
|
-
}
|
|
179
|
+
export { DirectoryWatcher } from "./directory-watcher";
|
|
192
180
|
export declare class FileCache {
|
|
193
181
|
private capacity;
|
|
194
182
|
private cache;
|
|
@@ -202,4 +190,3 @@ export declare class FileCache {
|
|
|
202
190
|
has(key: string): boolean;
|
|
203
191
|
keys(): string[];
|
|
204
192
|
}
|
|
205
|
-
export {};
|
package/dist/storage/fs.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { basename, joinPath, normalizePath } from "./path";
|
|
1
|
+
import { basename, normalizePath } from "./path";
|
|
3
2
|
export class TAbstractFile {
|
|
4
3
|
parent;
|
|
5
4
|
path;
|
|
@@ -76,172 +75,7 @@ export class TFolder extends TAbstractFile {
|
|
|
76
75
|
return this.parent === null;
|
|
77
76
|
}
|
|
78
77
|
}
|
|
79
|
-
|
|
80
|
-
const vaultAdapter = adapter;
|
|
81
|
-
return (typeof vaultAdapter.watch === "function" &&
|
|
82
|
-
vaultAdapter.getCapabilities?.().nativeWatch === true);
|
|
83
|
-
}
|
|
84
|
-
export class DirectoryWatcher extends EventDispatcher {
|
|
85
|
-
adapter;
|
|
86
|
-
pollingInterval;
|
|
87
|
-
watchers = new Map();
|
|
88
|
-
constructor(adapter, pollingInterval = 5000) {
|
|
89
|
-
super();
|
|
90
|
-
this.adapter = adapter;
|
|
91
|
-
this.pollingInterval = pollingInterval;
|
|
92
|
-
}
|
|
93
|
-
watch(path, options = {}) {
|
|
94
|
-
if (Array.isArray(path)) {
|
|
95
|
-
path.forEach((p) => this.watch(p));
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
path = normalizePath(path);
|
|
99
|
-
const watcherOptions = {
|
|
100
|
-
recursive: options.recursive || false,
|
|
101
|
-
interval: options.interval || this.pollingInterval,
|
|
102
|
-
lastSnapshot: null,
|
|
103
|
-
timeout: null,
|
|
104
|
-
nativeSubscription: null,
|
|
105
|
-
};
|
|
106
|
-
this.watchers.set(path, watcherOptions);
|
|
107
|
-
if (isNativeWatchAdapter(this.adapter)) {
|
|
108
|
-
watcherOptions.nativeSubscription =
|
|
109
|
-
this.adapter.watch(path, options, (event) => {
|
|
110
|
-
const normalizedEvent = event.type === "error"
|
|
111
|
-
? { ...event, path: this.toEventPath(event.path) }
|
|
112
|
-
: { ...event, path: this.toEventPath(event.path) };
|
|
113
|
-
this.dispatch("all", normalizedEvent);
|
|
114
|
-
if (normalizedEvent.type === "error") {
|
|
115
|
-
this.dispatch("error", {
|
|
116
|
-
error: normalizedEvent.error,
|
|
117
|
-
path: normalizedEvent.path,
|
|
118
|
-
});
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
this.dispatch(normalizedEvent.type, normalizedEvent.path);
|
|
122
|
-
}) ?? null;
|
|
123
|
-
return {
|
|
124
|
-
close: () => this.unwatch(path),
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
this.takeSnapshot(path, watcherOptions.recursive).then((snapshot) => {
|
|
128
|
-
watcherOptions.lastSnapshot = snapshot;
|
|
129
|
-
watcherOptions.timeout = setInterval(() => {
|
|
130
|
-
this.checkForChanges(path, watcherOptions);
|
|
131
|
-
}, watcherOptions.interval);
|
|
132
|
-
});
|
|
133
|
-
return {
|
|
134
|
-
close: () => this.unwatch(path),
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
unwatch(path) {
|
|
138
|
-
path = normalizePath(path);
|
|
139
|
-
const watcher = this.watchers.get(path);
|
|
140
|
-
if (!watcher) {
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
watcher.nativeSubscription?.close();
|
|
144
|
-
if (watcher.timeout) {
|
|
145
|
-
clearInterval(watcher.timeout);
|
|
146
|
-
}
|
|
147
|
-
this.watchers.delete(path);
|
|
148
|
-
}
|
|
149
|
-
close() {
|
|
150
|
-
for (const path of this.watchers.keys()) {
|
|
151
|
-
this.unwatch(path);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
async takeSnapshot(path, recursive) {
|
|
155
|
-
path = normalizePath(path);
|
|
156
|
-
const snapshot = new Map();
|
|
157
|
-
try {
|
|
158
|
-
const stats = await this.adapter.stat(path);
|
|
159
|
-
if (!stats)
|
|
160
|
-
return snapshot;
|
|
161
|
-
snapshot.set(this.toEventPath(path), stats);
|
|
162
|
-
if (stats.type === "folder") {
|
|
163
|
-
const { files, folders } = await this.adapter.list(path);
|
|
164
|
-
for (const file of files) {
|
|
165
|
-
const entryPath = joinPath(path, file);
|
|
166
|
-
const entryStats = await this.adapter.stat(entryPath);
|
|
167
|
-
if (!entryStats)
|
|
168
|
-
continue;
|
|
169
|
-
snapshot.set(this.toEventPath(entryPath), entryStats);
|
|
170
|
-
}
|
|
171
|
-
if (!recursive)
|
|
172
|
-
return snapshot;
|
|
173
|
-
for (const folder of folders) {
|
|
174
|
-
const entryPath = joinPath(path, folder);
|
|
175
|
-
const subSnapshot = await this.takeSnapshot(entryPath, recursive);
|
|
176
|
-
for (const [subPath, subStats] of subSnapshot.entries()) {
|
|
177
|
-
snapshot.set(subPath, subStats);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
catch (error) {
|
|
183
|
-
console.error("fs:watch", error);
|
|
184
|
-
this.trigger("error", { error, path });
|
|
185
|
-
this.trigger("all", { type: "error", path, error });
|
|
186
|
-
}
|
|
187
|
-
return snapshot;
|
|
188
|
-
}
|
|
189
|
-
toEventPath(path) {
|
|
190
|
-
path = normalizePath(path);
|
|
191
|
-
return path === "/" ? "/" : path.replace(/^\/+/, "");
|
|
192
|
-
}
|
|
193
|
-
async checkForChanges(path, watcherOptions) {
|
|
194
|
-
path = normalizePath(path);
|
|
195
|
-
try {
|
|
196
|
-
const newSnapshot = await this.takeSnapshot(path, watcherOptions.recursive);
|
|
197
|
-
if (watcherOptions.lastSnapshot) {
|
|
198
|
-
const changes = this.diffSnapshot(watcherOptions.lastSnapshot, newSnapshot);
|
|
199
|
-
for (const change of changes) {
|
|
200
|
-
this.dispatch(change.type, change.path);
|
|
201
|
-
this.dispatch("all", change);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
watcherOptions.lastSnapshot = newSnapshot;
|
|
205
|
-
}
|
|
206
|
-
catch (err) {
|
|
207
|
-
const error = err;
|
|
208
|
-
if (error.code === "ENOENT") {
|
|
209
|
-
this.dispatch("delete", path);
|
|
210
|
-
this.dispatch("all", { type: "delete", path });
|
|
211
|
-
if (this.watchers.has(path)) {
|
|
212
|
-
this.unwatch(path);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
console.error("fs:watch", error);
|
|
217
|
-
this.dispatch("error", { error, path });
|
|
218
|
-
this.trigger("all", { type: "error", path, error });
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
diffSnapshot(oldSnapshot, newSnapshot) {
|
|
223
|
-
const changes = [];
|
|
224
|
-
for (const [path, stats] of newSnapshot) {
|
|
225
|
-
if (!oldSnapshot.has(path)) {
|
|
226
|
-
changes.push({ type: "create", path });
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
const oldStats = oldSnapshot.get(path);
|
|
230
|
-
if (oldStats.mtime !== stats.mtime ||
|
|
231
|
-
oldStats.size !== stats.size ||
|
|
232
|
-
oldStats.type !== stats.type) {
|
|
233
|
-
changes.push({ type: "modify", path });
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
for (const path of oldSnapshot.keys()) {
|
|
238
|
-
if (!newSnapshot.has(path)) {
|
|
239
|
-
changes.push({ type: "delete", path });
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
return changes;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
78
|
+
export { DirectoryWatcher } from "./directory-watcher";
|
|
245
79
|
export class FileCache {
|
|
246
80
|
capacity;
|
|
247
81
|
cache;
|
|
@@ -83,7 +83,9 @@ export function fieldValue(data, field) {
|
|
|
83
83
|
function scalarOf(value) {
|
|
84
84
|
if (value === undefined)
|
|
85
85
|
return undefined;
|
|
86
|
-
if (value === null ||
|
|
86
|
+
if (value === null ||
|
|
87
|
+
typeof value === "string" ||
|
|
88
|
+
typeof value === "number") {
|
|
87
89
|
return value;
|
|
88
90
|
}
|
|
89
91
|
if (typeof value === "boolean")
|
|
@@ -161,20 +163,22 @@ function afterCursor(sortValues, rowId, after, orderBy) {
|
|
|
161
163
|
for (let index = 0; index < length; index += 1) {
|
|
162
164
|
const spec = orderBy[index] ?? { field: "id", direction: "asc" };
|
|
163
165
|
const direction = spec.direction === "desc" ? -1 : 1;
|
|
164
|
-
const
|
|
166
|
+
const left = sortValues[index] ?? null;
|
|
167
|
+
const right = cursor.values[index] ?? null;
|
|
168
|
+
const comparison = compareScalars(left, right);
|
|
165
169
|
if (comparison === 0)
|
|
166
170
|
continue;
|
|
171
|
+
if (spec.nulls && (left == null || right == null)) {
|
|
172
|
+
return left == null ? spec.nulls === "last" : spec.nulls === "first";
|
|
173
|
+
}
|
|
167
174
|
return comparison * direction > 0;
|
|
168
175
|
}
|
|
169
|
-
return rowId >
|
|
176
|
+
return rowId.localeCompare(cursor.rowId) > 0;
|
|
170
177
|
}
|
|
171
178
|
export function selectProjectionRow(data, select) {
|
|
172
179
|
if (!select?.length)
|
|
173
180
|
return data;
|
|
174
|
-
|
|
175
|
-
for (const field of select)
|
|
176
|
-
picked[field] = data[field];
|
|
177
|
-
return picked;
|
|
181
|
+
return Object.fromEntries(select.map((field) => [field, fieldValue(data, field)]));
|
|
178
182
|
}
|
|
179
183
|
export function evaluateProjectionQuery(rows, query, revision, indexStatus) {
|
|
180
184
|
const orderBy = query.orderBy ?? [];
|
|
@@ -186,7 +190,8 @@ export function evaluateProjectionQuery(rows, query, revision, indexStatus) {
|
|
|
186
190
|
if (comparison !== 0) {
|
|
187
191
|
if (spec.nulls === "first" && fieldValue(left.data, spec.field) == null)
|
|
188
192
|
return -1;
|
|
189
|
-
if (spec.nulls === "first" &&
|
|
193
|
+
if (spec.nulls === "first" &&
|
|
194
|
+
fieldValue(right.data, spec.field) == null)
|
|
190
195
|
return 1;
|
|
191
196
|
if (spec.nulls === "last" && fieldValue(left.data, spec.field) == null)
|
|
192
197
|
return 1;
|
|
@@ -253,7 +258,11 @@ export function indexedValuesForRow(projectionId, row, fields) {
|
|
|
253
258
|
return values;
|
|
254
259
|
}
|
|
255
260
|
export function compileProjectionQuerySql(projectionId, query, definition) {
|
|
256
|
-
const args = [
|
|
261
|
+
const args = [
|
|
262
|
+
projectionId,
|
|
263
|
+
definition.schemaVersion,
|
|
264
|
+
definition.configHash,
|
|
265
|
+
];
|
|
257
266
|
const where = query.includeStale
|
|
258
267
|
? "r.projection_id = ? AND s.schema_version = ? AND s.config_hash = ?"
|
|
259
268
|
: `r.projection_id = ?
|
|
@@ -280,14 +289,18 @@ export function compileProjectionQuerySql(projectionId, query, definition) {
|
|
|
280
289
|
};
|
|
281
290
|
}
|
|
282
291
|
function jsonExtract(field) {
|
|
283
|
-
return `json_extract(r.data_json, '$.${field.replaceAll("'", "''")}')`;
|
|
292
|
+
return `json_extract(r.data_json, '$.${JSON.stringify(field).replaceAll("'", "''")}')`;
|
|
284
293
|
}
|
|
285
294
|
function compileFilterSql(filter, args) {
|
|
286
295
|
switch (filter.op) {
|
|
287
296
|
case "and":
|
|
288
|
-
return filter.operands
|
|
297
|
+
return (filter.operands
|
|
298
|
+
.map((operand) => `(${compileFilterSql(operand, args)})`)
|
|
299
|
+
.join(" AND ") || "1");
|
|
289
300
|
case "or":
|
|
290
|
-
return filter.operands
|
|
301
|
+
return (filter.operands
|
|
302
|
+
.map((operand) => `(${compileFilterSql(operand, args)})`)
|
|
303
|
+
.join(" OR ") || "0");
|
|
291
304
|
case "not":
|
|
292
305
|
return `NOT (${compileFilterSql(filter.operand, args)})`;
|
|
293
306
|
case "exists":
|
|
@@ -297,9 +310,14 @@ function compileFilterSql(filter, args) {
|
|
|
297
310
|
case "in": {
|
|
298
311
|
if (filter.values.length === 0)
|
|
299
312
|
return "0";
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
313
|
+
const values = filter.values.filter((value) => value != null);
|
|
314
|
+
const placeholders = values.map(() => "?").join(", ");
|
|
315
|
+
args.push(...values);
|
|
316
|
+
const expr = jsonExtract(filter.field);
|
|
317
|
+
const member = values.length ? `${expr} IN (${placeholders})` : "0";
|
|
318
|
+
return values.length !== filter.values.length
|
|
319
|
+
? `(${expr} IS NULL OR ${member})`
|
|
320
|
+
: member;
|
|
303
321
|
}
|
|
304
322
|
case "compare": {
|
|
305
323
|
const expr = jsonExtract(filter.field);
|
|
@@ -27,6 +27,8 @@ export declare class MemoryVaultAdapter implements VaultAdapter, VaultIdentityAd
|
|
|
27
27
|
openRead(path: string): Promise<VaultReadHandle>;
|
|
28
28
|
atomicWrite(path: string, source: ReadableStream<Uint8Array>, options?: AtomicDataWriteOptions): Promise<void>;
|
|
29
29
|
write(path: string, data: string, options?: DataWriteOptions): Promise<void>;
|
|
30
|
+
/** Compare and mutate synchronously before yielding to another memory writer. */
|
|
31
|
+
writeTextIfUnchanged(path: string, data: string, expected: string | null, options?: DataWriteOptions): Promise<void>;
|
|
30
32
|
writeBinary(path: string, data: ArrayBuffer, options?: DataWriteOptions): Promise<void>;
|
|
31
33
|
append(path: string, data: string, options?: DataWriteOptions): Promise<void>;
|
|
32
34
|
appendBinary(path: string, data: ArrayBuffer, options?: DataWriteOptions): Promise<void>;
|
|
@@ -67,6 +67,7 @@ export class MemoryVaultAdapter {
|
|
|
67
67
|
nativeWatch: false,
|
|
68
68
|
resourceUrls: false,
|
|
69
69
|
systemTrash: false,
|
|
70
|
+
conditionalTextWrite: true,
|
|
70
71
|
};
|
|
71
72
|
}
|
|
72
73
|
async exists(path) {
|
|
@@ -134,7 +135,7 @@ export class MemoryVaultAdapter {
|
|
|
134
135
|
try {
|
|
135
136
|
while (true) {
|
|
136
137
|
if (options.signal?.aborted) {
|
|
137
|
-
throw options.signal.reason ?? new DOMException("Aborted", "AbortError");
|
|
138
|
+
throw (options.signal.reason ?? new DOMException("Aborted", "AbortError"));
|
|
138
139
|
}
|
|
139
140
|
const next = await reader.read();
|
|
140
141
|
if (next.done)
|
|
@@ -157,6 +158,18 @@ export class MemoryVaultAdapter {
|
|
|
157
158
|
async write(path, data, options) {
|
|
158
159
|
await this.#writeValue(path, data, options);
|
|
159
160
|
}
|
|
161
|
+
/** Compare and mutate synchronously before yielding to another memory writer. */
|
|
162
|
+
async writeTextIfUnchanged(path, data, expected, options) {
|
|
163
|
+
if (expected !== null && typeof expected !== "string")
|
|
164
|
+
throw fsError("EINVAL", path);
|
|
165
|
+
const normalized = this.#path(path);
|
|
166
|
+
const stored = this.#files.get(normalized);
|
|
167
|
+
if (stored
|
|
168
|
+
? typeof stored.data !== "string" || stored.data !== expected
|
|
169
|
+
: expected !== null)
|
|
170
|
+
throw fsError("ECONFLICT", normalized);
|
|
171
|
+
return this.#writeValue(normalized, data, options);
|
|
172
|
+
}
|
|
160
173
|
async writeBinary(path, data, options) {
|
|
161
174
|
await this.#writeValue(path, data, options);
|
|
162
175
|
}
|
package/dist/storage/path.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/** Shared vault-local state default for every Lapis application host. */
|
|
2
|
+
export declare const DEFAULT_APP_STATE_DIRECTORY = ".lapis";
|
|
3
|
+
/** Resolve an application-owned path beneath the shared state directory. */
|
|
4
|
+
export declare function appStatePath(...parts: string[]): string;
|
|
1
5
|
/**
|
|
2
6
|
* Normalize a vault-style path by removing redundant segments and separators.
|
|
3
7
|
*
|
|
@@ -12,8 +16,8 @@ export declare function basename(path: string): string;
|
|
|
12
16
|
/**
|
|
13
17
|
* Returns whether a vault path belongs to Lapis' portable internal data.
|
|
14
18
|
*
|
|
15
|
-
* Internal data can occur beneath any folder-scoped feature root. Callers
|
|
16
|
-
*
|
|
19
|
+
* Internal data can occur beneath any folder-scoped feature root. Callers that
|
|
20
|
+
* present ordinary vault content should hide these paths, while explicit
|
|
17
21
|
* storage and indexing operations remain free to address them directly.
|
|
18
22
|
*
|
|
19
23
|
* @public
|
package/dist/storage/path.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/** Shared vault-local state default for every Lapis application host. */
|
|
2
|
+
export const DEFAULT_APP_STATE_DIRECTORY = ".lapis";
|
|
3
|
+
/** Resolve an application-owned path beneath the shared state directory. */
|
|
4
|
+
export function appStatePath(...parts) {
|
|
5
|
+
return joinPath(DEFAULT_APP_STATE_DIRECTORY, ...parts);
|
|
6
|
+
}
|
|
1
7
|
/**
|
|
2
8
|
* Normalize a vault-style path by removing redundant segments and separators.
|
|
3
9
|
*
|
|
@@ -66,8 +72,8 @@ export function basename(path) {
|
|
|
66
72
|
/**
|
|
67
73
|
* Returns whether a vault path belongs to Lapis' portable internal data.
|
|
68
74
|
*
|
|
69
|
-
* Internal data can occur beneath any folder-scoped feature root. Callers
|
|
70
|
-
*
|
|
75
|
+
* Internal data can occur beneath any folder-scoped feature root. Callers that
|
|
76
|
+
* present ordinary vault content should hide these paths, while explicit
|
|
71
77
|
* storage and indexing operations remain free to address them directly.
|
|
72
78
|
*
|
|
73
79
|
* @public
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** SQL narrows only what its scalar semantics can prove; the AST remains final. */
|
|
2
|
+
export function projectionQueryCandidates(query) {
|
|
3
|
+
return {
|
|
4
|
+
where: query.where ? candidate(query.where).filter : undefined,
|
|
5
|
+
includeStale: query.includeStale,
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
function candidate(filter) {
|
|
9
|
+
switch (filter.op) {
|
|
10
|
+
case "and":
|
|
11
|
+
case "or": {
|
|
12
|
+
const branches = filter.operands.map(candidate);
|
|
13
|
+
const exact = branches.every((branch) => branch.exact);
|
|
14
|
+
if (filter.op === "or" && branches.some((branch) => !branch.filter)) {
|
|
15
|
+
return { exact };
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
filter: {
|
|
19
|
+
op: filter.op,
|
|
20
|
+
operands: branches.flatMap((branch) => branch.filter ? [branch.filter] : []),
|
|
21
|
+
},
|
|
22
|
+
exact,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
case "not": {
|
|
26
|
+
const child = candidate(filter.operand);
|
|
27
|
+
return child.exact
|
|
28
|
+
? {
|
|
29
|
+
filter: {
|
|
30
|
+
op: "not",
|
|
31
|
+
operand: child.filter ?? { op: "and", operands: [] },
|
|
32
|
+
},
|
|
33
|
+
exact: true,
|
|
34
|
+
}
|
|
35
|
+
: { exact: false };
|
|
36
|
+
}
|
|
37
|
+
case "exists":
|
|
38
|
+
case "not-exists":
|
|
39
|
+
return { filter, exact: true };
|
|
40
|
+
case "in": {
|
|
41
|
+
if (!filter.values.length)
|
|
42
|
+
return { filter: { op: "or", operands: [] }, exact: true };
|
|
43
|
+
if (filter.values.every((value) => value == null)) {
|
|
44
|
+
return {
|
|
45
|
+
filter: { op: "not-exists", field: filter.field },
|
|
46
|
+
exact: true,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return filter.values.some((value) => value == null)
|
|
50
|
+
? { exact: false }
|
|
51
|
+
: { filter: { op: "exists", field: filter.field }, exact: false };
|
|
52
|
+
}
|
|
53
|
+
case "compare": {
|
|
54
|
+
if (filter.value == null) {
|
|
55
|
+
if (filter.comparison === "eq" || filter.comparison === "ne")
|
|
56
|
+
return { filter, exact: true };
|
|
57
|
+
return {
|
|
58
|
+
filter: filter.comparison === "lt" || filter.comparison === "lte"
|
|
59
|
+
? { op: "exists", field: filter.field }
|
|
60
|
+
: { op: "or", operands: [] },
|
|
61
|
+
exact: true,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return filter.comparison === "ne"
|
|
65
|
+
? { exact: false }
|
|
66
|
+
: { filter: { op: "exists", field: filter.field }, exact: false };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
1
|
+
import { z } from "zod/v3";
|
|
2
2
|
import type { AppDatabase } from "./app-database";
|
|
3
3
|
export declare const REMOTE_APP_DATABASE_MAX_ARGUMENTS = 4;
|
|
4
4
|
export declare const REMOTE_APP_DATABASE_MAX_MESSAGE_BYTES: number;
|
|
5
5
|
export declare const REMOTE_APP_DATABASE_METHODS: readonly ["migrate", "beginSearchIndexingBatch", "endSearchIndexingBatch", "configureSearchEmbeddingProvider", "getSearchEmbeddingProvider", "getSearchEmbeddingRuntimeStatus", "getSearchIndexStats", "getMeta", "setMeta", "scanMeta", "transactMeta", "getNotebookState", "setNotebookState", "deleteNotebookState", "loadMetadataSnapshot", "saveMetadataSnapshot", "getFileHistory", "storeFileHistoryRevision", "listNotifications", "upsertNotification", "markNotificationRead", "clearNotification", "clearAllNotifications", "getMemorySourceState", "listMemorySourceStates", "upsertMemorySourceState", "deleteMemorySourceState", "upsertMemoryCandidate", "queryMemoryCandidates", "deleteMemoryCandidatesByConversation", "recordMemoryRecallSignal", "listMemoryRecallSignals", "claimMemoryJob", "updateMemoryJob", "listMemoryJobs", "clearMemoryDerivedState", "getChangeRevision", "upsertIndexedFile", "getIndexedFile", "listIndexedFileManifest", "queryIndexedMetadata", "queryIndexedMetadataPage", "queryMetadataFacets", "queryMetadataLinks", "deleteIndexedFile", "renameIndexedFile", "upsertSearchDocument", "deleteSearchDocument", "getSearchDocument", "listSearchDocumentManifest", "listSearchDocuments", "rebuildSearchIndex", "searchDocuments", "searchDocumentPaths", "upsertTaskProjection", "deleteTaskProjection", "queryTasks", "getTaskRow", "listChildLinks", "listTaskDescendants", "registerProjectionDefinition", "unregisterProjectionDefinition", "replaceProjectionSource", "markProjectionSourceError", "deleteProjectionSource", "queryProjection", "getProjectionRow", "queryRelated"];
|
|
6
6
|
export type RemoteAppDatabaseMethod = (typeof REMOTE_APP_DATABASE_METHODS)[number];
|
|
7
|
-
export type RemoteAppDatabaseArgs<Method extends RemoteAppDatabaseMethod> = AppDatabase[Method] extends (...args: infer Args) => unknown ? Args : never;
|
|
7
|
+
export type RemoteAppDatabaseArgs<Method extends RemoteAppDatabaseMethod> = Method extends RemoteAppDatabaseMethod ? AppDatabase[Method] extends (...args: infer Args) => unknown ? Args : never : never;
|
|
8
8
|
export type RemoteAppDatabaseResult<Method extends RemoteAppDatabaseMethod> = AppDatabase[Method] extends (...args: never[]) => infer Result ? Awaited<Result> : never;
|
|
9
9
|
export type RemoteAppDatabaseDomain = "lifecycle" | "metadata" | "search" | "history" | "notifications" | "memory" | "tasks" | "projections";
|
|
10
10
|
export interface RemoteAppDatabaseContractEntry<Method extends RemoteAppDatabaseMethod> {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** Application host identity, independent of optional database/model services. */
|
|
2
|
+
export type RuntimeTarget = "web-pwa" | "deno-desktop" | "tauri-desktop" | "node-server" | "rust-server" | "deno-server" | "test";
|
|
3
|
+
export declare function isNativeDesktopRuntime(runtime?: RuntimeTarget | null): runtime is "deno-desktop" | "tauri-desktop";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { SearchDocumentRecord } from "./app-database";
|
|
2
|
+
import type { SearchEmbeddingProviderConfig } from "./search-embedding-provider";
|
|
3
|
+
export declare function rebindSearchDocument(document: SearchDocumentRecord, config: SearchEmbeddingProviderConfig | null): SearchDocumentRecord;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function rebindSearchDocument(document, config) {
|
|
2
|
+
const copy = JSON.parse(JSON.stringify(document));
|
|
3
|
+
if (!config || !copy.chunks?.length)
|
|
4
|
+
return copy;
|
|
5
|
+
copy.chunks = copy.chunks.map((chunk) => chunk.text.trim().length
|
|
6
|
+
? {
|
|
7
|
+
...chunk,
|
|
8
|
+
embedding: {
|
|
9
|
+
status: "pending",
|
|
10
|
+
modelId: config.modelId ?? "lapis/token-hash-v0",
|
|
11
|
+
modelVersion: config.modelVersion,
|
|
12
|
+
dimensions: config.dimensions,
|
|
13
|
+
dirty: true,
|
|
14
|
+
},
|
|
15
|
+
}
|
|
16
|
+
: chunk);
|
|
17
|
+
return copy;
|
|
18
|
+
}
|
|
@@ -32,6 +32,7 @@ export declare class TursoAppDatabase implements AppDatabase {
|
|
|
32
32
|
readonly kind: Extract<AppDatabaseKind, "turso-native" | "turso-wasm">;
|
|
33
33
|
private connection;
|
|
34
34
|
private opened;
|
|
35
|
+
private closeTask;
|
|
35
36
|
private nativeFullTextSearch;
|
|
36
37
|
private nativeVectorSearch;
|
|
37
38
|
private searchEmbeddingProviderConfig;
|
|
@@ -47,6 +48,7 @@ export declare class TursoAppDatabase implements AppDatabase {
|
|
|
47
48
|
beginSearchIndexingBatch(): Promise<void>;
|
|
48
49
|
endSearchIndexingBatch(): Promise<void>;
|
|
49
50
|
configureSearchEmbeddingProvider(provider: SearchEmbeddingProviderConfig | null): Promise<void>;
|
|
51
|
+
private configureSearchProviderImmediately;
|
|
50
52
|
getSearchEmbeddingProvider(): Promise<SearchEmbeddingProviderConfig | null>;
|
|
51
53
|
getSearchEmbeddingRuntimeStatus(): Promise<SearchEmbeddingRuntimeStatus | null>;
|
|
52
54
|
getSearchIndexStats(): Promise<AppDatabaseSearchIndexStats>;
|