@kubun/id 0.10.0 → 0.12.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.
@@ -1,5 +1,5 @@
1
- import { AttachmentType, KubunID } from './base.js';
2
- export declare class AttachmentID extends KubunID<AttachmentType.BINARY> {
1
+ import { ATTACHMENT_BINARY, KubunID } from './base.js';
2
+ export declare class AttachmentID extends KubunID<typeof ATTACHMENT_BINARY> {
3
3
  #private;
4
4
  static create(value: Uint8Array, mimeType?: string): AttachmentID;
5
5
  static fromBytes(input: Uint8Array): AttachmentID;
package/lib/attachment.js CHANGED
@@ -1 +1,96 @@
1
- import{fromUTF as t,toUTF as e}from"@enkaku/codec";import{base36 as r}from"multiformats/bases/base36";import{AttachmentType as n,KubunID as i,NAMESPACE_CODE as s}from"./base.js";import{concat as m}from"./bytes.js";import{decodeVarint as o,digestBytes as c,encodeVarint as a}from"./utils.js";let h="application/octet-stream";export class AttachmentID extends i{static create(t,e){return new AttachmentID(c(t),t.byteLength,e)}static fromBytes(t){let r=0,[i,m]=o(t);if(i!==s)throw Error("Invalid KubunID: namespace mismatch");let[c,a]=o(t,r+=m);if(c!==n.BINARY)throw Error("Invalid KubunID: type mismatch");let[h,f]=o(t,r+=a);r+=f;let p=t.slice(r,r+h),[u,g]=o(t,r+=h),[l,y]=o(t,r+=g);return 0===l?new AttachmentID(p,u):(r+=y,new AttachmentID(p,u,e(t.slice(r,r+l))))}static fromString(t){return AttachmentID.fromBytes(r.decode(t))}static from(t){if(t instanceof AttachmentID)return t;if(t instanceof Uint8Array)return AttachmentID.fromBytes(t);if("string"==typeof t)return AttachmentID.fromString(t);throw Error("Unsupported input type")}#t;#e;#r;constructor(e,r,i=h){let s,o=m([a(e.byteLength),e,a(r)]);if(i===h)s=m([o,a(0)]);else{let e=t(i);s=m([o,a(e.byteLength),e])}super(n.BINARY,s),this.#t=r,this.#e=e,this.#r=i}get contentLength(){return this.#t}get digest(){return this.#e}get mimeType(){return this.#r}}
1
+ import { fromUTF, toUTF } from '@sozai/codec';
2
+ import { base36 } from 'multiformats/bases/base36';
3
+ import { ATTACHMENT_BINARY, KubunID, NAMESPACE_CODE } from './base.js';
4
+ import { concat } from './bytes.js';
5
+ import { decodeVarint, digestBytes, encodeVarint } from './utils.js';
6
+ const DEFAULT_MIME_TYPE = 'application/octet-stream';
7
+ export class AttachmentID extends KubunID {
8
+ static create(value, mimeType) {
9
+ return new AttachmentID(digestBytes(value), value.byteLength, mimeType);
10
+ }
11
+ static fromBytes(input) {
12
+ let offset = 0;
13
+ // Check namespace = is it a KubunID?
14
+ const [namespace, namespaceLength] = decodeVarint(input);
15
+ if (namespace !== NAMESPACE_CODE) {
16
+ throw new Error('Invalid KubunID: namespace mismatch');
17
+ }
18
+ offset += namespaceLength;
19
+ // Check type matches
20
+ const [type, typeLength] = decodeVarint(input, offset);
21
+ if (type !== ATTACHMENT_BINARY) {
22
+ throw new Error('Invalid KubunID: type mismatch');
23
+ }
24
+ offset += typeLength;
25
+ // Decode digest
26
+ const [digestLength, digestVarintLength] = decodeVarint(input, offset);
27
+ offset += digestVarintLength;
28
+ const digest = input.slice(offset, offset + digestLength);
29
+ offset += digestLength;
30
+ // Extract content length
31
+ const [contentLength, contentVarintLength] = decodeVarint(input, offset);
32
+ offset += contentVarintLength;
33
+ // Check if MIME type is provided
34
+ const [mimeTypeBytesLength, mimeTypeVarintLength] = decodeVarint(input, offset);
35
+ if (mimeTypeBytesLength === 0) {
36
+ // No MIME type encoded, use default
37
+ return new AttachmentID(digest, contentLength);
38
+ }
39
+ // Decode MIME type value
40
+ offset += mimeTypeVarintLength;
41
+ const mimeTypeBytes = input.slice(offset, offset + mimeTypeBytesLength);
42
+ return new AttachmentID(digest, contentLength, toUTF(mimeTypeBytes));
43
+ }
44
+ static fromString(input) {
45
+ return AttachmentID.fromBytes(base36.decode(input));
46
+ }
47
+ static from(input) {
48
+ if (input instanceof AttachmentID) {
49
+ return input;
50
+ }
51
+ if (input instanceof Uint8Array) {
52
+ return AttachmentID.fromBytes(input);
53
+ }
54
+ if (typeof input === 'string') {
55
+ return AttachmentID.fromString(input);
56
+ }
57
+ throw new Error('Unsupported input type');
58
+ }
59
+ #contentLength;
60
+ #digest;
61
+ #mimeType;
62
+ constructor(digest, contentLength, mimeType = DEFAULT_MIME_TYPE){
63
+ let data;
64
+ const baseData = concat([
65
+ encodeVarint(digest.byteLength),
66
+ digest,
67
+ encodeVarint(contentLength)
68
+ ]);
69
+ if (mimeType === DEFAULT_MIME_TYPE) {
70
+ data = concat([
71
+ baseData,
72
+ encodeVarint(0)
73
+ ]);
74
+ } else {
75
+ const typeBytes = fromUTF(mimeType);
76
+ data = concat([
77
+ baseData,
78
+ encodeVarint(typeBytes.byteLength),
79
+ typeBytes
80
+ ]);
81
+ }
82
+ super(ATTACHMENT_BINARY, data);
83
+ this.#contentLength = contentLength;
84
+ this.#digest = digest;
85
+ this.#mimeType = mimeType;
86
+ }
87
+ get contentLength() {
88
+ return this.#contentLength;
89
+ }
90
+ get digest() {
91
+ return this.#digest;
92
+ }
93
+ get mimeType() {
94
+ return this.#mimeType;
95
+ }
96
+ }
package/lib/base.d.ts CHANGED
@@ -1,19 +1,24 @@
1
1
  export declare const NAMESPACE_CODE = 181;
2
- export declare enum AttachmentType {
3
- BINARY = 1
4
- }
5
- export declare enum ModelType {
6
- SCALAR = 10,
7
- SHAPE = 11,
8
- DOCUMENT = 20,
9
- CLUSTER = 21
10
- }
11
- export declare enum DocumentType {
12
- MERGE_DOCUMENT = 30
13
- }
14
- export declare enum ExternalType {
15
- PLUGIN_NODE = 40
16
- }
2
+ /**
3
+ * Immutable references
4
+ */
5
+ export declare const ATTACHMENT_BINARY = 1;
6
+ export type AttachmentType = typeof ATTACHMENT_BINARY;
7
+ export declare const MODEL_SCALAR = 10;
8
+ export declare const MODEL_SHAPE = 11;
9
+ export declare const MODEL_DOCUMENT = 20;
10
+ export declare const MODEL_CLUSTER = 21;
11
+ export type ModelType = typeof MODEL_SCALAR | typeof MODEL_SHAPE | typeof MODEL_DOCUMENT | typeof MODEL_CLUSTER;
12
+ /**
13
+ * Mutable references
14
+ */
15
+ export declare const DOCUMENT_MERGE = 30;
16
+ export type DocumentType = typeof DOCUMENT_MERGE;
17
+ /**
18
+ * External references
19
+ */
20
+ export declare const EXTERNAL_PLUGIN_NODE = 40;
21
+ export type ExternalType = typeof EXTERNAL_PLUGIN_NODE;
17
22
  export type KubunType = AttachmentType | ModelType | DocumentType | ExternalType;
18
23
  export declare class KubunID<T extends KubunType = KubunType> {
19
24
  #private;
package/lib/base.js CHANGED
@@ -1 +1,61 @@
1
- var t,e,s,r;import{base36 as i}from"multiformats/bases/base36";import{concat as n,equals as o}from"./bytes.js";import{encodeVarint as a}from"./utils.js";export const NAMESPACE_CODE=181;let y=a(181);export var AttachmentType=((t={})[t.BINARY=1]="BINARY",t);export var ModelType=((e={})[e.SCALAR=10]="SCALAR",e[e.SHAPE=11]="SHAPE",e[e.DOCUMENT=20]="DOCUMENT",e[e.CLUSTER=21]="CLUSTER",e);export var DocumentType=((s={})[s.MERGE_DOCUMENT=30]="MERGE_DOCUMENT",s);export var ExternalType=((r={})[r.PLUGIN_NODE=40]="PLUGIN_NODE",r);export class KubunID{#t;#e;#s;#r;constructor(t,e){this.#t=t,this.#e=e}get type(){return this.#t}get data(){return this.#e}get bytes(){return null==this.#s&&(this.#s=this.toBytes()),this.#s}equals(t){return t instanceof KubunID&&t.type===this.type&&o(t.data,this.data)}toBytes(){return n([y,a(this.#t),this.#e])}toString(){return null==this.#r&&(this.#r=i.encode(this.bytes)),this.#r}[Symbol.for("nodejs.util.inspect.custom")](){return`KubunID(${this.toString()})`}}
1
+ import { base36 } from 'multiformats/bases/base36';
2
+ import { concat, equals } from './bytes.js';
3
+ import { encodeVarint } from './utils.js';
4
+ export const NAMESPACE_CODE = 0xb5;
5
+ const NAMESPACE_BYTES = encodeVarint(NAMESPACE_CODE);
6
+ /**
7
+ * Immutable references
8
+ */ export const ATTACHMENT_BINARY = 1;
9
+ // DAG-only
10
+ export const MODEL_SCALAR = 10;
11
+ export const MODEL_SHAPE = 11;
12
+ // Circular
13
+ export const MODEL_DOCUMENT = 20;
14
+ export const MODEL_CLUSTER = 21;
15
+ /**
16
+ * Mutable references
17
+ */ export const DOCUMENT_MERGE = 30;
18
+ /**
19
+ * External references
20
+ */ export const EXTERNAL_PLUGIN_NODE = 40;
21
+ export class KubunID {
22
+ #type;
23
+ #dataBytes;
24
+ #idBytes;
25
+ #string;
26
+ constructor(type, dataBytes){
27
+ this.#type = type;
28
+ this.#dataBytes = dataBytes;
29
+ }
30
+ get type() {
31
+ return this.#type;
32
+ }
33
+ get data() {
34
+ return this.#dataBytes;
35
+ }
36
+ get bytes() {
37
+ if (this.#idBytes == null) {
38
+ this.#idBytes = this.toBytes();
39
+ }
40
+ return this.#idBytes;
41
+ }
42
+ equals(other) {
43
+ return other instanceof KubunID && other.type === this.type && equals(other.data, this.data);
44
+ }
45
+ toBytes() {
46
+ return concat([
47
+ NAMESPACE_BYTES,
48
+ encodeVarint(this.#type),
49
+ this.#dataBytes
50
+ ]);
51
+ }
52
+ toString() {
53
+ if (this.#string == null) {
54
+ this.#string = base36.encode(this.bytes);
55
+ }
56
+ return this.#string;
57
+ }
58
+ [Symbol.for('nodejs.util.inspect.custom')]() {
59
+ return `KubunID(${this.toString()})`;
60
+ }
61
+ }
package/lib/bytes.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare function concat(arrays: Uint8Array[], providedLength?: number): Uint8Array;
1
+ export declare function concat(arrays: Array<Uint8Array>, providedLength?: number): Uint8Array;
2
2
  export declare function equals(a: Uint8Array, b: Uint8Array): boolean;
package/lib/bytes.js CHANGED
@@ -1 +1,24 @@
1
- export function concat(e,t){let n=new Uint8Array(t??e.reduce((e,t)=>e+t.length,0)),r=0;for(let t of e)n.set(t,r),r+=t.length;return n}export function equals(e,t){if(e===t)return!0;if(e.byteLength!==t.byteLength)return!1;for(let n=0;n<e.byteLength;n++)if(e[n]!==t[n])return!1;return!0}
1
+ export function concat(arrays, providedLength) {
2
+ const length = providedLength ?? arrays.reduce((acc, curr)=>acc + curr.length, 0);
3
+ const output = new Uint8Array(length);
4
+ let offset = 0;
5
+ for (const arr of arrays){
6
+ output.set(arr, offset);
7
+ offset += arr.length;
8
+ }
9
+ return output;
10
+ }
11
+ export function equals(a, b) {
12
+ if (a === b) {
13
+ return true;
14
+ }
15
+ if (a.byteLength !== b.byteLength) {
16
+ return false;
17
+ }
18
+ for(let i = 0; i < a.byteLength; i++){
19
+ if (a[i] !== b[i]) {
20
+ return false;
21
+ }
22
+ }
23
+ return true;
24
+ }
@@ -1,5 +1,5 @@
1
- import { KubunID, ModelType } from './base.js';
2
- export declare class ClusterModelID extends KubunID<ModelType.CLUSTER> {
1
+ import { KubunID, MODEL_CLUSTER } from './base.js';
2
+ export declare class ClusterModelID extends KubunID<typeof MODEL_CLUSTER> {
3
3
  static fromDigest(digestBytes: Uint8Array): ClusterModelID;
4
4
  static fromBytes(input: Uint8Array): ClusterModelID;
5
5
  static fromString(input: string): ClusterModelID;
@@ -1 +1,26 @@
1
- import{base36 as r}from"multiformats/bases/base36";import{KubunID as t,ModelType as e,NAMESPACE_CODE as s}from"./base.js";import{decodeVarint as o}from"./utils.js";export class ClusterModelID extends t{static fromDigest(r){return new ClusterModelID(r)}static fromBytes(r){let[t,i]=o(r);if(t!==s)throw Error("Invalid KubunID: namespace mismatch");let[m,l]=o(r,i);if(m!==e.CLUSTER)throw Error("Invalid KubunID: type mismatch");return new ClusterModelID(r.slice(i+l))}static fromString(t){return ClusterModelID.fromBytes(r.decode(t))}constructor(r){super(e.CLUSTER,r)}}
1
+ import { base36 } from 'multiformats/bases/base36';
2
+ import { KubunID, MODEL_CLUSTER, NAMESPACE_CODE } from './base.js';
3
+ import { decodeVarint } from './utils.js';
4
+ export class ClusterModelID extends KubunID {
5
+ static fromDigest(digestBytes) {
6
+ return new ClusterModelID(digestBytes);
7
+ }
8
+ static fromBytes(input) {
9
+ const [namespace, namespaceLength] = decodeVarint(input);
10
+ if (namespace !== NAMESPACE_CODE) {
11
+ throw new Error('Invalid KubunID: namespace mismatch');
12
+ }
13
+ const [type, typeLength] = decodeVarint(input, namespaceLength);
14
+ if (type !== MODEL_CLUSTER) {
15
+ throw new Error('Invalid KubunID: type mismatch');
16
+ }
17
+ const digestBytes = input.slice(namespaceLength + typeLength);
18
+ return new ClusterModelID(digestBytes);
19
+ }
20
+ static fromString(input) {
21
+ return ClusterModelID.fromBytes(base36.decode(input));
22
+ }
23
+ constructor(digestBytes){
24
+ super(MODEL_CLUSTER, digestBytes);
25
+ }
26
+ }
package/lib/decode.js CHANGED
@@ -1 +1,34 @@
1
- import{base36 as r}from"multiformats/bases/base36";import{AttachmentID as e}from"./attachment.js";import{AttachmentType as t,DocumentType as o,ExternalType as m,ModelType as s,NAMESPACE_CODE as n}from"./base.js";import{ClusterModelID as f}from"./cluster-model.js";import{DocumentID as a}from"./document.js";import{DocumentModelID as u,ScalarModelID as i,ShapeModelID as c}from"./model.js";import{PluginNodeID as p}from"./plugin-node.js";import{decodeVarint as d}from"./utils.js";export function decodeID(l){let y="string"==typeof l?r.decode(l):l,[E,B]=d(y);if(E!==n)throw Error("Invalid KubunID: namespace mismatch");let[j]=d(y,B);switch(j){case t.BINARY:return e.fromBytes(y);case s.SCALAR:return i.fromBytes(y);case s.SHAPE:return c.fromBytes(y);case s.DOCUMENT:return u.fromBytes(y);case s.CLUSTER:return f.fromBytes(y);case o.MERGE_DOCUMENT:return a.fromBytes(y);case m.PLUGIN_NODE:return p.fromBytes(y);default:throw Error(`Invalid KubunID: unknown type ${j}`)}}
1
+ import { base36 } from 'multiformats/bases/base36';
2
+ import { AttachmentID } from './attachment.js';
3
+ import { ATTACHMENT_BINARY, DOCUMENT_MERGE, EXTERNAL_PLUGIN_NODE, MODEL_CLUSTER, MODEL_DOCUMENT, MODEL_SCALAR, MODEL_SHAPE, NAMESPACE_CODE } from './base.js';
4
+ import { ClusterModelID } from './cluster-model.js';
5
+ import { DocumentID } from './document.js';
6
+ import { DocumentModelID, ScalarModelID, ShapeModelID } from './model.js';
7
+ import { PluginNodeID } from './plugin-node.js';
8
+ import { decodeVarint } from './utils.js';
9
+ export function decodeID(input) {
10
+ const bytes = typeof input === 'string' ? base36.decode(input) : input;
11
+ const [namespace, namespaceLength] = decodeVarint(bytes);
12
+ if (namespace !== NAMESPACE_CODE) {
13
+ throw new Error('Invalid KubunID: namespace mismatch');
14
+ }
15
+ const [type] = decodeVarint(bytes, namespaceLength);
16
+ switch(type){
17
+ case ATTACHMENT_BINARY:
18
+ return AttachmentID.fromBytes(bytes);
19
+ case MODEL_SCALAR:
20
+ return ScalarModelID.fromBytes(bytes);
21
+ case MODEL_SHAPE:
22
+ return ShapeModelID.fromBytes(bytes);
23
+ case MODEL_DOCUMENT:
24
+ return DocumentModelID.fromBytes(bytes);
25
+ case MODEL_CLUSTER:
26
+ return ClusterModelID.fromBytes(bytes);
27
+ case DOCUMENT_MERGE:
28
+ return DocumentID.fromBytes(bytes);
29
+ case EXTERNAL_PLUGIN_NODE:
30
+ return PluginNodeID.fromBytes(bytes);
31
+ default:
32
+ throw new Error(`Invalid KubunID: unknown type ${type}`);
33
+ }
34
+ }
package/lib/document.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { DocumentType, KubunID } from './base.js';
1
+ import { DOCUMENT_MERGE, KubunID } from './base.js';
2
2
  import { DocumentModelID } from './model.js';
3
- export declare class DocumentID extends KubunID<DocumentType.MERGE_DOCUMENT> {
3
+ export declare class DocumentID extends KubunID<typeof DOCUMENT_MERGE> {
4
4
  #private;
5
5
  static create(model: DocumentModelID | Uint8Array | string, owner: string | Uint8Array, unique: Uint8Array): DocumentID;
6
6
  static fromBytes(input: Uint8Array): DocumentID;
package/lib/document.js CHANGED
@@ -1 +1,81 @@
1
- import{fromUTF as t}from"@enkaku/codec";import{base36 as e}from"multiformats/bases/base36";import{DocumentType as r,KubunID as o,NAMESPACE_CODE as n}from"./base.js";import{concat as m}from"./bytes.js";import{DocumentModelID as i}from"./model.js";import{decodeVarint as s,digestBytes as c,encodeVarint as a}from"./utils.js";export class DocumentID extends o{static create(e,r,o){let n=m(["string"==typeof r?t(r):r,o]);return new DocumentID(i.from(e),c(n))}static fromBytes(t){let e=0,[o,m]=s(t);if(o!==n)throw Error("Invalid KubunID: namespace mismatch");let[c,a]=s(t,e+=m);if(c!==r.MERGE_DOCUMENT)throw Error("Invalid KubunID: type mismatch");let[u,f]=s(t,e+=a);e+=f;let l=t.slice(e,e+u),[D,d]=s(t,e+=u);e+=d;let p=new i(l,D),[I,h]=s(t,e);return e+=h,new DocumentID(p,t.slice(e,e+I))}static fromString(t){return DocumentID.fromBytes(e.decode(t))}static from(t){if(t instanceof DocumentID)return t;if(t instanceof Uint8Array)return DocumentID.fromBytes(t);if("string"==typeof t)return DocumentID.fromString(t);throw Error("Unsupported input type")}#t;#e;constructor(t,e){if(t.isLocal)throw Error("Invalid DocumentID: model cannot be local");let o=m([a(t.data.byteLength),t.data,a(t.index),a(e.byteLength),e]);super(r.MERGE_DOCUMENT,o),this.#t=t,this.#e=e}get model(){return this.#t}get content(){return this.#e}}
1
+ import { fromUTF } from '@sozai/codec';
2
+ import { base36 } from 'multiformats/bases/base36';
3
+ import { DOCUMENT_MERGE, KubunID, NAMESPACE_CODE } from './base.js';
4
+ import { concat } from './bytes.js';
5
+ import { DocumentModelID } from './model.js';
6
+ import { decodeVarint, digestBytes, encodeVarint } from './utils.js';
7
+ export class DocumentID extends KubunID {
8
+ static create(model, owner, unique) {
9
+ const contentBytes = concat([
10
+ typeof owner === 'string' ? fromUTF(owner) : owner,
11
+ unique
12
+ ]);
13
+ return new DocumentID(DocumentModelID.from(model), digestBytes(contentBytes));
14
+ }
15
+ static fromBytes(input) {
16
+ let offset = 0;
17
+ // Check namespace = is it a KubunID?
18
+ const [namespace, namespaceLength] = decodeVarint(input);
19
+ if (namespace !== NAMESPACE_CODE) {
20
+ throw new Error('Invalid KubunID: namespace mismatch');
21
+ }
22
+ offset += namespaceLength;
23
+ // Check type matches
24
+ const [type, typeLength] = decodeVarint(input, offset);
25
+ if (type !== DOCUMENT_MERGE) {
26
+ throw new Error('Invalid KubunID: type mismatch');
27
+ }
28
+ offset += typeLength;
29
+ // Decode model ID: digest bytes followed by index
30
+ const [modelDataByteLength, modelDataVarintLength] = decodeVarint(input, offset);
31
+ offset += modelDataVarintLength;
32
+ const modelDigest = input.slice(offset, offset + modelDataByteLength);
33
+ offset += modelDataByteLength;
34
+ const [modelIndex, modelIndexVarintLength] = decodeVarint(input, offset);
35
+ offset += modelIndexVarintLength;
36
+ const modelID = new DocumentModelID(modelDigest, modelIndex);
37
+ // Extract content digest bytes
38
+ const [contentByteLength, contentVarintLength] = decodeVarint(input, offset);
39
+ offset += contentVarintLength;
40
+ const contentBytes = input.slice(offset, offset + contentByteLength);
41
+ return new DocumentID(modelID, contentBytes);
42
+ }
43
+ static fromString(input) {
44
+ return DocumentID.fromBytes(base36.decode(input));
45
+ }
46
+ static from(input) {
47
+ if (input instanceof DocumentID) {
48
+ return input;
49
+ }
50
+ if (input instanceof Uint8Array) {
51
+ return DocumentID.fromBytes(input);
52
+ }
53
+ if (typeof input === 'string') {
54
+ return DocumentID.fromString(input);
55
+ }
56
+ throw new Error('Unsupported input type');
57
+ }
58
+ #model;
59
+ #content;
60
+ constructor(model, contentDigestBytes){
61
+ if (model.isLocal) {
62
+ throw new Error('Invalid DocumentID: model cannot be local');
63
+ }
64
+ const data = concat([
65
+ encodeVarint(model.data.byteLength),
66
+ model.data,
67
+ encodeVarint(model.index),
68
+ encodeVarint(contentDigestBytes.byteLength),
69
+ contentDigestBytes
70
+ ]);
71
+ super(DOCUMENT_MERGE, data);
72
+ this.#model = model;
73
+ this.#content = contentDigestBytes;
74
+ }
75
+ get model() {
76
+ return this.#model;
77
+ }
78
+ get content() {
79
+ return this.#content;
80
+ }
81
+ }
package/lib/index.js CHANGED
@@ -1 +1,8 @@
1
- export{AttachmentID}from"./attachment.js";export{KubunID}from"./base.js";export{ClusterModelID}from"./cluster-model.js";export{decodeID}from"./decode.js";export{DocumentID}from"./document.js";export{DocumentModelID,ScalarModelID,ShapeModelID}from"./model.js";export{PluginNodeID}from"./plugin-node.js";export{digestBytes,digestJSON}from"./utils.js";
1
+ export { AttachmentID } from './attachment.js';
2
+ export { KubunID } from './base.js';
3
+ export { ClusterModelID } from './cluster-model.js';
4
+ export { decodeID } from './decode.js';
5
+ export { DocumentID } from './document.js';
6
+ export { DocumentModelID, ScalarModelID, ShapeModelID } from './model.js';
7
+ export { PluginNodeID } from './plugin-node.js';
8
+ export { digestBytes, digestJSON } from './utils.js';
package/lib/model.d.ts CHANGED
@@ -1,17 +1,17 @@
1
- import { KubunID, ModelType } from './base.js';
2
- export declare class ScalarModelID extends KubunID<ModelType.SCALAR> {
1
+ import { KubunID, MODEL_DOCUMENT, MODEL_SCALAR, MODEL_SHAPE } from './base.js';
2
+ export declare class ScalarModelID extends KubunID<typeof MODEL_SCALAR> {
3
3
  static create(value: unknown): ScalarModelID;
4
4
  static fromBytes(input: Uint8Array): ScalarModelID;
5
5
  static fromString(input: string): ScalarModelID;
6
6
  constructor(digestBytes: Uint8Array);
7
7
  }
8
- export declare class ShapeModelID extends KubunID<ModelType.SHAPE> {
8
+ export declare class ShapeModelID extends KubunID<typeof MODEL_SHAPE> {
9
9
  static create(value: unknown): ShapeModelID;
10
10
  static fromBytes(input: Uint8Array): ShapeModelID;
11
11
  static fromString(input: string): ShapeModelID;
12
12
  constructor(digestBytes: Uint8Array);
13
13
  }
14
- export declare class DocumentModelID extends KubunID<ModelType.DOCUMENT> {
14
+ export declare class DocumentModelID extends KubunID<typeof MODEL_DOCUMENT> {
15
15
  #private;
16
16
  static fromBytes(input: Uint8Array): DocumentModelID;
17
17
  static fromString(input: string): DocumentModelID;
package/lib/model.js CHANGED
@@ -1 +1,111 @@
1
- import{base36 as e}from"multiformats/bases/base36";import{KubunID as t,ModelType as r,NAMESPACE_CODE as o}from"./base.js";import{concat as n}from"./bytes.js";import{decodeVarint as s,digestJSON as i,encodeVarint as a}from"./utils.js";export class ScalarModelID extends t{static create(e){return new ScalarModelID(i(e))}static fromBytes(e){let[t,n]=s(e);if(t!==o)throw Error("Invalid KubunID: namespace mismatch");let[i,a]=s(e,n);if(i!==r.SCALAR)throw Error("Invalid KubunID: type mismatch");return new ScalarModelID(e.slice(n+a))}static fromString(t){return ScalarModelID.fromBytes(e.decode(t))}constructor(e){super(r.SCALAR,e)}}export class ShapeModelID extends t{static create(e){return new ShapeModelID(i(e))}static fromBytes(e){let[t,n]=s(e);if(t!==o)throw Error("Invalid KubunID: namespace mismatch");let[i,a]=s(e,n);if(i!==r.SHAPE)throw Error("Invalid KubunID: type mismatch");return new ShapeModelID(e.slice(n+a))}static fromString(t){return ShapeModelID.fromBytes(e.decode(t))}constructor(e){super(r.SHAPE,e)}}export class DocumentModelID extends t{static fromBytes(e){let[t,n]=s(e);if(t!==o)throw Error("Invalid KubunID: namespace mismatch");let[i,a]=s(e,n);if(i!==r.DOCUMENT)throw Error("Invalid KubunID: type mismatch");let c=e.slice(n+a,e.byteLength-1),[l]=s(e,e.byteLength-1);return new DocumentModelID(c,l)}static fromString(t){return DocumentModelID.fromBytes(e.decode(t))}static from(e){if(e instanceof DocumentModelID)return e;if(e instanceof Uint8Array)return DocumentModelID.fromBytes(e);if("string"==typeof e)return DocumentModelID.fromString(e);throw Error("Unsupported input type")}static local(e){return new DocumentModelID(new Uint8Array(0),e)}#e;#t;constructor(e,t){if(t>127)throw RangeError(`Index ${t} exceeds maximum of 127`);super(r.DOCUMENT,e),this.#e=t,this.#t=0===e.length}get index(){return this.#e}get isLocal(){return this.#t}toBytes(){return n([super.toBytes(),a(this.#e)])}toGlobal(e){let t=e instanceof DocumentModelID?e.data:e;return new DocumentModelID(t,this.#e)}}
1
+ import { base36 } from 'multiformats/bases/base36';
2
+ import { KubunID, MODEL_DOCUMENT, MODEL_SCALAR, MODEL_SHAPE, NAMESPACE_CODE } from './base.js';
3
+ import { concat } from './bytes.js';
4
+ import { decodeVarint, digestJSON, encodeVarint } from './utils.js';
5
+ export class ScalarModelID extends KubunID {
6
+ static create(value) {
7
+ return new ScalarModelID(digestJSON(value));
8
+ }
9
+ static fromBytes(input) {
10
+ const [namespace, namespaceLength] = decodeVarint(input);
11
+ if (namespace !== NAMESPACE_CODE) {
12
+ throw new Error('Invalid KubunID: namespace mismatch');
13
+ }
14
+ const [type, typeLength] = decodeVarint(input, namespaceLength);
15
+ if (type !== MODEL_SCALAR) {
16
+ throw new Error('Invalid KubunID: type mismatch');
17
+ }
18
+ const digestBytes = input.slice(namespaceLength + typeLength);
19
+ return new ScalarModelID(digestBytes);
20
+ }
21
+ static fromString(input) {
22
+ return ScalarModelID.fromBytes(base36.decode(input));
23
+ }
24
+ constructor(digestBytes){
25
+ super(MODEL_SCALAR, digestBytes);
26
+ }
27
+ }
28
+ export class ShapeModelID extends KubunID {
29
+ static create(value) {
30
+ return new ShapeModelID(digestJSON(value));
31
+ }
32
+ static fromBytes(input) {
33
+ const [namespace, namespaceLength] = decodeVarint(input);
34
+ if (namespace !== NAMESPACE_CODE) {
35
+ throw new Error('Invalid KubunID: namespace mismatch');
36
+ }
37
+ const [type, typeLength] = decodeVarint(input, namespaceLength);
38
+ if (type !== MODEL_SHAPE) {
39
+ throw new Error('Invalid KubunID: type mismatch');
40
+ }
41
+ const digestBytes = input.slice(namespaceLength + typeLength);
42
+ return new ShapeModelID(digestBytes);
43
+ }
44
+ static fromString(input) {
45
+ return ShapeModelID.fromBytes(base36.decode(input));
46
+ }
47
+ constructor(digestBytes){
48
+ super(MODEL_SHAPE, digestBytes);
49
+ }
50
+ }
51
+ const MAX_INDEX = 127;
52
+ export class DocumentModelID extends KubunID {
53
+ static fromBytes(input) {
54
+ const [namespace, namespaceLength] = decodeVarint(input);
55
+ if (namespace !== NAMESPACE_CODE) {
56
+ throw new Error('Invalid KubunID: namespace mismatch');
57
+ }
58
+ const [type, typeLength] = decodeVarint(input, namespaceLength);
59
+ if (type !== MODEL_DOCUMENT) {
60
+ throw new Error('Invalid KubunID: type mismatch');
61
+ }
62
+ const digestBytes = input.slice(namespaceLength + typeLength, input.byteLength - 1);
63
+ const [index] = decodeVarint(input, input.byteLength - 1);
64
+ return new DocumentModelID(digestBytes, index);
65
+ }
66
+ static fromString(input) {
67
+ return DocumentModelID.fromBytes(base36.decode(input));
68
+ }
69
+ static from(input) {
70
+ if (input instanceof DocumentModelID) {
71
+ return input;
72
+ }
73
+ if (input instanceof Uint8Array) {
74
+ return DocumentModelID.fromBytes(input);
75
+ }
76
+ if (typeof input === 'string') {
77
+ return DocumentModelID.fromString(input);
78
+ }
79
+ throw new Error('Unsupported input type');
80
+ }
81
+ static local(index) {
82
+ return new DocumentModelID(new Uint8Array(0), index);
83
+ }
84
+ #index;
85
+ #isLocal;
86
+ constructor(digestBytes, index){
87
+ if (index > MAX_INDEX) {
88
+ // index should be encoded in a single byte
89
+ throw new RangeError(`Index ${index} exceeds maximum of ${MAX_INDEX}`);
90
+ }
91
+ super(MODEL_DOCUMENT, digestBytes);
92
+ this.#index = index;
93
+ this.#isLocal = digestBytes.length === 0;
94
+ }
95
+ get index() {
96
+ return this.#index;
97
+ }
98
+ get isLocal() {
99
+ return this.#isLocal;
100
+ }
101
+ toBytes() {
102
+ return concat([
103
+ super.toBytes(),
104
+ encodeVarint(this.#index)
105
+ ]);
106
+ }
107
+ toGlobal(digestBytesOrModelID) {
108
+ const digestBytes = digestBytesOrModelID instanceof DocumentModelID ? digestBytesOrModelID.data : digestBytesOrModelID;
109
+ return new DocumentModelID(digestBytes, this.#index);
110
+ }
111
+ }
@@ -1,5 +1,5 @@
1
- import { ExternalType, KubunID } from './base.js';
2
- export declare class PluginNodeID extends KubunID<ExternalType.PLUGIN_NODE> {
1
+ import { EXTERNAL_PLUGIN_NODE, KubunID } from './base.js';
2
+ export declare class PluginNodeID extends KubunID<typeof EXTERNAL_PLUGIN_NODE> {
3
3
  #private;
4
4
  static create(plugin: string, typeName: string, localID: string): PluginNodeID;
5
5
  static fromBytes(input: Uint8Array): PluginNodeID;
@@ -1 +1,84 @@
1
- import{fromUTF as t,toUTF as e}from"@enkaku/codec";import{base36 as r}from"multiformats/bases/base36";import{ExternalType as i,KubunID as n,NAMESPACE_CODE as o}from"./base.js";import{concat as s}from"./bytes.js";import{decodeVarint as l,encodeVarint as u}from"./utils.js";export class PluginNodeID extends n{static create(t,e,r){return new PluginNodeID(t,e,r)}static fromBytes(t){let r=0,[n,s]=l(t);if(n!==o)throw Error("Invalid KubunID: namespace mismatch");let[u,a]=l(t,r+=s);if(u!==i.PLUGIN_NODE)throw Error("Invalid KubunID: type mismatch");let[m,c]=l(t,r+=a);r+=c;let p=0===m?"":e(t.slice(r,r+m)),[f,g]=l(t,r+=m);r+=g;let I=0===f?"":e(t.slice(r,r+f)),[y,D]=l(t,r+=f);return r+=D,new PluginNodeID(p,I,0===y?"":e(t.slice(r,r+y)))}static fromString(t){return PluginNodeID.fromBytes(r.decode(t))}static from(t){if(t instanceof PluginNodeID)return t;if(t instanceof Uint8Array)return PluginNodeID.fromBytes(t);if("string"==typeof t)return PluginNodeID.fromString(t);throw Error("Unsupported input type")}#t;#e;#r;constructor(e,r,n){let o=t(e),l=t(r),a=t(n),m=s([u(o.byteLength),o,u(l.byteLength),l,u(a.byteLength),a]);super(i.PLUGIN_NODE,m),this.#t=e,this.#e=r,this.#r=n}get plugin(){return this.#t}get typeName(){return this.#e}get localID(){return this.#r}}
1
+ import { fromUTF, toUTF } from '@sozai/codec';
2
+ import { base36 } from 'multiformats/bases/base36';
3
+ import { EXTERNAL_PLUGIN_NODE, KubunID, NAMESPACE_CODE } from './base.js';
4
+ import { concat } from './bytes.js';
5
+ import { decodeVarint, encodeVarint } from './utils.js';
6
+ export class PluginNodeID extends KubunID {
7
+ static create(plugin, typeName, localID) {
8
+ return new PluginNodeID(plugin, typeName, localID);
9
+ }
10
+ static fromBytes(input) {
11
+ let offset = 0;
12
+ // Check namespace
13
+ const [namespace, namespaceLength] = decodeVarint(input);
14
+ if (namespace !== NAMESPACE_CODE) {
15
+ throw new Error('Invalid KubunID: namespace mismatch');
16
+ }
17
+ offset += namespaceLength;
18
+ // Check type matches
19
+ const [type, typeLength] = decodeVarint(input, offset);
20
+ if (type !== EXTERNAL_PLUGIN_NODE) {
21
+ throw new Error('Invalid KubunID: type mismatch');
22
+ }
23
+ offset += typeLength;
24
+ // Decode plugin
25
+ const [pluginLength, pluginVarintLength] = decodeVarint(input, offset);
26
+ offset += pluginVarintLength;
27
+ const plugin = pluginLength === 0 ? '' : toUTF(input.slice(offset, offset + pluginLength));
28
+ offset += pluginLength;
29
+ // Decode typeName
30
+ const [typeNameLength, typeNameVarintLength] = decodeVarint(input, offset);
31
+ offset += typeNameVarintLength;
32
+ const typeName = typeNameLength === 0 ? '' : toUTF(input.slice(offset, offset + typeNameLength));
33
+ offset += typeNameLength;
34
+ // Decode localID
35
+ const [localIDLength, localIDVarintLength] = decodeVarint(input, offset);
36
+ offset += localIDVarintLength;
37
+ const localID = localIDLength === 0 ? '' : toUTF(input.slice(offset, offset + localIDLength));
38
+ return new PluginNodeID(plugin, typeName, localID);
39
+ }
40
+ static fromString(input) {
41
+ return PluginNodeID.fromBytes(base36.decode(input));
42
+ }
43
+ static from(input) {
44
+ if (input instanceof PluginNodeID) {
45
+ return input;
46
+ }
47
+ if (input instanceof Uint8Array) {
48
+ return PluginNodeID.fromBytes(input);
49
+ }
50
+ if (typeof input === 'string') {
51
+ return PluginNodeID.fromString(input);
52
+ }
53
+ throw new Error('Unsupported input type');
54
+ }
55
+ #plugin;
56
+ #typeName;
57
+ #localID;
58
+ constructor(plugin, typeName, localID){
59
+ const pluginBytes = fromUTF(plugin);
60
+ const typeNameBytes = fromUTF(typeName);
61
+ const localIDBytes = fromUTF(localID);
62
+ const data = concat([
63
+ encodeVarint(pluginBytes.byteLength),
64
+ pluginBytes,
65
+ encodeVarint(typeNameBytes.byteLength),
66
+ typeNameBytes,
67
+ encodeVarint(localIDBytes.byteLength),
68
+ localIDBytes
69
+ ]);
70
+ super(EXTERNAL_PLUGIN_NODE, data);
71
+ this.#plugin = plugin;
72
+ this.#typeName = typeName;
73
+ this.#localID = localID;
74
+ }
75
+ get plugin() {
76
+ return this.#plugin;
77
+ }
78
+ get typeName() {
79
+ return this.#typeName;
80
+ }
81
+ get localID() {
82
+ return this.#localID;
83
+ }
84
+ }
package/lib/utils.js CHANGED
@@ -1 +1,19 @@
1
- import{canonicalStringify as e,fromUTF as t}from"@enkaku/codec";import{blake3 as n}from"@noble/hashes/blake3.js";import r from"varint";export function digestBytes(e){return n(e)}export function digestJSON(n){return digestBytes(t(e(n)))}export function decodeVarint(e,t){return[r.decode(e,t),r.decode.bytes??0]}export function encodeVarint(e){return r.encode(e,new Uint8Array(r.encodingLength(e)))}
1
+ import { blake3 } from '@noble/hashes/blake3.js';
2
+ import { canonicalStringify, fromUTF } from '@sozai/codec';
3
+ import varint from 'varint';
4
+ export function digestBytes(bytes) {
5
+ return blake3(bytes);
6
+ }
7
+ export function digestJSON(value) {
8
+ return digestBytes(fromUTF(canonicalStringify(value)));
9
+ }
10
+ export function decodeVarint(bytes, offset) {
11
+ const value = varint.decode(bytes, offset);
12
+ return [
13
+ value,
14
+ varint.decode.bytes ?? 0
15
+ ];
16
+ }
17
+ export function encodeVarint(value) {
18
+ return varint.encode(value, new Uint8Array(varint.encodingLength(value)));
19
+ }
package/package.json CHANGED
@@ -1,36 +1,36 @@
1
1
  {
2
2
  "name": "@kubun/id",
3
- "version": "0.10.0",
4
- "license": "see LICENSE.md",
3
+ "version": "0.12.0",
5
4
  "keywords": [],
5
+ "license": "see LICENSE.md",
6
+ "sideEffects": false,
6
7
  "type": "module",
7
- "main": "lib/index.js",
8
- "types": "lib/index.d.ts",
9
8
  "exports": {
10
9
  ".": "./lib/index.js"
11
10
  },
11
+ "main": "lib/index.js",
12
+ "types": "lib/index.d.ts",
12
13
  "files": [
13
14
  "lib/*",
14
15
  "LICENSE.md"
15
16
  ],
16
- "sideEffects": false,
17
17
  "dependencies": {
18
- "@enkaku/codec": "^0.16.0",
19
18
  "@noble/hashes": "^2.2.0",
20
- "multiformats": "^14.0.0",
19
+ "@sozai/codec": "^0.4.0",
20
+ "multiformats": "^14.0.5",
21
21
  "varint": "^6.0.0"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/varint": "^6.0.3"
25
25
  },
26
26
  "scripts": {
27
+ "build": "pnpm run build:clean && pnpm run build:js && pnpm run build:types",
27
28
  "build:clean": "del lib",
28
- "build:js": "swc src -d ./lib --config-file ../../swc.json --strip-leading-paths",
29
+ "build:js": "swc src -d ./lib --config-file ../../node_modules/@kigu/dev/swc.json --strip-leading-paths",
29
30
  "build:types": "tsc --emitDeclarationOnly --skipLibCheck",
30
31
  "build:types:ci": "tsc --emitDeclarationOnly --declarationMap false",
31
- "build": "pnpm run build:clean && pnpm run build:js && pnpm run build:types",
32
+ "test": "pnpm run test:types && pnpm run test:unit",
32
33
  "test:types": "tsc --noEmit",
33
- "test:unit": "vitest run",
34
- "test": "pnpm run test:types && pnpm run test:unit"
34
+ "test:unit": "vitest run"
35
35
  }
36
36
  }