@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.
@@ -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 && idMap[field.model] != null) {
171
- fieldsMeta[key] = {
172
- ...field,
173
- model: idMap[field.model]
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 {
@@ -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()
@@ -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
  }
@@ -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).map((idx)=>({
120
- originalIndex: idx,
121
- model: models[idx]
122
- })).sort((a, b)=>a.model.name.localeCompare(b.model.name));
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: models[origIdx]
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
- for(let newIndex = 0; newIndex < sorted.length; newIndex++){
149
- internalIndexMap.set(sorted[newIndex].originalIndex, newIndex);
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
- for (const modelIdx of groups[gi]){
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
- groupDeps[gi].add(depGroup);
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
- groupDeps[gi].add(depGroup);
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].has(next)) {
246
- remaining[gi]--;
247
- if (remaining[gi] === 0) {
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(let i = 0; i < group.length; i++){
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 origIdx = group[i];
285
- const modelName = models[origIdx].name;
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);
@@ -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
  };
@@ -227,6 +227,9 @@ export const mutateGraphParams = {
227
227
  }
228
228
  ]
229
229
  },
230
+ owner: {
231
+ type: 'string'
232
+ },
230
233
  transactionID: {
231
234
  type: 'string'
232
235
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubun/protocol",
3
- "version": "0.16.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.16.0",
21
- "@kubun/logger": "^0.16.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",