durable-actors-observer 0.4.4 → 0.4.6

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.md CHANGED
@@ -31,3 +31,11 @@ Control-plane endpoints require a project in the path: `/v1/projects/{project_id
31
31
  The observer version follows the SDK and runtime version. Run `pnpm release:prepare <version>` at the repository root before publishing a GitHub release. Release preflight checks all versions, and the workflow publishes the observer before the SDK. The SDK's `workspace:*` dependency becomes the exact observer version when packed.
32
32
 
33
33
  The localhost-only `durable-actors dev` runtime allows observability requests without a secret, even when a secret is configured for application routes. Hosted runtimes retain their configured admin authentication.
34
+
35
+ ## Persisted actor state
36
+
37
+ Select an actor instance in `ActorObserver` to inspect persisted fields, JSON types, nested values, and version diffs. Request and connection links filter the existing request history. The standard `HttpObserverClient` and `durable-actors observe` include this capability; custom clients implement `getState` and `listStateHistory` to enable it.
38
+
39
+ Values come from the actor's existing snapshot objects in the configured storage bucket, including dormant actors. Analytics stores only a state-version signal. Request events trigger a refresh; polling recovers from missed events and asynchronous bucket uploads. History uses rebuildable metadata-only sidecars beside snapshots and retains no duplicate state bodies. Available versions follow the bucket's snapshot retention/lifecycle policy.
40
+
41
+ Attribution identifies the committing request. A reentrant commit may include mutations from other interleaved requests; the UI labels this explicitly. Declared field types describe the current deployment schema, which may differ from older stored values. Inspection is read-only and uses the existing authenticated project observability API.
@@ -1,15 +1,19 @@
1
1
  export interface FilterSuggestion {
2
+ id?: string;
2
3
  group: string;
3
4
  value: string;
4
5
  hint?: string;
6
+ keywords?: string[];
5
7
  }
6
8
  export interface FilterComboboxProps {
7
9
  label: string;
8
10
  placeholder: string;
9
11
  value: string;
10
12
  onChange: (value: string) => void;
13
+ onSelectSuggestion?: (suggestion: FilterSuggestion) => void;
11
14
  suggestions: FilterSuggestion[];
12
15
  limit?: number;
16
+ className?: string;
13
17
  }
14
- export declare function FilterCombobox({ label, placeholder, value, onChange, suggestions, limit }: FilterComboboxProps): import("react").JSX.Element;
15
- export declare function matchSuggestions(suggestions: FilterSuggestion[], value: string, limit: number): FilterSuggestion[];
18
+ export declare function FilterCombobox({ label, placeholder, value, onChange, onSelectSuggestion, suggestions, limit, className }: FilterComboboxProps): import("react").JSX.Element;
19
+ export declare function matchSuggestions(suggestions: FilterSuggestion[], value: string, limit: number, includeExactMatches?: boolean): FilterSuggestion[];
@@ -1,11 +1,15 @@
1
1
  import type { ObserverClient, RequestTrace } from "./client.js";
2
2
  import type { TimeRange } from "./time-range.js";
3
3
  interface RequestObserverProps {
4
+ focus?: {
5
+ requestId?: string;
6
+ connectionId?: string;
7
+ };
4
8
  client: Pick<ObserverClient, "watchRequests" | "listRequests">;
5
9
  actor?: Pick<RequestTrace, "actorName" | "actorId">;
6
10
  timeRange?: TimeRange;
7
11
  onTimeRangeChange?: (range: TimeRange) => void;
8
12
  }
9
- declare function RequestObserver({ client, actor, timeRange, onTimeRangeChange }: RequestObserverProps): import("react").JSX.Element;
13
+ declare function RequestObserver({ client, actor, timeRange, onTimeRangeChange, focus }: RequestObserverProps): import("react").JSX.Element;
10
14
  export { RequestObserver };
11
15
  export type { RequestObserverProps };
@@ -0,0 +1,13 @@
1
+ import type { ObserverClient } from "./client.js";
2
+ type Focus = {
3
+ requestId?: string;
4
+ connectionId?: string;
5
+ };
6
+ interface Props {
7
+ client: ObserverClient;
8
+ actorName: string;
9
+ actorId: string;
10
+ onInspectRequest?: (focus: Focus) => void;
11
+ }
12
+ export declare function StateInspector(props: Props): import("react").JSX.Element;
13
+ export {};
@@ -0,0 +1,18 @@
1
+ (function(){function e(e){let t=/^\/(.*)\/([gimyu]*)$/.exec(e.toString());if(!t)throw Error(`Invalid RegExp`);return new RegExp(t[1]??``,t[2])}function t(n){if(typeof n!=`object`)return n;if(n===null)return null;if(Array.isArray(n))return n.map(t);if(n instanceof Date)return new Date(n.getTime());if(n instanceof RegExp)return e(n);let r={};for(let e in n)Object.prototype.hasOwnProperty.call(n,e)&&(r[e]=t(n[e]));return r}function n(e,t){if(e.length===0)throw Error(t||`Expected a non-empty array`)}function r(e,t){if(e.length<2)throw Error(t||`Expected an array with at least 2 items`)}let i=e=>e[e.length-1];var a=class{setResult(e){return this.result=e,this.hasResult=!0,this}exit(){return this.exiting=!0,this}push(e,t){return e.parent=this,t!==void 0&&(e.childName=t),e.root=this.root||this,e.options=e.options||this.options,this.children?(n(this.children),i(this.children).next=e,this.children.push(e)):(this.children=[e],this.nextAfterChildren=this.next||null,this.next=e),e.next=this,this}},o=class extends a{constructor(e,t){super(),this.left=e,this.right=t,this.pipe=`diff`}prepareDeltaResult(e){if(typeof e==`object`&&(this.options?.omitRemovedValues&&Array.isArray(e)&&e.length>1&&(e.length===2||e[2]===0||e[2]===3)&&(e[0]=0),this.options?.cloneDiffValues)){let n=typeof this.options?.cloneDiffValues==`function`?this.options?.cloneDiffValues:t;typeof e[0]==`object`&&(e[0]=n(e[0])),typeof e[1]==`object`&&(e[1]=n(e[1]))}return e}setResult(e){return this.prepareDeltaResult(e),super.setResult(e)}},s=class extends a{constructor(e,t){super(),this.left=e,this.delta=t,this.pipe=`patch`}},c=class extends a{constructor(e){super(),this.delta=e,this.pipe=`reverse`}},l=class{constructor(e){this.name=e,this.filters=[]}process(e){if(!this.processor)throw Error(`add this pipe to a processor before using it`);let t=this.debug,n=this.filters.length,r=e;for(let e=0;e<n;e++){let n=this.filters[e];if(n&&(t&&this.log(`filter: ${n.filterName}`),n(r),typeof r==`object`&&r.exiting)){r.exiting=!1;break}}!r.next&&this.resultCheck&&this.resultCheck(r)}log(e){console.log(`[jsondiffpatch] ${this.name} pipe, ${e}`)}append(...e){return this.filters.push(...e),this}prepend(...e){return this.filters.unshift(...e),this}indexOf(e){if(!e)throw Error(`a filter name is required`);for(let t=0;t<this.filters.length;t++)if(this.filters[t]?.filterName===e)return t;throw Error(`filter not found: ${e}`)}list(){return this.filters.map(e=>e.filterName)}after(e,...t){let n=this.indexOf(e);return this.filters.splice(n+1,0,...t),this}before(e,...t){let n=this.indexOf(e);return this.filters.splice(n,0,...t),this}replace(e,...t){let n=this.indexOf(e);return this.filters.splice(n,1,...t),this}remove(e){let t=this.indexOf(e);return this.filters.splice(t,1),this}clear(){return this.filters.length=0,this}shouldHaveResult(e){return e===!1?(this.resultCheck=null,this):(this.resultCheck||=e=>{if(!e.hasResult){console.log(e);let t=Error(`${this.name} failed`);throw t.noResult=!0,t}},this)}},u=class{constructor(e){this.selfOptions=e||{},this.pipes={}}options(e){return e&&(this.selfOptions=e),this.selfOptions}pipe(e,t){let n=t;if(typeof e==`string`){if(n===void 0)return this.pipes[e];this.pipes[e]=n}if(e&&e.name){if(n=e,n.processor===this)return n;this.pipes[n.name]=n}if(!n)throw Error(`pipe is not defined: ${e}`);return n.processor=this,n}process(e,t){let n=e;n.options=this.options();let r=t||e.pipe||`default`,i;for(;r;)n.nextAfterChildren!==void 0&&(n.next=n.nextAfterChildren,n.nextAfterChildren=null),typeof r==`string`&&(r=this.pipe(r)),r.process(n),i=r,r=null,n&&n.next&&(n=n.next,r=n.pipe||i);return n.hasResult?n.result:void 0}};let d=(e,t,n,r)=>e[n]===t[r],f=(e,t,n,r)=>{let i=e.length,a=t.length,o,s,c=Array(i+1);for(o=0;o<i+1;o++){let e=Array(a+1);for(s=0;s<a+1;s++)e[s]=0;c[o]=e}for(c.match=n,o=1;o<i+1;o++){let i=c[o];if(i===void 0)throw Error(`LCS matrix row is undefined`);let l=c[o-1];if(l===void 0)throw Error(`LCS matrix row is undefined`);for(s=1;s<a+1;s++)n(e,t,o-1,s-1,r)?i[s]=(l[s-1]??0)+1:i[s]=Math.max(l[s]??0,i[s-1]??0)}return c},p=(e,t,n,r)=>{let i=t.length,a=n.length,o={sequence:[],indices1:[],indices2:[]};for(;i!==0&&a!==0;){if(e.match===void 0)throw Error(`LCS matrix match function is undefined`);if(e.match(t,n,i-1,a-1,r))o.sequence.unshift(t[i-1]),o.indices1.unshift(i-1),o.indices2.unshift(a-1),--i,--a;else{let t=e[i];if(t===void 0)throw Error(`LCS matrix row is undefined`);let n=t[a-1];if(n===void 0)throw Error(`LCS matrix value is undefined`);let r=e[i-1];if(r===void 0)throw Error(`LCS matrix row is undefined`);let o=r[a];if(o===void 0)throw Error(`LCS matrix value is undefined`);n>o?--a:--i}}return o};var m={get:(e,t,n,r)=>{let i=r||{},a=f(e,t,n||d,i);return p(a,e,t,i)}};function h(e,t,n,r){for(let i=0;i<n;i++){let n=e[i];for(let e=0;e<r;e++){let r=t[e];if(i!==e&&n===r)return!0}}return!1}function g(e,t,n,r,i){let a=e[n],o=t[r];if(a===o)return!0;if(typeof a!=`object`||typeof o!=`object`)return!1;let s=i.objectHash;if(!s)return i.matchByPosition&&n===r;i.hashCache1=i.hashCache1||[];let c=i.hashCache1[n];if(c===void 0&&(i.hashCache1[n]=c=s(a,n)),c===void 0)return!1;i.hashCache2=i.hashCache2||[];let l=i.hashCache2[r];return l===void 0&&(i.hashCache2[r]=l=s(o,r)),l!==void 0&&c===l}let _=function(e){if(!e.leftIsArray)return;let t={objectHash:e.options?.objectHash,matchByPosition:e.options?.matchByPosition},n=0,r=0,i,a,s,c=e.left,l=e.right,u=c.length,d=l.length,f;for(u>0&&d>0&&!t.objectHash&&typeof t.matchByPosition!=`boolean`&&(t.matchByPosition=!h(c,l,u,d));n<u&&n<d&&g(c,l,n,n,t);)i=n,f=new o(c[i],l[i]),e.push(f,i),n++;for(;r+n<u&&r+n<d&&g(c,l,u-1-r,d-1-r,t);)a=u-1-r,s=d-1-r,f=new o(c[a],l[s]),e.push(f,s),r++;let p;if(n+r===u){if(u===d){e.setResult(void 0).exit();return}for(p||={_t:`a`},i=n;i<d-r;i++)p[i]=[l[i]],e.prepareDeltaResult(p[i]);e.setResult(p).exit();return}if(n+r===d){for(p||={_t:`a`},i=n;i<u-r;i++){let t=`_${i}`;p[t]=[c[i],0,0],e.prepareDeltaResult(p[t])}e.setResult(p).exit();return}t.hashCache1=void 0,t.hashCache2=void 0;let _=c.slice(n,u-r),v=l.slice(n,d-r),y=m.get(_,v,g,t),b=[];for(p||={_t:`a`},i=n;i<u-r;i++)if(y.indices1.indexOf(i-n)<0){let t=`_${i}`;p[t]=[c[i],0,0],e.prepareDeltaResult(p[t]),b.push(i)}let x=!0;e.options?.arrays&&e.options.arrays.detectMove===!1&&(x=!1);let S=!1;e.options?.arrays?.includeValueOnMove&&(S=!0);let C=b.length;for(i=n;i<d-r;i++){let r=y.indices2.indexOf(i-n);if(r<0){let r=!1;if(x&&C>0)for(let u=0;u<C;u++){a=b[u];let d=a===void 0?void 0:p[`_${a}`];if(a!==void 0&&d&&g(_,v,a-n,i-n,t)){d.splice(1,2,i,3),d.splice(1,2,i,3),S||(d[0]=``),s=i,f=new o(c[a],l[s]),e.push(f,s),b.splice(u,1),r=!0;break}}r||(p[i]=[l[i]],e.prepareDeltaResult(p[i]))}else{if(y.indices1[r]===void 0)throw Error(`Invalid indexOnArray2: ${r}, seq.indices1: ${y.indices1}`);if(a=y.indices1[r]+n,y.indices2[r]===void 0)throw Error(`Invalid indexOnArray2: ${r}, seq.indices2: ${y.indices2}`);s=y.indices2[r]+n,f=new o(c[a],l[s]),e.push(f,s)}}e.setResult(p).exit()};_.filterName=`arrays`;let v={numerically(e,t){return e-t},numericallyBy(e){return(t,n)=>t[e]-n[e]}},y=function(e){if(!e.nested)return;let t=e.delta;if(t._t!==`a`)return;let n,r,i=t,a=e.left,o=[],c=[],l=[];for(n in i)if(n!==`_t`){if(n[0]===`_`){let e=n;if(i[e]!==void 0&&(i[e][2]===0||i[e][2]===3))o.push(Number.parseInt(n.slice(1),10));else throw Error(`only removal or move can be applied at original array indices, invalid diff type: ${i[e]?.[2]}`)}else{let e=n;i[e].length===1?c.push({index:Number.parseInt(e,10),value:i[e][0]}):l.push({index:Number.parseInt(e,10),delta:i[e]})}}for(o=o.sort(v.numerically),n=o.length-1;n>=0;n--){if(r=o[n],r===void 0)continue;let e=i[`_${r}`],t=a.splice(r,1)[0];e?.[2]===3&&c.push({index:e[1],value:t})}c=c.sort(v.numericallyBy(`index`));let u=c.length;for(n=0;n<u;n++){let e=c[n];e!==void 0&&a.splice(e.index,0,e.value)}let d=l.length;if(d>0)for(n=0;n<d;n++){let t=l[n];if(t===void 0)continue;let r=new s(a[t.index],t.delta);e.push(r,t.index)}if(!e.children){e.setResult(a).exit();return}e.exit()};y.filterName=`arrays`;let b=function(e){if(!e||!e.children||e.delta._t!==`a`)return;let t=e.left,n=e.children.length;for(let r=0;r<n;r++){let n=e.children[r];if(n===void 0)continue;let i=n.childName;t[i]=n.result}e.setResult(t).exit()};b.filterName=`arraysCollectChildren`;let x=function(e){if(!e.nested){let t=e.delta;if(t[2]===3){let n=t;e.newName=`_${n[1]}`,e.setResult([n[0],Number.parseInt(e.childName.substring(1),10),3]).exit()}return}let t=e.delta;if(t._t!==`a`)return;let n=t;for(let t in n){if(t===`_t`)continue;let r=new c(n[t]);e.push(r,t)}e.exit()};x.filterName=`arrays`;let S=(e,t,n)=>{if(typeof t==`string`&&t[0]===`_`)return Number.parseInt(t.substring(1),10);if(Array.isArray(n)&&n[2]===0)return`_${t}`;let r=+t;for(let n in e){let i=e[n];if(Array.isArray(i)){if(i[2]===3){let e=Number.parseInt(n.substring(1),10),a=i[1];if(a===+t)return e;e<=r&&a>r?r++:e>=r&&a<r&&r--}else i[2]===0?Number.parseInt(n.substring(1),10)<=r&&r++:i.length===1&&Number.parseInt(n,10)<=r&&r--}}return r},C=e=>{if(!e||!e.children)return;let t=e.delta;if(t._t!==`a`)return;let n=t,r=e.children.length,i={_t:`a`};for(let t=0;t<r;t++){let r=e.children[t];if(r===void 0)continue;let a=r.newName;if(a===void 0){if(r.childName===void 0)throw Error(`child.childName is undefined`);a=S(n,r.childName,r.result)}i[a]!==r.result&&(i[a]=r.result)}e.setResult(i).exit()};C.filterName=`arraysCollectChildren`;let w=function(e){e.left instanceof Date?(e.right instanceof Date&&e.left.getTime()===e.right.getTime()?e.setResult(void 0):e.setResult([e.left,e.right]),e.exit()):e.right instanceof Date&&e.setResult([e.left,e.right]).exit()};w.filterName=`dates`;let T=new Set([`__proto__`]),E=e=>{if(!e||!e.children)return;let t=e.children.length,n=e.result;for(let r=0;r<t;r++){let t=e.children[r];if(t!==void 0&&t.result!==void 0){if(n||={},t.childName===void 0)throw Error(`diff child.childName is undefined`);n[t.childName]=t.result}}n&&e.leftIsArray&&(n._t=`a`),e.setResult(n).exit()};E.filterName=`collectChildren`;let D=e=>{if(e.leftIsArray||e.leftType!==`object`)return;let t=e.left,n=e.right,r=e.options?.propertyFilter;for(let i in t){if(!Object.prototype.hasOwnProperty.call(t,i)||r&&!r(i,e))continue;let a=new o(t[i],n[i]);e.push(a,i)}for(let i in n)if(Object.prototype.hasOwnProperty.call(n,i)&&(!r||r(i,e))&&t[i]===void 0){let t=new o(void 0,n[i]);e.push(t,i)}if(!e.children||e.children.length===0){e.setResult(void 0).exit();return}e.exit()};D.filterName=`objects`;let O=function(e){if(!e.nested)return;let t=e.delta;if(t._t)return;let n=t,r=!1;for(let t in n){if(T.has(t)||!Object.prototype.hasOwnProperty.call(n,t))continue;let i=e.left,a=new s(typeof i==`object`&&i&&Object.prototype.hasOwnProperty.call(i,t)?i[t]:void 0,n[t]);e.push(a,t),r=!0}if(!r){e.setResult(e.left).exit();return}e.exit()};O.filterName=`objects`;let k=function(e){if(!e||!e.children||e.delta._t)return;if(e.left===null||typeof e.left!=`object`){e.setResult(e.left).exit();return}let t=e.left,n=e.children.length;for(let r=0;r<n;r++){let n=e.children[r];if(n===void 0)continue;let i=n.childName;T.has(i)||(Object.prototype.hasOwnProperty.call(e.left,i)&&n.result===void 0?delete t[i]:t[i]!==n.result&&(t[i]=n.result))}e.setResult(t).exit()};k.filterName=`collectChildren`;let A=function(e){if(!e.nested||e.delta._t)return;let t=e.delta,n=!1;for(let r in t){if(T.has(r)||!Object.prototype.hasOwnProperty.call(t,r))continue;let i=new c(t[r]);e.push(i,r),n=!0}if(!n){e.setResult({}).exit();return}e.exit()};A.filterName=`objects`;let j=e=>{if(!e||!e.children||e.delta._t)return;let t=e.children.length,n={};for(let r=0;r<t;r++){let t=e.children[r];if(t===void 0)continue;let i=t.childName;T.has(i)||n[i]!==t.result&&(n[i]=t.result)}e.setResult(n).exit()};j.filterName=`collectChildren`;let M=null;function N(e,t){if(!M){let n;if(e?.textDiff?.diffMatchPatch)n=new e.textDiff.diffMatchPatch;else{if(!t)return null;let e=Error("The diff-match-patch library was not provided. Pass the library in through the options or use the `jsondiffpatch/with-text-diffs` entry-point.");throw e.diff_match_patch_not_found=!0,e}M={diff:(e,t)=>n.patch_toText(n.patch_make(e,t)),patch:(e,t)=>{let r=n.patch_apply(n.patch_fromText(t),e);for(let e of r[1])if(!e){let e=Error(`text patch failed`);throw e.textPatchFailed=!0,e}return r[0]}}}return M}let P=function(e){if(e.leftType!==`string`)return;let t=e.left,n=e.right,r=e.options?.textDiff?.minLength||60;if(t.length<r||n.length<r){e.setResult([t,n]).exit();return}let i=N(e.options);if(!i){e.setResult([t,n]).exit();return}let a=i.diff;e.setResult([a(t,n),0,2]).exit()};P.filterName=`texts`;let F=function(e){if(e.nested)return;let t=e.delta;if(t[2]!==2)return;let n=t,r=N(e.options,!0).patch;e.setResult(r(e.left,n[0])).exit()};F.filterName=`texts`;let I=e=>{let t=/^@@ +-(\d+),(\d+) +\+(\d+),(\d+) +@@$/,n=e.split(`
2
+ `);for(let e=0;e<n.length;e++){let r=n[e];if(r===void 0)continue;let i=r.slice(0,1);if(i===`@`){let i=t.exec(r);if(i!==null){let t=e;n[t]=`@@ -${i[3]},${i[4]} +${i[1]},${i[2]} @@`}}else if(i===`+`){if(n[e]=`-${n[e]?.slice(1)}`,n[e-1]?.slice(0,1)===`+`){let t=n[e];n[e]=n[e-1],n[e-1]=t}}else i===`-`&&(n[e]=`+${n[e]?.slice(1)}`)}return n.join(`
3
+ `)},L=function(e){if(e.nested)return;let t=e.delta;if(t[2]!==2)return;let n=t;e.setResult([I(n[0]),0,2]).exit()};L.filterName=`texts`;let R=function(e){if(e.left===e.right){e.setResult(void 0).exit();return}if(e.left===void 0){if(typeof e.right==`function`)throw Error(`functions are not supported`);e.setResult([e.right]).exit();return}if(e.right===void 0){e.setResult([e.left,0,0]).exit();return}if(typeof e.left==`function`||typeof e.right==`function`)throw Error(`functions are not supported`);if(e.leftType=e.left===null?`null`:typeof e.left,e.rightType=e.right===null?`null`:typeof e.right,e.leftType!==e.rightType){e.setResult([e.left,e.right]).exit();return}if(e.leftType===`boolean`||e.leftType===`number`){e.setResult([e.left,e.right]).exit();return}if(e.leftType===`object`&&(e.leftIsArray=Array.isArray(e.left)),e.rightType===`object`&&(e.rightIsArray=Array.isArray(e.right)),e.leftIsArray!==e.rightIsArray){e.setResult([e.left,e.right]).exit();return}e.left instanceof RegExp&&(e.right instanceof RegExp?e.setResult([e.left.toString(),e.right.toString()]).exit():e.setResult([e.left,e.right]).exit())};R.filterName=`trivial`;let z=function(e){if(e.delta===void 0){e.setResult(e.left).exit();return}if(e.nested=!Array.isArray(e.delta),e.nested)return;let t=e.delta;if(t.length===1){e.setResult(t[0]).exit();return}if(t.length===2){if(e.left instanceof RegExp){let n=/^\/(.*)\/([gimyu]+)$/.exec(t[1]);if(n?.[1]){e.setResult(new RegExp(n[1],n[2])).exit();return}}e.setResult(t[1]).exit();return}t.length===3&&t[2]===0&&e.setResult(void 0).exit()};z.filterName=`trivial`;let B=function(e){if(e.delta===void 0){e.setResult(e.delta).exit();return}if(e.nested=!Array.isArray(e.delta),e.nested)return;let t=e.delta;if(t.length===1){e.setResult([t[0],0,0]).exit();return}if(t.length===2){e.setResult([t[1],t[0]]).exit();return}t.length===3&&t[2]===0&&e.setResult([t[0]]).exit()};B.filterName=`trivial`;var V=class{constructor(e){this.processor=new u(e),this.processor.pipe(new l(`diff`).append(E,R,w,P,D,_).shouldHaveResult()),this.processor.pipe(new l(`patch`).append(k,b,z,F,O,y).shouldHaveResult()),this.processor.pipe(new l(`reverse`).append(j,C,B,L,A,x).shouldHaveResult())}options(e){return this.processor.options(e)}diff(e,t){return this.processor.process(new o(e,t))}patch(e,t){return this.processor.process(new s(e,t))}reverse(e){return this.processor.process(new c(e))}unpatch(e,t){return this.patch(e,this.reverse(t))}clone(e){return t(e)}};function H(e){return new V(e)}var U=class{format(e,t){let n={};this.prepareContext(n);let r=n;return this.recurse(r,e,t),this.finalize(r)}prepareContext(e){e.buffer=[],e.out=function(...e){if(!this.buffer)throw Error(`context buffer is not initialized`);this.buffer.push(...e)}}typeFormattterNotFound(e,t){throw Error(`cannot format delta type: ${t}`)}typeFormattterErrorFormatter(e,t,n,r,i,a,o){}finalize({buffer:e}){return Array.isArray(e)?e.join(``):``}recurse(e,t,n,r,i,a,o){let s=t&&a?a.value:n;if(t===void 0&&r===void 0)return;let c=this.getDeltaType(t,a),l=c===`node`?t._t===`a`?`array`:`object`:``;r===void 0?this.rootBegin(e,c,l):this.nodeBegin(e,r,i,c,l,o??!1);let u;try{u=c===`unknown`?this.typeFormattterNotFound(e,c):this[`format_${c}`],u.call(this,e,t,s,r,i,a)}catch(n){this.typeFormattterErrorFormatter(e,n,t,s,r,i,a),typeof console<`u`&&console.error&&console.error(n.stack)}r===void 0?this.rootEnd(e,c,l):this.nodeEnd(e,r,i,c,l,o??!1)}formatDeltaChildren(e,t,n){this.forEachDeltaKey(t,n,(r,i,a,o)=>{this.recurse(e,t[r],n?n[i]:void 0,r,i,a,o)})}forEachDeltaKey(e,t,n){let r=[];if(e._t!==`a`){let i=Object.keys(e);typeof t==`object`&&t&&r.push(...Object.keys(t));for(let e of i)r.indexOf(e)>=0||r.push(e);for(let e=0;e<r.length;e++){let t=r[e];t!==void 0&&n(t,t,void 0,e===r.length-1)}return}let i={};for(let t in e)if(Object.prototype.hasOwnProperty.call(e,t)){let n=e[t];if(Array.isArray(n)&&n[2]===3){let e=n;i[e[1]]=Number.parseInt(t.substring(1))}}let a=e,o=0,s=0,c=Array.isArray(t)?t:void 0,l=c?c.length:Object.keys(a).reduce((e,t)=>{if(t===`_t`)return e;if(t.substring(0,1)===`_`){let n=a[t],r=Number.parseInt(t.substring(1)),i=Array.isArray(n)&&n.length>=3&&n[2]===3?n[1]:void 0,o=Math.max(r,i??0);return o>e?o:e}let n=Number.parseInt(t),r=i[n],o=Math.max(r??0,n??0);return o>e?o:e},0)+1,u=l,d,f=(...e)=>{d&&n(...d),d=e},p=()=>{d&&n(d[0],d[1],d[2],!0)};for(;o<l||s<u||`${s}`in a;){let e=!1,t=`_${o}`,n=`${s}`,r=s in i?i[s]:void 0;if(t in a){e=!0;let n=a[t];f(t,r??o,r?{key:`_${r}`,value:c?c[r]:void 0}:void 0,!1),Array.isArray(n)?n[2]===0?(u--,o++):(n[2],o++):o++}if(n in a){e=!0;let t=a[n],i=Array.isArray(t)&&t.length===1;f(n,r??o,r?{key:`_${r}`,value:c?c[r]:void 0}:void 0,!1),i?(u++,s++):(r===void 0&&o++,s++)}e||((c&&r===void 0||this.includeMoveDestinations!==!1)&&f(n,r??o,r?{key:`_${r}`,value:c?c[r]:void 0}:void 0,!1),r===void 0&&o++,s++)}p()}getDeltaType(e,t){if(e===void 0)return t===void 0?`unchanged`:`movedestination`;if(Array.isArray(e)){if(e.length===1)return`added`;if(e.length===2)return`modified`;if(e.length===3&&e[2]===0)return`deleted`;if(e.length===3&&e[2]===2)return`textdiff`;if(e.length===3&&e[2]===3)return`moved`}else if(typeof e==`object`)return`node`;return`unknown`}parseTextDiff(e){let t=[],n=e.split(`
4
+ @@ `);for(let e of n){let n={pieces:[]},i=/^(?:@@ )?[-+]?(\d+),(\d+)/.exec(e)?.slice(1);if(!i)throw Error(`invalid text diff format`);r(i),n.location={line:i[0],chr:i[1]};let a=e.split(`
5
+ `).slice(1);for(let e=0,t=a.length;e<t;e++){let t=a[e];if(t===void 0||!t.length)continue;let r={type:`context`};t.substring(0,1)===`+`?r.type=`added`:t.substring(0,1)===`-`&&(r.type=`deleted`),r.text=t.slice(1),n.pieces.push(r)}t.push(n)}return t}},W=class extends U{typeFormattterErrorFormatter(e,t){let n=typeof t==`object`&&t&&`message`in t&&typeof t.message==`string`?t.message:String(t);e.out(`<pre class="jsondiffpatch-error">${G(n)}</pre>`)}formatValue(e,t){let n=t===void 0?`undefined`:G(JSON.stringify(t,null,2));e.out(`<pre>${n}</pre>`)}formatTextDiffString(e,t){let n=this.parseTextDiff(t);e.out(`<ul class="jsondiffpatch-textdiff">`);for(let t=0,r=n.length;t<r;t++){let r=n[t];if(r===void 0)return;e.out(`<li><div class="jsondiffpatch-textdiff-location"><span class="jsondiffpatch-textdiff-line-number">${r.location.line}</span><span class="jsondiffpatch-textdiff-char">${r.location.chr}</span></div><div class="jsondiffpatch-textdiff-line">`);let i=r.pieces;for(let t=0,n=i.length;t<n;t++){let n=i[t];if(n===void 0)return;e.out(`<span class="jsondiffpatch-textdiff-${n.type}">${G(decodeURI(n.text))}</span>`)}e.out(`</div></li>`)}e.out(`</ul>`)}rootBegin(e,t,n){let r=`jsondiffpatch-${t}${n?` jsondiffpatch-child-node-type-${n}`:``}`;e.out(`<div class="jsondiffpatch-delta ${r}">`)}rootEnd(e){e.out(`</div>${e.hasArrows?`<script type="text/javascript">setTimeout(${K.toString()},10);<\/script>`:``}`)}nodeBegin(e,t,n,r,i){let a=`jsondiffpatch-${r}${i?` jsondiffpatch-child-node-type-${i}`:``}`,o=typeof n==`number`&&t.substring(0,1)===`_`?t.substring(1):t;e.out(`<li class="${a}" data-key="${G(t)}"><div class="jsondiffpatch-property-name">${G(o)}</div>`)}nodeEnd(e){e.out(`</li>`)}format_unchanged(e,t,n){n!==void 0&&(e.out(`<div class="jsondiffpatch-value">`),this.formatValue(e,n),e.out(`</div>`))}format_movedestination(e,t,n){n!==void 0&&(e.out(`<div class="jsondiffpatch-value">`),this.formatValue(e,n),e.out(`</div>`))}format_node(e,t,n){let r=t._t===`a`?`array`:`object`;e.out(`<ul class="jsondiffpatch-node jsondiffpatch-node-type-${r}">`),this.formatDeltaChildren(e,t,n),e.out(`</ul>`)}format_added(e,t){e.out(`<div class="jsondiffpatch-value">`),this.formatValue(e,t[0]),e.out(`</div>`)}format_modified(e,t){e.out(`<div class="jsondiffpatch-value jsondiffpatch-left-value">`),this.formatValue(e,t[0]),e.out(`</div><div class="jsondiffpatch-value jsondiffpatch-right-value">`),this.formatValue(e,t[1]),e.out(`</div>`)}format_deleted(e,t){e.out(`<div class="jsondiffpatch-value">`),this.formatValue(e,t[0]),e.out(`</div>`)}format_moved(e,t){e.out(`<div class="jsondiffpatch-value">`),this.formatValue(e,t[0]),e.out(`</div><div class="jsondiffpatch-moved-destination">${t[1]}</div>`),e.out(`<div class="jsondiffpatch-arrow" style="position: relative; left: -34px;">
6
+ <svg width="30" height="60" style="position: absolute; display: none;">
7
+ <defs>
8
+ <marker id="markerArrow" markerWidth="8" markerHeight="8"
9
+ refx="2" refy="4" stroke="#88f"
10
+ orient="auto" markerUnits="userSpaceOnUse">
11
+ <path d="M1,1 L1,7 L7,4 L1,1" style="fill: #339;" />
12
+ </marker>
13
+ </defs>
14
+ <path d="M30,0 Q-10,25 26,50"
15
+ style="stroke: #88f; stroke-width: 2px; fill: none; stroke-opacity: 0.5; marker-end: url(#markerArrow);"
16
+ ></path>
17
+ </svg>
18
+ </div>`),e.hasArrows=!0}format_textdiff(e,t){e.out(`<div class="jsondiffpatch-value">`),this.formatTextDiffString(e,t[0]),e.out(`</div>`)}};function G(e){if(typeof e==`number`)return e;let t=String(e);for(let e of[[/&/g,`&amp;`],[/</g,`&lt;`],[/>/g,`&gt;`],[/'/g,`&apos;`],[/"/g,`&quot;`]])t=t.replace(e[0],e[1]);return t}let K=function(e){let t=e||document,n=({textContent:e,innerText:t})=>e||t,r=(e,t,n)=>{let r=e.querySelectorAll(t);for(let e=0,t=r.length;e<t;e++)n(r[e])},i=({children:e},t)=>{for(let n=0,r=e.length;n<r;n++){let r=e[n];r&&t(r,n)}};r(t,`.jsondiffpatch-arrow`,({parentNode:e,children:t,style:r})=>{let a=e,o=t[0],s=o.children[1];o.style.display=`none`;let c=a.querySelector(`.jsondiffpatch-moved-destination`);if(!(c instanceof HTMLElement))return;let l=n(c),u=a.parentNode;if(!u)return;let d;if(i(u,e=>{e.getAttribute(`data-key`)===l&&(d=e)}),d)try{let e=d.offsetTop-a.offsetTop;o.setAttribute(`height`,`${Math.abs(e)+6}`),r.top=`${-8+(e>0?0:e)}px`;let t=e>0?`M30,0 Q-10,${Math.round(e/2)} 26,${e-4}`:`M30,${-e} Q-10,${Math.round(-e/2)} 26,4`;s.setAttribute(`d`,t),o.style.display=``}catch(e){console.debug(`[jsondiffpatch] error adjusting arrows: ${e}`)}})},q;function J(e,t){return q||=new W,q.format(e,t)}let Y=H({arrays:{detectMove:!1}});function X(e,t){let n=Y.diff(e,t);return n?J(n,e)??``:``}self.onmessage=e=>{try{self.postMessage({html:X(e.data.before,e.data.after)})}catch{self.postMessage({error:`Could not compare these versions.`})}}})();
package/dist/client.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { type OverviewMetrics } from "./overview-metrics.js";
2
2
  import { type QueueWaitRow } from "./queue-wait.js";
3
3
  import { type SocketSessionRow } from "./socket-sessions.js";
4
+ import { type StateHistoryPage, type StateQuery, type StateResponse } from "./state-data.js";
4
5
  import type { ResolvedRange } from "./time-range.js";
5
6
  type ActorResidency = "live" | "dormant" | "unknown";
6
7
  interface ActorInstance {
@@ -26,6 +27,11 @@ interface ActorInventory {
26
27
  }[];
27
28
  }
28
29
  interface ObserverClient {
30
+ getState?(query: StateQuery, signal?: AbortSignal): Promise<StateResponse>;
31
+ listStateHistory?(query: Omit<StateQuery, "version"> & {
32
+ before?: number;
33
+ limit?: number;
34
+ }, signal?: AbortSignal): Promise<StateHistoryPage>;
29
35
  getMetrics?(range: ResolvedRange, signal?: AbortSignal): Promise<OverviewMetrics>;
30
36
  listQueueWaits?(query: ResolvedRange & {
31
37
  actorName?: string;
@@ -41,6 +47,11 @@ declare class HttpObserverClient implements ObserverClient {
41
47
  private readonly baseUrl;
42
48
  private readonly request;
43
49
  constructor(baseUrl?: string, request?: typeof fetch);
50
+ getState(query: StateQuery, signal?: AbortSignal): Promise<StateResponse>;
51
+ listStateHistory(query: Omit<StateQuery, "version"> & {
52
+ before?: number;
53
+ limit?: number;
54
+ }, signal?: AbortSignal): Promise<StateHistoryPage>;
44
55
  getMetrics(range: ResolvedRange, signal?: AbortSignal): Promise<OverviewMetrics>;
45
56
  listQueueWaits(query: ResolvedRange & {
46
57
  actorName?: string;
@@ -57,6 +68,7 @@ declare class HttpObserverClient implements ObserverClient {
57
68
  export { HttpObserverClient };
58
69
  export type { ActorConnection, ActorInstance, ActorInventory, ActorResidency, ObserverClient };
59
70
  export interface RequestTrace {
71
+ stateVersion?: number;
60
72
  projectId: string;
61
73
  metadata?: unknown;
62
74
  eventId?: string;
@@ -75,6 +87,8 @@ export interface RequestTrace {
75
87
  outcome: "completed" | "failed" | "rejected" | "rerouted" | "interrupted";
76
88
  }
77
89
  export interface RequestHistoryQuery {
90
+ requestId?: string;
91
+ connectionId?: string;
78
92
  actorName?: string;
79
93
  actorId?: string;
80
94
  outcome?: RequestTrace["outcome"];
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  declare const buttonVariants: (props?: ({
4
- variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
4
+ variant?: "default" | "link" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
5
5
  size?: "default" | "sm" | "lg" | "icon" | "icon-sm" | "icon-lg" | null | undefined;
6
6
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
7
  declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
@@ -0,0 +1,7 @@
1
+ import * as React from "react";
2
+ declare function NativeSelect({ className, size, ...props }: Omit<React.ComponentProps<"select">, "size"> & {
3
+ size?: "sm" | "default";
4
+ }): React.JSX.Element;
5
+ declare function NativeSelectOption({ className, ...props }: React.ComponentProps<"option">): React.JSX.Element;
6
+ declare function NativeSelectOptGroup({ className, ...props }: React.ComponentProps<"optgroup">): React.JSX.Element;
7
+ export { NativeSelect, NativeSelectOptGroup, NativeSelectOption };
@@ -1,5 +1,7 @@
1
1
  import * as React from "react";
2
- declare function Table({ className, ...props }: React.ComponentProps<"table">): React.JSX.Element;
2
+ declare function Table({ className, containerProps, ...props }: React.ComponentProps<"table"> & {
3
+ containerProps?: React.ComponentProps<"div">;
4
+ }): React.JSX.Element;
3
5
  declare function TableHeader({ className, ...props }: React.ComponentProps<"thead">): React.JSX.Element;
4
6
  declare function TableBody({ className, ...props }: React.ComponentProps<"tbody">): React.JSX.Element;
5
7
  declare function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">): React.JSX.Element;
package/dist/index.d.ts CHANGED
@@ -29,3 +29,4 @@ export type { TimeRange, ResolvedRange } from "./time-range.js";
29
29
  export type { OverviewMetrics, ClassMetrics } from "./overview-metrics.js";
30
30
  export type { QueueWaitRow, QueueWaitStats } from "./queue-wait.js";
31
31
  export type { SocketSession, SocketSessionRow, SocketSessionStatus } from "./socket-sessions.js";
32
+ export type { StateAttribution, StateRecord, StateSnapshot, StateQuery, StateResponse, StateHistoryPage } from "./state-data.js";