@anokye-labs/kbexplorer-engine 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 +77 -0
- package/dist/build-manifest-BT0sY84J.d.ts +239 -0
- package/dist/build-manifest-BkgZUL0E.d.cts +239 -0
- package/dist/chunk-ASLGNOYV.js +220 -0
- package/dist/chunk-BA526FDQ.js +16 -0
- package/dist/chunk-DJ2DBEEK.js +424 -0
- package/dist/chunk-FJ4GTN4U.js +973 -0
- package/dist/chunk-HXAS3BSD.js +187 -0
- package/dist/chunk-IWEURXYH.js +273 -0
- package/dist/chunk-JNQVSNLC.js +55 -0
- package/dist/chunk-MW4BLXVK.js +72 -0
- package/dist/chunk-NOGBKE7C.js +351 -0
- package/dist/chunk-XVI6CBSX.js +412 -0
- package/dist/chunk-YTMIERYM.js +67 -0
- package/dist/github-api-source-KV5HZARH.js +4 -0
- package/dist/index.cjs +6218 -0
- package/dist/index.d.cts +1396 -0
- package/dist/index.d.ts +1396 -0
- package/dist/index.js +2892 -0
- package/dist/node-wasm-VSXBOCPD.js +9 -0
- package/dist/plugin-loader-K4VU6ODV.js +2 -0
- package/dist/repo-data-0JvFdLGv.d.cts +461 -0
- package/dist/repo-data-0JvFdLGv.d.ts +461 -0
- package/dist/sources.cjs +1191 -0
- package/dist/sources.d.cts +194 -0
- package/dist/sources.d.ts +194 -0
- package/dist/sources.js +357 -0
- package/dist/sqlite-graph-store-NH2NHL2B.js +2 -0
- package/dist/sqlite-runtime-CysPjjzX.d.cts +96 -0
- package/dist/sqlite-runtime-CysPjjzX.d.ts +96 -0
- package/dist/store-orchestrator-337XWIXO.js +5 -0
- package/dist/store.cjs +1112 -0
- package/dist/store.d.cts +37 -0
- package/dist/store.d.ts +37 -0
- package/dist/store.js +7 -0
- package/package.json +70 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { GRAPH_STORE_API_VERSION, GRAPH_STORE_CACHE_KEY_VERSION } from '@anokye-labs/kbexplorer-core';
|
|
2
|
+
|
|
3
|
+
// src/store/fingerprint.ts
|
|
4
|
+
var GRAPH_STORE_DERIVATION_VERSION = "template-graph-derivation-v3";
|
|
5
|
+
var GRAPH_STORE_PROVIDER_ID = "provider-pipeline";
|
|
6
|
+
function buildProviderResultCacheKey(source, config, data, providerId = GRAPH_STORE_PROVIDER_ID, previousContentHash) {
|
|
7
|
+
return contentHashFor({
|
|
8
|
+
apiVersion: GRAPH_STORE_API_VERSION,
|
|
9
|
+
cacheKeyVersion: GRAPH_STORE_CACHE_KEY_VERSION,
|
|
10
|
+
derivationVersion: GRAPH_STORE_DERIVATION_VERSION,
|
|
11
|
+
sourceId: source.id,
|
|
12
|
+
providerId,
|
|
13
|
+
previousContentHash,
|
|
14
|
+
config,
|
|
15
|
+
data: stableProviderData(data, providerId)
|
|
16
|
+
}).then((contentHash) => ({
|
|
17
|
+
scope: "provider-result",
|
|
18
|
+
providerId,
|
|
19
|
+
sourceId: sourceIdFor(source, config),
|
|
20
|
+
contentHash,
|
|
21
|
+
variant: [
|
|
22
|
+
GRAPH_STORE_API_VERSION,
|
|
23
|
+
GRAPH_STORE_CACHE_KEY_VERSION,
|
|
24
|
+
GRAPH_STORE_DERIVATION_VERSION
|
|
25
|
+
].join(":")
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
function hashProviderResultPrefix(providerId, nodes) {
|
|
29
|
+
return contentHashFor({
|
|
30
|
+
apiVersion: GRAPH_STORE_API_VERSION,
|
|
31
|
+
cacheKeyVersion: GRAPH_STORE_CACHE_KEY_VERSION,
|
|
32
|
+
derivationVersion: GRAPH_STORE_DERIVATION_VERSION,
|
|
33
|
+
providerId,
|
|
34
|
+
nodes
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function sourceIdFor(source, config) {
|
|
38
|
+
const sourceConfig = config.source;
|
|
39
|
+
return [
|
|
40
|
+
source.id,
|
|
41
|
+
sourceConfig.owner,
|
|
42
|
+
sourceConfig.repo,
|
|
43
|
+
sourceConfig.branch ?? "main",
|
|
44
|
+
sourceConfig.path ?? ""
|
|
45
|
+
].join(":");
|
|
46
|
+
}
|
|
47
|
+
async function contentHashFor(value) {
|
|
48
|
+
const crypto = globalThis.crypto?.subtle;
|
|
49
|
+
if (!crypto) {
|
|
50
|
+
throw new Error("Graph store hashing requires Web Crypto SubtleCrypto support.");
|
|
51
|
+
}
|
|
52
|
+
const bytes = new TextEncoder().encode(stableStringify(value));
|
|
53
|
+
const digest = await crypto.digest("SHA-256", bytes);
|
|
54
|
+
return {
|
|
55
|
+
algorithm: "sha256",
|
|
56
|
+
digest: bytesToHex(new Uint8Array(digest)),
|
|
57
|
+
encoding: "hex"
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function bytesToHex(bytes) {
|
|
61
|
+
return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
62
|
+
}
|
|
63
|
+
function stableRepoData(data) {
|
|
64
|
+
return {
|
|
65
|
+
repo: data.repo,
|
|
66
|
+
tree: data.tree.map((item) => ({
|
|
67
|
+
path: item.path,
|
|
68
|
+
mode: item.mode,
|
|
69
|
+
type: item.type,
|
|
70
|
+
sha: item.sha,
|
|
71
|
+
size: item.size
|
|
72
|
+
})),
|
|
73
|
+
authoredContent: data.authoredContent,
|
|
74
|
+
nodemapRaw: data.nodemapRaw,
|
|
75
|
+
nodemapFiles: data.nodemapFiles,
|
|
76
|
+
nodemapDirs: data.nodemapDirs,
|
|
77
|
+
issues: data.issues.map((issue) => ({
|
|
78
|
+
number: issue.number,
|
|
79
|
+
title: issue.title,
|
|
80
|
+
body: issue.body,
|
|
81
|
+
state: issue.state,
|
|
82
|
+
labels: issue.labels,
|
|
83
|
+
assignees: issue.assignees,
|
|
84
|
+
user: issue.user,
|
|
85
|
+
html_url: issue.html_url,
|
|
86
|
+
created_at: issue.created_at,
|
|
87
|
+
updated_at: issue.updated_at
|
|
88
|
+
})),
|
|
89
|
+
pullRequests: data.pullRequests,
|
|
90
|
+
commits: data.commits,
|
|
91
|
+
branches: data.branches,
|
|
92
|
+
repoMetadata: data.repoMetadata,
|
|
93
|
+
releases: data.releases,
|
|
94
|
+
structuralFiles: data.structuralFiles,
|
|
95
|
+
structuredNodeMapRaw: data.structuredNodeMapRaw,
|
|
96
|
+
contentModel: data.contentModel,
|
|
97
|
+
readme: data.readme
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function stableProviderData(data, providerId) {
|
|
101
|
+
switch (providerId) {
|
|
102
|
+
case "files":
|
|
103
|
+
return {
|
|
104
|
+
repo: data.repo,
|
|
105
|
+
tree: data.tree.map((item) => ({
|
|
106
|
+
path: item.path,
|
|
107
|
+
mode: item.mode,
|
|
108
|
+
type: item.type,
|
|
109
|
+
sha: item.sha,
|
|
110
|
+
size: item.size
|
|
111
|
+
}))
|
|
112
|
+
};
|
|
113
|
+
case "authored":
|
|
114
|
+
return {
|
|
115
|
+
authoredContent: data.authoredContent,
|
|
116
|
+
nodemapRaw: data.nodemapRaw,
|
|
117
|
+
nodemapFiles: data.nodemapFiles,
|
|
118
|
+
nodemapDirs: data.nodemapDirs
|
|
119
|
+
};
|
|
120
|
+
case "work":
|
|
121
|
+
return {
|
|
122
|
+
issues: data.issues.map((issue) => ({
|
|
123
|
+
number: issue.number,
|
|
124
|
+
title: issue.title,
|
|
125
|
+
body: issue.body,
|
|
126
|
+
state: issue.state,
|
|
127
|
+
labels: issue.labels,
|
|
128
|
+
assignees: issue.assignees,
|
|
129
|
+
user: issue.user,
|
|
130
|
+
html_url: issue.html_url,
|
|
131
|
+
created_at: issue.created_at,
|
|
132
|
+
updated_at: issue.updated_at
|
|
133
|
+
})),
|
|
134
|
+
pullRequests: data.pullRequests,
|
|
135
|
+
commits: data.commits,
|
|
136
|
+
branches: data.branches,
|
|
137
|
+
repoMetadata: data.repoMetadata,
|
|
138
|
+
releases: data.releases
|
|
139
|
+
};
|
|
140
|
+
case "content-model":
|
|
141
|
+
return {
|
|
142
|
+
contentModel: data.contentModel
|
|
143
|
+
};
|
|
144
|
+
case "person":
|
|
145
|
+
return {
|
|
146
|
+
issues: data.issues.map((issue) => ({
|
|
147
|
+
number: issue.number,
|
|
148
|
+
title: issue.title,
|
|
149
|
+
state: issue.state,
|
|
150
|
+
assignees: issue.assignees,
|
|
151
|
+
user: issue.user
|
|
152
|
+
})),
|
|
153
|
+
pullRequests: data.pullRequests.map((pr) => ({
|
|
154
|
+
number: pr.number,
|
|
155
|
+
title: pr.title,
|
|
156
|
+
state: pr.state,
|
|
157
|
+
html_url: pr.html_url,
|
|
158
|
+
user: pr.user,
|
|
159
|
+
assignees: pr.assignees
|
|
160
|
+
}))
|
|
161
|
+
};
|
|
162
|
+
case "structural":
|
|
163
|
+
return {
|
|
164
|
+
structuralFiles: data.structuralFiles,
|
|
165
|
+
structuredNodeMapRaw: data.structuredNodeMapRaw
|
|
166
|
+
};
|
|
167
|
+
default:
|
|
168
|
+
return stableRepoData(data);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function stableStringify(value) {
|
|
172
|
+
return JSON.stringify(normalizeForJson(value));
|
|
173
|
+
}
|
|
174
|
+
function normalizeForJson(value) {
|
|
175
|
+
if (Array.isArray(value)) return value.map(normalizeForJson);
|
|
176
|
+
if (!value || typeof value !== "object") return value;
|
|
177
|
+
const out = {};
|
|
178
|
+
for (const key of Object.keys(value).sort()) {
|
|
179
|
+
const item = value[key];
|
|
180
|
+
if (typeof item !== "function" && item !== void 0) {
|
|
181
|
+
out[key] = normalizeForJson(item);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return out;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export { GRAPH_STORE_DERIVATION_VERSION, GRAPH_STORE_PROVIDER_ID, buildProviderResultCacheKey, hashProviderResultPrefix };
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { GRAPH_STORE_DERIVATION_VERSION } from './chunk-HXAS3BSD.js';
|
|
2
|
+
import { formatGraphStoreCacheKey, formatContentHash, GRAPH_STORE_API_VERSION, GRAPH_STORE_CACHE_KEY_VERSION } from '@anokye-labs/kbexplorer-core';
|
|
3
|
+
import initSqlJs from 'sql.js';
|
|
4
|
+
|
|
5
|
+
var DB_NAME = "kbexplorer-graph-store";
|
|
6
|
+
var STORE_NAME = "sqlite";
|
|
7
|
+
var DB_KEY = "graph-store.sqlite";
|
|
8
|
+
var sqlModuleCache = /* @__PURE__ */ new Map();
|
|
9
|
+
async function loadSqlJs(locateFile) {
|
|
10
|
+
const cacheKey = locateFile ?? "default";
|
|
11
|
+
const cached = sqlModuleCache.get(cacheKey);
|
|
12
|
+
if (cached) return cached;
|
|
13
|
+
const promise = (async () => {
|
|
14
|
+
if (locateFile) {
|
|
15
|
+
return initSqlJs({ locateFile });
|
|
16
|
+
}
|
|
17
|
+
if (typeof process !== "undefined" && process.versions?.node) {
|
|
18
|
+
const { nodeLocateFile } = await import('./node-wasm-VSXBOCPD.js');
|
|
19
|
+
return initSqlJs({ locateFile: nodeLocateFile() });
|
|
20
|
+
}
|
|
21
|
+
return initSqlJs();
|
|
22
|
+
})();
|
|
23
|
+
sqlModuleCache.set(cacheKey, promise);
|
|
24
|
+
return promise;
|
|
25
|
+
}
|
|
26
|
+
async function openPersistedDatabase(byteStore = new IndexedDbSqliteByteStore(), locateFile) {
|
|
27
|
+
const SQL = await loadSqlJs(locateFile);
|
|
28
|
+
const bytes = await byteStore.load();
|
|
29
|
+
const db = bytes ? new SQL.Database(bytes) : new SQL.Database();
|
|
30
|
+
return {
|
|
31
|
+
db,
|
|
32
|
+
persist: async () => {
|
|
33
|
+
await byteStore.save(db.export());
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
var MemorySqliteByteStore = class {
|
|
38
|
+
bytes;
|
|
39
|
+
async load() {
|
|
40
|
+
return this.bytes ? new Uint8Array(this.bytes) : void 0;
|
|
41
|
+
}
|
|
42
|
+
async save(bytes) {
|
|
43
|
+
this.bytes = new Uint8Array(bytes);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var IndexedDbSqliteByteStore = class {
|
|
47
|
+
async load() {
|
|
48
|
+
const db = await openIndexedDb();
|
|
49
|
+
return requestToPromise(
|
|
50
|
+
db.transaction(STORE_NAME, "readonly").objectStore(STORE_NAME).get(DB_KEY)
|
|
51
|
+
).finally(() => db.close());
|
|
52
|
+
}
|
|
53
|
+
async save(bytes) {
|
|
54
|
+
const db = await openIndexedDb();
|
|
55
|
+
await requestToPromise(
|
|
56
|
+
db.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME).put(bytes, DB_KEY)
|
|
57
|
+
).finally(() => db.close());
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
function openIndexedDb() {
|
|
61
|
+
if (!globalThis.indexedDB) {
|
|
62
|
+
throw new Error("Graph store SQLite persistence requires IndexedDB support.");
|
|
63
|
+
}
|
|
64
|
+
return new Promise((resolve, reject) => {
|
|
65
|
+
const request = globalThis.indexedDB.open(DB_NAME, 1);
|
|
66
|
+
request.onupgradeneeded = () => {
|
|
67
|
+
request.result.createObjectStore(STORE_NAME);
|
|
68
|
+
};
|
|
69
|
+
request.onsuccess = () => resolve(request.result);
|
|
70
|
+
request.onerror = () => reject(request.error ?? new Error("Failed to open graph store IndexedDB database."));
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function requestToPromise(request) {
|
|
74
|
+
return new Promise((resolve, reject) => {
|
|
75
|
+
request.onsuccess = () => resolve(request.result);
|
|
76
|
+
request.onerror = () => reject(request.error ?? new Error("IndexedDB graph store request failed."));
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/store/sqlite-graph-store.ts
|
|
81
|
+
var SQLITE_SCHEMA_VERSION = "sqlite-graph-store-v1";
|
|
82
|
+
var SQLiteGraphStore = class _SQLiteGraphStore {
|
|
83
|
+
db;
|
|
84
|
+
persist;
|
|
85
|
+
constructor(db, persist) {
|
|
86
|
+
this.db = db;
|
|
87
|
+
this.persist = persist;
|
|
88
|
+
this.migrate();
|
|
89
|
+
}
|
|
90
|
+
static async create(byteStore, locateFile) {
|
|
91
|
+
const { db, persist } = await openPersistedDatabase(byteStore, locateFile);
|
|
92
|
+
return new _SQLiteGraphStore(db, persist);
|
|
93
|
+
}
|
|
94
|
+
async get(key) {
|
|
95
|
+
const row = this.selectEntry(formatGraphStoreCacheKey(key));
|
|
96
|
+
if (!row) return void 0;
|
|
97
|
+
const entry = rowToEntry(row);
|
|
98
|
+
if (formatGraphStoreCacheKey(entry.key) !== formatGraphStoreCacheKey(key)) {
|
|
99
|
+
return void 0;
|
|
100
|
+
}
|
|
101
|
+
return entry;
|
|
102
|
+
}
|
|
103
|
+
async put(entry) {
|
|
104
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
105
|
+
const createdAt = entry.createdAt ?? now;
|
|
106
|
+
const updatedAt = entry.updatedAt ?? now;
|
|
107
|
+
this.db.run(
|
|
108
|
+
`insert into entries (
|
|
109
|
+
cache_key, key_json, scope, provider_id, source_id, variant, content_hash,
|
|
110
|
+
value_json, dependencies_json, metadata_json, created_at, updated_at
|
|
111
|
+
) values (
|
|
112
|
+
$cache_key, $key_json, $scope, $provider_id, $source_id, $variant, $content_hash,
|
|
113
|
+
$value_json, $dependencies_json, $metadata_json, $created_at, $updated_at
|
|
114
|
+
)
|
|
115
|
+
on conflict(cache_key) do update set
|
|
116
|
+
key_json = excluded.key_json,
|
|
117
|
+
scope = excluded.scope,
|
|
118
|
+
provider_id = excluded.provider_id,
|
|
119
|
+
source_id = excluded.source_id,
|
|
120
|
+
variant = excluded.variant,
|
|
121
|
+
content_hash = excluded.content_hash,
|
|
122
|
+
value_json = excluded.value_json,
|
|
123
|
+
dependencies_json = excluded.dependencies_json,
|
|
124
|
+
metadata_json = excluded.metadata_json,
|
|
125
|
+
updated_at = excluded.updated_at`,
|
|
126
|
+
{
|
|
127
|
+
$cache_key: formatGraphStoreCacheKey(entry.key),
|
|
128
|
+
$key_json: JSON.stringify(entry.key),
|
|
129
|
+
$scope: entry.key.scope,
|
|
130
|
+
$provider_id: entry.key.providerId,
|
|
131
|
+
$source_id: entry.key.sourceId ?? null,
|
|
132
|
+
$variant: entry.key.variant ?? null,
|
|
133
|
+
$content_hash: formatContentHash(entry.key.contentHash),
|
|
134
|
+
$value_json: JSON.stringify(entry.value),
|
|
135
|
+
$dependencies_json: JSON.stringify(entry.dependencies ?? []),
|
|
136
|
+
$metadata_json: JSON.stringify(entry.metadata ?? {}),
|
|
137
|
+
$created_at: createdAt,
|
|
138
|
+
$updated_at: updatedAt
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
await this.persist();
|
|
142
|
+
}
|
|
143
|
+
async delete(key) {
|
|
144
|
+
const cacheKey = formatGraphStoreCacheKey(key);
|
|
145
|
+
const before = this.countEntries();
|
|
146
|
+
this.db.run("delete from entries where cache_key = $cache_key", { $cache_key: cacheKey });
|
|
147
|
+
const deleted = this.countEntries() < before;
|
|
148
|
+
if (deleted) await this.persist();
|
|
149
|
+
return deleted;
|
|
150
|
+
}
|
|
151
|
+
async invalidate(match) {
|
|
152
|
+
const rows = this.selectEntries();
|
|
153
|
+
let deleted = 0;
|
|
154
|
+
for (const row of rows) {
|
|
155
|
+
const entry = rowToEntry(row);
|
|
156
|
+
if (matchesInvalidation(entry, match)) {
|
|
157
|
+
this.db.run("delete from entries where cache_key = $cache_key", { $cache_key: row.cache_key });
|
|
158
|
+
deleted++;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (deleted > 0) await this.persist();
|
|
162
|
+
return deleted;
|
|
163
|
+
}
|
|
164
|
+
migrate() {
|
|
165
|
+
this.db.run(`
|
|
166
|
+
create table if not exists metadata (
|
|
167
|
+
key text primary key,
|
|
168
|
+
value text not null
|
|
169
|
+
);
|
|
170
|
+
create table if not exists entries (
|
|
171
|
+
cache_key text primary key,
|
|
172
|
+
key_json text not null,
|
|
173
|
+
scope text not null,
|
|
174
|
+
provider_id text not null,
|
|
175
|
+
source_id text,
|
|
176
|
+
variant text,
|
|
177
|
+
content_hash text not null,
|
|
178
|
+
value_json text not null,
|
|
179
|
+
dependencies_json text not null,
|
|
180
|
+
metadata_json text not null,
|
|
181
|
+
created_at text not null,
|
|
182
|
+
updated_at text not null
|
|
183
|
+
);
|
|
184
|
+
create index if not exists idx_entries_scope on entries(scope);
|
|
185
|
+
create index if not exists idx_entries_provider on entries(provider_id);
|
|
186
|
+
create index if not exists idx_entries_source on entries(source_id);
|
|
187
|
+
create index if not exists idx_entries_variant on entries(variant);
|
|
188
|
+
create index if not exists idx_entries_content_hash on entries(content_hash);
|
|
189
|
+
`);
|
|
190
|
+
this.setMetadata("sqlite_schema_version", SQLITE_SCHEMA_VERSION);
|
|
191
|
+
this.setMetadata("graph_store_api_version", GRAPH_STORE_API_VERSION);
|
|
192
|
+
this.setMetadata("graph_store_cache_key_version", GRAPH_STORE_CACHE_KEY_VERSION);
|
|
193
|
+
this.setMetadata("graph_store_derivation_version", GRAPH_STORE_DERIVATION_VERSION);
|
|
194
|
+
}
|
|
195
|
+
setMetadata(key, value) {
|
|
196
|
+
this.db.run(
|
|
197
|
+
`insert into metadata (key, value) values ($key, $value)
|
|
198
|
+
on conflict(key) do update set value = excluded.value`,
|
|
199
|
+
{ $key: key, $value: value }
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
selectEntry(cacheKey) {
|
|
203
|
+
const statement = this.db.prepare(
|
|
204
|
+
`select cache_key, key_json, value_json, dependencies_json, metadata_json, created_at, updated_at
|
|
205
|
+
from entries where cache_key = $cache_key limit 1`
|
|
206
|
+
);
|
|
207
|
+
try {
|
|
208
|
+
statement.bind({ $cache_key: cacheKey });
|
|
209
|
+
if (!statement.step()) return void 0;
|
|
210
|
+
return statement.getAsObject();
|
|
211
|
+
} finally {
|
|
212
|
+
statement.free();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
selectEntries() {
|
|
216
|
+
const statement = this.db.prepare(
|
|
217
|
+
"select cache_key, key_json, value_json, dependencies_json, metadata_json, created_at, updated_at from entries"
|
|
218
|
+
);
|
|
219
|
+
const rows = [];
|
|
220
|
+
try {
|
|
221
|
+
while (statement.step()) {
|
|
222
|
+
rows.push(statement.getAsObject());
|
|
223
|
+
}
|
|
224
|
+
return rows;
|
|
225
|
+
} finally {
|
|
226
|
+
statement.free();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
countEntries() {
|
|
230
|
+
const statement = this.db.prepare("select count(*) as count from entries");
|
|
231
|
+
try {
|
|
232
|
+
if (!statement.step()) return 0;
|
|
233
|
+
const row = statement.getAsObject();
|
|
234
|
+
return row.count;
|
|
235
|
+
} finally {
|
|
236
|
+
statement.free();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
function rowToEntry(row) {
|
|
241
|
+
try {
|
|
242
|
+
return {
|
|
243
|
+
key: JSON.parse(row.key_json),
|
|
244
|
+
value: JSON.parse(row.value_json),
|
|
245
|
+
dependencies: JSON.parse(row.dependencies_json) ?? [],
|
|
246
|
+
metadata: JSON.parse(row.metadata_json),
|
|
247
|
+
createdAt: row.created_at,
|
|
248
|
+
updatedAt: row.updated_at
|
|
249
|
+
};
|
|
250
|
+
} catch (err) {
|
|
251
|
+
throw new Error(`Failed to deserialize graph store entry ${row.cache_key}: ${err instanceof Error ? err.message : String(err)}`, {
|
|
252
|
+
cause: err
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function matchesInvalidation(entry, match) {
|
|
257
|
+
if (match.scope && entry.key.scope !== match.scope) return false;
|
|
258
|
+
if (match.providerId && entry.key.providerId !== match.providerId) return false;
|
|
259
|
+
if (match.sourceId && entry.key.sourceId !== match.sourceId) {
|
|
260
|
+
const dependencyMatch = entry.dependencies?.some((dep) => dep.sourceId === match.sourceId) ?? false;
|
|
261
|
+
if (!dependencyMatch) return false;
|
|
262
|
+
}
|
|
263
|
+
if (match.variant && entry.key.variant !== match.variant) return false;
|
|
264
|
+
if (match.contentHash) {
|
|
265
|
+
const hash = formatContentHash(match.contentHash);
|
|
266
|
+
const keyMatch = formatContentHash(entry.key.contentHash) === hash;
|
|
267
|
+
const dependencyMatch = entry.dependencies?.some((dep) => formatContentHash(dep.contentHash) === hash) ?? false;
|
|
268
|
+
if (!keyMatch && !dependencyMatch) return false;
|
|
269
|
+
}
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export { IndexedDbSqliteByteStore, MemorySqliteByteStore, SQLiteGraphStore, loadSqlJs, openPersistedDatabase };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// src/identity.ts
|
|
2
|
+
function urnIdentity(namespace, body) {
|
|
3
|
+
return `urn:${namespace}:${body}`;
|
|
4
|
+
}
|
|
5
|
+
function urnBody(...parts) {
|
|
6
|
+
return parts.map((part) => encodeURIComponent(String(part))).join(":");
|
|
7
|
+
}
|
|
8
|
+
function assignIdentity(node) {
|
|
9
|
+
switch (node.source.type) {
|
|
10
|
+
case "file":
|
|
11
|
+
return urnIdentity("file", node.source.path);
|
|
12
|
+
case "authored":
|
|
13
|
+
return urnIdentity("content", node.id);
|
|
14
|
+
case "readme":
|
|
15
|
+
return urnIdentity("content", "readme");
|
|
16
|
+
case "issue":
|
|
17
|
+
return urnIdentity("issue", node.source.number);
|
|
18
|
+
case "pull_request":
|
|
19
|
+
return urnIdentity("pr", node.source.number);
|
|
20
|
+
case "commit":
|
|
21
|
+
return urnIdentity("commit", node.source.sha);
|
|
22
|
+
case "release":
|
|
23
|
+
return urnIdentity("release", node.source.tag);
|
|
24
|
+
case "person":
|
|
25
|
+
return urnIdentity("person", node.source.alias ?? node.source.login);
|
|
26
|
+
case "workflow":
|
|
27
|
+
return urnIdentity("structural", node.source.path);
|
|
28
|
+
case "external":
|
|
29
|
+
return urnIdentity("external", urnBody(node.source.provider, node.id));
|
|
30
|
+
case "structured": {
|
|
31
|
+
const ldId = node.jsonld?.["@id"];
|
|
32
|
+
if (typeof ldId === "string" && ldId) return ldId;
|
|
33
|
+
return void 0;
|
|
34
|
+
}
|
|
35
|
+
case "section":
|
|
36
|
+
return void 0;
|
|
37
|
+
default:
|
|
38
|
+
return void 0;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function shareIdentity(a, b) {
|
|
42
|
+
return !!(a.identity && b.identity && a.identity === b.identity);
|
|
43
|
+
}
|
|
44
|
+
function buildIdentityIndex(nodes) {
|
|
45
|
+
const index = /* @__PURE__ */ new Map();
|
|
46
|
+
for (const n of nodes) {
|
|
47
|
+
if (!n.identity) continue;
|
|
48
|
+
const existing = index.get(n.identity) ?? [];
|
|
49
|
+
existing.push(n.id);
|
|
50
|
+
index.set(n.identity, existing);
|
|
51
|
+
}
|
|
52
|
+
return index;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { assignIdentity, buildIdentityIndex, shareIdentity, urnBody, urnIdentity };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// src/glob.ts
|
|
2
|
+
function globToRegex(pattern) {
|
|
3
|
+
let re = "";
|
|
4
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
5
|
+
const c = pattern[i];
|
|
6
|
+
if (c === "*" && pattern[i + 1] === "*") {
|
|
7
|
+
re += ".*";
|
|
8
|
+
i += 1;
|
|
9
|
+
if (pattern[i + 1] === "/") i += 1;
|
|
10
|
+
} else if (c === "*") {
|
|
11
|
+
re += "[^/]*";
|
|
12
|
+
} else if (c === "?") {
|
|
13
|
+
re += "[^/]";
|
|
14
|
+
} else if (".+^${}()|[]\\".includes(c)) {
|
|
15
|
+
re += "\\" + c;
|
|
16
|
+
} else {
|
|
17
|
+
re += c;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return new RegExp(`^${re}$`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// src/sources/build-manifest.ts
|
|
24
|
+
function toManifestPullRequest(pr) {
|
|
25
|
+
const mapped = {
|
|
26
|
+
number: pr.number,
|
|
27
|
+
title: pr.title,
|
|
28
|
+
body: pr.body,
|
|
29
|
+
state: pr.state,
|
|
30
|
+
labels: pr.labels,
|
|
31
|
+
html_url: pr.html_url,
|
|
32
|
+
created_at: pr.created_at,
|
|
33
|
+
updated_at: pr.updated_at
|
|
34
|
+
};
|
|
35
|
+
if (pr.head_branch !== void 0) mapped.head_branch = pr.head_branch;
|
|
36
|
+
return mapped;
|
|
37
|
+
}
|
|
38
|
+
async function buildManifest(source, options = {}) {
|
|
39
|
+
const data = await source.getRepoData();
|
|
40
|
+
const manifest = {
|
|
41
|
+
configRaw: options.configRaw ?? null,
|
|
42
|
+
authoredContent: data.authoredContent,
|
|
43
|
+
tree: data.tree,
|
|
44
|
+
readme: data.readme,
|
|
45
|
+
issues: data.issues,
|
|
46
|
+
pullRequests: data.pullRequests.map(toManifestPullRequest),
|
|
47
|
+
commits: data.commits,
|
|
48
|
+
generatedAt: options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
49
|
+
};
|
|
50
|
+
if (data.branches.length > 0) manifest.branches = data.branches;
|
|
51
|
+
if (data.releases.length > 0) manifest.releases = data.releases;
|
|
52
|
+
if (data.repoMetadata) manifest.repoMetadata = data.repoMetadata;
|
|
53
|
+
if (data.nodemapRaw !== null) manifest.nodemapRaw = data.nodemapRaw;
|
|
54
|
+
if (data.nodemapFiles !== void 0) manifest.nodemapFiles = data.nodemapFiles;
|
|
55
|
+
if (data.nodemapDirs !== void 0) manifest.nodemapDirs = data.nodemapDirs;
|
|
56
|
+
if (data.structuredNodeMapRaw !== null) manifest.structuredNodeMapRaw = data.structuredNodeMapRaw;
|
|
57
|
+
if (Object.keys(data.structuralFiles).length > 0) manifest.structuralFiles = data.structuralFiles;
|
|
58
|
+
if (data.contentModel) manifest.contentModel = data.contentModel;
|
|
59
|
+
if (data.themeFileRaw) manifest.themeFileRaw = data.themeFileRaw;
|
|
60
|
+
if (options.augmentFrom) {
|
|
61
|
+
const live = await options.augmentFrom.getRepoData();
|
|
62
|
+
manifest.issues = live.issues;
|
|
63
|
+
manifest.pullRequests = live.pullRequests.map(toManifestPullRequest);
|
|
64
|
+
manifest.commits = live.commits;
|
|
65
|
+
if (live.repoMetadata !== null) manifest.repoMetadata = live.repoMetadata;
|
|
66
|
+
if (live.branches.length > 0) manifest.branches = live.branches;
|
|
67
|
+
if (live.releases.length > 0) manifest.releases = live.releases;
|
|
68
|
+
}
|
|
69
|
+
return manifest;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { buildManifest, globToRegex };
|