@kubun/protocol 0.16.0 → 0.17.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/lib/models/cluster.js
CHANGED
|
@@ -167,11 +167,14 @@ export class ClusterBuilder {
|
|
|
167
167
|
...model.fieldsMeta
|
|
168
168
|
};
|
|
169
169
|
for (const [key, field] of Object.entries(fieldsMeta)){
|
|
170
|
-
if (field.type === 'document' && field.model != null
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
170
|
+
if (field.type === 'document' && field.model != null) {
|
|
171
|
+
const globalID = idMap[field.model];
|
|
172
|
+
if (globalID != null) {
|
|
173
|
+
fieldsMeta[key] = {
|
|
174
|
+
...field,
|
|
175
|
+
model: globalID
|
|
176
|
+
};
|
|
177
|
+
}
|
|
175
178
|
}
|
|
176
179
|
}
|
|
177
180
|
return {
|
package/lib/models/document.js
CHANGED
|
@@ -580,7 +580,7 @@ export class DocumentModelNormalizer {
|
|
|
580
580
|
continue;
|
|
581
581
|
}
|
|
582
582
|
const match = field.model.match(LOCAL_ID_REGEXP);
|
|
583
|
-
if (match != null) {
|
|
583
|
+
if (match?.[1] != null) {
|
|
584
584
|
this.#fieldsMeta[key] = {
|
|
585
585
|
...field,
|
|
586
586
|
model: DocumentModelID.local(Number.parseInt(match[1], 10)).toString()
|
package/lib/models/graph.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export declare class GraphModel {
|
|
|
20
20
|
get aliases(): Record<string, string>;
|
|
21
21
|
get record(): DocumentModelsRecord;
|
|
22
22
|
getAlias(modelID: string): string | null;
|
|
23
|
+
aliasID(alias: string): string;
|
|
23
24
|
getModel(aliasOrID: string): DocumentModel | null;
|
|
24
25
|
toJSON(): GraphModelJSON;
|
|
25
26
|
}
|
package/lib/models/graph.js
CHANGED
|
@@ -42,6 +42,13 @@ export class GraphModel {
|
|
|
42
42
|
}
|
|
43
43
|
return null;
|
|
44
44
|
}
|
|
45
|
+
aliasID(alias) {
|
|
46
|
+
const id = this.#aliases[alias];
|
|
47
|
+
if (id == null) {
|
|
48
|
+
throw new Error(`Unknown model alias: ${alias}`);
|
|
49
|
+
}
|
|
50
|
+
return id;
|
|
51
|
+
}
|
|
45
52
|
getModel(aliasOrID) {
|
|
46
53
|
const id = this.#aliases[aliasOrID] ?? aliasOrID;
|
|
47
54
|
return this.#record[id] ?? null;
|
|
@@ -57,13 +57,13 @@ import { ClusterBuilder, clusterToRecord } from './cluster.js';
|
|
|
57
57
|
currentIndex++;
|
|
58
58
|
stack.push(node);
|
|
59
59
|
onStack[node] = true;
|
|
60
|
-
for (const dep of deps[node]){
|
|
60
|
+
for (const dep of deps[node] ?? []){
|
|
61
61
|
if (dep >= n) continue;
|
|
62
62
|
if (indices[dep] === -1) {
|
|
63
63
|
strongConnect(dep);
|
|
64
|
-
lowlinks[node] = Math.min(lowlinks[node], lowlinks[dep]);
|
|
64
|
+
lowlinks[node] = Math.min(lowlinks[node] ?? 0, lowlinks[dep] ?? 0);
|
|
65
65
|
} else if (onStack[dep]) {
|
|
66
|
-
lowlinks[node] = Math.min(lowlinks[node], indices[dep]);
|
|
66
|
+
lowlinks[node] = Math.min(lowlinks[node] ?? 0, indices[dep] ?? 0);
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
if (lowlinks[node] === indices[node]) {
|
|
@@ -84,7 +84,7 @@ import { ClusterBuilder, clusterToRecord } from './cluster.js';
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
// Sort each SCC internally and sort SCCs by smallest index
|
|
87
|
-
return sccs.map((scc)=>scc.sort((a, b)=>a - b)).sort((a, b)=>a[0] - b[0]);
|
|
87
|
+
return sccs.map((scc)=>scc.sort((a, b)=>a - b)).sort((a, b)=>(a[0] ?? 0) - (b[0] ?? 0));
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
90
|
* Find cluster groups from model definitions.
|
|
@@ -106,7 +106,7 @@ import { ClusterBuilder, clusterToRecord } from './cluster.js';
|
|
|
106
106
|
const localInterfaceDeps = new Map();
|
|
107
107
|
for (const origIdx of group){
|
|
108
108
|
const filtered = new Set();
|
|
109
|
-
for (const dep of interfaceDeps[origIdx]){
|
|
109
|
+
for (const dep of interfaceDeps[origIdx] ?? []){
|
|
110
110
|
if (groupSet.has(dep)) filtered.add(dep);
|
|
111
111
|
}
|
|
112
112
|
localInterfaceDeps.set(origIdx, filtered);
|
|
@@ -116,10 +116,15 @@ import { ClusterBuilder, clusterToRecord } from './cluster.js';
|
|
|
116
116
|
remaining.set(origIdx, localInterfaceDeps.get(origIdx)?.size ?? 0);
|
|
117
117
|
}
|
|
118
118
|
const sorted = [];
|
|
119
|
-
const ready = group.filter((idx)=>(remaining.get(idx) ?? 0) === 0).
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
119
|
+
const ready = group.filter((idx)=>(remaining.get(idx) ?? 0) === 0).flatMap((idx)=>{
|
|
120
|
+
const model = models[idx];
|
|
121
|
+
return model == null ? [] : [
|
|
122
|
+
{
|
|
123
|
+
originalIndex: idx,
|
|
124
|
+
model
|
|
125
|
+
}
|
|
126
|
+
];
|
|
127
|
+
}).sort((a, b)=>a.model.name.localeCompare(b.model.name));
|
|
123
128
|
while(ready.length > 0){
|
|
124
129
|
const next = ready.shift();
|
|
125
130
|
if (next == null) break;
|
|
@@ -129,9 +134,11 @@ import { ClusterBuilder, clusterToRecord } from './cluster.js';
|
|
|
129
134
|
const count = (remaining.get(origIdx) ?? 1) - 1;
|
|
130
135
|
remaining.set(origIdx, count);
|
|
131
136
|
if (count === 0) {
|
|
137
|
+
const model = models[origIdx];
|
|
138
|
+
if (model == null) continue;
|
|
132
139
|
const entry = {
|
|
133
140
|
originalIndex: origIdx,
|
|
134
|
-
model
|
|
141
|
+
model
|
|
135
142
|
};
|
|
136
143
|
const insertIdx = ready.findIndex((r)=>r.model.name.localeCompare(entry.model.name) > 0);
|
|
137
144
|
if (insertIdx === -1) {
|
|
@@ -145,9 +152,9 @@ import { ClusterBuilder, clusterToRecord } from './cluster.js';
|
|
|
145
152
|
}
|
|
146
153
|
// Build mapping: original index → new cluster-internal index
|
|
147
154
|
const internalIndexMap = new Map();
|
|
148
|
-
|
|
149
|
-
internalIndexMap.set(
|
|
150
|
-
}
|
|
155
|
+
sorted.forEach((entry, newIndex)=>{
|
|
156
|
+
internalIndexMap.set(entry.originalIndex, newIndex);
|
|
157
|
+
});
|
|
151
158
|
// Rewrite references
|
|
152
159
|
return sorted.map(({ model })=>{
|
|
153
160
|
const rewritten = {
|
|
@@ -207,7 +214,7 @@ import { ClusterBuilder, clusterToRecord } from './cluster.js';
|
|
|
207
214
|
// Map each model index to its group index
|
|
208
215
|
const modelToGroup = new Map();
|
|
209
216
|
for(let gi = 0; gi < groups.length; gi++){
|
|
210
|
-
for (const modelIdx of groups[gi]){
|
|
217
|
+
for (const modelIdx of groups[gi] ?? []){
|
|
211
218
|
modelToGroup.set(modelIdx, gi);
|
|
212
219
|
}
|
|
213
220
|
}
|
|
@@ -216,19 +223,21 @@ import { ClusterBuilder, clusterToRecord } from './cluster.js';
|
|
|
216
223
|
length: groups.length
|
|
217
224
|
}, ()=>new Set());
|
|
218
225
|
for(let gi = 0; gi < groups.length; gi++){
|
|
219
|
-
|
|
226
|
+
const gd = groupDeps[gi];
|
|
227
|
+
if (gd == null) continue;
|
|
228
|
+
for (const modelIdx of groups[gi] ?? []){
|
|
220
229
|
// Interface deps
|
|
221
|
-
for (const dep of interfaceDeps[modelIdx]){
|
|
230
|
+
for (const dep of interfaceDeps[modelIdx] ?? []){
|
|
222
231
|
const depGroup = modelToGroup.get(dep);
|
|
223
232
|
if (depGroup != null && depGroup !== gi) {
|
|
224
|
-
|
|
233
|
+
gd.add(depGroup);
|
|
225
234
|
}
|
|
226
235
|
}
|
|
227
236
|
// One-way fieldsMeta deps (to models outside this group)
|
|
228
|
-
for (const dep of fieldsMetaDeps[modelIdx]){
|
|
237
|
+
for (const dep of fieldsMetaDeps[modelIdx] ?? []){
|
|
229
238
|
const depGroup = modelToGroup.get(dep);
|
|
230
239
|
if (depGroup != null && depGroup !== gi) {
|
|
231
|
-
|
|
240
|
+
gd.add(depGroup);
|
|
232
241
|
}
|
|
233
242
|
}
|
|
234
243
|
}
|
|
@@ -242,9 +251,10 @@ import { ClusterBuilder, clusterToRecord } from './cluster.js';
|
|
|
242
251
|
if (next == null) break;
|
|
243
252
|
sorted.push(next);
|
|
244
253
|
for(let gi = 0; gi < groupDeps.length; gi++){
|
|
245
|
-
if (groupDeps[gi]
|
|
246
|
-
remaining[gi]
|
|
247
|
-
|
|
254
|
+
if (groupDeps[gi]?.has(next)) {
|
|
255
|
+
const count = (remaining[gi] ?? 0) - 1;
|
|
256
|
+
remaining[gi] = count;
|
|
257
|
+
if (count === 0) {
|
|
248
258
|
ready.push(gi);
|
|
249
259
|
}
|
|
250
260
|
}
|
|
@@ -269,6 +279,7 @@ function buildOptimalClusters(models, externalClusters) {
|
|
|
269
279
|
const result = [];
|
|
270
280
|
for (const groupIdx of buildOrder){
|
|
271
281
|
const group = groups[groupIdx];
|
|
282
|
+
if (group == null) continue;
|
|
272
283
|
const prepared = prepareClusterModels(models, group, interfaceDeps, globalIDMap);
|
|
273
284
|
const builder = new ClusterBuilder({
|
|
274
285
|
externalClusters: Object.keys(builtClusters).length > 0 ? builtClusters : undefined
|
|
@@ -278,11 +289,12 @@ function buildOptimalClusters(models, externalClusters) {
|
|
|
278
289
|
result.push(cluster);
|
|
279
290
|
// Record global IDs for models in this cluster
|
|
280
291
|
const clusterDigest = digestJSON(cluster.models);
|
|
281
|
-
for(
|
|
292
|
+
for (const origIdx of group){
|
|
282
293
|
// Find which cluster-internal index corresponds to this original model
|
|
283
294
|
// prepareClusterModels sorts by interface deps + name, so we match by name
|
|
284
|
-
const
|
|
285
|
-
|
|
295
|
+
const model = models[origIdx];
|
|
296
|
+
if (model == null) continue;
|
|
297
|
+
const modelName = model.name;
|
|
286
298
|
const clusterInternalIdx = cluster.models.findIndex((m)=>m.name === modelName);
|
|
287
299
|
if (clusterInternalIdx !== -1) {
|
|
288
300
|
const globalID = new DocumentModelID(clusterDigest, clusterInternalIdx);
|
package/lib/services/graph.d.ts
CHANGED
|
@@ -3586,6 +3586,9 @@ export declare const mutateGraphParams: {
|
|
|
3586
3586
|
readonly type: "null";
|
|
3587
3587
|
}];
|
|
3588
3588
|
};
|
|
3589
|
+
readonly owner: {
|
|
3590
|
+
readonly type: "string";
|
|
3591
|
+
};
|
|
3589
3592
|
readonly transactionID: {
|
|
3590
3593
|
readonly type: "string";
|
|
3591
3594
|
};
|
|
@@ -7119,6 +7122,9 @@ export declare const graphProtocol: {
|
|
|
7119
7122
|
readonly type: "null";
|
|
7120
7123
|
}];
|
|
7121
7124
|
};
|
|
7125
|
+
readonly owner: {
|
|
7126
|
+
readonly type: "string";
|
|
7127
|
+
};
|
|
7122
7128
|
readonly transactionID: {
|
|
7123
7129
|
readonly type: "string";
|
|
7124
7130
|
};
|
package/lib/services/graph.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubun/protocol",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"keywords": [],
|
|
5
5
|
"license": "see LICENSE.md",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@enkaku/protocol": "^0.21.1",
|
|
19
19
|
"@enkaku/server": "^0.21.2",
|
|
20
|
-
"@kubun/id": "^0.
|
|
21
|
-
"@kubun/logger": "^0.
|
|
20
|
+
"@kubun/id": "^0.17.0",
|
|
21
|
+
"@kubun/logger": "^0.17.0",
|
|
22
22
|
"@sozai/codec": "^0.4.0",
|
|
23
23
|
"@sozai/schema": "^0.1.2",
|
|
24
24
|
"change-case": "^5.4.4"
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build": "pnpm run build:clean && pnpm run build:js && pnpm run build:types",
|
|
35
35
|
"build:clean": "del lib",
|
|
36
|
-
"build:js": "swc src -d ./lib --config-file ../../node_modules/@kigu/dev/swc.json --strip-leading-paths",
|
|
37
|
-
"build:types": "tsc --emitDeclarationOnly --skipLibCheck",
|
|
36
|
+
"build:js": "del 'lib/**/*.js' && swc src -d ./lib --config-file ../../node_modules/@kigu/dev/swc.json --strip-leading-paths",
|
|
37
|
+
"build:types": "del 'lib/**/*.d.ts' 'lib/**/*.d.ts.map' && tsc --emitDeclarationOnly --skipLibCheck",
|
|
38
38
|
"build:types:ci": "tsc --emitDeclarationOnly --declarationMap false",
|
|
39
39
|
"test": "pnpm run test:types && pnpm run test:unit",
|
|
40
40
|
"test:types": "tsc --noEmit -p tsconfig.test.json",
|