@deepseek-ai/dsh-client-resources 0.1.5-alpha.1 → 0.1.5-alpha.2

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/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/client/resources/README.md
5
- README.md: 7c32293c8d4250b11f8beaaf473a62145c915bce
6
- README.zh.md: b53089a2449f379f43156f610b587656a998ece3
5
+ README.md: 6b5afc82230be6930c41a01a584aeed39f596c37
6
+ README.zh.md: 6b928883bb54cd4663efa7a20a7bc768d4f8399e
package/README.md CHANGED
@@ -33,12 +33,12 @@ Nothing needs configuration to mount: the plugin provides `ctx.resources` and co
33
33
  <a id="read-a-resource"></a>
34
34
  ### Read a resource
35
35
 
36
- Every slot component receives `useResource` in its props. `useResource<P>(address)` names the protocol as the type argument and returns `{ status, value, failure, reload }`: `none` when no provider is registered for the address's protocol (or the address is not a `dsh-resource://` URL), `loading` while the provider has not yielded, `live` with the latest `ok` frame's value, and `failed` when the latest frame reported a failure, with that failure beside the last value. `reload()` asks the provider for a fresh value and is a no-op without one. Subscribing through the hook is what holds the resource open; a component that mounts while another holder keeps the resource alive reads the latest value at once.
36
+ Every slot component receives `useResource` in its props. `useResource<P>(address)` names the protocol as the type argument and returns `{ status, value, failure }`: `none` when no provider is registered for the address's protocol (or the address is not a `dsh-resource://` URL), `loading` while the provider has not yielded, `live` with the latest `ok` frame's value, and `failed` when the latest frame reported a failure, with that failure beside the last value. Subscribing through the hook is what holds the resource open; a component that mounts while another holder keeps the resource alive reads the latest value at once.
37
37
 
38
38
  <a id="provide-a-protocol"></a>
39
39
  ### Provide a protocol
40
40
 
41
- The protocol's owning client package declares its value type in `ResourceProtocolMap` and registers one provider as an owned effect. `open` yields `RemoteResult` frames: the current content first and one frame per later change, with a failure as an `ok: false` frame rather than a throw; it must stop when `signal` aborts. `reload` is optional:
41
+ The protocol's owning client package declares its value type in `ResourceProtocolMap` and registers one provider as an owned effect. `open` yields `RemoteResult` frames: the current content first and one frame per later change, with a failure as an `ok: false` frame rather than a throw; it must stop when `signal` aborts:
42
42
 
43
43
  ```ts ignore-check
44
44
  declare module '@deepseek-ai/dsh-client-ui-slots' {
@@ -54,7 +54,6 @@ export function apply(ctx) {
54
54
  yield await readNote(address, signal)
55
55
  for await (const change of followNote(address, signal)) yield change
56
56
  },
57
- reload(address) { requestReread(address) },
58
57
  }), 'my-notes: note resource provider')
59
58
  }
60
59
  ```
@@ -72,7 +71,7 @@ A protocol has exactly one provider; a second registration throws. Registering a
72
71
  <a id="lifecycle"></a>
73
72
  ### Lifecycle
74
73
 
75
- One record per address holds a snapshot store, a holder count (hook subscribers plus pins), and the running stream's `AbortController`. The first holder opens the provider's stream; every later holder shares it; the last holder's release aborts the stream and resets the snapshot to idle (`loading` with a provider, `none` without). Records are kept for the page lifetime so `source()` stays reference-stable across React's render-then-subscribe window and a StrictMode remount. `reload` is one function per record and never changes.
74
+ One record per address holds a snapshot store, a holder count (hook subscribers plus pins), and the running stream's `AbortController`. The first holder opens the provider's stream; every later holder shares it; the last holder's release aborts the stream and resets the snapshot to idle (`loading` with a provider, `none` without). Records are kept for the page lifetime so `source()` stays reference-stable across React's render-then-subscribe window and a StrictMode remount.
76
75
 
77
76
  <a id="failures"></a>
78
77
  ### Failures
package/README.zh.md CHANGED
@@ -33,12 +33,12 @@ kind: "package-reference"
33
33
  <a id="read-a-resource"></a>
34
34
  ### 读取资源
35
35
 
