@super-line/core 0.5.0 → 0.6.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/dist/index.cjs CHANGED
@@ -28,6 +28,7 @@ __export(index_exports, {
28
28
  classifyContract: () => classifyContract,
29
29
  defineContract: () => defineContract,
30
30
  jsonSerializer: () => jsonSerializer,
31
+ removeAtPath: () => removeAtPath,
31
32
  validate: () => validate,
32
33
  validateSync: () => validateSync
33
34
  });
@@ -153,6 +154,23 @@ function classifyContract(contract, convert) {
153
154
 
154
155
  // src/wire.ts
155
156
  var PROTOCOL = "superline.v1";
157
+
158
+ // src/store.ts
159
+ var removeAtPath = (root, path) => {
160
+ if (path.length === 0) return root;
161
+ if (typeof root !== "object" || root === null) return root;
162
+ const [head, ...rest] = path;
163
+ if (Array.isArray(root)) {
164
+ const next2 = root.slice();
165
+ if (rest.length === 0) next2.splice(Number(head), 1);
166
+ else next2[Number(head)] = removeAtPath(next2[Number(head)], rest);
167
+ return next2;
168
+ }
169
+ const next = { ...root };
170
+ if (rest.length === 0) delete next[head];
171
+ else next[head] = removeAtPath(next[head], rest);
172
+ return next;
173
+ };
156
174
  // Annotate the CommonJS export names for ESM import in node:
157
175
  0 && (module.exports = {
158
176
  INSPECTOR_ROLE,
@@ -163,6 +181,7 @@ var PROTOCOL = "superline.v1";
163
181
  classifyContract,
164
182
  defineContract,
165
183
  jsonSerializer,
184
+ removeAtPath,
166
185
  validate,
167
186
  validateSync
168
187
  });
package/dist/index.d.cts CHANGED
@@ -617,6 +617,13 @@ type Frame = ClientFrame | ServerFrame;
617
617
  * siblings behind this interface.
618
618
  */
619
619
  type Awaitable<T> = T | Promise<T>;
620
+ /**
621
+ * Return a structural clone of `root` with the value at `path` removed — the surgical-delete primitive shared
622
+ * by every Store's replica halves. Clones only along the path (not a deep clone): fed to a diff-and-patch
623
+ * `set`, only the removed key is rewritten, so concurrent edits to sibling keys still merge. Never mutates
624
+ * `root` (the live snapshot must stay intact). `path === []` returns `root` unchanged.
625
+ */
626
+ declare const removeAtPath: (root: unknown, path: (string | number)[]) => unknown;
620
627
  /** The ACL identity a Resource's access is keyed by (`identify(conn) ?? conn.id`). */
621
628
  type Principal = string;
622
629
  /** Per-principal capabilities on a Resource. */
@@ -670,6 +677,15 @@ interface ServerStore {
670
677
  list(): Awaitable<string[]>;
671
678
  /** Subscribe to every applied mutation — the single fan-out source. Returns an unsubscribe fn. */
672
679
  onChange(cb: (change: StoreChange) => void): () => void;
680
+ /**
681
+ * Open a reactive in-process replica over a Resource's canonical state — the server-side co-writer.
682
+ * Optional; stores opt in (those that don't, surface as "reactive open not supported"). Mutations made
683
+ * through it fan out via {@link ServerStore.onChange} exactly like {@link ServerStore.apply}. `origin`
684
+ * (default `"server"`) is stamped on its fan-out Changes for echo-break + inspector attribution.
685
+ */
686
+ open?(id: string, opts?: {
687
+ origin?: string;
688
+ }): ServerReplica;
673
689
  /** Release any resources held by the store. */
674
690
  close?(): Awaitable<void>;
675
691
  }
@@ -695,9 +711,27 @@ interface ResourceReplica {
695
711
  subscribe(cb: () => void): () => void;
696
712
  set(data: unknown): StoreChange | null;
697
713
  update(partial: unknown): StoreChange | null;
714
+ /** Remove the value at `path` (a surgical key removal that merges, unlike a full-doc `set`). */
715
+ delete(path: (string | number)[]): StoreChange | null;
698
716
  applyRemote(change: StoreChange): void;
699
717
  seed(snapshot: unknown): void;
700
718
  }
719
+ /**
720
+ * A reactive **server-side** replica over one Resource's canonical state — the server half's mirror of
721
+ * {@link ResourceReplica}, simpler because the server mutates canonical state directly: there is no wire to
722
+ * send up (no return Change to forward) and no second copy to reconcile (no `applyRemote`/`seed`). `set`/
723
+ * `update`/`delete` mutate canonical state in place and fan out through {@link ServerStore.onChange}; reads
724
+ * are live and `subscribe` reflects every applied mutation (local co-writes AND relayed remote Changes).
725
+ * Returned by {@link ServerStore.open}; surfaced to apps as `srv.store(name).open(id)`.
726
+ */
727
+ interface ServerReplica {
728
+ getSnapshot(): unknown;
729
+ subscribe(cb: () => void): () => void;
730
+ set(data: unknown): void;
731
+ update(partial: unknown): void;
732
+ delete(path: (string | number)[]): void;
733
+ close(): void;
734
+ }
701
735
 
702
736
  /**
703
737
  * The client↔server transport seam. A transport moves opaque encoded bytes over a
@@ -777,4 +811,4 @@ interface ClientTransport {
777
811
  }): RawConn;
778
812
  }
779
813
 
780
- export { type AccessRules, type Adapter, type AnyData, type AuthOutcome, type ClientFrame, type ClientInput, type ClientStore, type ClientTransport, type ConnDescriptor, type ConnView, type Contract, type DataOf, type Directional, type EmitData, type ErrFrame, type ErrorCode, type EventData, type Events, type EvtFrame, type Frame, type Handshake, INSPECTOR_ROLE, INSPECTOR_SUBPROTOCOL, type InferIn, type InferOut, type InspectedContract, type InspectedDirectional, type InspectedMessage, InspectorContract, type InspectorEvent, type MessageFlavor, type NodeStat, type NodeView, type Output, PROTOCOL, type Perms, type PingFrame, type PongFrame, type PresenceStore, type Principal, type PubFrame, type RawConn, type ReqFrame, type RequestDef, type Requests, type ResFrame, type Resource, type ResourceReplica, type RoleBlock, type RoleOf, type RoleRequests, type RoleTopics, type SChangeFrame, type SCloseFrame, type SErrFrame, type SOpenFrame, type SReadFrame, type SReqFrame, type SResFrame, type SWriteFrame, type Schema, type SchemaConverter, type Serializer, type ServerEntry, type ServerFrame, type ServerInput, type ServerMessageDef, type ServerMessages, type ServerRequestDef, type ServerRequests, type ServerStore, type ServerTransport, type SharedEvents, type SharedRequests, type SharedServerRequests, type SharedTopics, type StoreChange, type SubFrame, SuperLineError, type SuperLineErrorCode, type Topics, type UnsubFrame, classifyContract, defineContract, jsonSerializer, validate, validateSync };
814
+ export { type AccessRules, type Adapter, type AnyData, type AuthOutcome, type ClientFrame, type ClientInput, type ClientStore, type ClientTransport, type ConnDescriptor, type ConnView, type Contract, type DataOf, type Directional, type EmitData, type ErrFrame, type ErrorCode, type EventData, type Events, type EvtFrame, type Frame, type Handshake, INSPECTOR_ROLE, INSPECTOR_SUBPROTOCOL, type InferIn, type InferOut, type InspectedContract, type InspectedDirectional, type InspectedMessage, InspectorContract, type InspectorEvent, type MessageFlavor, type NodeStat, type NodeView, type Output, PROTOCOL, type Perms, type PingFrame, type PongFrame, type PresenceStore, type Principal, type PubFrame, type RawConn, type ReqFrame, type RequestDef, type Requests, type ResFrame, type Resource, type ResourceReplica, type RoleBlock, type RoleOf, type RoleRequests, type RoleTopics, type SChangeFrame, type SCloseFrame, type SErrFrame, type SOpenFrame, type SReadFrame, type SReqFrame, type SResFrame, type SWriteFrame, type Schema, type SchemaConverter, type Serializer, type ServerEntry, type ServerFrame, type ServerInput, type ServerMessageDef, type ServerMessages, type ServerReplica, type ServerRequestDef, type ServerRequests, type ServerStore, type ServerTransport, type SharedEvents, type SharedRequests, type SharedServerRequests, type SharedTopics, type StoreChange, type SubFrame, SuperLineError, type SuperLineErrorCode, type Topics, type UnsubFrame, classifyContract, defineContract, jsonSerializer, removeAtPath, validate, validateSync };
package/dist/index.d.ts CHANGED
@@ -617,6 +617,13 @@ type Frame = ClientFrame | ServerFrame;
617
617
  * siblings behind this interface.
618
618
  */
619
619
  type Awaitable<T> = T | Promise<T>;
620
+ /**
621
+ * Return a structural clone of `root` with the value at `path` removed — the surgical-delete primitive shared
622
+ * by every Store's replica halves. Clones only along the path (not a deep clone): fed to a diff-and-patch
623
+ * `set`, only the removed key is rewritten, so concurrent edits to sibling keys still merge. Never mutates
624
+ * `root` (the live snapshot must stay intact). `path === []` returns `root` unchanged.
625
+ */
626
+ declare const removeAtPath: (root: unknown, path: (string | number)[]) => unknown;
620
627
  /** The ACL identity a Resource's access is keyed by (`identify(conn) ?? conn.id`). */
621
628
  type Principal = string;
622
629
  /** Per-principal capabilities on a Resource. */
@@ -670,6 +677,15 @@ interface ServerStore {
670
677
  list(): Awaitable<string[]>;
671
678
  /** Subscribe to every applied mutation — the single fan-out source. Returns an unsubscribe fn. */
672
679
  onChange(cb: (change: StoreChange) => void): () => void;
680
+ /**
681
+ * Open a reactive in-process replica over a Resource's canonical state — the server-side co-writer.
682
+ * Optional; stores opt in (those that don't, surface as "reactive open not supported"). Mutations made
683
+ * through it fan out via {@link ServerStore.onChange} exactly like {@link ServerStore.apply}. `origin`
684
+ * (default `"server"`) is stamped on its fan-out Changes for echo-break + inspector attribution.
685
+ */
686
+ open?(id: string, opts?: {
687
+ origin?: string;
688
+ }): ServerReplica;
673
689
  /** Release any resources held by the store. */
674
690
  close?(): Awaitable<void>;
675
691
  }
@@ -695,9 +711,27 @@ interface ResourceReplica {
695
711
  subscribe(cb: () => void): () => void;
696
712
  set(data: unknown): StoreChange | null;
697
713
  update(partial: unknown): StoreChange | null;
714
+ /** Remove the value at `path` (a surgical key removal that merges, unlike a full-doc `set`). */
715
+ delete(path: (string | number)[]): StoreChange | null;
698
716
  applyRemote(change: StoreChange): void;
699
717
  seed(snapshot: unknown): void;
700
718
  }
719
+ /**
720
+ * A reactive **server-side** replica over one Resource's canonical state — the server half's mirror of
721
+ * {@link ResourceReplica}, simpler because the server mutates canonical state directly: there is no wire to
722
+ * send up (no return Change to forward) and no second copy to reconcile (no `applyRemote`/`seed`). `set`/
723
+ * `update`/`delete` mutate canonical state in place and fan out through {@link ServerStore.onChange}; reads
724
+ * are live and `subscribe` reflects every applied mutation (local co-writes AND relayed remote Changes).
725
+ * Returned by {@link ServerStore.open}; surfaced to apps as `srv.store(name).open(id)`.
726
+ */
727
+ interface ServerReplica {
728
+ getSnapshot(): unknown;
729
+ subscribe(cb: () => void): () => void;
730
+ set(data: unknown): void;
731
+ update(partial: unknown): void;
732
+ delete(path: (string | number)[]): void;
733
+ close(): void;
734
+ }
701
735
 
702
736
  /**
703
737
  * The client↔server transport seam. A transport moves opaque encoded bytes over a
@@ -777,4 +811,4 @@ interface ClientTransport {
777
811
  }): RawConn;
778
812
  }
779
813
 
780
- export { type AccessRules, type Adapter, type AnyData, type AuthOutcome, type ClientFrame, type ClientInput, type ClientStore, type ClientTransport, type ConnDescriptor, type ConnView, type Contract, type DataOf, type Directional, type EmitData, type ErrFrame, type ErrorCode, type EventData, type Events, type EvtFrame, type Frame, type Handshake, INSPECTOR_ROLE, INSPECTOR_SUBPROTOCOL, type InferIn, type InferOut, type InspectedContract, type InspectedDirectional, type InspectedMessage, InspectorContract, type InspectorEvent, type MessageFlavor, type NodeStat, type NodeView, type Output, PROTOCOL, type Perms, type PingFrame, type PongFrame, type PresenceStore, type Principal, type PubFrame, type RawConn, type ReqFrame, type RequestDef, type Requests, type ResFrame, type Resource, type ResourceReplica, type RoleBlock, type RoleOf, type RoleRequests, type RoleTopics, type SChangeFrame, type SCloseFrame, type SErrFrame, type SOpenFrame, type SReadFrame, type SReqFrame, type SResFrame, type SWriteFrame, type Schema, type SchemaConverter, type Serializer, type ServerEntry, type ServerFrame, type ServerInput, type ServerMessageDef, type ServerMessages, type ServerRequestDef, type ServerRequests, type ServerStore, type ServerTransport, type SharedEvents, type SharedRequests, type SharedServerRequests, type SharedTopics, type StoreChange, type SubFrame, SuperLineError, type SuperLineErrorCode, type Topics, type UnsubFrame, classifyContract, defineContract, jsonSerializer, validate, validateSync };
814
+ export { type AccessRules, type Adapter, type AnyData, type AuthOutcome, type ClientFrame, type ClientInput, type ClientStore, type ClientTransport, type ConnDescriptor, type ConnView, type Contract, type DataOf, type Directional, type EmitData, type ErrFrame, type ErrorCode, type EventData, type Events, type EvtFrame, type Frame, type Handshake, INSPECTOR_ROLE, INSPECTOR_SUBPROTOCOL, type InferIn, type InferOut, type InspectedContract, type InspectedDirectional, type InspectedMessage, InspectorContract, type InspectorEvent, type MessageFlavor, type NodeStat, type NodeView, type Output, PROTOCOL, type Perms, type PingFrame, type PongFrame, type PresenceStore, type Principal, type PubFrame, type RawConn, type ReqFrame, type RequestDef, type Requests, type ResFrame, type Resource, type ResourceReplica, type RoleBlock, type RoleOf, type RoleRequests, type RoleTopics, type SChangeFrame, type SCloseFrame, type SErrFrame, type SOpenFrame, type SReadFrame, type SReqFrame, type SResFrame, type SWriteFrame, type Schema, type SchemaConverter, type Serializer, type ServerEntry, type ServerFrame, type ServerInput, type ServerMessageDef, type ServerMessages, type ServerReplica, type ServerRequestDef, type ServerRequests, type ServerStore, type ServerTransport, type SharedEvents, type SharedRequests, type SharedServerRequests, type SharedTopics, type StoreChange, type SubFrame, SuperLineError, type SuperLineErrorCode, type Topics, type UnsubFrame, classifyContract, defineContract, jsonSerializer, removeAtPath, validate, validateSync };
package/dist/index.js CHANGED
@@ -118,6 +118,23 @@ function classifyContract(contract, convert) {
118
118
 
119
119
  // src/wire.ts
120
120
  var PROTOCOL = "superline.v1";
121
+
122
+ // src/store.ts
123
+ var removeAtPath = (root, path) => {
124
+ if (path.length === 0) return root;
125
+ if (typeof root !== "object" || root === null) return root;
126
+ const [head, ...rest] = path;
127
+ if (Array.isArray(root)) {
128
+ const next2 = root.slice();
129
+ if (rest.length === 0) next2.splice(Number(head), 1);
130
+ else next2[Number(head)] = removeAtPath(next2[Number(head)], rest);
131
+ return next2;
132
+ }
133
+ const next = { ...root };
134
+ if (rest.length === 0) delete next[head];
135
+ else next[head] = removeAtPath(next[head], rest);
136
+ return next;
137
+ };
121
138
  export {
122
139
  INSPECTOR_ROLE,
123
140
  INSPECTOR_SUBPROTOCOL,
@@ -127,6 +144,7 @@ export {
127
144
  classifyContract,
128
145
  defineContract,
129
146
  jsonSerializer,
147
+ removeAtPath,
130
148
  validate,
131
149
  validateSync
132
150
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@super-line/core",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "description": "Shared contract, validation, wire protocol and errors for super-line.",
6
6
  "license": "MIT",