@ai-matrx/records 0.42.0 → 0.43.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.
@@ -67,10 +67,12 @@ __export(react_exports, {
67
67
  choiceValuesOf: () => choiceValuesOf,
68
68
  choicesOf: () => choicesOf,
69
69
  err: () => err,
70
+ forgetAllOps: () => forgetAllOps,
70
71
  highestLevel: () => highestLevel,
71
72
  holdsARetiredChoice: () => holdsARetiredChoice,
72
73
  indexedDbStore: () => indexedDbStore,
73
74
  isDecided: () => isDecided,
75
+ isOwnOp: () => isOwnOp,
74
76
  isRecordsErr: () => isRecordsErr,
75
77
  isTheChosen: () => isTheChosen,
76
78
  looksLikeAnId: () => looksLikeAnId,
@@ -78,12 +80,14 @@ __export(react_exports, {
78
80
  measureKey: () => measureKey,
79
81
  memoryStore: () => memoryStore,
80
82
  mintClientKey: () => mintClientKey,
83
+ mintOpId: () => mintOpId,
81
84
  ok: () => ok,
82
85
  openCaptureQueue: () => openCaptureQueue,
83
86
  optionKey: () => optionKey,
84
87
  optionLabel: () => optionLabel,
85
88
  portalPath: () => portalPath,
86
89
  publicFormPath: () => publicFormPath,
90
+ rememberedOpCount: () => rememberedOpCount,
87
91
  scopeChip: () => scopeChip,
88
92
  tableShapeChanged: () => tableShapeChanged,
89
93
  useEntityFieldMutation: () => useEntityFieldMutation,
@@ -110,6 +114,45 @@ module.exports = __toCommonJS(react_exports);
110
114
  // src/react/context.tsx
111
115
  var import_react = require("react");
112
116
 
117
+ // src/ops.ts
118
+ var REMEMBER_MS = 3e4;
119
+ var REMEMBER_MAX = 500;
120
+ var ours = /* @__PURE__ */ new Map();
121
+ function trim(now) {
122
+ for (const [id, at] of ours) {
123
+ if (now - at <= REMEMBER_MS) break;
124
+ ours.delete(id);
125
+ }
126
+ while (ours.size > REMEMBER_MAX) {
127
+ const oldest = ours.keys().next();
128
+ if (oldest.done === true) break;
129
+ ours.delete(oldest.value);
130
+ }
131
+ }
132
+ function mintOpId() {
133
+ const id = crypto.randomUUID();
134
+ const now = Date.now();
135
+ ours.set(id, now);
136
+ trim(now);
137
+ return id;
138
+ }
139
+ function isOwnOp(opId) {
140
+ if (!opId) return false;
141
+ const at = ours.get(opId);
142
+ if (at === void 0) return false;
143
+ if (Date.now() - at > REMEMBER_MS) {
144
+ ours.delete(opId);
145
+ return false;
146
+ }
147
+ return true;
148
+ }
149
+ function forgetAllOps() {
150
+ ours.clear();
151
+ }
152
+ function rememberedOpCount() {
153
+ return ours.size;
154
+ }
155
+
113
156
  // src/level.ts
114
157
  var PERMISSION_LEVELS = [
115
158
  "viewer",
@@ -587,6 +630,7 @@ var STORE_DOORS = [
587
630
  { name: "read_paths_outside_the_door", args: "", returns: "TABLE(object_name text, why text)", security: "invoker" },
588
631
  { name: "read_record", args: "p_organization_id uuid, p_record_id uuid, p_by_id boolean DEFAULT false", returns: "jsonb", security: "definer" },
589
632
  { name: "read_records", args: "p_organization_id uuid, p_table_id uuid, p_by_id boolean DEFAULT false, p_limit integer DEFAULT 200, p_offset integer DEFAULT 0", returns: "TABLE(id uuid, document jsonb, level permission_level)", security: "definer" },
633
+ { name: "read_records_by_ids", args: "p_organization_id uuid, p_table_id uuid, p_record_ids uuid[], p_by_id boolean DEFAULT false", returns: "TABLE(id uuid, document jsonb, level permission_level)", security: "definer" },
590
634
  { name: "realtime_topic_admits", args: "p_topic text", returns: "boolean", security: "definer" },
591
635
  { name: "record_aggregate", args: "p_organization_id uuid, p_table_id uuid, p_group_by jsonb DEFAULT '[]'::jsonb, p_measures jsonb DEFAULT '[]'::jsonb, p_bucket jsonb DEFAULT NULL::jsonb, p_filter jsonb DEFAULT '{}'::jsonb, p_limit integer DEFAULT 200, p_required text DEFAULT 'viewer'::text", returns: "TABLE(groups jsonb, measures jsonb, row_count bigint)", security: "definer" },
592
636
  { name: "record_applicability", args: "p_organization_id uuid, p_record_id uuid", returns: "TABLE(rule_id uuid, rule_name text, rule_version integer, applies boolean, answer jsonb)", security: "invoker" },
@@ -611,6 +655,7 @@ var STORE_DOORS = [
611
655
  { name: "record_values", args: "p_organization_id uuid, p_record_id uuid", returns: "jsonb", security: "invoker" },
612
656
  { name: "record_values_of", args: "p_row custom.record", returns: "jsonb", security: "invoker" },
613
657
  { name: "record_values_versioned", args: "p_organization_id uuid, p_record_id uuid", returns: "TABLE(field_key text, field_id uuid, value jsonb, value_version integer, source jsonb, absent_reason text, actor text, on_behalf_of text, written_at timestamp with time zone, alternates jsonb)", security: "definer" },
658
+ { name: "record_words", args: "p_organization_id uuid, p_record_id uuid, p_noun text DEFAULT NULL::text", returns: "text", security: "definer" },
614
659
  { name: "record_write", args: "p_organization_id uuid, p_table_id uuid, p_data jsonb", returns: "uuid", security: "definer" },
615
660
  { name: "record_write_many", args: "p_organization_id uuid, p_table_id uuid, p_rows jsonb[], p_ids uuid[] DEFAULT NULL::uuid[]", returns: "uuid[]", security: "definer" },
616
661
  { name: "refusals_claiming_a_level_never_asked", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
@@ -811,18 +856,18 @@ var STORE_KNOBS = [
811
856
  { key: "world_publish_enabled", value: "false", type: "boolean" }
812
857
  ];
813
858
  var STORE_REFUSAL_CODES = [
814
- { code: "02000", raised_by: "_checklist_instantiate,checklist_declare,checklist_run,checklist_step_complete,checklist_step_refusal,checklist_template_shape,conversation_scope_bind,dashboard_delete,dashboard_run,doc_letterhead,doc_render_body,doc_render_document,doc_render_read,doc_sign,doc_signature_intact,doc_signature_read,doc_template_delete,doc_template_read,doc_template_save,enrich_pin,entity_field_retire,entity_field_update,entity_record_read,entity_value_write,external_history_event,external_rows,external_stub_upsert,external_writes_set,io_restore,migrate_delete,migrate_extract_parent,migrate_merge,migrate_reclass,migrate_rename,migrate_reparent,migrate_retype,migrate_split,migrate_undo,organization_clear,portal_card,portal_declare,portal_invite,portal_preview,portal_principal_bind,portal_revoke,read_record,record_delete,record_restore,record_restore_preview,record_table,record_update,relation_uncarry,share_access,share_grant,share_lane_set,share_people,share_revoke,sign_request_cancel,sign_request_create,sign_request_remind,sign_request_unchanged,table_share_outside_accept,table_share_outside_invite,table_share_outside_resend,table_share_outside_revoke,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_assign,work_record_states,work_set_state" },
859
+ { code: "02000", raised_by: "_checklist_instantiate,_table_share_invite_payload,checklist_declare,checklist_run,checklist_step_complete,checklist_step_refusal,checklist_template_shape,conversation_scope_bind,dashboard_delete,dashboard_run,doc_letterhead,doc_render_body,doc_render_document,doc_render_read,doc_sign,doc_signature_intact,doc_signature_read,doc_template_delete,doc_template_read,doc_template_save,enrich_pin,entity_field_retire,entity_field_update,entity_record_read,entity_value_write,external_history_event,external_rows,external_stub_upsert,external_writes_set,io_restore,migrate_delete,migrate_extract_parent,migrate_merge,migrate_reclass,migrate_rename,migrate_reparent,migrate_retype,migrate_split,migrate_undo,organization_clear,portal_card,portal_declare,portal_invite,portal_preview,portal_principal_bind,portal_revoke,read_record,record_delete,record_restore,record_restore_preview,record_table,record_update,relation_uncarry,share_access,share_grant,share_lane_set,share_people,share_revoke,sign_request_cancel,sign_request_create,sign_request_remind,sign_request_unchanged,table_share_outside_accept,table_share_outside_invite,table_share_outside_resend,table_share_outside_revoke,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_assign,work_record_states,work_set_state" },
815
860
  { code: "0A000", raised_by: "checklist_step_complete,external_rows,external_source_declare,external_write_through,promote_field,promoted_index_expr,promoted_query_sql,promoted_read,rule_eval,work_assign" },
816
861
  { code: "22003", raised_by: "context_resolve" },
817
862
  { code: "22004", raised_by: "_entity_custom_fields_guard,_value_envelope,actor_word,agg_assert_key,agg_sql,anon_capture,anon_token_issue,anon_write,assert_client_may_reach,booking_declare,capture_submit,checklist_declare,context_resolve,dashboard_block_normalize,dashboard_declare,dashboard_window_sql,doc_render_write,doc_sign,doc_signature_write,doc_template_save,enrich_land,enrich_normalize,external_history_event,external_rows,external_source_declare,external_stub_upsert,external_write_through,external_writes_set,field_history,form_declare,form_submit,home_add,io_comment_write,io_import_begin,io_infer_column,io_outbox_drain,io_restore,migrate_choice_keys,migrate_purge,migrate_reclass,migrate_split,migrate_undo,organization_clear,organization_contents,pipeline_declare,pipeline_gate_preview,portal_declare,portal_invite,portal_principal_bind,provenance_retention_days,provenance_write,query_across_homes,query_by_coordinates,query_rollup,record_delete,record_reparent,record_resolve,record_restore,record_update,record_write,record_write_many,relation_carry,relation_own,rule_declare,share_grant,sign_request_create,sign_request_sign,subscription_declare,table_declare,table_share_outside_invite,value_restore,view_declare,work_approval_decide,work_approval_request,work_template_declare" },
818
863
  { code: "22007", raised_by: "dashboard_window_sql" },
819
864
  { code: "22012", raised_by: "rule_eval" },
820
- { code: "22023", raised_by: "_booking_availability,_entity_custom_fields_guard,_value_envelope,_work_shape_guard,actor_word,agg_assert_key,agg_sql,anon_token_issue,booking_declare,containment_parent,dashboard_block_normalize,dashboard_window_sql,doc_render_body,doc_render_write,doc_signature_write,enrich_declare,enrich_land,enrich_normalize,enrich_pin,entity_value_write,external_history_event,external_source_declare,external_stub_upsert,external_write_through,field_history,io_export,io_import_begin,io_import_finish,io_import_plan,io_import_report,io_proposal_accept,migrate_merge,migrate_reclass,my_levels,organization_clear,page_size,pin_agent_cells,pipeline_move,portal_declare,provenance_write,query_by_coordinates,query_rollup,record_update,record_write_many,relation_carry,rule_eval,rule_members,share_grant,share_lane_set,sign_request_create,sign_request_sign,subscription_declare,table_rules,visibility_as_of,work_approval_request,work_list,work_slot_hold" },
865
+ { code: "22023", raised_by: "_booking_availability,_entity_custom_fields_guard,_take_op_id,_value_envelope,_work_shape_guard,actor_word,agg_assert_key,agg_sql,anon_token_issue,booking_declare,containment_parent,dashboard_block_normalize,dashboard_window_sql,doc_render_body,doc_render_write,doc_signature_write,enrich_declare,enrich_land,enrich_normalize,enrich_pin,entity_value_write,external_history_event,external_source_declare,external_stub_upsert,external_write_through,field_history,io_export,io_import_begin,io_import_finish,io_import_plan,io_import_report,io_proposal_accept,migrate_merge,migrate_reclass,my_levels,organization_clear,page_size,pin_agent_cells,pipeline_move,portal_declare,provenance_write,query_by_coordinates,query_rollup,record_update,record_write_many,relation_carry,rule_eval,rule_members,share_grant,share_lane_set,sign_request_create,sign_request_sign,subscription_declare,table_rules,visibility_as_of,work_approval_request,work_list,work_slot_hold" },
821
866
  { code: "23503", raised_by: "_booking_availability,_checklist_instantiate,_containment_guard,_field_document_for,_pipeline_stage_key,_record_rule_uses,agg_digest_assemble,anon_publish,anon_rate_take,anon_token_issue,anon_write,assert_organization_wall,booking_cancel,booking_confirm,booking_declare,booking_hold,booking_reschedule,capture_publish,checklist_declare,checklist_steps_table,comment_write,dashboard_declare,delete_rule,doc_sign,doc_template_save,enrich_declare,enrich_due,enrich_land,form_declare,form_submit,home_add,inbound_declare,inbound_mail_land,inbound_set,io_comment_write,io_import_begin,io_import_finish,io_import_report,io_import_rows,io_proposal_accept,migrate_demote,migrate_promote,pipeline_board,pipeline_declare,pipeline_move,pipeline_read,pipeline_transition_refusal,promote_field,promote_table,record_applicability,record_reparent,relation_carry,relation_own,resolve_first_match,rule_applies,rule_declare,rule_eval,rule_members,rule_run,sign_request_create,subscription_mute,subscription_preview,view_declare,work_set_state,work_take_assignment,work_template_instantiate" },
822
867
  { code: "23505", raised_by: "_unique_rule_holds,doc_sign,doc_signature_write,entity_field_declare,field_declare,home_add,inbound_declare,io_proposal_accept,relation_carry,relation_own,share_grant,sign_request_cancel,sign_request_create,table_share_outside_invite,table_share_outside_resend,work_approval_decide,work_slot_hold" },
823
- { code: "23514", raised_by: "_checklist_instantiate,_checklist_step_guard,_containment_guard,_dated_values_guard,_derived_fields,_entity_custom_fields_guard,_field_class_guard,_field_document_for,_field_shape_guard,_field_type_parity_guard,_merge_field_shape_guard,_merge_field_temporal_guard,_promoted_field_cap_guard,_record_rule_uses,_resolve_choice_words,_rule_shape_guard,_rule_topology_guard,_store_relation_edge_names_its_field,_table_columns_word_guard,_table_shape_guard,_undeclared_key_guard,_value_envelope,_work_shape_guard,_workdoors_approval_guard,assert_columns_are_defined,assert_entity_is_organization_scoped,capture_publish,capture_sheet_declare,checklist_declare,checklist_step_complete,doc_sign,doc_signature_write,doc_template_save,entity_field_declare,entity_field_retire,entity_field_update,entity_records_find,entity_table,field_declare,field_retire,field_update,home_add,io_import_rows,migrate_merge,relation_carry,relation_own,sign_request_create,sign_request_sign,table_declare,validate_value_envelope,validate_values,work_set_state,work_slots_declare,work_take_assignment,work_template_instantiate" },
868
+ { code: "23514", raised_by: "_checklist_instantiate,_checklist_step_guard,_containment_guard,_dated_values_guard,_derived_fields,_entity_custom_fields_guard,_field_class_guard,_field_document_for,_field_shape_guard,_field_type_parity_guard,_merge_field_shape_guard,_merge_field_temporal_guard,_promoted_field_cap_guard,_record_rule_uses,_resolve_choice_words,_rule_shape_guard,_rule_topology_guard,_store_relation_edge_names_its_field,_table_columns_word_guard,_table_shape_guard,_undeclared_key_guard,_value_envelope,_work_shape_guard,_workdoors_approval_guard,assert_columns_are_defined,assert_entity_is_organization_scoped,booking_declare,capture_publish,capture_sheet_declare,checklist_declare,checklist_step_complete,doc_sign,doc_signature_write,doc_template_save,entity_field_declare,entity_field_retire,entity_field_update,entity_records_find,entity_table,field_declare,field_retire,field_update,home_add,io_import_rows,migrate_merge,relation_carry,relation_own,sign_request_create,sign_request_sign,table_declare,validate_value_envelope,validate_values,work_set_state,work_slots_declare,work_take_assignment,work_template_instantiate" },
824
869
  { code: "40001", raised_by: "has_visibility_at" },
825
- { code: "42501", raised_by: "_doc_render_immutable,_doc_signature_immutable,_field_definition_write,_field_write_door,_rule_definition_write,_store_door,anon_capture,anon_inbound_land,anon_publish,anon_token_issue,anon_token_verify,anon_write,assert_client_may_change,assert_client_may_open,assert_client_may_reach,assert_may_know_table,assert_organization_admin,assert_store_door,booking_confirm,booking_declare,booking_hold,capture_submit,checklist_run,comment_write,conversation_scope_bind,conversation_scope_unbind,enrich_declare,enrich_due,enrich_land,enrich_normalize,entity_field_declare,entity_field_retire,entity_field_update,entity_value_write,external_write_through,form_declare,form_submit,inbound_mail_land,io_comment_resolve,io_comment_write,io_import_begin,io_import_finish,io_restore,migrate_purge,migrate_reclass,my_levels,organization_clear,portal_declare,portal_invitation,portal_invite,portal_principal_bind,promote_table,query_visibility_parity,read_record,read_records,record_table,share_grant,subscription_mute,subscription_preview,table_share_outside_accept,table_share_outside_invite,table_share_outside_resend,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_person" },
870
+ { code: "42501", raised_by: "_doc_render_immutable,_doc_signature_immutable,_field_definition_write,_field_write_door,_rule_definition_write,_store_door,anon_capture,anon_inbound_land,anon_publish,anon_token_issue,anon_token_verify,anon_write,assert_client_may_change,assert_client_may_open,assert_client_may_reach,assert_may_know_table,assert_organization_admin,assert_store_door,booking_confirm,booking_declare,booking_hold,capture_submit,checklist_run,comment_write,conversation_scope_bind,conversation_scope_unbind,enrich_declare,enrich_due,enrich_land,enrich_normalize,entity_field_declare,entity_field_retire,entity_field_update,entity_value_write,external_write_through,form_declare,form_submit,inbound_mail_land,io_comment_resolve,io_comment_write,io_import_begin,io_import_finish,io_restore,migrate_purge,migrate_reclass,my_levels,organization_clear,portal_declare,portal_invitation,portal_invite,portal_principal_bind,promote_table,query_visibility_parity,read_record,read_records,read_records_by_ids,record_table,share_grant,subscription_mute,subscription_preview,table_share_outside_accept,table_share_outside_invite,table_share_outside_resend,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_person" },
826
871
  { code: "42703", raised_by: "entity_table,portal_declare" },
827
872
  { code: "53400", raised_by: "anon_rate_take,delete_cascade_closure,enrich_due,enrich_land,promote_field" },
828
873
  { code: "54001", raised_by: "record_delete" },
@@ -1905,6 +1950,13 @@ var DOORS = {
1905
1950
  // this person could see.
1906
1951
  readRecord: "read_record",
1907
1952
  readRecords: "read_records",
1953
+ // THE SAME READ DOOR, ADDRESSED BY AN ID SET. A realtime notice names the exact ids that
1954
+ // moved; before this existed the only door that took them was the PAGE door, so a
1955
+ // three-cell change re-read fifty rows in every watching browser. It is a separate NAME
1956
+ // rather than a sixth argument to `read_records` because adding a defaulted argument to a
1957
+ // live Postgres function makes every existing call ambiguous — `is not unique`. Same
1958
+ // ladder, same level, same masking, same page ceiling.
1959
+ readRecordsByIds: "read_records_by_ids",
1908
1960
  // DOOR-8, the two clocks. `p_recorded_at` is what the store SAID then;
1909
1961
  // `p_world_on` is what was TRUE of the world on that date, read out of dated
1910
1962
  // values. A client that answered either one itself would be guessing.
@@ -2481,17 +2533,18 @@ function createRecordsClient(config) {
2481
2533
  async recordWrite({ table_id, data }) {
2482
2534
  return callDoor(
2483
2535
  DOORS.recordWrite,
2484
- { p_organization_id: org, p_table_id: table_id, p_data: data },
2536
+ { p_organization_id: org, p_table_id: table_id, p_data: { ...data, _op_id: mintOpId() } },
2485
2537
  "recordWrite"
2486
2538
  );
2487
2539
  },
2488
2540
  async recordWriteMany({ table_id, rows, ids }) {
2541
+ const opId = mintOpId();
2489
2542
  return callDoor(
2490
2543
  DOORS.recordWriteMany,
2491
2544
  {
2492
2545
  p_organization_id: org,
2493
2546
  p_table_id: table_id,
2494
- p_rows: rows,
2547
+ p_rows: rows.map((row) => ({ ...row, _op_id: opId })),
2495
2548
  ...ids === void 0 ? {} : { p_ids: ids }
2496
2549
  },
2497
2550
  "recordWriteMany"
@@ -2503,7 +2556,7 @@ function createRecordsClient(config) {
2503
2556
  {
2504
2557
  p_organization_id: org,
2505
2558
  p_record_id: record_id,
2506
- p_patch: patch,
2559
+ p_patch: { ...patch, _op_id: mintOpId() },
2507
2560
  ...expectedVersion === void 0 ? {} : { p_expected_version: expectedVersion }
2508
2561
  },
2509
2562
  "recordUpdate"
@@ -2545,6 +2598,21 @@ function createRecordsClient(config) {
2545
2598
  }
2546
2599
  return ok({ record_id, document, hidden, computed, computedUnavailable });
2547
2600
  },
2601
+ async listByIds({ table_id, ids }) {
2602
+ if (ids.length === 0) return ok([]);
2603
+ const door = await callDoor(
2604
+ DOORS.readRecordsByIds,
2605
+ { p_organization_id: org, p_table_id: table_id, p_record_ids: ids },
2606
+ "listByIds"
2607
+ );
2608
+ if (!door.ok) return err(door.error);
2609
+ return ok(
2610
+ (door.data ?? []).map((row) => {
2611
+ const { document, hidden } = unfold(row.document);
2612
+ return { id: row.id, document, level: row.level, hidden };
2613
+ })
2614
+ );
2615
+ },
2548
2616
  async list({ table_id, limit = 50, offset = 0 }) {
2549
2617
  const door = await callDoor(
2550
2618
  DOORS.readRecords,
@@ -4263,7 +4331,11 @@ function useAsync(run, deps) {
4263
4331
  };
4264
4332
  }, [client, nonce, ...deps]);
4265
4333
  const reload = (0, import_react2.useCallback)(() => setNonce((n) => n + 1), []);
4266
- return { ...state, reload };
4334
+ const setData = (0, import_react2.useCallback)((update) => {
4335
+ if (!alive.current) return;
4336
+ setState((s) => ({ ...s, data: update(s.data) }));
4337
+ }, []);
4338
+ return { ...state, reload, setData };
4267
4339
  }
4268
4340
  function useTable(tableId) {
4269
4341
  return useAsync(
@@ -4352,14 +4424,49 @@ function useRecords(tableId, options = {}) {
4352
4424
  [tableId, pageSize, page]
4353
4425
  );
4354
4426
  const realtime = client.config.realtime;
4355
- const { reload } = base;
4427
+ const { reload, setData } = base;
4356
4428
  (0, import_react2.useEffect)(() => {
4357
4429
  if (!realtime || !tableId) return;
4358
4430
  return realtime.subscribeRecords(
4359
4431
  { organization_id: client.config.organizationId, table_id: tableId },
4360
- () => reload()
4432
+ {
4433
+ records(ids) {
4434
+ if (ids === null) {
4435
+ void reload();
4436
+ return;
4437
+ }
4438
+ if (ids.length === 0) return;
4439
+ void (async () => {
4440
+ const answered = await client.listByIds({ table_id: tableId, ids });
4441
+ if (!answered.ok) {
4442
+ void reload();
4443
+ return;
4444
+ }
4445
+ const fresh = new Map(answered.data.map((row) => [row.id, row]));
4446
+ const onThisPage = (id) => (base.data?.rows ?? []).some((row) => row.id === id);
4447
+ const needsThePage = ids.some((id) => !onThisPage(id) && fresh.has(id));
4448
+ if (needsThePage) {
4449
+ void reload();
4450
+ return;
4451
+ }
4452
+ setData(
4453
+ (current) => current === null ? current : {
4454
+ ...current,
4455
+ // A named id that came back replaces the row on screen; one that did NOT
4456
+ // is a record this reader may no longer see (deleted, or unshared), so it
4457
+ // leaves the page — exactly what the page read would have done by
4458
+ // omission.
4459
+ rows: current.rows.filter((row) => !(ids.includes(row.id) && !fresh.has(row.id))).map((row) => fresh.get(row.id) ?? row)
4460
+ }
4461
+ );
4462
+ })();
4463
+ },
4464
+ shape() {
4465
+ if (tableId) tableShapeChanged(tableId);
4466
+ }
4467
+ }
4361
4468
  );
4362
- }, [realtime, tableId, client.config.organizationId, reload]);
4469
+ }, [realtime, tableId, client, reload, setData, base.data]);
4363
4470
  const live = Boolean(realtime && tableId);
4364
4471
  const liveReason = realtime ? tableId ? "Live: changes to this table re-read through the read door." : "Not live: no table selected." : "Not live: this host bound no realtime port, so this list updates when you reload it.";
4365
4472
  return { ...base, live, liveReason };