36
- 每个 slot 组件都在 props 上收到 `useResource`。`useResource<P>(address)` 以类型参数命名协议,返回 `{ status, value, failure, reload }`:地址协议没有提供方(或地址不是 `dsh-resource://` URL)时为 `none`,提供方尚未产出值时为 `loading`,`live` 携带最新一个 `ok` 帧的值,`failed` 表示最新一帧报告了失败,失败放在最后一个值旁。`reload()` 请提供方给一个新值,没有提供方时是空操作。通过 hook 订阅就是钉住资源的方式;另一个持有者让资源保持存活时,新挂载的组件立刻读到最新值。
36
+ 每个 slot 组件都在 props 上收到 `useResource`。`useResource<P>(address)` 以类型参数命名协议,返回 `{ status, value, failure }`:地址协议没有提供方(或地址不是 `dsh-resource://` URL)时为 `none`,提供方尚未产出值时为 `loading`,`live` 携带最新一个 `ok` 帧的值,`failed` 表示最新一帧报告了失败,失败放在最后一个值旁。通过 hook 订阅就是钉住资源的方式;另一个持有者让资源保持存活时,新挂载的组件立刻读到最新值。
37
37
 
38
38
  <a id="provide-a-protocol"></a>
39
39
  ### 提供协议
40
40
 
41
- 协议所属的客户端包在 `ResourceProtocolMap` 声明其值类型,并以自有 effect 注册一个提供方。`open` 产出 `RemoteResult` 帧:先是当前内容,之后每次变化一帧,失败以 `ok: false` 帧而非抛错表达;必须在 `signal` 中止时停止。`reload` 可选:
41
+ 协议所属的客户端包在 `ResourceProtocolMap` 声明其值类型,并以自有 effect 注册一个提供方。`open` 产出 `RemoteResult` 帧:先是当前内容,之后每次变化一帧,失败以 `ok: false` 帧而非抛错表达;必须在 `signal` 中止时停止:
42
42
 
43
43
  ```ts ignore-check
44
44
  declare module '@deepseek-ai/dsh-client-ui-slots' {
@@ -54,7 +54,6 @@ export function apply(ctx) {
54
54
  yield await readNote(address, signal)
55
55
  for await (const change of followNote(address, signal)) yield change
56
56
  },
57
- reload(address) { requestReread(address) },
58
57
  }), 'my-notes: note resource provider')
59
58
  }
60
59
  ```
@@ -72,7 +71,7 @@ export function apply(ctx) {
72
71
  <a id="lifecycle"></a>
73
72
  ### 生命周期
74
73
 
75
- 每个地址一条记录,持有一个快照 store、一个持有者计数(hook 订阅者加 pin)与运行中流的 `AbortController`。第一个持有者打开提供方的流;之后的持有者共享它;最后一个持有者释放时中止流并把快照重置为空闲(有提供方为 `loading`,没有为 `none`)。记录在页面存续期内保留,使 `source()` 在 React 渲染到订阅的窗口与 StrictMode 重挂载之间保持引用稳定。`reload` 每条记录一个函数,永不变化。
74
+ 每个地址一条记录,持有一个快照 store、一个持有者计数(hook 订阅者加 pin)与运行中流的 `AbortController`。第一个持有者打开提供方的流;之后的持有者共享它;最后一个持有者释放时中止流并把快照重置为空闲(有提供方为 `loading`,没有为 `none`)。记录在页面存续期内保留,使 `source()` 在 React 渲染到订阅的窗口与 StrictMode 重挂载之间保持引用稳定。
76
75
 
77
76
  <a id="failures"></a>
78
77
  ### 失败
package/lib/client.js CHANGED
@@ -23,12 +23,11 @@ window.__ModuleLoader__.load({
23
23
  if (parsed.protocol !== `dsh-resource:`) return void 0;
24
24
  return parsed.hostname === "" ? void 0 : parsed.hostname.toLowerCase();
25
25
  }
26
- function idle(status, reload) {
26
+ function idle(status) {
27
27
  return {
28
28
  status,
29
29
  value: void 0,
30
- failure: void 0,
31
- reload
30
+ failure: void 0
32
31
  };
33
32
  }
34
33
  /** The `ctx.resources` implementation. */
@@ -77,15 +76,11 @@ window.__ModuleLoader__.load({
77
76
  }
78
77
  create(address) {
79
78
  const protocol = protocolOf(address);
80
- const reload = () => {
81
- this.providerOf(protocol)?.reload?.(address);
82
- };
83
- const store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(idle(this.providerOf(protocol) === void 0 ? "none" : "loading", reload));
79
+ const store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(idle(this.providerOf(protocol) === void 0 ? "none" : "loading"));
84
80
  const record = {
85
81
  address,
86
82
  protocol,
87
83
  store,
88
- reload,
89
84
  holders: 0,
90
85
  controller: void 0,
91
86
  source: {
@@ -119,7 +114,7 @@ window.__ModuleLoader__.load({
119
114
  record.holders -= 1;
120
115
  if (record.holders > 0) return;
121
116
  this.stop(record);
122
- record.store.set(idle(this.providerOf(record.protocol) === void 0 ? "none" : "loading", record.reload));
117
+ record.store.set(idle(this.providerOf(record.protocol) === void 0 ? "none" : "loading"));
123
118
  }
124
119
  /** The provider arrived: a held record opens its stream, an idle one turns `loading`. */
125
120
  attach(record) {
@@ -127,19 +122,19 @@ window.__ModuleLoader__.load({
127
122
  this.start(record);
128
123
  return;
129
124
  }
130
- record.store.set(idle("loading", record.reload));
125
+ record.store.set(idle("loading"));
131
126
  }
132
127
  /** The provider left: the stream ends and the record reports `none`. */
133
128
  detach(record) {
134
129
  this.stop(record);
135
- record.store.set(idle("none", record.reload));
130
+ record.store.set(idle("none"));
136
131
  }
137
132
  start(record) {
138
133
  const provider = this.providerOf(record.protocol);
139
134
  if (provider === void 0) return;
140
135
  const controller = new AbortController();
141
136
  record.controller = controller;
142
- if (record.store.getSnapshot().status !== "loading") record.store.set(idle("loading", record.reload));
137
+ if (record.store.getSnapshot().status !== "loading") record.store.set(idle("loading"));
143
138
  this.consume(record, provider, controller.signal);
144
139
  }
145
140
  stop(record) {
@@ -154,13 +149,11 @@ window.__ModuleLoader__.load({
154
149
  record.store.set(frame.ok ? {
155
150
  status: "live",
156
151
  value: frame.value,
157
- failure: void 0,
158
- reload: record.reload
152
+ failure: void 0
159
153
  } : {
160
154
  status: "failed",
161
155
  value: record.store.getSnapshot().value,
162
- failure: frame.error,
163
- reload: record.reload
156
+ failure: frame.error
164
157
  });
165
158
  }
166
159
  }
@@ -45,8 +45,6 @@ export interface ResourceSnapshot<Value> {
45
45
  readonly value: Value | undefined;
46
46
  /** The latest frame's failure; present only while `status` is `failed`. */
47
47
  readonly failure: RemoteFailure | undefined;
48
- /** Ask the provider for a fresh frame; a no-op when its protocol has no provider or no `reload`. */
49
- readonly reload: () => void;
50
48
  }
51
49
  /**
52
50
  * Global standard hook: the current state of one address, typed by the
@@ -74,11 +72,6 @@ export interface ResourceProvider<P extends ResourceProtocol> {
74
72
  * @returns the frame stream; it must stop once `ctx.signal` aborts.
75
73
  */
76
74
  open(address: string, ctx: ResourceOpenContext): AsyncIterable<RemoteResult<ResourceProtocolMap[P]>>;
77
- /**
78
- * Produce a fresh frame on the open stream. Absent when the protocol has no refresh.
79
- * @param address - the full address, a `dsh-resource://<type>/…` URL.
80
- */
81
- reload?(address: string): void;
82
75
  }
83
76
  /**
84
77
  * The `ctx.resources` service. One resource is one address; it stays open
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-resources",
3
3
  "description": "Unified client resource model: protocol-registered providers turn URL addresses into live values, consumed through the useResource global standard hook",
4
- "version": "0.1.5-alpha.1",
4
+ "version": "0.1.5-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -39,11 +39,11 @@
39
39
  },
40
40
  "devDependencies": {
41
41
  "@deepseek-ai/cordis": "^4.0.2",
42
- "@deepseek-ai/dsh-client-store": "^0.1.5-alpha.1",
43
- "@deepseek-ai/dsh-client-test-runtime": "^0.1.5-alpha.1",
44
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.5-alpha.1",
45
- "@deepseek-ai/dsh-typert-protocol": "^0.1.5-alpha.1",
46
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-alpha.1"
42
+ "@deepseek-ai/dsh-client-store": "^0.1.5-alpha.2",
43
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-alpha.2",
44
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.5-alpha.2",
45
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.5-alpha.2",
46
+ "@deepseek-ai/dsh-client-test-runtime": "^0.1.5-alpha.2"
47
47
  },
48
48
  "files": [
49
49
  "lib/index.js",