@milaboratories/pl-tree 1.12.13 → 1.12.15

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.
Files changed (44) hide show
  1. package/dist/accessors.cjs +71 -1
  2. package/dist/accessors.cjs.map +1 -1
  3. package/dist/accessors.d.ts +29 -1
  4. package/dist/accessors.d.ts.map +1 -1
  5. package/dist/accessors.js +68 -1
  6. package/dist/accessors.js.map +1 -1
  7. package/dist/dump.cjs.map +1 -1
  8. package/dist/dump.d.ts.map +1 -1
  9. package/dist/dump.js.map +1 -1
  10. package/dist/index.cjs +4 -0
  11. package/dist/index.d.ts +3 -3
  12. package/dist/index.js +2 -2
  13. package/dist/snapshot.cjs +1 -2
  14. package/dist/snapshot.cjs.map +1 -1
  15. package/dist/snapshot.d.ts.map +1 -1
  16. package/dist/snapshot.js +1 -1
  17. package/dist/snapshot.js.map +1 -1
  18. package/dist/state.cjs +78 -9
  19. package/dist/state.cjs.map +1 -1
  20. package/dist/state.d.ts +31 -4
  21. package/dist/state.d.ts.map +1 -1
  22. package/dist/state.js +78 -8
  23. package/dist/state.js.map +1 -1
  24. package/dist/sync.cjs +4 -2
  25. package/dist/sync.cjs.map +1 -1
  26. package/dist/sync.d.ts.map +1 -1
  27. package/dist/sync.js +3 -1
  28. package/dist/sync.js.map +1 -1
  29. package/dist/synchronized_tree.cjs +106 -10
  30. package/dist/synchronized_tree.cjs.map +1 -1
  31. package/dist/synchronized_tree.d.ts +49 -5
  32. package/dist/synchronized_tree.d.ts.map +1 -1
  33. package/dist/synchronized_tree.js +107 -11
  34. package/dist/synchronized_tree.js.map +1 -1
  35. package/dist/traversal_ops.d.ts.map +1 -1
  36. package/dist/value_and_error.cjs.map +1 -1
  37. package/dist/value_and_error.d.ts.map +1 -1
  38. package/dist/value_and_error.js.map +1 -1
  39. package/dist/value_or_error.d.ts.map +1 -1
  40. package/package.json +6 -6
  41. package/src/accessors.ts +79 -0
  42. package/src/state.ts +101 -12
  43. package/src/sync.ts +3 -2
  44. package/src/synchronized_tree.ts +153 -12
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.cjs","names":["PlTreeEntry","PlTreeEntryAccessor"],"sources":["../src/snapshot.ts"],"sourcesContent":["import type { SignedResourceId, ResourceType } from \"@milaboratories/pl-client\";\nimport type { Optional, Writable } from \"utility-types\";\nimport type { ZodType, z } from \"zod\";\nimport type { PlTreeNodeAccessor } from \"./accessors\";\nimport { PlTreeEntry, PlTreeEntryAccessor } from \"./accessors\";\nimport type { ComputableCtx } from \"@milaboratories/computable\";\nimport { notEmpty } from \"@milaboratories/ts-helpers\";\n\n/**\n * A DTO that can be generated from a tree node to make a snapshot of specific parts of it's state.\n * Such snapshots can then be used in core that requires this information without the need of\n * retrieving state from the tree.\n */\nexport type ResourceSnapshot<\n Data = undefined,\n Fields extends Record<string, SignedResourceId | undefined> | undefined = undefined,\n KV extends Record<string, unknown> | undefined = undefined,\n> = {\n readonly id: SignedResourceId;\n readonly type: ResourceType;\n readonly data: Data;\n readonly fields: Fields;\n readonly kv: KV;\n};\n\n/** The most generic type of ResourceSnapshot. */\ntype ResourceSnapshotGeneric = ResourceSnapshot<\n unknown,\n Record<string, SignedResourceId | undefined> | undefined,\n Record<string, unknown> | undefined\n>;\n\n/** Request that we'll pass to getResourceSnapshot function. We infer the type of ResourceSnapshot from this. */\nexport type ResourceSnapshotSchema<\n Data extends ZodType | \"raw\" | undefined = undefined,\n Fields extends Record<string, boolean> | undefined = undefined,\n KV extends Record<string, ZodType | \"raw\"> | undefined = undefined,\n> = {\n readonly data: Data;\n readonly fields: Fields;\n readonly kv: KV;\n};\n\n/** Creates ResourceSnapshotSchema. It converts an optional schema type to schema type. */\nexport function rsSchema<\n const Data extends ZodType | \"raw\" | undefined = undefined,\n const Fields extends Record<string, boolean> | undefined = undefined,\n const KV extends Record<string, ZodType | \"raw\"> | undefined = undefined,\n>(\n schema: Optional<ResourceSnapshotSchema<Data, Fields, KV>>,\n): ResourceSnapshotSchema<Data, Fields, KV> {\n return schema as any;\n}\n\n/** The most generic type of ResourceSnapshotSchema. */\ntype ResourceSnapshotSchemaGeneric = ResourceSnapshotSchema<\n ZodType | \"raw\" | undefined,\n Record<string, boolean> | undefined,\n Record<string, ZodType | \"raw\"> | undefined\n>;\n\n/**\n * If Data is 'raw' in schema, we'll get bytes,\n * if it's Zod, we'll parse it via zod.\n * Or else we just got undefined in the field.\n */\ntype InferDataType<Data extends ZodType | \"raw\" | undefined> = Data extends \"raw\"\n ? Uint8Array\n : Data extends ZodType\n ? z.infer<Data>\n : undefined;\n\n/**\n * If Fields is a record of field names to booleans,\n * then if the value of the field is true, we'll require this field and throw a Error if it wasn't found.\n * If it's false and doesn't exist, we'll return undefined.\n * If Fields type is undefined, we won't set fields at all.\n */\ntype InferFieldsType<Fields extends Record<string, boolean> | undefined> = Fields extends undefined\n ? undefined\n : {\n [FieldName in keyof Fields]: Fields[FieldName] extends true\n ? SignedResourceId\n : SignedResourceId | undefined;\n };\n\n/**\n * If KV is undefined, won't set it.\n * If one of values is Zod, we'll get KV and converts it to Zod schema.\n * If the value is 'raw', just returns bytes.\n */\ntype InferKVType<KV extends Record<string, ZodType | \"raw\"> | undefined> = KV extends undefined\n ? undefined\n : {\n [FieldName in keyof KV]: KV[FieldName] extends ZodType ? z.infer<KV[FieldName]> : Uint8Array;\n };\n\n/** Infer ResourceSnapshot from ResourceShapshotSchema, S can be any ResourceSnapshotSchema. */\nexport type InferSnapshot<S extends ResourceSnapshotSchemaGeneric> = ResourceSnapshot<\n InferDataType<S[\"data\"]>,\n InferFieldsType<S[\"fields\"]>,\n InferKVType<S[\"kv\"]>\n>;\n\n/** Gets a ResourceSnapshot from PlTreeEntry. */\nexport function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneric>(\n res: PlTreeEntry,\n schema: Schema,\n ctx: ComputableCtx,\n): InferSnapshot<Schema>;\nexport function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneric>(\n res: PlTreeEntryAccessor | PlTreeNodeAccessor,\n schema: Schema,\n): InferSnapshot<Schema>;\nexport function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneric>(\n res: PlTreeEntry | PlTreeEntryAccessor | PlTreeNodeAccessor,\n schema: Schema,\n ctx?: ComputableCtx,\n): InferSnapshot<Schema> {\n const node =\n res instanceof PlTreeEntry\n ? notEmpty(ctx).accessor(res).node()\n : res instanceof PlTreeEntryAccessor\n ? res.node()\n : res;\n const info = node.resourceInfo;\n const result: Optional<Writable<ResourceSnapshotGeneric>, \"data\" | \"fields\" | \"kv\"> = { ...info };\n\n if (schema.data !== undefined) {\n if (schema.data === \"raw\") result.data = node.getData();\n else result.data = schema.data.parse(node.getDataAsJson());\n }\n\n if (schema.fields !== undefined) {\n const fields: Record<string, SignedResourceId | undefined> = {};\n // even if field is not defined, corresponding object field\n // with \"undefined\" value will still be added\n for (const [fieldName, required] of Object.entries(schema.fields))\n fields[fieldName] = node.traverse({\n field: fieldName,\n errorIfFieldNotSet: required,\n stableIfNotFound: !required,\n })?.id;\n result.fields = fields;\n }\n\n if (schema.kv !== undefined) {\n const kv: Record<string, unknown> = {};\n for (const [fieldName, type] of Object.entries(schema.kv)) {\n const value = node.getKeyValue(fieldName);\n\n if (value === undefined) {\n throw new Error(`Key not found ${fieldName}`);\n } else if (type === \"raw\") {\n kv[fieldName] = value;\n } else {\n kv[fieldName] = type.parse(JSON.parse(Buffer.from(value).toString(\"utf-8\")));\n }\n }\n result.kv = kv;\n }\n\n return result as any;\n}\n\n/** @deprecated */\nexport type ResourceWithData = {\n readonly id: SignedResourceId;\n readonly type: ResourceType;\n readonly fields: Map<string, SignedResourceId | undefined>;\n readonly data?: Uint8Array;\n};\n\n/** @deprecated */\nexport function treeEntryToResourceWithData(\n res: PlTreeEntry | ResourceWithData,\n fields: string[],\n ctx: ComputableCtx,\n): ResourceWithData {\n if (res instanceof PlTreeEntry) {\n const node = ctx.accessor(res).node();\n const info = node.resourceInfo;\n\n const fValues: [string, SignedResourceId | undefined][] = fields.map((name) => [\n name,\n node.getField(name)?.value?.id,\n ]);\n\n return {\n ...info,\n fields: new Map(fValues),\n data: node.getData() ?? new Uint8Array(),\n };\n }\n\n return res;\n}\n\n/** @deprecated */\nexport type ResourceWithMetadata = {\n readonly id: SignedResourceId;\n readonly type: ResourceType;\n readonly metadata: Record<string, any>;\n};\n\n/** @deprecated */\nexport function treeEntryToResourceWithMetadata(\n res: PlTreeEntry | ResourceWithMetadata,\n mdKeys: string[],\n ctx: ComputableCtx,\n): ResourceWithMetadata {\n if (!(res instanceof PlTreeEntry)) return res;\n\n const node = ctx.accessor(res).node();\n const info = node.resourceInfo;\n const mdEntries: [string, any][] = mdKeys.map((k) => [k, node.getKeyValue(k)]);\n\n return {\n ...info,\n metadata: Object.fromEntries(mdEntries),\n };\n}\n"],"mappings":";;;;;AA4CA,SAAgB,SAKd,QAC0C;AAC1C,QAAO;;AA+DT,SAAgB,qBACd,KACA,QACA,KACuB;CACvB,MAAM,OACJ,eAAeA,kBAAAA,eAAAA,GAAAA,2BAAAA,UACF,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,GAClC,eAAeC,kBAAAA,sBACb,IAAI,MAAM,GACV;CAER,MAAM,SAAgF,EAAE,GAD3E,KAAK,cAC+E;AAEjG,KAAI,OAAO,SAAS,KAAA,EAClB,KAAI,OAAO,SAAS,MAAO,QAAO,OAAO,KAAK,SAAS;KAClD,QAAO,OAAO,OAAO,KAAK,MAAM,KAAK,eAAe,CAAC;AAG5D,KAAI,OAAO,WAAW,KAAA,GAAW;EAC/B,MAAM,SAAuD,EAAE;AAG/D,OAAK,MAAM,CAAC,WAAW,aAAa,OAAO,QAAQ,OAAO,OAAO,CAC/D,QAAO,aAAa,KAAK,SAAS;GAChC,OAAO;GACP,oBAAoB;GACpB,kBAAkB,CAAC;GACpB,CAAC,EAAE;AACN,SAAO,SAAS;;AAGlB,KAAI,OAAO,OAAO,KAAA,GAAW;EAC3B,MAAM,KAA8B,EAAE;AACtC,OAAK,MAAM,CAAC,WAAW,SAAS,OAAO,QAAQ,OAAO,GAAG,EAAE;GACzD,MAAM,QAAQ,KAAK,YAAY,UAAU;AAEzC,OAAI,UAAU,KAAA,EACZ,OAAM,IAAI,MAAM,iBAAiB,YAAY;YACpC,SAAS,MAClB,IAAG,aAAa;OAEhB,IAAG,aAAa,KAAK,MAAM,KAAK,MAAM,OAAO,KAAK,MAAM,CAAC,SAAS,QAAQ,CAAC,CAAC;;AAGhF,SAAO,KAAK;;AAGd,QAAO;;;AAYT,SAAgB,4BACd,KACA,QACA,KACkB;AAClB,KAAI,eAAeD,kBAAAA,aAAa;EAC9B,MAAM,OAAO,IAAI,SAAS,IAAI,CAAC,MAAM;EACrC,MAAM,OAAO,KAAK;EAElB,MAAM,UAAoD,OAAO,KAAK,SAAS,CAC7E,MACA,KAAK,SAAS,KAAK,EAAE,OAAO,GAC7B,CAAC;AAEF,SAAO;GACL,GAAG;GACH,QAAQ,IAAI,IAAI,QAAQ;GACxB,MAAM,KAAK,SAAS,IAAI,IAAI,YAAY;GACzC;;AAGH,QAAO;;;AAWT,SAAgB,gCACd,KACA,QACA,KACsB;AACtB,KAAI,EAAE,eAAeA,kBAAAA,aAAc,QAAO;CAE1C,MAAM,OAAO,IAAI,SAAS,IAAI,CAAC,MAAM;CACrC,MAAM,OAAO,KAAK;CAClB,MAAM,YAA6B,OAAO,KAAK,MAAM,CAAC,GAAG,KAAK,YAAY,EAAE,CAAC,CAAC;AAE9E,QAAO;EACL,GAAG;EACH,UAAU,OAAO,YAAY,UAAU;EACxC"}
1
+ {"version":3,"file":"snapshot.cjs","names":["PlTreeEntry","PlTreeEntryAccessor"],"sources":["../src/snapshot.ts"],"sourcesContent":["import type { SignedResourceId, ResourceType } from \"@milaboratories/pl-client\";\nimport type { Optional, Writable } from \"utility-types\";\nimport type { ZodType, z } from \"zod\";\nimport type { PlTreeNodeAccessor } from \"./accessors\";\nimport { PlTreeEntry, PlTreeEntryAccessor } from \"./accessors\";\nimport type { ComputableCtx } from \"@milaboratories/computable\";\nimport { notEmpty } from \"@milaboratories/ts-helpers\";\n\n/**\n * A DTO that can be generated from a tree node to make a snapshot of specific parts of it's state.\n * Such snapshots can then be used in core that requires this information without the need of\n * retrieving state from the tree.\n */\nexport type ResourceSnapshot<\n Data = undefined,\n Fields extends Record<string, SignedResourceId | undefined> | undefined = undefined,\n KV extends Record<string, unknown> | undefined = undefined,\n> = {\n readonly id: SignedResourceId;\n readonly type: ResourceType;\n readonly data: Data;\n readonly fields: Fields;\n readonly kv: KV;\n};\n\n/** The most generic type of ResourceSnapshot. */\ntype ResourceSnapshotGeneric = ResourceSnapshot<\n unknown,\n Record<string, SignedResourceId | undefined> | undefined,\n Record<string, unknown> | undefined\n>;\n\n/** Request that we'll pass to getResourceSnapshot function. We infer the type of ResourceSnapshot from this. */\nexport type ResourceSnapshotSchema<\n Data extends ZodType | \"raw\" | undefined = undefined,\n Fields extends Record<string, boolean> | undefined = undefined,\n KV extends Record<string, ZodType | \"raw\"> | undefined = undefined,\n> = {\n readonly data: Data;\n readonly fields: Fields;\n readonly kv: KV;\n};\n\n/** Creates ResourceSnapshotSchema. It converts an optional schema type to schema type. */\nexport function rsSchema<\n const Data extends ZodType | \"raw\" | undefined = undefined,\n const Fields extends Record<string, boolean> | undefined = undefined,\n const KV extends Record<string, ZodType | \"raw\"> | undefined = undefined,\n>(\n schema: Optional<ResourceSnapshotSchema<Data, Fields, KV>>,\n): ResourceSnapshotSchema<Data, Fields, KV> {\n return schema as any;\n}\n\n/** The most generic type of ResourceSnapshotSchema. */\ntype ResourceSnapshotSchemaGeneric = ResourceSnapshotSchema<\n ZodType | \"raw\" | undefined,\n Record<string, boolean> | undefined,\n Record<string, ZodType | \"raw\"> | undefined\n>;\n\n/**\n * If Data is 'raw' in schema, we'll get bytes,\n * if it's Zod, we'll parse it via zod.\n * Or else we just got undefined in the field.\n */\ntype InferDataType<Data extends ZodType | \"raw\" | undefined> = Data extends \"raw\"\n ? Uint8Array\n : Data extends ZodType\n ? z.infer<Data>\n : undefined;\n\n/**\n * If Fields is a record of field names to booleans,\n * then if the value of the field is true, we'll require this field and throw a Error if it wasn't found.\n * If it's false and doesn't exist, we'll return undefined.\n * If Fields type is undefined, we won't set fields at all.\n */\ntype InferFieldsType<Fields extends Record<string, boolean> | undefined> = Fields extends undefined\n ? undefined\n : {\n [FieldName in keyof Fields]: Fields[FieldName] extends true\n ? SignedResourceId\n : SignedResourceId | undefined;\n };\n\n/**\n * If KV is undefined, won't set it.\n * If one of values is Zod, we'll get KV and converts it to Zod schema.\n * If the value is 'raw', just returns bytes.\n */\ntype InferKVType<KV extends Record<string, ZodType | \"raw\"> | undefined> = KV extends undefined\n ? undefined\n : {\n [FieldName in keyof KV]: KV[FieldName] extends ZodType ? z.infer<KV[FieldName]> : Uint8Array;\n };\n\n/** Infer ResourceSnapshot from ResourceShapshotSchema, S can be any ResourceSnapshotSchema. */\nexport type InferSnapshot<S extends ResourceSnapshotSchemaGeneric> = ResourceSnapshot<\n InferDataType<S[\"data\"]>,\n InferFieldsType<S[\"fields\"]>,\n InferKVType<S[\"kv\"]>\n>;\n\n/** Gets a ResourceSnapshot from PlTreeEntry. */\nexport function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneric>(\n res: PlTreeEntry,\n schema: Schema,\n ctx: ComputableCtx,\n): InferSnapshot<Schema>;\nexport function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneric>(\n res: PlTreeEntryAccessor | PlTreeNodeAccessor,\n schema: Schema,\n): InferSnapshot<Schema>;\nexport function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneric>(\n res: PlTreeEntry | PlTreeEntryAccessor | PlTreeNodeAccessor,\n schema: Schema,\n ctx?: ComputableCtx,\n): InferSnapshot<Schema> {\n const node =\n res instanceof PlTreeEntry\n ? notEmpty(ctx).accessor(res).node()\n : res instanceof PlTreeEntryAccessor\n ? res.node()\n : res;\n const info = node.resourceInfo;\n const result: Optional<Writable<ResourceSnapshotGeneric>, \"data\" | \"fields\" | \"kv\"> = { ...info };\n\n if (schema.data !== undefined) {\n if (schema.data === \"raw\") result.data = node.getData();\n else result.data = schema.data.parse(node.getDataAsJson());\n }\n\n if (schema.fields !== undefined) {\n const fields: Record<string, SignedResourceId | undefined> = {};\n // even if field is not defined, corresponding object field\n // with \"undefined\" value will still be added\n for (const [fieldName, required] of Object.entries(schema.fields))\n fields[fieldName] = node.traverse({\n field: fieldName,\n errorIfFieldNotSet: required,\n stableIfNotFound: !required,\n })?.id;\n result.fields = fields;\n }\n\n if (schema.kv !== undefined) {\n const kv: Record<string, unknown> = {};\n for (const [fieldName, type] of Object.entries(schema.kv)) {\n const value = node.getKeyValue(fieldName);\n\n if (value === undefined) {\n throw new Error(`Key not found ${fieldName}`);\n } else if (type === \"raw\") {\n kv[fieldName] = value;\n } else {\n kv[fieldName] = type.parse(JSON.parse(Buffer.from(value).toString(\"utf-8\")));\n }\n }\n result.kv = kv;\n }\n\n return result as any;\n}\n\n/** @deprecated */\nexport type ResourceWithData = {\n readonly id: SignedResourceId;\n readonly type: ResourceType;\n readonly fields: Map<string, SignedResourceId | undefined>;\n readonly data?: Uint8Array;\n};\n\n/** @deprecated */\nexport function treeEntryToResourceWithData(\n res: PlTreeEntry | ResourceWithData,\n fields: string[],\n ctx: ComputableCtx,\n): ResourceWithData {\n if (res instanceof PlTreeEntry) {\n const node = ctx.accessor(res).node();\n const info = node.resourceInfo;\n\n const fValues: [string, SignedResourceId | undefined][] = fields.map((name) => [\n name,\n node.getField(name)?.value?.id,\n ]);\n\n return {\n ...info,\n fields: new Map(fValues),\n data: node.getData() ?? new Uint8Array(),\n };\n }\n\n return res;\n}\n\n/** @deprecated */\nexport type ResourceWithMetadata = {\n readonly id: SignedResourceId;\n readonly type: ResourceType;\n readonly metadata: Record<string, any>;\n};\n\n/** @deprecated */\nexport function treeEntryToResourceWithMetadata(\n res: PlTreeEntry | ResourceWithMetadata,\n mdKeys: string[],\n ctx: ComputableCtx,\n): ResourceWithMetadata {\n if (!(res instanceof PlTreeEntry)) return res;\n\n const node = ctx.accessor(res).node();\n const info = node.resourceInfo;\n const mdEntries: [string, any][] = mdKeys.map((k) => [k, node.getKeyValue(k)]);\n\n return {\n ...info,\n metadata: Object.fromEntries(mdEntries),\n };\n}\n"],"mappings":";;;;AA4CA,SAAgB,SAKd,QAC0C;CAC1C,OAAO;AACT;AA8DA,SAAgB,qBACd,KACA,QACA,KACuB;CACvB,MAAM,OACJ,eAAeA,kBAAAA,eAAAA,GAAAA,2BAAAA,SAAAA,CACF,GAAG,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,KAAK,IACjC,eAAeC,kBAAAA,sBACb,IAAI,KAAK,IACT;CAER,MAAM,SAAgF,EAAE,GAD3E,KAAK,aAC8E;CAEhG,IAAI,OAAO,SAAS,KAAA,GAClB,IAAI,OAAO,SAAS,OAAO,OAAO,OAAO,KAAK,QAAQ;MACjD,OAAO,OAAO,OAAO,KAAK,MAAM,KAAK,cAAc,CAAC;CAG3D,IAAI,OAAO,WAAW,KAAA,GAAW;EAC/B,MAAM,SAAuD,CAAC;EAG9D,KAAK,MAAM,CAAC,WAAW,aAAa,OAAO,QAAQ,OAAO,MAAM,GAC9D,OAAO,aAAa,KAAK,SAAS;GAChC,OAAO;GACP,oBAAoB;GACpB,kBAAkB,CAAC;EACrB,CAAC,CAAC,EAAE;EACN,OAAO,SAAS;CAClB;CAEA,IAAI,OAAO,OAAO,KAAA,GAAW;EAC3B,MAAM,KAA8B,CAAC;EACrC,KAAK,MAAM,CAAC,WAAW,SAAS,OAAO,QAAQ,OAAO,EAAE,GAAG;GACzD,MAAM,QAAQ,KAAK,YAAY,SAAS;GAExC,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,iBAAiB,WAAW;QACvC,IAAI,SAAS,OAClB,GAAG,aAAa;QAEhB,GAAG,aAAa,KAAK,MAAM,KAAK,MAAM,OAAO,KAAK,KAAK,CAAC,CAAC,SAAS,OAAO,CAAC,CAAC;EAE/E;EACA,OAAO,KAAK;CACd;CAEA,OAAO;AACT;;AAWA,SAAgB,4BACd,KACA,QACA,KACkB;CAClB,IAAI,eAAeD,kBAAAA,aAAa;EAC9B,MAAM,OAAO,IAAI,SAAS,GAAG,CAAC,CAAC,KAAK;EACpC,MAAM,OAAO,KAAK;EAElB,MAAM,UAAoD,OAAO,KAAK,SAAS,CAC7E,MACA,KAAK,SAAS,IAAI,CAAC,EAAE,OAAO,EAC9B,CAAC;EAED,OAAO;GACL,GAAG;GACH,QAAQ,IAAI,IAAI,OAAO;GACvB,MAAM,KAAK,QAAQ,qBAAK,IAAI,WAAW;EACzC;CACF;CAEA,OAAO;AACT;;AAUA,SAAgB,gCACd,KACA,QACA,KACsB;CACtB,IAAI,EAAE,eAAeA,kBAAAA,cAAc,OAAO;CAE1C,MAAM,OAAO,IAAI,SAAS,GAAG,CAAC,CAAC,KAAK;CACpC,MAAM,OAAO,KAAK;CAClB,MAAM,YAA6B,OAAO,KAAK,MAAM,CAAC,GAAG,KAAK,YAAY,CAAC,CAAC,CAAC;CAE7E,OAAO;EACL,GAAG;EACH,UAAU,OAAO,YAAY,SAAS;CACxC;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.d.ts","names":[],"sources":["../src/snapshot.ts"],"mappings":";;;;;;;;AAaA;;;;KAAY,gBAAA,kCAEK,MAAA,SAAe,gBAAA,kDACnB,MAAA;EAAA,SAEF,EAAA,EAAI,gBAAA;EAAA,SACJ,IAAA,EAAM,YAAA;EAAA,SACN,IAAA,EAAM,IAAA;EAAA,SACN,MAAA,EAAQ,MAAA;EAAA,SACR,EAAA,EAAI,EAAA;AAAA;;KAWH,sBAAA,cACG,OAAA,iDACE,MAAA,sDACJ,MAAA,SAAe,OAAA;EAAA,SAEjB,IAAA,EAAM,IAAA;EAAA,SACN,MAAA,EAAQ,MAAA;EAAA,SACR,EAAA,EAAI,EAAA;AAAA;;iBAIC,QAAA,oBACK,OAAA,uDACE,MAAA,4DACJ,MAAA,SAAe,OAAA,kCAAA,CAEhC,MAAA,EAAQ,QAAA,CAAS,sBAAA,CAAuB,IAAA,EAAM,MAAA,EAAQ,EAAA,KACrD,sBAAA,CAAuB,IAAA,EAAM,MAAA,EAAQ,EAAA;;KAKnC,6BAAA,GAAgC,sBAAA,CACnC,OAAA,sBACA,MAAA,+BACA,MAAA,SAAe,OAAA;;;;;;KAQZ,aAAA,cAA2B,OAAA,wBAA+B,IAAA,iBAC3D,UAAA,GACA,IAAA,SAAa,OAAA,GACX,CAAA,CAAE,KAAA,CAAM,IAAA;;;;;AApCd;;KA6CK,eAAA,gBAA+B,MAAA,iCAAuC,MAAA,uDAGjD,MAAA,GAAS,MAAA,CAAO,SAAA,iBAChC,gBAAA,GACA,gBAAA;;;;;;KAQL,WAAA,YAAuB,MAAA,SAAe,OAAA,yBAAgC,EAAA,uDAGjD,EAAA,GAAK,EAAA,CAAG,SAAA,UAAmB,OAAA,GAAU,CAAA,CAAE,KAAA,CAAM,EAAA,CAAG,SAAA,KAAc,UAAA;;KAI5E,aAAA,WAAwB,6BAAA,IAAiC,gBAAA,CACnE,aAAA,CAAc,CAAA,WACd,eAAA,CAAgB,CAAA,aAChB,WAAA,CAAY,CAAA;;iBAIE,oBAAA,gBAAoC,6BAAA,CAAA,CAClD,GAAA,EAAK,WAAA,EACL,MAAA,EAAQ,MAAA,EACR,GAAA,EAAK,aAAA,GACJ,aAAA,CAAc,MAAA;AAAA,iBACD,oBAAA,gBAAoC,6BAAA,CAAA,CAClD,GAAA,EAAK,mBAAA,GAAsB,kBAAA,EAC3B,MAAA,EAAQ,MAAA,GACP,aAAA,CAAc,MAAA;;KAqDL,gBAAA;EAAA,SACD,EAAA,EAAI,gBAAA;EAAA,SACJ,IAAA,EAAM,YAAA;EAAA,SACN,MAAA,EAAQ,GAAA,SAAY,gBAAA;EAAA,SACpB,IAAA,GAAO,UAAA;AAAA;;iBAIF,2BAAA,CACd,GAAA,EAAK,WAAA,GAAc,gBAAA,EACnB,MAAA,YACA,GAAA,EAAK,aAAA,GACJ,gBAAA;AAtIH;AAAA,KA2JY,oBAAA;EAAA,SACD,EAAA,EAAI,gBAAA;EAAA,SACJ,IAAA,EAAM,YAAA;EAAA,SACN,QAAA,EAAU,MAAA;AAAA;;iBAIL,+BAAA,CACd,GAAA,EAAK,WAAA,GAAc,oBAAA,EACnB,MAAA,YACA,GAAA,EAAK,aAAA,GACJ,oBAAA"}
1
+ {"version":3,"file":"snapshot.d.ts","names":[],"sources":["../src/snapshot.ts"],"mappings":";;;;;;;;AAaA;;;;KAAY,gBAAA,kCAEK,MAAA,SAAe,gBAAA,kDACnB,MAAA;EAAA,SAEF,EAAA,EAAI,gBAAA;EAAA,SACJ,IAAA,EAAM,YAAA;EAAA,SACN,IAAA,EAAM,IAAA;EAAA,SACN,MAAA,EAAQ,MAAA;EAAA,SACR,EAAA,EAAI,EAAA;AAAA;;KAWH,sBAAA,cACG,OAAA,iDACE,MAAA,sDACJ,MAAA,SAAe,OAAA;EAAA,SAEjB,IAAA,EAAM,IAAA;EAAA,SACN,MAAA,EAAQ,MAAA;EAAA,SACR,EAAA,EAAI,EAAA;AAAA;;iBAIC,QAAA,oBACK,OAAA,uDACE,MAAA,4DACJ,MAAA,SAAe,OAAA,mCAEhC,MAAA,EAAQ,QAAA,CAAS,sBAAA,CAAuB,IAAA,EAAM,MAAA,EAAQ,EAAA,KACrD,sBAAA,CAAuB,IAAA,EAAM,MAAA,EAAQ,EAAA;;KAKnC,6BAAA,GAAgC,sBAAA,CACnC,OAAA,sBACA,MAAA,+BACA,MAAA,SAAe,OAAA;;;;;;KAQZ,aAAA,cAA2B,OAAA,wBAA+B,IAAA,iBAC3D,UAAA,GACA,IAAA,SAAa,OAAA,GACX,CAAA,CAAE,KAAA,CAAM,IAAA;;;;AA/CG;AAWjB;;KA6CK,eAAA,gBAA+B,MAAA,iCAAuC,MAAA,uDAGjD,MAAA,GAAS,MAAA,CAAO,SAAA,iBAChC,gBAAA,GACA,gBAAA;;;;;;KAQL,WAAA,YAAuB,MAAA,SAAe,OAAA,yBAAgC,EAAA,uDAGjD,EAAA,GAAK,EAAA,CAAG,SAAA,UAAmB,OAAA,GAAU,CAAA,CAAE,KAAA,CAAM,EAAA,CAAG,SAAA,KAAc,UAAA;;KAI5E,aAAA,WAAwB,6BAAA,IAAiC,gBAAA,CACnE,aAAA,CAAc,CAAA,WACd,eAAA,CAAgB,CAAA,aAChB,WAAA,CAAY,CAAA;;iBAIE,oBAAA,gBAAoC,6BAAA,EAClD,GAAA,EAAK,WAAA,EACL,MAAA,EAAQ,MAAA,EACR,GAAA,EAAK,aAAA,GACJ,aAAA,CAAc,MAAA;AAAA,iBACD,oBAAA,gBAAoC,6BAAA,EAClD,GAAA,EAAK,mBAAA,GAAsB,kBAAA,EAC3B,MAAA,EAAQ,MAAA,GACP,aAAA,CAAc,MAAA;;KAqDL,gBAAA;EAAA,SACD,EAAA,EAAI,gBAAA;EAAA,SACJ,IAAA,EAAM,YAAA;EAAA,SACN,MAAA,EAAQ,GAAA,SAAY,gBAAA;EAAA,SACpB,IAAA,GAAO,UAAA;AAAA;;iBAIF,2BAAA,CACd,GAAA,EAAK,WAAA,GAAc,gBAAA,EACnB,MAAA,YACA,GAAA,EAAK,aAAA,GACJ,gBAAA;AAtIH;AAAA,KA2JY,oBAAA;EAAA,SACD,EAAA,EAAI,gBAAA;EAAA,SACJ,IAAA,EAAM,YAAA;EAAA,SACN,QAAA,EAAU,MAAA;AAAA;;iBAIL,+BAAA,CACd,GAAA,EAAK,WAAA,GAAc,oBAAA,EACnB,MAAA,YACA,GAAA,EAAK,aAAA,GACJ,oBAAA"}
package/dist/snapshot.js CHANGED
@@ -40,7 +40,7 @@ function treeEntryToResourceWithData(res, fields, ctx) {
40
40
  return {
41
41
  ...info,
42
42
  fields: new Map(fValues),
43
- data: node.getData() ?? new Uint8Array()
43
+ data: node.getData() ?? /* @__PURE__ */ new Uint8Array()
44
44
  };
45
45
  }
46
46
  return res;
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","names":[],"sources":["../src/snapshot.ts"],"sourcesContent":["import type { SignedResourceId, ResourceType } from \"@milaboratories/pl-client\";\nimport type { Optional, Writable } from \"utility-types\";\nimport type { ZodType, z } from \"zod\";\nimport type { PlTreeNodeAccessor } from \"./accessors\";\nimport { PlTreeEntry, PlTreeEntryAccessor } from \"./accessors\";\nimport type { ComputableCtx } from \"@milaboratories/computable\";\nimport { notEmpty } from \"@milaboratories/ts-helpers\";\n\n/**\n * A DTO that can be generated from a tree node to make a snapshot of specific parts of it's state.\n * Such snapshots can then be used in core that requires this information without the need of\n * retrieving state from the tree.\n */\nexport type ResourceSnapshot<\n Data = undefined,\n Fields extends Record<string, SignedResourceId | undefined> | undefined = undefined,\n KV extends Record<string, unknown> | undefined = undefined,\n> = {\n readonly id: SignedResourceId;\n readonly type: ResourceType;\n readonly data: Data;\n readonly fields: Fields;\n readonly kv: KV;\n};\n\n/** The most generic type of ResourceSnapshot. */\ntype ResourceSnapshotGeneric = ResourceSnapshot<\n unknown,\n Record<string, SignedResourceId | undefined> | undefined,\n Record<string, unknown> | undefined\n>;\n\n/** Request that we'll pass to getResourceSnapshot function. We infer the type of ResourceSnapshot from this. */\nexport type ResourceSnapshotSchema<\n Data extends ZodType | \"raw\" | undefined = undefined,\n Fields extends Record<string, boolean> | undefined = undefined,\n KV extends Record<string, ZodType | \"raw\"> | undefined = undefined,\n> = {\n readonly data: Data;\n readonly fields: Fields;\n readonly kv: KV;\n};\n\n/** Creates ResourceSnapshotSchema. It converts an optional schema type to schema type. */\nexport function rsSchema<\n const Data extends ZodType | \"raw\" | undefined = undefined,\n const Fields extends Record<string, boolean> | undefined = undefined,\n const KV extends Record<string, ZodType | \"raw\"> | undefined = undefined,\n>(\n schema: Optional<ResourceSnapshotSchema<Data, Fields, KV>>,\n): ResourceSnapshotSchema<Data, Fields, KV> {\n return schema as any;\n}\n\n/** The most generic type of ResourceSnapshotSchema. */\ntype ResourceSnapshotSchemaGeneric = ResourceSnapshotSchema<\n ZodType | \"raw\" | undefined,\n Record<string, boolean> | undefined,\n Record<string, ZodType | \"raw\"> | undefined\n>;\n\n/**\n * If Data is 'raw' in schema, we'll get bytes,\n * if it's Zod, we'll parse it via zod.\n * Or else we just got undefined in the field.\n */\ntype InferDataType<Data extends ZodType | \"raw\" | undefined> = Data extends \"raw\"\n ? Uint8Array\n : Data extends ZodType\n ? z.infer<Data>\n : undefined;\n\n/**\n * If Fields is a record of field names to booleans,\n * then if the value of the field is true, we'll require this field and throw a Error if it wasn't found.\n * If it's false and doesn't exist, we'll return undefined.\n * If Fields type is undefined, we won't set fields at all.\n */\ntype InferFieldsType<Fields extends Record<string, boolean> | undefined> = Fields extends undefined\n ? undefined\n : {\n [FieldName in keyof Fields]: Fields[FieldName] extends true\n ? SignedResourceId\n : SignedResourceId | undefined;\n };\n\n/**\n * If KV is undefined, won't set it.\n * If one of values is Zod, we'll get KV and converts it to Zod schema.\n * If the value is 'raw', just returns bytes.\n */\ntype InferKVType<KV extends Record<string, ZodType | \"raw\"> | undefined> = KV extends undefined\n ? undefined\n : {\n [FieldName in keyof KV]: KV[FieldName] extends ZodType ? z.infer<KV[FieldName]> : Uint8Array;\n };\n\n/** Infer ResourceSnapshot from ResourceShapshotSchema, S can be any ResourceSnapshotSchema. */\nexport type InferSnapshot<S extends ResourceSnapshotSchemaGeneric> = ResourceSnapshot<\n InferDataType<S[\"data\"]>,\n InferFieldsType<S[\"fields\"]>,\n InferKVType<S[\"kv\"]>\n>;\n\n/** Gets a ResourceSnapshot from PlTreeEntry. */\nexport function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneric>(\n res: PlTreeEntry,\n schema: Schema,\n ctx: ComputableCtx,\n): InferSnapshot<Schema>;\nexport function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneric>(\n res: PlTreeEntryAccessor | PlTreeNodeAccessor,\n schema: Schema,\n): InferSnapshot<Schema>;\nexport function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneric>(\n res: PlTreeEntry | PlTreeEntryAccessor | PlTreeNodeAccessor,\n schema: Schema,\n ctx?: ComputableCtx,\n): InferSnapshot<Schema> {\n const node =\n res instanceof PlTreeEntry\n ? notEmpty(ctx).accessor(res).node()\n : res instanceof PlTreeEntryAccessor\n ? res.node()\n : res;\n const info = node.resourceInfo;\n const result: Optional<Writable<ResourceSnapshotGeneric>, \"data\" | \"fields\" | \"kv\"> = { ...info };\n\n if (schema.data !== undefined) {\n if (schema.data === \"raw\") result.data = node.getData();\n else result.data = schema.data.parse(node.getDataAsJson());\n }\n\n if (schema.fields !== undefined) {\n const fields: Record<string, SignedResourceId | undefined> = {};\n // even if field is not defined, corresponding object field\n // with \"undefined\" value will still be added\n for (const [fieldName, required] of Object.entries(schema.fields))\n fields[fieldName] = node.traverse({\n field: fieldName,\n errorIfFieldNotSet: required,\n stableIfNotFound: !required,\n })?.id;\n result.fields = fields;\n }\n\n if (schema.kv !== undefined) {\n const kv: Record<string, unknown> = {};\n for (const [fieldName, type] of Object.entries(schema.kv)) {\n const value = node.getKeyValue(fieldName);\n\n if (value === undefined) {\n throw new Error(`Key not found ${fieldName}`);\n } else if (type === \"raw\") {\n kv[fieldName] = value;\n } else {\n kv[fieldName] = type.parse(JSON.parse(Buffer.from(value).toString(\"utf-8\")));\n }\n }\n result.kv = kv;\n }\n\n return result as any;\n}\n\n/** @deprecated */\nexport type ResourceWithData = {\n readonly id: SignedResourceId;\n readonly type: ResourceType;\n readonly fields: Map<string, SignedResourceId | undefined>;\n readonly data?: Uint8Array;\n};\n\n/** @deprecated */\nexport function treeEntryToResourceWithData(\n res: PlTreeEntry | ResourceWithData,\n fields: string[],\n ctx: ComputableCtx,\n): ResourceWithData {\n if (res instanceof PlTreeEntry) {\n const node = ctx.accessor(res).node();\n const info = node.resourceInfo;\n\n const fValues: [string, SignedResourceId | undefined][] = fields.map((name) => [\n name,\n node.getField(name)?.value?.id,\n ]);\n\n return {\n ...info,\n fields: new Map(fValues),\n data: node.getData() ?? new Uint8Array(),\n };\n }\n\n return res;\n}\n\n/** @deprecated */\nexport type ResourceWithMetadata = {\n readonly id: SignedResourceId;\n readonly type: ResourceType;\n readonly metadata: Record<string, any>;\n};\n\n/** @deprecated */\nexport function treeEntryToResourceWithMetadata(\n res: PlTreeEntry | ResourceWithMetadata,\n mdKeys: string[],\n ctx: ComputableCtx,\n): ResourceWithMetadata {\n if (!(res instanceof PlTreeEntry)) return res;\n\n const node = ctx.accessor(res).node();\n const info = node.resourceInfo;\n const mdEntries: [string, any][] = mdKeys.map((k) => [k, node.getKeyValue(k)]);\n\n return {\n ...info,\n metadata: Object.fromEntries(mdEntries),\n };\n}\n"],"mappings":";;;;AA4CA,SAAgB,SAKd,QAC0C;AAC1C,QAAO;;AA+DT,SAAgB,qBACd,KACA,QACA,KACuB;CACvB,MAAM,OACJ,eAAe,cACX,SAAS,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,GAClC,eAAe,sBACb,IAAI,MAAM,GACV;CAER,MAAM,SAAgF,EAAE,GAD3E,KAAK,cAC+E;AAEjG,KAAI,OAAO,SAAS,KAAA,EAClB,KAAI,OAAO,SAAS,MAAO,QAAO,OAAO,KAAK,SAAS;KAClD,QAAO,OAAO,OAAO,KAAK,MAAM,KAAK,eAAe,CAAC;AAG5D,KAAI,OAAO,WAAW,KAAA,GAAW;EAC/B,MAAM,SAAuD,EAAE;AAG/D,OAAK,MAAM,CAAC,WAAW,aAAa,OAAO,QAAQ,OAAO,OAAO,CAC/D,QAAO,aAAa,KAAK,SAAS;GAChC,OAAO;GACP,oBAAoB;GACpB,kBAAkB,CAAC;GACpB,CAAC,EAAE;AACN,SAAO,SAAS;;AAGlB,KAAI,OAAO,OAAO,KAAA,GAAW;EAC3B,MAAM,KAA8B,EAAE;AACtC,OAAK,MAAM,CAAC,WAAW,SAAS,OAAO,QAAQ,OAAO,GAAG,EAAE;GACzD,MAAM,QAAQ,KAAK,YAAY,UAAU;AAEzC,OAAI,UAAU,KAAA,EACZ,OAAM,IAAI,MAAM,iBAAiB,YAAY;YACpC,SAAS,MAClB,IAAG,aAAa;OAEhB,IAAG,aAAa,KAAK,MAAM,KAAK,MAAM,OAAO,KAAK,MAAM,CAAC,SAAS,QAAQ,CAAC,CAAC;;AAGhF,SAAO,KAAK;;AAGd,QAAO;;;AAYT,SAAgB,4BACd,KACA,QACA,KACkB;AAClB,KAAI,eAAe,aAAa;EAC9B,MAAM,OAAO,IAAI,SAAS,IAAI,CAAC,MAAM;EACrC,MAAM,OAAO,KAAK;EAElB,MAAM,UAAoD,OAAO,KAAK,SAAS,CAC7E,MACA,KAAK,SAAS,KAAK,EAAE,OAAO,GAC7B,CAAC;AAEF,SAAO;GACL,GAAG;GACH,QAAQ,IAAI,IAAI,QAAQ;GACxB,MAAM,KAAK,SAAS,IAAI,IAAI,YAAY;GACzC;;AAGH,QAAO;;;AAWT,SAAgB,gCACd,KACA,QACA,KACsB;AACtB,KAAI,EAAE,eAAe,aAAc,QAAO;CAE1C,MAAM,OAAO,IAAI,SAAS,IAAI,CAAC,MAAM;CACrC,MAAM,OAAO,KAAK;CAClB,MAAM,YAA6B,OAAO,KAAK,MAAM,CAAC,GAAG,KAAK,YAAY,EAAE,CAAC,CAAC;AAE9E,QAAO;EACL,GAAG;EACH,UAAU,OAAO,YAAY,UAAU;EACxC"}
1
+ {"version":3,"file":"snapshot.js","names":[],"sources":["../src/snapshot.ts"],"sourcesContent":["import type { SignedResourceId, ResourceType } from \"@milaboratories/pl-client\";\nimport type { Optional, Writable } from \"utility-types\";\nimport type { ZodType, z } from \"zod\";\nimport type { PlTreeNodeAccessor } from \"./accessors\";\nimport { PlTreeEntry, PlTreeEntryAccessor } from \"./accessors\";\nimport type { ComputableCtx } from \"@milaboratories/computable\";\nimport { notEmpty } from \"@milaboratories/ts-helpers\";\n\n/**\n * A DTO that can be generated from a tree node to make a snapshot of specific parts of it's state.\n * Such snapshots can then be used in core that requires this information without the need of\n * retrieving state from the tree.\n */\nexport type ResourceSnapshot<\n Data = undefined,\n Fields extends Record<string, SignedResourceId | undefined> | undefined = undefined,\n KV extends Record<string, unknown> | undefined = undefined,\n> = {\n readonly id: SignedResourceId;\n readonly type: ResourceType;\n readonly data: Data;\n readonly fields: Fields;\n readonly kv: KV;\n};\n\n/** The most generic type of ResourceSnapshot. */\ntype ResourceSnapshotGeneric = ResourceSnapshot<\n unknown,\n Record<string, SignedResourceId | undefined> | undefined,\n Record<string, unknown> | undefined\n>;\n\n/** Request that we'll pass to getResourceSnapshot function. We infer the type of ResourceSnapshot from this. */\nexport type ResourceSnapshotSchema<\n Data extends ZodType | \"raw\" | undefined = undefined,\n Fields extends Record<string, boolean> | undefined = undefined,\n KV extends Record<string, ZodType | \"raw\"> | undefined = undefined,\n> = {\n readonly data: Data;\n readonly fields: Fields;\n readonly kv: KV;\n};\n\n/** Creates ResourceSnapshotSchema. It converts an optional schema type to schema type. */\nexport function rsSchema<\n const Data extends ZodType | \"raw\" | undefined = undefined,\n const Fields extends Record<string, boolean> | undefined = undefined,\n const KV extends Record<string, ZodType | \"raw\"> | undefined = undefined,\n>(\n schema: Optional<ResourceSnapshotSchema<Data, Fields, KV>>,\n): ResourceSnapshotSchema<Data, Fields, KV> {\n return schema as any;\n}\n\n/** The most generic type of ResourceSnapshotSchema. */\ntype ResourceSnapshotSchemaGeneric = ResourceSnapshotSchema<\n ZodType | \"raw\" | undefined,\n Record<string, boolean> | undefined,\n Record<string, ZodType | \"raw\"> | undefined\n>;\n\n/**\n * If Data is 'raw' in schema, we'll get bytes,\n * if it's Zod, we'll parse it via zod.\n * Or else we just got undefined in the field.\n */\ntype InferDataType<Data extends ZodType | \"raw\" | undefined> = Data extends \"raw\"\n ? Uint8Array\n : Data extends ZodType\n ? z.infer<Data>\n : undefined;\n\n/**\n * If Fields is a record of field names to booleans,\n * then if the value of the field is true, we'll require this field and throw a Error if it wasn't found.\n * If it's false and doesn't exist, we'll return undefined.\n * If Fields type is undefined, we won't set fields at all.\n */\ntype InferFieldsType<Fields extends Record<string, boolean> | undefined> = Fields extends undefined\n ? undefined\n : {\n [FieldName in keyof Fields]: Fields[FieldName] extends true\n ? SignedResourceId\n : SignedResourceId | undefined;\n };\n\n/**\n * If KV is undefined, won't set it.\n * If one of values is Zod, we'll get KV and converts it to Zod schema.\n * If the value is 'raw', just returns bytes.\n */\ntype InferKVType<KV extends Record<string, ZodType | \"raw\"> | undefined> = KV extends undefined\n ? undefined\n : {\n [FieldName in keyof KV]: KV[FieldName] extends ZodType ? z.infer<KV[FieldName]> : Uint8Array;\n };\n\n/** Infer ResourceSnapshot from ResourceShapshotSchema, S can be any ResourceSnapshotSchema. */\nexport type InferSnapshot<S extends ResourceSnapshotSchemaGeneric> = ResourceSnapshot<\n InferDataType<S[\"data\"]>,\n InferFieldsType<S[\"fields\"]>,\n InferKVType<S[\"kv\"]>\n>;\n\n/** Gets a ResourceSnapshot from PlTreeEntry. */\nexport function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneric>(\n res: PlTreeEntry,\n schema: Schema,\n ctx: ComputableCtx,\n): InferSnapshot<Schema>;\nexport function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneric>(\n res: PlTreeEntryAccessor | PlTreeNodeAccessor,\n schema: Schema,\n): InferSnapshot<Schema>;\nexport function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneric>(\n res: PlTreeEntry | PlTreeEntryAccessor | PlTreeNodeAccessor,\n schema: Schema,\n ctx?: ComputableCtx,\n): InferSnapshot<Schema> {\n const node =\n res instanceof PlTreeEntry\n ? notEmpty(ctx).accessor(res).node()\n : res instanceof PlTreeEntryAccessor\n ? res.node()\n : res;\n const info = node.resourceInfo;\n const result: Optional<Writable<ResourceSnapshotGeneric>, \"data\" | \"fields\" | \"kv\"> = { ...info };\n\n if (schema.data !== undefined) {\n if (schema.data === \"raw\") result.data = node.getData();\n else result.data = schema.data.parse(node.getDataAsJson());\n }\n\n if (schema.fields !== undefined) {\n const fields: Record<string, SignedResourceId | undefined> = {};\n // even if field is not defined, corresponding object field\n // with \"undefined\" value will still be added\n for (const [fieldName, required] of Object.entries(schema.fields))\n fields[fieldName] = node.traverse({\n field: fieldName,\n errorIfFieldNotSet: required,\n stableIfNotFound: !required,\n })?.id;\n result.fields = fields;\n }\n\n if (schema.kv !== undefined) {\n const kv: Record<string, unknown> = {};\n for (const [fieldName, type] of Object.entries(schema.kv)) {\n const value = node.getKeyValue(fieldName);\n\n if (value === undefined) {\n throw new Error(`Key not found ${fieldName}`);\n } else if (type === \"raw\") {\n kv[fieldName] = value;\n } else {\n kv[fieldName] = type.parse(JSON.parse(Buffer.from(value).toString(\"utf-8\")));\n }\n }\n result.kv = kv;\n }\n\n return result as any;\n}\n\n/** @deprecated */\nexport type ResourceWithData = {\n readonly id: SignedResourceId;\n readonly type: ResourceType;\n readonly fields: Map<string, SignedResourceId | undefined>;\n readonly data?: Uint8Array;\n};\n\n/** @deprecated */\nexport function treeEntryToResourceWithData(\n res: PlTreeEntry | ResourceWithData,\n fields: string[],\n ctx: ComputableCtx,\n): ResourceWithData {\n if (res instanceof PlTreeEntry) {\n const node = ctx.accessor(res).node();\n const info = node.resourceInfo;\n\n const fValues: [string, SignedResourceId | undefined][] = fields.map((name) => [\n name,\n node.getField(name)?.value?.id,\n ]);\n\n return {\n ...info,\n fields: new Map(fValues),\n data: node.getData() ?? new Uint8Array(),\n };\n }\n\n return res;\n}\n\n/** @deprecated */\nexport type ResourceWithMetadata = {\n readonly id: SignedResourceId;\n readonly type: ResourceType;\n readonly metadata: Record<string, any>;\n};\n\n/** @deprecated */\nexport function treeEntryToResourceWithMetadata(\n res: PlTreeEntry | ResourceWithMetadata,\n mdKeys: string[],\n ctx: ComputableCtx,\n): ResourceWithMetadata {\n if (!(res instanceof PlTreeEntry)) return res;\n\n const node = ctx.accessor(res).node();\n const info = node.resourceInfo;\n const mdEntries: [string, any][] = mdKeys.map((k) => [k, node.getKeyValue(k)]);\n\n return {\n ...info,\n metadata: Object.fromEntries(mdEntries),\n };\n}\n"],"mappings":";;;;AA4CA,SAAgB,SAKd,QAC0C;CAC1C,OAAO;AACT;AA8DA,SAAgB,qBACd,KACA,QACA,KACuB;CACvB,MAAM,OACJ,eAAe,cACX,SAAS,GAAG,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,KAAK,IACjC,eAAe,sBACb,IAAI,KAAK,IACT;CAER,MAAM,SAAgF,EAAE,GAD3E,KAAK,aAC8E;CAEhG,IAAI,OAAO,SAAS,KAAA,GAClB,IAAI,OAAO,SAAS,OAAO,OAAO,OAAO,KAAK,QAAQ;MACjD,OAAO,OAAO,OAAO,KAAK,MAAM,KAAK,cAAc,CAAC;CAG3D,IAAI,OAAO,WAAW,KAAA,GAAW;EAC/B,MAAM,SAAuD,CAAC;EAG9D,KAAK,MAAM,CAAC,WAAW,aAAa,OAAO,QAAQ,OAAO,MAAM,GAC9D,OAAO,aAAa,KAAK,SAAS;GAChC,OAAO;GACP,oBAAoB;GACpB,kBAAkB,CAAC;EACrB,CAAC,CAAC,EAAE;EACN,OAAO,SAAS;CAClB;CAEA,IAAI,OAAO,OAAO,KAAA,GAAW;EAC3B,MAAM,KAA8B,CAAC;EACrC,KAAK,MAAM,CAAC,WAAW,SAAS,OAAO,QAAQ,OAAO,EAAE,GAAG;GACzD,MAAM,QAAQ,KAAK,YAAY,SAAS;GAExC,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,iBAAiB,WAAW;QACvC,IAAI,SAAS,OAClB,GAAG,aAAa;QAEhB,GAAG,aAAa,KAAK,MAAM,KAAK,MAAM,OAAO,KAAK,KAAK,CAAC,CAAC,SAAS,OAAO,CAAC,CAAC;EAE/E;EACA,OAAO,KAAK;CACd;CAEA,OAAO;AACT;;AAWA,SAAgB,4BACd,KACA,QACA,KACkB;CAClB,IAAI,eAAe,aAAa;EAC9B,MAAM,OAAO,IAAI,SAAS,GAAG,CAAC,CAAC,KAAK;EACpC,MAAM,OAAO,KAAK;EAElB,MAAM,UAAoD,OAAO,KAAK,SAAS,CAC7E,MACA,KAAK,SAAS,IAAI,CAAC,EAAE,OAAO,EAC9B,CAAC;EAED,OAAO;GACL,GAAG;GACH,QAAQ,IAAI,IAAI,OAAO;GACvB,MAAM,KAAK,QAAQ,qBAAK,IAAI,WAAW;EACzC;CACF;CAEA,OAAO;AACT;;AAUA,SAAgB,gCACd,KACA,QACA,KACsB;CACtB,IAAI,EAAE,eAAe,cAAc,OAAO;CAE1C,MAAM,OAAO,IAAI,SAAS,GAAG,CAAC,CAAC,KAAK;CACpC,MAAM,OAAO,KAAK;CAClB,MAAM,YAA6B,OAAO,KAAK,MAAM,CAAC,GAAG,KAAK,YAAY,CAAC,CAAC,CAAC;CAE7E,OAAO;EACL,GAAG;EACH,UAAU,OAAO,YAAY,SAAS;CACxC;AACF"}
package/dist/state.cjs CHANGED
@@ -1,4 +1,3 @@
1
- require("./_virtual/_rolldown/runtime.cjs");
2
1
  const require_accessors = require("./accessors.cjs");
3
2
  let _milaboratories_pl_client = require("@milaboratories/pl-client");
4
3
  let _milaboratories_computable = require("@milaboratories/computable");
@@ -10,6 +9,13 @@ var TreeStateUpdateError = class extends Error {
10
9
  }
11
10
  };
12
11
  var PlTreeField = class {
12
+ name;
13
+ type;
14
+ value;
15
+ error;
16
+ status;
17
+ valueIsFinal;
18
+ resourceVersion;
13
19
  change = new _milaboratories_computable.ChangeSource();
14
20
  constructor(name, type, value, error, status, valueIsFinal, resourceVersion) {
15
21
  this.name = name;
@@ -244,16 +250,31 @@ var PlTreeResource = class {
244
250
  }
245
251
  };
246
252
  var PlTreeState = class {
253
+ isFinalPredicate;
247
254
  /** resource heap */
248
255
  resources = /* @__PURE__ */ new Map();
249
256
  resourcesAdded = new _milaboratories_computable.ChangeSource();
257
+ /** Marked when the root set changes (roots discovered or removed), so multi-root
258
+ * accessors that read the set recompute. */
259
+ rootsChanged = new _milaboratories_computable.ChangeSource();
250
260
  /** Resets to false if any invalid state transitions are registered,
251
261
  * after that tree will produce errors for any read or write operations */
252
262
  _isValid = true;
253
263
  invalidationMessage;
254
- constructor(root, isFinalPredicate) {
255
- this.root = root;
264
+ /** The set of roots — resources protected from GC. Originally a single `root`,
265
+ * generalized to a set so several explicit roots and dynamically-discovered shared
266
+ * roots can coexist in one heap. Mutated through {@link setRoots}. */
267
+ roots;
268
+ constructor(roots, isFinalPredicate) {
256
269
  this.isFinalPredicate = isFinalPredicate;
270
+ this.roots = roots instanceof Set ? new Set(roots) : /* @__PURE__ */ new Set([roots]);
271
+ }
272
+ /** Backward-compatible single-root accessor. Returns the sole root and THROWS if the
273
+ * tree has zero or more than one root, so a multi-root tree can never be read as if it
274
+ * had one. Mirrors the {@link entry} guard. */
275
+ get root() {
276
+ if (this.roots.size !== 1) throw new Error(`single-root accessor used on a tree with ${this.roots.size} roots; use the multi-root API`);
277
+ return this.roots.values().next().value;
257
278
  }
258
279
  forEachResource(cb) {
259
280
  this.resources.forEach((v) => cb(v));
@@ -261,6 +282,13 @@ var PlTreeState = class {
261
282
  checkValid() {
262
283
  if (!this._isValid) throw new Error(this.invalidationMessage ?? "tree is in invalid state");
263
284
  }
285
+ /** Reactive read of the current root set. Attaches the watcher to {@link rootsChanged}
286
+ * so a Computable recomputes when discovered roots appear or disappear. */
287
+ getRoots(watcher) {
288
+ this.checkValid();
289
+ this.rootsChanged.attachWatcher(watcher);
290
+ return [...this.roots];
291
+ }
264
292
  get(watcher, rid) {
265
293
  this.checkValid();
266
294
  const res = this.resources.get(rid);
@@ -435,6 +463,19 @@ var PlTreeState = class {
435
463
  }
436
464
  res.refCount++;
437
465
  }
466
+ this.collectGarbage(decrementRefs);
467
+ if (!allowOrphanInputs) {
468
+ for (const rd of resourceData) if (!this.resources.has(rd.id)) {
469
+ this.invalidateTree();
470
+ throw new TreeStateUpdateError(`orphan input resource ${rd.id}`);
471
+ }
472
+ }
473
+ }
474
+ /** Runs the refcount-decrement garbage-collection cascade over the given worklist.
475
+ * A resource reaching refCount 0 that is not a root is removed, and its outgoing
476
+ * references are decremented in turn, until the worklist drains. Factored out of
477
+ * {@link updateFromResourceData} so {@link setRoots} can reuse the same cascade. */
478
+ collectGarbage(decrementRefs) {
438
479
  let currentRefs = decrementRefs;
439
480
  while (currentRefs.length > 0) {
440
481
  const nextRefs = [];
@@ -445,7 +486,7 @@ var PlTreeState = class {
445
486
  throw new TreeStateUpdateError(`orphan resource ${rid}`);
446
487
  }
447
488
  res.refCount--;
448
- if (res.refCount === 0 && res.id !== this.root) {
489
+ if (res.refCount === 0 && !this.roots.has(res.id)) {
449
490
  res.fieldsMap.forEach((field) => {
450
491
  if ((0, _milaboratories_pl_client.isNotNullSignedResourceId)(field.value)) nextRefs.push(field.value);
451
492
  if ((0, _milaboratories_pl_client.isNotNullSignedResourceId)(field.error)) nextRefs.push(field.error);
@@ -458,11 +499,38 @@ var PlTreeState = class {
458
499
  }
459
500
  currentRefs = nextRefs;
460
501
  }
461
- if (!allowOrphanInputs) {
462
- for (const rd of resourceData) if (!this.resources.has(rd.id)) {
463
- this.invalidateTree();
464
- throw new TreeStateUpdateError(`orphan input resource ${rd.id}`);
465
- }
502
+ }
503
+ /** Replaces the current root set with `newRoots`.
504
+ *
505
+ * Roots that leave the set lose their GC protection: each removed root present in the
506
+ * heap is collected directly (a root sits at refCount 0, so it is never enqueued by an
507
+ * ordinary decrement), and its subtree cascades to collection through the existing
508
+ * refcount GC — the standard removal mechanic, applied to a root. Roots newly added to
509
+ * the set are protected immediately; their resources arrive on the next refresh poll. */
510
+ setRoots(newRoots) {
511
+ this.checkValid();
512
+ const removed = [];
513
+ for (const rid of this.roots) if (!newRoots.has(rid)) removed.push(rid);
514
+ let added = false;
515
+ for (const rid of newRoots) if (!this.roots.has(rid)) added = true;
516
+ if (removed.length === 0 && !added) return;
517
+ this.roots.clear();
518
+ for (const rid of newRoots) this.roots.add(rid);
519
+ this.rootsChanged.markChanged("root set changed");
520
+ for (const rid of removed) {
521
+ const res = this.resources.get(rid);
522
+ if (res === void 0) continue;
523
+ if (res.refCount > 0) continue;
524
+ const seed = [];
525
+ res.fieldsMap.forEach((field) => {
526
+ if ((0, _milaboratories_pl_client.isNotNullSignedResourceId)(field.value)) seed.push(field.value);
527
+ if ((0, _milaboratories_pl_client.isNotNullSignedResourceId)(field.error)) seed.push(field.error);
528
+ field.change.markChanged(`field ${field.name} removed after root ${(0, _milaboratories_pl_client.resourceIdToString)(res.id)} left the root set`);
529
+ });
530
+ if ((0, _milaboratories_pl_client.isNotNullSignedResourceId)(res.error)) seed.push(res.error);
531
+ res.resourceRemoved.markChanged(`resource removed after leaving the root set: ${(0, _milaboratories_pl_client.resourceIdToString)(res.id)}`);
532
+ this.resources.delete(rid);
533
+ this.collectGarbage(seed);
466
534
  }
467
535
  }
468
536
  /** @deprecated use "entry" instead */
@@ -477,6 +545,7 @@ var PlTreeState = class {
477
545
  invalidateTree(msg) {
478
546
  this._isValid = false;
479
547
  this.invalidationMessage = msg;
548
+ this.rootsChanged.markChanged("tree invalidated");
480
549
  this.resources.forEach((res) => {
481
550
  res.markAllChanged();
482
551
  });
@@ -1 +1 @@
1
- {"version":3,"file":"state.cjs","names":["ChangeSource","KeyedChangeSource","NullSignedResourceId","PlTreeEntry"],"sources":["../src/state.ts"],"sourcesContent":["import type {\n BasicResourceData,\n FieldData,\n FieldStatus,\n FieldType,\n KeyValue,\n OptionalSignedResourceId,\n ResourceData,\n SignedResourceId,\n ResourceKind,\n ResourceType,\n} from \"@milaboratories/pl-client\";\nimport {\n isNotNullSignedResourceId,\n isNullSignedResourceId,\n NullSignedResourceId,\n resourceIdToString,\n stringifyWithResourceId,\n} from \"@milaboratories/pl-client\";\nimport type { Watcher } from \"@milaboratories/computable\";\nimport { ChangeSource, KeyedChangeSource } from \"@milaboratories/computable\";\nimport { PlTreeEntry } from \"./accessors\";\nimport type { ValueAndError } from \"./value_and_error\";\nimport type { MiLogger } from \"@milaboratories/ts-helpers\";\nimport { cachedDecode, cachedDeserialize, notEmpty } from \"@milaboratories/ts-helpers\";\nimport type { FieldTraversalStep, GetFieldStep } from \"./traversal_ops\";\nimport type { FinalResourceDataPredicate } from \"@milaboratories/pl-client\";\n\nexport type ExtendedResourceData = ResourceData & {\n kv: KeyValue[];\n};\n\nexport class TreeStateUpdateError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nclass PlTreeField implements FieldData {\n readonly change = new ChangeSource();\n\n constructor(\n public readonly name: string,\n public type: FieldType,\n public value: OptionalSignedResourceId,\n public error: OptionalSignedResourceId,\n public status: FieldStatus,\n public valueIsFinal: boolean,\n /** Last version of resource this field was observed, used to garbage collect fields in tree patching procedure */\n public resourceVersion: number,\n ) {}\n\n get state(): FieldData {\n return {\n name: this.name,\n type: this.type,\n status: this.status,\n value: this.value,\n error: this.error,\n valueIsFinal: this.valueIsFinal,\n };\n }\n}\n\nconst InitialResourceVersion = 0;\n\nexport type ResourceDataWithFinalState = ResourceData & {\n finalState: boolean;\n};\n\n/** Never store instances of this class, always get fresh instance from {@link PlTreeState} */\nexport class PlTreeResource implements ResourceDataWithFinalState {\n /** Tracks number of other resources referencing this resource. Used to perform garbage collection in tree patching procedure */\n refCount: number = 0;\n\n /** Increments each time resource is checked for difference with new state */\n version: number = InitialResourceVersion;\n /** Set to resource version when resource state, or it's fields have changed */\n dataVersion: number = InitialResourceVersion;\n\n readonly fieldsMap: Map<string, PlTreeField> = new Map();\n\n readonly kv = new Map<string, Uint8Array>();\n\n readonly resourceRemoved = new ChangeSource();\n\n // following change source are removed when resource is marked as final\n\n finalChanged? = new ChangeSource();\n\n resourceStateChange? = new ChangeSource();\n\n lockedChange? = new ChangeSource();\n inputAndServiceFieldListChanged? = new ChangeSource();\n outputFieldListChanged? = new ChangeSource();\n dynamicFieldListChanged? = new ChangeSource();\n\n // kvChangedGlobal? = new ChangeSource();\n kvChangedPerKey? = new KeyedChangeSource();\n\n readonly id: SignedResourceId;\n originalResourceId: OptionalSignedResourceId;\n\n readonly kind: ResourceKind;\n readonly type: ResourceType;\n\n readonly data?: Uint8Array;\n private dataAsString?: string;\n private dataAsJson?: unknown;\n\n error: OptionalSignedResourceId;\n\n inputsLocked: boolean;\n outputsLocked: boolean;\n resourceReady: boolean;\n finalFlag: boolean;\n\n /** Set externally by the tree, using {@link FinalResourceDataPredicate} */\n _finalState: boolean = false;\n\n private readonly logger?: MiLogger;\n\n constructor(initialState: BasicResourceData, logger?: MiLogger) {\n this.id = initialState.id;\n this.originalResourceId = initialState.originalResourceId;\n this.kind = initialState.kind;\n this.type = initialState.type;\n this.data = initialState.data;\n this.error = initialState.error;\n this.inputsLocked = initialState.inputsLocked;\n this.outputsLocked = initialState.outputsLocked;\n this.resourceReady = initialState.resourceReady;\n this.finalFlag = initialState.final;\n this.logger = logger;\n }\n\n // TODO add logging\n\n private info(msg: string) {\n if (this.logger !== undefined) this.logger.info(msg);\n }\n\n private warn(msg: string) {\n if (this.logger !== undefined) this.logger.warn(msg);\n }\n\n get final(): boolean {\n return this.finalFlag;\n }\n\n get finalState(): boolean {\n return this._finalState;\n }\n\n get fields(): FieldData[] {\n return [...this.fieldsMap.values()];\n }\n\n public getField(\n watcher: Watcher,\n _step:\n | (Omit<GetFieldStep, \"errorIfFieldNotFound\"> & { errorIfFieldNotFound: true })\n | (Omit<GetFieldStep, \"errorIfFieldNotSet\"> & { errorIfFieldNotSet: true }),\n onUnstable: (marker: string) => void,\n ): ValueAndError<SignedResourceId>;\n public getField(\n watcher: Watcher,\n _step: string | GetFieldStep,\n onUnstable: (marker: string) => void,\n ): ValueAndError<SignedResourceId> | undefined;\n public getField(\n watcher: Watcher,\n _step: string | GetFieldStep,\n onUnstable: (marker: string) => void = () => {},\n ): ValueAndError<SignedResourceId> | undefined {\n const step: FieldTraversalStep = typeof _step === \"string\" ? { field: _step } : _step;\n\n const field = this.fieldsMap.get(step.field);\n if (field === undefined) {\n if (step.errorIfFieldNotFound || step.errorIfFieldNotSet)\n throw new Error(\n `Field \"${step.field}\" not found in resource ${resourceIdToString(this.id)}`,\n );\n\n if (!this.inputsLocked) this.inputAndServiceFieldListChanged?.attachWatcher(watcher);\n else if (step.assertFieldType === \"Service\" || step.assertFieldType === \"Input\") {\n if (step.allowPermanentAbsence)\n // stable absence of field\n return undefined;\n else throw new Error(`Service or input field not found ${step.field}.`);\n }\n\n if (!this.outputsLocked) this.outputFieldListChanged?.attachWatcher(watcher);\n else if (step.assertFieldType === \"Output\") {\n if (step.allowPermanentAbsence)\n // stable absence of field\n return undefined;\n else throw new Error(`Output field not found ${step.field}.`);\n }\n\n this.dynamicFieldListChanged?.attachWatcher(watcher);\n if (!this._finalState && !step.stableIfNotFound) onUnstable(\"field_not_found:\" + step.field);\n\n return undefined;\n } else {\n if (step.assertFieldType !== undefined && field.type !== step.assertFieldType)\n throw new Error(\n `Unexpected field type: expected ${step.assertFieldType} but got ${field.type} for the field name ${step.field}`,\n );\n\n const ret = {} as ValueAndError<SignedResourceId>;\n if (isNotNullSignedResourceId(field.value)) ret.value = field.value;\n if (isNotNullSignedResourceId(field.error)) ret.error = field.error;\n if (ret.value === undefined && ret.error === undefined)\n // this method returns value and error of the field, thus those values are considered to be accessed;\n // any existing but not resolved field here is considered to be unstable, in the sense it is\n // considered to acquire some resolved value eventually\n onUnstable(\"field_not_resolved:\" + step.field);\n field.change.attachWatcher(watcher);\n return ret;\n }\n }\n\n public getInputsLocked(watcher: Watcher): boolean {\n if (!this.inputsLocked)\n // reverse transition can't happen, so there is no reason to wait for value to change\n this.resourceStateChange?.attachWatcher(watcher);\n return this.inputsLocked;\n }\n\n public getOutputsLocked(watcher: Watcher): boolean {\n if (!this.outputsLocked)\n // reverse transition can't happen, so there is no reason to wait for value to change\n this.resourceStateChange?.attachWatcher(watcher);\n return this.outputsLocked;\n }\n\n public get isReadyOrError(): boolean {\n return (\n this.error !== NullSignedResourceId ||\n this.resourceReady ||\n this.originalResourceId !== NullSignedResourceId\n );\n }\n\n public getIsFinal(watcher: Watcher): boolean {\n this.finalChanged?.attachWatcher(watcher);\n return this._finalState;\n }\n\n public getIsReadyOrError(watcher: Watcher): boolean {\n if (!this.isReadyOrError)\n // reverse transition can't happen, so there is no reason to wait for value to change if it is already true\n this.resourceStateChange?.attachWatcher(watcher);\n return this.isReadyOrError;\n }\n\n public getError(watcher: Watcher): SignedResourceId | undefined {\n if (isNullSignedResourceId(this.error)) {\n this.resourceStateChange?.attachWatcher(watcher);\n return undefined;\n } else {\n // reverse transition can't happen, so there is no reason to wait for value to change, if error already set\n return this.error;\n }\n }\n\n public listInputFields(watcher: Watcher): string[] {\n const ret: string[] = [];\n this.fieldsMap.forEach((field, name) => {\n if (field.type === \"Input\" || field.type === \"Service\") ret.push(name);\n });\n if (!this.inputsLocked) this.inputAndServiceFieldListChanged?.attachWatcher(watcher);\n\n return ret;\n }\n\n public listOutputFields(watcher: Watcher): string[] {\n const ret: string[] = [];\n this.fieldsMap.forEach((field, name) => {\n if (field.type === \"Output\") ret.push(name);\n });\n if (!this.outputsLocked) this.outputFieldListChanged?.attachWatcher(watcher);\n\n return ret;\n }\n\n public listDynamicFields(watcher: Watcher): string[] {\n const ret: string[] = [];\n this.fieldsMap.forEach((field, name) => {\n if (field.type !== \"Input\" && field.type !== \"Output\") ret.push(name);\n });\n this.dynamicFieldListChanged?.attachWatcher(watcher);\n\n return ret;\n }\n\n public getKeyValue(watcher: Watcher, key: string): Uint8Array | undefined {\n this.kvChangedPerKey?.attachWatcher(key, watcher);\n return this.kv.get(key);\n }\n\n public getKeyValueString(watcher: Watcher, key: string): string | undefined {\n const bytes = this.getKeyValue(watcher, key);\n if (bytes === undefined) return undefined;\n return cachedDecode(bytes);\n }\n\n public getKeyValueAsJson<T = unknown>(watcher: Watcher, key: string): T | undefined {\n const bytes = this.getKeyValue(watcher, key);\n if (bytes === undefined) return undefined;\n return cachedDeserialize(bytes);\n }\n\n public getDataAsString(): string | undefined {\n if (this.data === undefined) return undefined;\n if (this.dataAsString === undefined) this.dataAsString = cachedDecode(this.data);\n return this.dataAsString;\n }\n\n public getDataAsJson<T = unknown>(): T | undefined {\n if (this.data === undefined) return undefined;\n if (this.dataAsJson === undefined) this.dataAsJson = cachedDeserialize(this.data);\n return this.dataAsJson as T;\n }\n\n verifyReadyState() {\n if (this.resourceReady && !this.inputsLocked)\n throw new Error(\n `ready without input or output lock: ${stringifyWithResourceId(this.basicState)}`,\n );\n }\n\n get basicState(): BasicResourceData {\n return {\n id: this.id,\n kind: this.kind,\n type: this.type,\n data: this.data,\n resourceReady: this.resourceReady,\n inputsLocked: this.inputsLocked,\n outputsLocked: this.outputsLocked,\n error: this.error,\n originalResourceId: this.originalResourceId,\n final: this.finalFlag,\n };\n }\n\n get extendedState(): ExtendedResourceData {\n return {\n ...this.basicState,\n fields: this.fields,\n kv: Array.from(this.kv.entries()).map(([key, value]) => ({ key, value })),\n };\n }\n\n /** Called when {@link FinalResourceDataPredicate} returns true for the state. */\n markFinal() {\n if (this._finalState) return;\n\n this._finalState = true;\n notEmpty(this.finalChanged).markChanged(\"marked final\");\n this.finalChanged = undefined;\n this.resourceStateChange = undefined;\n this.dynamicFieldListChanged = undefined;\n this.inputAndServiceFieldListChanged = undefined;\n this.outputFieldListChanged = undefined;\n this.lockedChange = undefined;\n // this.kvChangedGlobal = undefined;\n this.kvChangedPerKey = undefined;\n }\n\n /** Used for invalidation */\n markAllChanged() {\n this.fieldsMap.forEach((field) => field.change.markChanged(\"marked all changed\"));\n this.finalChanged?.markChanged(\"marked all changed\");\n this.resourceStateChange?.markChanged(\"marked all changed\");\n this.lockedChange?.markChanged(\"marked all changed\");\n this.inputAndServiceFieldListChanged?.markChanged(\"marked all changed\");\n this.outputFieldListChanged?.markChanged(\"marked all changed\");\n this.dynamicFieldListChanged?.markChanged(\"marked all changed\");\n // this.kvChangedGlobal?.markChanged('marked all changed');\n this.kvChangedPerKey?.markAllChanged(\"marked all changed\");\n this.resourceRemoved.markChanged(\"marked all changed\");\n }\n}\n\nexport class PlTreeState {\n /** resource heap */\n private resources: Map<SignedResourceId, PlTreeResource> = new Map();\n private readonly resourcesAdded = new ChangeSource();\n /** Resets to false if any invalid state transitions are registered,\n * after that tree will produce errors for any read or write operations */\n private _isValid: boolean = true;\n private invalidationMessage?: string;\n\n constructor(\n /** This will be the only resource not deleted during GC round */\n public readonly root: SignedResourceId,\n public readonly isFinalPredicate: FinalResourceDataPredicate,\n ) {}\n\n public forEachResource(cb: (res: ResourceDataWithFinalState) => void): void {\n this.resources.forEach((v) => cb(v));\n }\n\n private checkValid() {\n if (!this._isValid) throw new Error(this.invalidationMessage ?? \"tree is in invalid state\");\n }\n\n public get(watcher: Watcher, rid: SignedResourceId): PlTreeResource {\n this.checkValid();\n const res = this.resources.get(rid);\n if (res === undefined) {\n // to make recovery from resource not found possible, considering some\n // race conditions, where computable is created before tree is updated\n this.resourcesAdded.attachWatcher(watcher);\n throw new Error(`resource ${resourceIdToString(rid)} not found in the tree`);\n }\n res.resourceRemoved.attachWatcher(watcher);\n return res;\n }\n\n updateFromResourceData(resourceData: ExtendedResourceData[], allowOrphanInputs: boolean = false) {\n this.checkValid();\n\n // All resources for which recount should be incremented, first are aggregated in this list\n const incrementRefs: SignedResourceId[] = [];\n const decrementRefs: SignedResourceId[] = [];\n\n // patching / creating resources\n for (const rd of resourceData) {\n let resource = this.resources.get(rd.id);\n\n const statBeforeMutation = resource?.basicState;\n const unexpectedTransitionError = (reason: string): never => {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { fields, ...rdWithoutFields } = rd;\n this.invalidateTree();\n throw new TreeStateUpdateError(\n `Unexpected resource state transition (${reason}): ${stringifyWithResourceId(\n rdWithoutFields,\n )} -> ${stringifyWithResourceId(statBeforeMutation)}`,\n );\n };\n\n if (resource !== undefined) {\n // updating existing resource\n\n if (resource.finalState)\n unexpectedTransitionError(\"resource state can\\t be updated after it is marked as final\");\n\n let changed = false;\n // updating resource version, even if it was not changed\n resource.version += 1;\n\n // duplicate / original\n if (resource.originalResourceId !== rd.originalResourceId) {\n if (resource.originalResourceId !== NullSignedResourceId)\n unexpectedTransitionError(\"originalResourceId can't change after it is set\");\n resource.originalResourceId = rd.originalResourceId;\n // duplicate status of the resource counts as ready for the external observer\n notEmpty(resource.resourceStateChange).markChanged(\n `originalResourceId changed for ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // error\n if (isNotNullSignedResourceId(rd.error) && resource.error !== rd.error) {\n if (isNotNullSignedResourceId(resource.error))\n unexpectedTransitionError(\"resource can't change attached error after it is set\");\n resource.error = rd.error;\n incrementRefs.push(resource.error);\n notEmpty(resource.resourceStateChange).markChanged(\n `error changed for ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // updating fields\n for (const fd of rd.fields) {\n let field = resource.fieldsMap.get(fd.name);\n\n if (!field) {\n // new field\n\n field = new PlTreeField(\n fd.name,\n fd.type,\n fd.value,\n fd.error,\n fd.status,\n fd.valueIsFinal,\n resource.version,\n );\n if (isNotNullSignedResourceId(fd.value)) incrementRefs.push(fd.value);\n if (isNotNullSignedResourceId(fd.error)) incrementRefs.push(fd.error);\n\n if (fd.type === \"Input\" || fd.type === \"Service\") {\n if (resource.inputsLocked)\n unexpectedTransitionError(\n `adding ${fd.type} (${fd.name}) field while inputs locked`,\n );\n notEmpty(resource.inputAndServiceFieldListChanged).markChanged(\n `new ${fd.type} field ${fd.name} added to ${resourceIdToString(resource.id)}`,\n );\n } else if (fd.type === \"Output\") {\n if (resource.outputsLocked)\n unexpectedTransitionError(\n `adding ${fd.type} (${fd.name}) field while outputs locked`,\n );\n notEmpty(resource.outputFieldListChanged).markChanged(\n `new ${fd.type} field ${fd.name} added to ${resourceIdToString(resource.id)}`,\n );\n } else {\n notEmpty(resource.dynamicFieldListChanged).markChanged(\n `new ${fd.type} field ${fd.name} added to ${resourceIdToString(resource.id)}`,\n );\n }\n\n resource.fieldsMap.set(fd.name, field);\n\n changed = true;\n } else {\n // change of old field\n\n // in principle this transition is possible, see assertions below\n if (field.type !== fd.type) {\n if (field.type !== \"Dynamic\")\n unexpectedTransitionError(`field changed type ${field.type} -> ${fd.type}`);\n notEmpty(resource.dynamicFieldListChanged).markChanged(\n `field ${fd.name} changed type from Dynamic to ${fd.type} in ${resourceIdToString(resource.id)}`,\n );\n if (field.type === \"Input\" || field.type === \"Service\") {\n if (resource.inputsLocked)\n unexpectedTransitionError(\n `adding input field \"${fd.name}\", while corresponding list is locked`,\n );\n notEmpty(resource.inputAndServiceFieldListChanged).markChanged(\n `field ${fd.name} changed to type ${fd.type} in ${resourceIdToString(resource.id)}`,\n );\n }\n if (field.type === \"Output\") {\n if (resource.outputsLocked)\n unexpectedTransitionError(\n `adding output field \"${fd.name}\", while corresponding list is locked`,\n );\n notEmpty(resource.outputFieldListChanged).markChanged(\n `field ${fd.name} changed to type ${fd.type} in ${resourceIdToString(resource.id)}`,\n );\n }\n field.type = fd.type;\n field.change.markChanged(\n `field ${fd.name} type changed to ${fd.type} in ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // field value\n if (field.value !== fd.value) {\n if (isNotNullSignedResourceId(field.value)) decrementRefs.push(field.value);\n field.value = fd.value;\n if (isNotNullSignedResourceId(fd.value)) incrementRefs.push(fd.value);\n field.change.markChanged(\n `field ${fd.name} value changed in ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // field error\n if (field.error !== fd.error) {\n if (isNotNullSignedResourceId(field.error)) decrementRefs.push(field.error);\n field.error = fd.error;\n if (isNotNullSignedResourceId(fd.error)) incrementRefs.push(fd.error);\n field.change.markChanged(\n `field ${fd.name} error changed in ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // field status\n if (field.status !== fd.status) {\n field.status = fd.status;\n field.change.markChanged(\n `field ${fd.name} status changed to ${fd.status} in ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // field valueIsFinal flag\n if (field.valueIsFinal !== fd.valueIsFinal) {\n field.valueIsFinal = fd.valueIsFinal;\n field.change.markChanged(\n `field ${fd.name} valueIsFinal changed to ${fd.valueIsFinal} in ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n field.resourceVersion = resource.version;\n }\n }\n\n // detecting removed fields\n resource.fieldsMap.forEach((field, fieldName, fields) => {\n if (field.resourceVersion !== resource!.version) {\n if (field.type === \"Input\" || field.type === \"Service\" || field.type === \"Output\")\n unexpectedTransitionError(`removal of ${field.type} field ${fieldName}`);\n field.change.markChanged(\n `dynamic field ${fieldName} removed from ${resourceIdToString(resource!.id)}`,\n );\n fields.delete(fieldName);\n\n if (isNotNullSignedResourceId(field.value)) decrementRefs.push(field.value);\n if (isNotNullSignedResourceId(field.error)) decrementRefs.push(field.error);\n\n notEmpty(resource!.dynamicFieldListChanged).markChanged(\n `dynamic field ${fieldName} removed from ${resourceIdToString(resource!.id)}`,\n );\n }\n });\n\n // inputsLocked\n if (resource.inputsLocked !== rd.inputsLocked) {\n if (resource.inputsLocked) unexpectedTransitionError(\"inputs unlocking is not permitted\");\n resource.inputsLocked = rd.inputsLocked;\n notEmpty(resource.lockedChange).markChanged(\n `inputs locked for ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // outputsLocked\n if (resource.outputsLocked !== rd.outputsLocked) {\n if (resource.outputsLocked)\n unexpectedTransitionError(\"outputs unlocking is not permitted\");\n resource.outputsLocked = rd.outputsLocked;\n notEmpty(resource.lockedChange).markChanged(\n `outputs locked for ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // ready flag\n if (resource.resourceReady !== rd.resourceReady) {\n const readyStateBefore = resource.resourceReady;\n resource.resourceReady = rd.resourceReady;\n resource.verifyReadyState();\n if (!resource.isReadyOrError)\n unexpectedTransitionError(\n `resource can't lose it's ready or error state (ready state before ${readyStateBefore})`,\n );\n notEmpty(resource.resourceStateChange).markChanged(\n `ready flag changed to ${rd.resourceReady} for ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // syncing kv\n for (const kv of rd.kv) {\n const current = resource.kv.get(kv.key);\n if (current === undefined) {\n resource.kv.set(kv.key, kv.value);\n notEmpty(resource.kvChangedPerKey).markChanged(\n kv.key,\n `kv added for ${resourceIdToString(resource.id)}: ${kv.key}`,\n );\n } else if (Buffer.compare(current, kv.value) !== 0) {\n resource.kv.set(kv.key, kv.value);\n notEmpty(resource.kvChangedPerKey).markChanged(\n kv.key,\n `kv changed for ${resourceIdToString(resource.id)}: ${kv.key}`,\n );\n }\n }\n\n if (resource.kv.size > rd.kv.length) {\n // only it this case it makes sense to check for deletions\n const newStateKeys = new Set(rd.kv.map((kv) => kv.key));\n\n // deleting keys not present in resource anymore\n resource.kv.forEach((_value, key, map) => {\n if (!newStateKeys.has(key)) {\n map.delete(key);\n notEmpty(resource!.kvChangedPerKey).markChanged(\n key,\n `kv deleted for ${resourceIdToString(resource!.id)}: ${key}`,\n );\n }\n });\n }\n\n if (changed) {\n // if resource was changed, updating resource data version\n resource.dataVersion = resource.version;\n if (this.isFinalPredicate(resource)) resource.markFinal();\n }\n } else {\n // creating new resource\n\n resource = new PlTreeResource(rd);\n resource.verifyReadyState();\n if (isNotNullSignedResourceId(resource.error)) incrementRefs.push(resource.error);\n for (const fd of rd.fields) {\n const field = new PlTreeField(\n fd.name,\n fd.type,\n fd.value,\n fd.error,\n fd.status,\n fd.valueIsFinal,\n InitialResourceVersion,\n );\n if (isNotNullSignedResourceId(fd.value)) incrementRefs.push(fd.value);\n if (isNotNullSignedResourceId(fd.error)) incrementRefs.push(fd.error);\n resource.fieldsMap.set(fd.name, field);\n }\n\n // adding kv\n for (const kv of rd.kv) resource.kv.set(kv.key, kv.value);\n\n // checking that resource is final, and if so, marking it\n if (this.isFinalPredicate(resource)) resource.markFinal();\n\n // adding the resource to the heap\n this.resources.set(resource.id, resource);\n this.resourcesAdded.markChanged(`new resource ${resourceIdToString(resource.id)} added`);\n }\n }\n\n // applying refCount increments\n for (const rid of incrementRefs) {\n const res = this.resources.get(rid);\n if (!res) {\n this.invalidateTree();\n throw new TreeStateUpdateError(`orphan resource ${rid}`);\n }\n res.refCount++;\n }\n\n // recursively applying refCount decrements / doing garbage collection\n let currentRefs = decrementRefs;\n while (currentRefs.length > 0) {\n const nextRefs: SignedResourceId[] = [];\n for (const rid of currentRefs) {\n const res = this.resources.get(rid);\n if (!res) {\n this.invalidateTree();\n throw new TreeStateUpdateError(`orphan resource ${rid}`);\n }\n res.refCount--;\n\n // garbage collection\n if (res.refCount === 0 && res.id !== this.root) {\n // removing fields\n res.fieldsMap.forEach((field) => {\n if (isNotNullSignedResourceId(field.value)) nextRefs.push(field.value);\n if (isNotNullSignedResourceId(field.error)) nextRefs.push(field.error);\n field.change.markChanged(\n `field ${field.name} removed during garbage collection of ${resourceIdToString(res.id)}`,\n );\n });\n if (isNotNullSignedResourceId(res.error)) nextRefs.push(res.error);\n res.resourceRemoved.markChanged(\n `resource removed during garbage collection: ${resourceIdToString(res.id)}`,\n );\n this.resources.delete(rid);\n }\n }\n currentRefs = nextRefs;\n }\n\n // checking for orphans (maybe removed in the future)\n if (!allowOrphanInputs) {\n for (const rd of resourceData) {\n if (!this.resources.has(rd.id)) {\n this.invalidateTree();\n throw new TreeStateUpdateError(`orphan input resource ${rd.id}`);\n }\n }\n }\n }\n\n /** @deprecated use \"entry\" instead */\n public accessor(rid: SignedResourceId = this.root): PlTreeEntry {\n this.checkValid();\n return this.entry(rid);\n }\n\n public entry(rid: SignedResourceId = this.root): PlTreeEntry {\n this.checkValid();\n return new PlTreeEntry({ treeProvider: () => this }, rid);\n }\n\n public invalidateTree(msg?: string) {\n this._isValid = false;\n this.invalidationMessage = msg;\n this.resources.forEach((res) => {\n res.markAllChanged();\n });\n }\n\n public dumpState(): ExtendedResourceData[] {\n return Array.from(this.resources.values()).map((res) => res.extendedState);\n }\n}\n"],"mappings":";;;;;;AAgCA,IAAa,uBAAb,cAA0C,MAAM;CAC9C,YAAY,SAAiB;AAC3B,QAAM,QAAQ;;;AAIlB,IAAM,cAAN,MAAuC;CACrC,SAAkB,IAAIA,2BAAAA,cAAc;CAEpC,YACE,MACA,MACA,OACA,OACA,QACA,cAEA,iBACA;AARgB,OAAA,OAAA;AACT,OAAA,OAAA;AACA,OAAA,QAAA;AACA,OAAA,QAAA;AACA,OAAA,SAAA;AACA,OAAA,eAAA;AAEA,OAAA,kBAAA;;CAGT,IAAI,QAAmB;AACrB,SAAO;GACL,MAAM,KAAK;GACX,MAAM,KAAK;GACX,QAAQ,KAAK;GACb,OAAO,KAAK;GACZ,OAAO,KAAK;GACZ,cAAc,KAAK;GACpB;;;AAIL,MAAM,yBAAyB;;AAO/B,IAAa,iBAAb,MAAkE;;CAEhE,WAAmB;;CAGnB,UAAkB;;CAElB,cAAsB;CAEtB,4BAA+C,IAAI,KAAK;CAExD,qBAAc,IAAI,KAAyB;CAE3C,kBAA2B,IAAIA,2BAAAA,cAAc;CAI7C,eAAgB,IAAIA,2BAAAA,cAAc;CAElC,sBAAuB,IAAIA,2BAAAA,cAAc;CAEzC,eAAgB,IAAIA,2BAAAA,cAAc;CAClC,kCAAmC,IAAIA,2BAAAA,cAAc;CACrD,yBAA0B,IAAIA,2BAAAA,cAAc;CAC5C,0BAA2B,IAAIA,2BAAAA,cAAc;CAG7C,kBAAmB,IAAIC,2BAAAA,mBAAmB;CAE1C;CACA;CAEA;CACA;CAEA;CACA;CACA;CAEA;CAEA;CACA;CACA;CACA;;CAGA,cAAuB;CAEvB;CAEA,YAAY,cAAiC,QAAmB;AAC9D,OAAK,KAAK,aAAa;AACvB,OAAK,qBAAqB,aAAa;AACvC,OAAK,OAAO,aAAa;AACzB,OAAK,OAAO,aAAa;AACzB,OAAK,OAAO,aAAa;AACzB,OAAK,QAAQ,aAAa;AAC1B,OAAK,eAAe,aAAa;AACjC,OAAK,gBAAgB,aAAa;AAClC,OAAK,gBAAgB,aAAa;AAClC,OAAK,YAAY,aAAa;AAC9B,OAAK,SAAS;;CAKhB,KAAa,KAAa;AACxB,MAAI,KAAK,WAAW,KAAA,EAAW,MAAK,OAAO,KAAK,IAAI;;CAGtD,KAAa,KAAa;AACxB,MAAI,KAAK,WAAW,KAAA,EAAW,MAAK,OAAO,KAAK,IAAI;;CAGtD,IAAI,QAAiB;AACnB,SAAO,KAAK;;CAGd,IAAI,aAAsB;AACxB,SAAO,KAAK;;CAGd,IAAI,SAAsB;AACxB,SAAO,CAAC,GAAG,KAAK,UAAU,QAAQ,CAAC;;CAerC,SACE,SACA,OACA,mBAA6C,IACA;EAC7C,MAAM,OAA2B,OAAO,UAAU,WAAW,EAAE,OAAO,OAAO,GAAG;EAEhF,MAAM,QAAQ,KAAK,UAAU,IAAI,KAAK,MAAM;AAC5C,MAAI,UAAU,KAAA,GAAW;AACvB,OAAI,KAAK,wBAAwB,KAAK,mBACpC,OAAM,IAAI,MACR,UAAU,KAAK,MAAM,2BAAA,GAAA,0BAAA,oBAA6C,KAAK,GAAG,GAC3E;AAEH,OAAI,CAAC,KAAK,aAAc,MAAK,iCAAiC,cAAc,QAAQ;YAC3E,KAAK,oBAAoB,aAAa,KAAK,oBAAoB,QACtE,KAAI,KAAK,sBAEP,QAAO,KAAA;OACJ,OAAM,IAAI,MAAM,oCAAoC,KAAK,MAAM,GAAG;AAGzE,OAAI,CAAC,KAAK,cAAe,MAAK,wBAAwB,cAAc,QAAQ;YACnE,KAAK,oBAAoB,SAChC,KAAI,KAAK,sBAEP,QAAO,KAAA;OACJ,OAAM,IAAI,MAAM,0BAA0B,KAAK,MAAM,GAAG;AAG/D,QAAK,yBAAyB,cAAc,QAAQ;AACpD,OAAI,CAAC,KAAK,eAAe,CAAC,KAAK,iBAAkB,YAAW,qBAAqB,KAAK,MAAM;AAE5F;SACK;AACL,OAAI,KAAK,oBAAoB,KAAA,KAAa,MAAM,SAAS,KAAK,gBAC5D,OAAM,IAAI,MACR,mCAAmC,KAAK,gBAAgB,WAAW,MAAM,KAAK,sBAAsB,KAAK,QAC1G;GAEH,MAAM,MAAM,EAAE;AACd,QAAA,GAAA,0BAAA,2BAA8B,MAAM,MAAM,CAAE,KAAI,QAAQ,MAAM;AAC9D,QAAA,GAAA,0BAAA,2BAA8B,MAAM,MAAM,CAAE,KAAI,QAAQ,MAAM;AAC9D,OAAI,IAAI,UAAU,KAAA,KAAa,IAAI,UAAU,KAAA,EAI3C,YAAW,wBAAwB,KAAK,MAAM;AAChD,SAAM,OAAO,cAAc,QAAQ;AACnC,UAAO;;;CAIX,gBAAuB,SAA2B;AAChD,MAAI,CAAC,KAAK,aAER,MAAK,qBAAqB,cAAc,QAAQ;AAClD,SAAO,KAAK;;CAGd,iBAAwB,SAA2B;AACjD,MAAI,CAAC,KAAK,cAER,MAAK,qBAAqB,cAAc,QAAQ;AAClD,SAAO,KAAK;;CAGd,IAAW,iBAA0B;AACnC,SACE,KAAK,UAAUC,0BAAAA,wBACf,KAAK,iBACL,KAAK,uBAAuBA,0BAAAA;;CAIhC,WAAkB,SAA2B;AAC3C,OAAK,cAAc,cAAc,QAAQ;AACzC,SAAO,KAAK;;CAGd,kBAAyB,SAA2B;AAClD,MAAI,CAAC,KAAK,eAER,MAAK,qBAAqB,cAAc,QAAQ;AAClD,SAAO,KAAK;;CAGd,SAAgB,SAAgD;AAC9D,OAAA,GAAA,0BAAA,wBAA2B,KAAK,MAAM,EAAE;AACtC,QAAK,qBAAqB,cAAc,QAAQ;AAChD;QAGA,QAAO,KAAK;;CAIhB,gBAAuB,SAA4B;EACjD,MAAM,MAAgB,EAAE;AACxB,OAAK,UAAU,SAAS,OAAO,SAAS;AACtC,OAAI,MAAM,SAAS,WAAW,MAAM,SAAS,UAAW,KAAI,KAAK,KAAK;IACtE;AACF,MAAI,CAAC,KAAK,aAAc,MAAK,iCAAiC,cAAc,QAAQ;AAEpF,SAAO;;CAGT,iBAAwB,SAA4B;EAClD,MAAM,MAAgB,EAAE;AACxB,OAAK,UAAU,SAAS,OAAO,SAAS;AACtC,OAAI,MAAM,SAAS,SAAU,KAAI,KAAK,KAAK;IAC3C;AACF,MAAI,CAAC,KAAK,cAAe,MAAK,wBAAwB,cAAc,QAAQ;AAE5E,SAAO;;CAGT,kBAAyB,SAA4B;EACnD,MAAM,MAAgB,EAAE;AACxB,OAAK,UAAU,SAAS,OAAO,SAAS;AACtC,OAAI,MAAM,SAAS,WAAW,MAAM,SAAS,SAAU,KAAI,KAAK,KAAK;IACrE;AACF,OAAK,yBAAyB,cAAc,QAAQ;AAEpD,SAAO;;CAGT,YAAmB,SAAkB,KAAqC;AACxE,OAAK,iBAAiB,cAAc,KAAK,QAAQ;AACjD,SAAO,KAAK,GAAG,IAAI,IAAI;;CAGzB,kBAAyB,SAAkB,KAAiC;EAC1E,MAAM,QAAQ,KAAK,YAAY,SAAS,IAAI;AAC5C,MAAI,UAAU,KAAA,EAAW,QAAO,KAAA;AAChC,UAAA,GAAA,2BAAA,cAAoB,MAAM;;CAG5B,kBAAsC,SAAkB,KAA4B;EAClF,MAAM,QAAQ,KAAK,YAAY,SAAS,IAAI;AAC5C,MAAI,UAAU,KAAA,EAAW,QAAO,KAAA;AAChC,UAAA,GAAA,2BAAA,mBAAyB,MAAM;;CAGjC,kBAA6C;AAC3C,MAAI,KAAK,SAAS,KAAA,EAAW,QAAO,KAAA;AACpC,MAAI,KAAK,iBAAiB,KAAA,EAAW,MAAK,gBAAA,GAAA,2BAAA,cAA4B,KAAK,KAAK;AAChF,SAAO,KAAK;;CAGd,gBAAmD;AACjD,MAAI,KAAK,SAAS,KAAA,EAAW,QAAO,KAAA;AACpC,MAAI,KAAK,eAAe,KAAA,EAAW,MAAK,cAAA,GAAA,2BAAA,mBAA+B,KAAK,KAAK;AACjF,SAAO,KAAK;;CAGd,mBAAmB;AACjB,MAAI,KAAK,iBAAiB,CAAC,KAAK,aAC9B,OAAM,IAAI,MACR,wCAAA,GAAA,0BAAA,yBAA+D,KAAK,WAAW,GAChF;;CAGL,IAAI,aAAgC;AAClC,SAAO;GACL,IAAI,KAAK;GACT,MAAM,KAAK;GACX,MAAM,KAAK;GACX,MAAM,KAAK;GACX,eAAe,KAAK;GACpB,cAAc,KAAK;GACnB,eAAe,KAAK;GACpB,OAAO,KAAK;GACZ,oBAAoB,KAAK;GACzB,OAAO,KAAK;GACb;;CAGH,IAAI,gBAAsC;AACxC,SAAO;GACL,GAAG,KAAK;GACR,QAAQ,KAAK;GACb,IAAI,MAAM,KAAK,KAAK,GAAG,SAAS,CAAC,CAAC,KAAK,CAAC,KAAK,YAAY;IAAE;IAAK;IAAO,EAAE;GAC1E;;;CAIH,YAAY;AACV,MAAI,KAAK,YAAa;AAEtB,OAAK,cAAc;AACnB,GAAA,GAAA,2BAAA,UAAS,KAAK,aAAa,CAAC,YAAY,eAAe;AACvD,OAAK,eAAe,KAAA;AACpB,OAAK,sBAAsB,KAAA;AAC3B,OAAK,0BAA0B,KAAA;AAC/B,OAAK,kCAAkC,KAAA;AACvC,OAAK,yBAAyB,KAAA;AAC9B,OAAK,eAAe,KAAA;AAEpB,OAAK,kBAAkB,KAAA;;;CAIzB,iBAAiB;AACf,OAAK,UAAU,SAAS,UAAU,MAAM,OAAO,YAAY,qBAAqB,CAAC;AACjF,OAAK,cAAc,YAAY,qBAAqB;AACpD,OAAK,qBAAqB,YAAY,qBAAqB;AAC3D,OAAK,cAAc,YAAY,qBAAqB;AACpD,OAAK,iCAAiC,YAAY,qBAAqB;AACvE,OAAK,wBAAwB,YAAY,qBAAqB;AAC9D,OAAK,yBAAyB,YAAY,qBAAqB;AAE/D,OAAK,iBAAiB,eAAe,qBAAqB;AAC1D,OAAK,gBAAgB,YAAY,qBAAqB;;;AAI1D,IAAa,cAAb,MAAyB;;CAEvB,4BAA2D,IAAI,KAAK;CACpE,iBAAkC,IAAIF,2BAAAA,cAAc;;;CAGpD,WAA4B;CAC5B;CAEA,YAEE,MACA,kBACA;AAFgB,OAAA,OAAA;AACA,OAAA,mBAAA;;CAGlB,gBAAuB,IAAqD;AAC1E,OAAK,UAAU,SAAS,MAAM,GAAG,EAAE,CAAC;;CAGtC,aAAqB;AACnB,MAAI,CAAC,KAAK,SAAU,OAAM,IAAI,MAAM,KAAK,uBAAuB,2BAA2B;;CAG7F,IAAW,SAAkB,KAAuC;AAClE,OAAK,YAAY;EACjB,MAAM,MAAM,KAAK,UAAU,IAAI,IAAI;AACnC,MAAI,QAAQ,KAAA,GAAW;AAGrB,QAAK,eAAe,cAAc,QAAQ;AAC1C,SAAM,IAAI,MAAM,aAAA,GAAA,0BAAA,oBAA+B,IAAI,CAAC,wBAAwB;;AAE9E,MAAI,gBAAgB,cAAc,QAAQ;AAC1C,SAAO;;CAGT,uBAAuB,cAAsC,oBAA6B,OAAO;AAC/F,OAAK,YAAY;EAGjB,MAAM,gBAAoC,EAAE;EAC5C,MAAM,gBAAoC,EAAE;AAG5C,OAAK,MAAM,MAAM,cAAc;GAC7B,IAAI,WAAW,KAAK,UAAU,IAAI,GAAG,GAAG;GAExC,MAAM,qBAAqB,UAAU;GACrC,MAAM,6BAA6B,WAA0B;IAE3D,MAAM,EAAE,QAAQ,GAAG,oBAAoB;AACvC,SAAK,gBAAgB;AACrB,UAAM,IAAI,qBACR,yCAAyC,OAAO,MAAA,GAAA,0BAAA,yBAC9C,gBACD,CAAC,OAAA,GAAA,0BAAA,yBAA8B,mBAAmB,GACpD;;AAGH,OAAI,aAAa,KAAA,GAAW;AAG1B,QAAI,SAAS,WACX,2BAA0B,6DAA8D;IAE1F,IAAI,UAAU;AAEd,aAAS,WAAW;AAGpB,QAAI,SAAS,uBAAuB,GAAG,oBAAoB;AACzD,SAAI,SAAS,uBAAuBE,0BAAAA,qBAClC,2BAA0B,kDAAkD;AAC9E,cAAS,qBAAqB,GAAG;AAEjC,MAAA,GAAA,2BAAA,UAAS,SAAS,oBAAoB,CAAC,YACrC,mCAAA,GAAA,0BAAA,oBAAqD,SAAS,GAAG,GAClE;AACD,eAAU;;AAIZ,SAAA,GAAA,0BAAA,2BAA8B,GAAG,MAAM,IAAI,SAAS,UAAU,GAAG,OAAO;AACtE,UAAA,GAAA,0BAAA,2BAA8B,SAAS,MAAM,CAC3C,2BAA0B,uDAAuD;AACnF,cAAS,QAAQ,GAAG;AACpB,mBAAc,KAAK,SAAS,MAAM;AAClC,MAAA,GAAA,2BAAA,UAAS,SAAS,oBAAoB,CAAC,YACrC,sBAAA,GAAA,0BAAA,oBAAwC,SAAS,GAAG,GACrD;AACD,eAAU;;AAIZ,SAAK,MAAM,MAAM,GAAG,QAAQ;KAC1B,IAAI,QAAQ,SAAS,UAAU,IAAI,GAAG,KAAK;AAE3C,SAAI,CAAC,OAAO;AAGV,cAAQ,IAAI,YACV,GAAG,MACH,GAAG,MACH,GAAG,OACH,GAAG,OACH,GAAG,QACH,GAAG,cACH,SAAS,QACV;AACD,WAAA,GAAA,0BAAA,2BAA8B,GAAG,MAAM,CAAE,eAAc,KAAK,GAAG,MAAM;AACrE,WAAA,GAAA,0BAAA,2BAA8B,GAAG,MAAM,CAAE,eAAc,KAAK,GAAG,MAAM;AAErE,UAAI,GAAG,SAAS,WAAW,GAAG,SAAS,WAAW;AAChD,WAAI,SAAS,aACX,2BACE,UAAU,GAAG,KAAK,IAAI,GAAG,KAAK,6BAC/B;AACH,QAAA,GAAA,2BAAA,UAAS,SAAS,gCAAgC,CAAC,YACjD,OAAO,GAAG,KAAK,SAAS,GAAG,KAAK,aAAA,GAAA,0BAAA,oBAA+B,SAAS,GAAG,GAC5E;iBACQ,GAAG,SAAS,UAAU;AAC/B,WAAI,SAAS,cACX,2BACE,UAAU,GAAG,KAAK,IAAI,GAAG,KAAK,8BAC/B;AACH,QAAA,GAAA,2BAAA,UAAS,SAAS,uBAAuB,CAAC,YACxC,OAAO,GAAG,KAAK,SAAS,GAAG,KAAK,aAAA,GAAA,0BAAA,oBAA+B,SAAS,GAAG,GAC5E;YAED,EAAA,GAAA,2BAAA,UAAS,SAAS,wBAAwB,CAAC,YACzC,OAAO,GAAG,KAAK,SAAS,GAAG,KAAK,aAAA,GAAA,0BAAA,oBAA+B,SAAS,GAAG,GAC5E;AAGH,eAAS,UAAU,IAAI,GAAG,MAAM,MAAM;AAEtC,gBAAU;YACL;AAIL,UAAI,MAAM,SAAS,GAAG,MAAM;AAC1B,WAAI,MAAM,SAAS,UACjB,2BAA0B,sBAAsB,MAAM,KAAK,MAAM,GAAG,OAAO;AAC7E,QAAA,GAAA,2BAAA,UAAS,SAAS,wBAAwB,CAAC,YACzC,SAAS,GAAG,KAAK,gCAAgC,GAAG,KAAK,OAAA,GAAA,0BAAA,oBAAyB,SAAS,GAAG,GAC/F;AACD,WAAI,MAAM,SAAS,WAAW,MAAM,SAAS,WAAW;AACtD,YAAI,SAAS,aACX,2BACE,uBAAuB,GAAG,KAAK,uCAChC;AACH,SAAA,GAAA,2BAAA,UAAS,SAAS,gCAAgC,CAAC,YACjD,SAAS,GAAG,KAAK,mBAAmB,GAAG,KAAK,OAAA,GAAA,0BAAA,oBAAyB,SAAS,GAAG,GAClF;;AAEH,WAAI,MAAM,SAAS,UAAU;AAC3B,YAAI,SAAS,cACX,2BACE,wBAAwB,GAAG,KAAK,uCACjC;AACH,SAAA,GAAA,2BAAA,UAAS,SAAS,uBAAuB,CAAC,YACxC,SAAS,GAAG,KAAK,mBAAmB,GAAG,KAAK,OAAA,GAAA,0BAAA,oBAAyB,SAAS,GAAG,GAClF;;AAEH,aAAM,OAAO,GAAG;AAChB,aAAM,OAAO,YACX,SAAS,GAAG,KAAK,mBAAmB,GAAG,KAAK,OAAA,GAAA,0BAAA,oBAAyB,SAAS,GAAG,GAClF;AACD,iBAAU;;AAIZ,UAAI,MAAM,UAAU,GAAG,OAAO;AAC5B,YAAA,GAAA,0BAAA,2BAA8B,MAAM,MAAM,CAAE,eAAc,KAAK,MAAM,MAAM;AAC3E,aAAM,QAAQ,GAAG;AACjB,YAAA,GAAA,0BAAA,2BAA8B,GAAG,MAAM,CAAE,eAAc,KAAK,GAAG,MAAM;AACrE,aAAM,OAAO,YACX,SAAS,GAAG,KAAK,qBAAA,GAAA,0BAAA,oBAAuC,SAAS,GAAG,GACrE;AACD,iBAAU;;AAIZ,UAAI,MAAM,UAAU,GAAG,OAAO;AAC5B,YAAA,GAAA,0BAAA,2BAA8B,MAAM,MAAM,CAAE,eAAc,KAAK,MAAM,MAAM;AAC3E,aAAM,QAAQ,GAAG;AACjB,YAAA,GAAA,0BAAA,2BAA8B,GAAG,MAAM,CAAE,eAAc,KAAK,GAAG,MAAM;AACrE,aAAM,OAAO,YACX,SAAS,GAAG,KAAK,qBAAA,GAAA,0BAAA,oBAAuC,SAAS,GAAG,GACrE;AACD,iBAAU;;AAIZ,UAAI,MAAM,WAAW,GAAG,QAAQ;AAC9B,aAAM,SAAS,GAAG;AAClB,aAAM,OAAO,YACX,SAAS,GAAG,KAAK,qBAAqB,GAAG,OAAO,OAAA,GAAA,0BAAA,oBAAyB,SAAS,GAAG,GACtF;AACD,iBAAU;;AAIZ,UAAI,MAAM,iBAAiB,GAAG,cAAc;AAC1C,aAAM,eAAe,GAAG;AACxB,aAAM,OAAO,YACX,SAAS,GAAG,KAAK,2BAA2B,GAAG,aAAa,OAAA,GAAA,0BAAA,oBAAyB,SAAS,GAAG,GAClG;AACD,iBAAU;;AAGZ,YAAM,kBAAkB,SAAS;;;AAKrC,aAAS,UAAU,SAAS,OAAO,WAAW,WAAW;AACvD,SAAI,MAAM,oBAAoB,SAAU,SAAS;AAC/C,UAAI,MAAM,SAAS,WAAW,MAAM,SAAS,aAAa,MAAM,SAAS,SACvE,2BAA0B,cAAc,MAAM,KAAK,SAAS,YAAY;AAC1E,YAAM,OAAO,YACX,iBAAiB,UAAU,iBAAA,GAAA,0BAAA,oBAAmC,SAAU,GAAG,GAC5E;AACD,aAAO,OAAO,UAAU;AAExB,WAAA,GAAA,0BAAA,2BAA8B,MAAM,MAAM,CAAE,eAAc,KAAK,MAAM,MAAM;AAC3E,WAAA,GAAA,0BAAA,2BAA8B,MAAM,MAAM,CAAE,eAAc,KAAK,MAAM,MAAM;AAE3E,OAAA,GAAA,2BAAA,UAAS,SAAU,wBAAwB,CAAC,YAC1C,iBAAiB,UAAU,iBAAA,GAAA,0BAAA,oBAAmC,SAAU,GAAG,GAC5E;;MAEH;AAGF,QAAI,SAAS,iBAAiB,GAAG,cAAc;AAC7C,SAAI,SAAS,aAAc,2BAA0B,oCAAoC;AACzF,cAAS,eAAe,GAAG;AAC3B,MAAA,GAAA,2BAAA,UAAS,SAAS,aAAa,CAAC,YAC9B,sBAAA,GAAA,0BAAA,oBAAwC,SAAS,GAAG,GACrD;AACD,eAAU;;AAIZ,QAAI,SAAS,kBAAkB,GAAG,eAAe;AAC/C,SAAI,SAAS,cACX,2BAA0B,qCAAqC;AACjE,cAAS,gBAAgB,GAAG;AAC5B,MAAA,GAAA,2BAAA,UAAS,SAAS,aAAa,CAAC,YAC9B,uBAAA,GAAA,0BAAA,oBAAyC,SAAS,GAAG,GACtD;AACD,eAAU;;AAIZ,QAAI,SAAS,kBAAkB,GAAG,eAAe;KAC/C,MAAM,mBAAmB,SAAS;AAClC,cAAS,gBAAgB,GAAG;AAC5B,cAAS,kBAAkB;AAC3B,SAAI,CAAC,SAAS,eACZ,2BACE,qEAAqE,iBAAiB,GACvF;AACH,MAAA,GAAA,2BAAA,UAAS,SAAS,oBAAoB,CAAC,YACrC,yBAAyB,GAAG,cAAc,QAAA,GAAA,0BAAA,oBAA0B,SAAS,GAAG,GACjF;AACD,eAAU;;AAIZ,SAAK,MAAM,MAAM,GAAG,IAAI;KACtB,MAAM,UAAU,SAAS,GAAG,IAAI,GAAG,IAAI;AACvC,SAAI,YAAY,KAAA,GAAW;AACzB,eAAS,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM;AACjC,OAAA,GAAA,2BAAA,UAAS,SAAS,gBAAgB,CAAC,YACjC,GAAG,KACH,iBAAA,GAAA,0BAAA,oBAAmC,SAAS,GAAG,CAAC,IAAI,GAAG,MACxD;gBACQ,OAAO,QAAQ,SAAS,GAAG,MAAM,KAAK,GAAG;AAClD,eAAS,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM;AACjC,OAAA,GAAA,2BAAA,UAAS,SAAS,gBAAgB,CAAC,YACjC,GAAG,KACH,mBAAA,GAAA,0BAAA,oBAAqC,SAAS,GAAG,CAAC,IAAI,GAAG,MAC1D;;;AAIL,QAAI,SAAS,GAAG,OAAO,GAAG,GAAG,QAAQ;KAEnC,MAAM,eAAe,IAAI,IAAI,GAAG,GAAG,KAAK,OAAO,GAAG,IAAI,CAAC;AAGvD,cAAS,GAAG,SAAS,QAAQ,KAAK,QAAQ;AACxC,UAAI,CAAC,aAAa,IAAI,IAAI,EAAE;AAC1B,WAAI,OAAO,IAAI;AACf,QAAA,GAAA,2BAAA,UAAS,SAAU,gBAAgB,CAAC,YAClC,KACA,mBAAA,GAAA,0BAAA,oBAAqC,SAAU,GAAG,CAAC,IAAI,MACxD;;OAEH;;AAGJ,QAAI,SAAS;AAEX,cAAS,cAAc,SAAS;AAChC,SAAI,KAAK,iBAAiB,SAAS,CAAE,UAAS,WAAW;;UAEtD;AAGL,eAAW,IAAI,eAAe,GAAG;AACjC,aAAS,kBAAkB;AAC3B,SAAA,GAAA,0BAAA,2BAA8B,SAAS,MAAM,CAAE,eAAc,KAAK,SAAS,MAAM;AACjF,SAAK,MAAM,MAAM,GAAG,QAAQ;KAC1B,MAAM,QAAQ,IAAI,YAChB,GAAG,MACH,GAAG,MACH,GAAG,OACH,GAAG,OACH,GAAG,QACH,GAAG,cACH,uBACD;AACD,UAAA,GAAA,0BAAA,2BAA8B,GAAG,MAAM,CAAE,eAAc,KAAK,GAAG,MAAM;AACrE,UAAA,GAAA,0BAAA,2BAA8B,GAAG,MAAM,CAAE,eAAc,KAAK,GAAG,MAAM;AACrE,cAAS,UAAU,IAAI,GAAG,MAAM,MAAM;;AAIxC,SAAK,MAAM,MAAM,GAAG,GAAI,UAAS,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM;AAGzD,QAAI,KAAK,iBAAiB,SAAS,CAAE,UAAS,WAAW;AAGzD,SAAK,UAAU,IAAI,SAAS,IAAI,SAAS;AACzC,SAAK,eAAe,YAAY,iBAAA,GAAA,0BAAA,oBAAmC,SAAS,GAAG,CAAC,QAAQ;;;AAK5F,OAAK,MAAM,OAAO,eAAe;GAC/B,MAAM,MAAM,KAAK,UAAU,IAAI,IAAI;AACnC,OAAI,CAAC,KAAK;AACR,SAAK,gBAAgB;AACrB,UAAM,IAAI,qBAAqB,mBAAmB,MAAM;;AAE1D,OAAI;;EAIN,IAAI,cAAc;AAClB,SAAO,YAAY,SAAS,GAAG;GAC7B,MAAM,WAA+B,EAAE;AACvC,QAAK,MAAM,OAAO,aAAa;IAC7B,MAAM,MAAM,KAAK,UAAU,IAAI,IAAI;AACnC,QAAI,CAAC,KAAK;AACR,UAAK,gBAAgB;AACrB,WAAM,IAAI,qBAAqB,mBAAmB,MAAM;;AAE1D,QAAI;AAGJ,QAAI,IAAI,aAAa,KAAK,IAAI,OAAO,KAAK,MAAM;AAE9C,SAAI,UAAU,SAAS,UAAU;AAC/B,WAAA,GAAA,0BAAA,2BAA8B,MAAM,MAAM,CAAE,UAAS,KAAK,MAAM,MAAM;AACtE,WAAA,GAAA,0BAAA,2BAA8B,MAAM,MAAM,CAAE,UAAS,KAAK,MAAM,MAAM;AACtE,YAAM,OAAO,YACX,SAAS,MAAM,KAAK,yCAAA,GAAA,0BAAA,oBAA2D,IAAI,GAAG,GACvF;OACD;AACF,UAAA,GAAA,0BAAA,2BAA8B,IAAI,MAAM,CAAE,UAAS,KAAK,IAAI,MAAM;AAClE,SAAI,gBAAgB,YAClB,gDAAA,GAAA,0BAAA,oBAAkE,IAAI,GAAG,GAC1E;AACD,UAAK,UAAU,OAAO,IAAI;;;AAG9B,iBAAc;;AAIhB,MAAI,CAAC;QACE,MAAM,MAAM,aACf,KAAI,CAAC,KAAK,UAAU,IAAI,GAAG,GAAG,EAAE;AAC9B,SAAK,gBAAgB;AACrB,UAAM,IAAI,qBAAqB,yBAAyB,GAAG,KAAK;;;;;CAOxE,SAAgB,MAAwB,KAAK,MAAmB;AAC9D,OAAK,YAAY;AACjB,SAAO,KAAK,MAAM,IAAI;;CAGxB,MAAa,MAAwB,KAAK,MAAmB;AAC3D,OAAK,YAAY;AACjB,SAAO,IAAIC,kBAAAA,YAAY,EAAE,oBAAoB,MAAM,EAAE,IAAI;;CAG3D,eAAsB,KAAc;AAClC,OAAK,WAAW;AAChB,OAAK,sBAAsB;AAC3B,OAAK,UAAU,SAAS,QAAQ;AAC9B,OAAI,gBAAgB;IACpB;;CAGJ,YAA2C;AACzC,SAAO,MAAM,KAAK,KAAK,UAAU,QAAQ,CAAC,CAAC,KAAK,QAAQ,IAAI,cAAc"}
1
+ {"version":3,"file":"state.cjs","names":["ChangeSource","KeyedChangeSource","NullSignedResourceId","PlTreeEntry"],"sources":["../src/state.ts"],"sourcesContent":["import type {\n BasicResourceData,\n FieldData,\n FieldStatus,\n FieldType,\n KeyValue,\n OptionalSignedResourceId,\n ResourceData,\n SignedResourceId,\n ResourceKind,\n ResourceType,\n} from \"@milaboratories/pl-client\";\nimport {\n isNotNullSignedResourceId,\n isNullSignedResourceId,\n NullSignedResourceId,\n resourceIdToString,\n stringifyWithResourceId,\n} from \"@milaboratories/pl-client\";\nimport type { Watcher } from \"@milaboratories/computable\";\nimport { ChangeSource, KeyedChangeSource } from \"@milaboratories/computable\";\nimport { PlTreeEntry } from \"./accessors\";\nimport type { ValueAndError } from \"./value_and_error\";\nimport type { MiLogger } from \"@milaboratories/ts-helpers\";\nimport { cachedDecode, cachedDeserialize, notEmpty } from \"@milaboratories/ts-helpers\";\nimport type { FieldTraversalStep, GetFieldStep } from \"./traversal_ops\";\nimport type { FinalResourceDataPredicate } from \"@milaboratories/pl-client\";\n\nexport type ExtendedResourceData = ResourceData & {\n kv: KeyValue[];\n};\n\nexport class TreeStateUpdateError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nclass PlTreeField implements FieldData {\n readonly change = new ChangeSource();\n\n constructor(\n public readonly name: string,\n public type: FieldType,\n public value: OptionalSignedResourceId,\n public error: OptionalSignedResourceId,\n public status: FieldStatus,\n public valueIsFinal: boolean,\n /** Last version of resource this field was observed, used to garbage collect fields in tree patching procedure */\n public resourceVersion: number,\n ) {}\n\n get state(): FieldData {\n return {\n name: this.name,\n type: this.type,\n status: this.status,\n value: this.value,\n error: this.error,\n valueIsFinal: this.valueIsFinal,\n };\n }\n}\n\nconst InitialResourceVersion = 0;\n\nexport type ResourceDataWithFinalState = ResourceData & {\n finalState: boolean;\n};\n\n/** Never store instances of this class, always get fresh instance from {@link PlTreeState} */\nexport class PlTreeResource implements ResourceDataWithFinalState {\n /** Tracks number of other resources referencing this resource. Used to perform garbage collection in tree patching procedure */\n refCount: number = 0;\n\n /** Increments each time resource is checked for difference with new state */\n version: number = InitialResourceVersion;\n /** Set to resource version when resource state, or it's fields have changed */\n dataVersion: number = InitialResourceVersion;\n\n readonly fieldsMap: Map<string, PlTreeField> = new Map();\n\n readonly kv = new Map<string, Uint8Array>();\n\n readonly resourceRemoved = new ChangeSource();\n\n // following change source are removed when resource is marked as final\n\n finalChanged? = new ChangeSource();\n\n resourceStateChange? = new ChangeSource();\n\n lockedChange? = new ChangeSource();\n inputAndServiceFieldListChanged? = new ChangeSource();\n outputFieldListChanged? = new ChangeSource();\n dynamicFieldListChanged? = new ChangeSource();\n\n // kvChangedGlobal? = new ChangeSource();\n kvChangedPerKey? = new KeyedChangeSource();\n\n readonly id: SignedResourceId;\n originalResourceId: OptionalSignedResourceId;\n\n readonly kind: ResourceKind;\n readonly type: ResourceType;\n\n readonly data?: Uint8Array;\n private dataAsString?: string;\n private dataAsJson?: unknown;\n\n error: OptionalSignedResourceId;\n\n inputsLocked: boolean;\n outputsLocked: boolean;\n resourceReady: boolean;\n finalFlag: boolean;\n\n /** Set externally by the tree, using {@link FinalResourceDataPredicate} */\n _finalState: boolean = false;\n\n private readonly logger?: MiLogger;\n\n constructor(initialState: BasicResourceData, logger?: MiLogger) {\n this.id = initialState.id;\n this.originalResourceId = initialState.originalResourceId;\n this.kind = initialState.kind;\n this.type = initialState.type;\n this.data = initialState.data;\n this.error = initialState.error;\n this.inputsLocked = initialState.inputsLocked;\n this.outputsLocked = initialState.outputsLocked;\n this.resourceReady = initialState.resourceReady;\n this.finalFlag = initialState.final;\n this.logger = logger;\n }\n\n // TODO add logging\n\n private info(msg: string) {\n if (this.logger !== undefined) this.logger.info(msg);\n }\n\n private warn(msg: string) {\n if (this.logger !== undefined) this.logger.warn(msg);\n }\n\n get final(): boolean {\n return this.finalFlag;\n }\n\n get finalState(): boolean {\n return this._finalState;\n }\n\n get fields(): FieldData[] {\n return [...this.fieldsMap.values()];\n }\n\n public getField(\n watcher: Watcher,\n _step:\n | (Omit<GetFieldStep, \"errorIfFieldNotFound\"> & { errorIfFieldNotFound: true })\n | (Omit<GetFieldStep, \"errorIfFieldNotSet\"> & { errorIfFieldNotSet: true }),\n onUnstable: (marker: string) => void,\n ): ValueAndError<SignedResourceId>;\n public getField(\n watcher: Watcher,\n _step: string | GetFieldStep,\n onUnstable: (marker: string) => void,\n ): ValueAndError<SignedResourceId> | undefined;\n public getField(\n watcher: Watcher,\n _step: string | GetFieldStep,\n onUnstable: (marker: string) => void = () => {},\n ): ValueAndError<SignedResourceId> | undefined {\n const step: FieldTraversalStep = typeof _step === \"string\" ? { field: _step } : _step;\n\n const field = this.fieldsMap.get(step.field);\n if (field === undefined) {\n if (step.errorIfFieldNotFound || step.errorIfFieldNotSet)\n throw new Error(\n `Field \"${step.field}\" not found in resource ${resourceIdToString(this.id)}`,\n );\n\n if (!this.inputsLocked) this.inputAndServiceFieldListChanged?.attachWatcher(watcher);\n else if (step.assertFieldType === \"Service\" || step.assertFieldType === \"Input\") {\n if (step.allowPermanentAbsence)\n // stable absence of field\n return undefined;\n else throw new Error(`Service or input field not found ${step.field}.`);\n }\n\n if (!this.outputsLocked) this.outputFieldListChanged?.attachWatcher(watcher);\n else if (step.assertFieldType === \"Output\") {\n if (step.allowPermanentAbsence)\n // stable absence of field\n return undefined;\n else throw new Error(`Output field not found ${step.field}.`);\n }\n\n this.dynamicFieldListChanged?.attachWatcher(watcher);\n if (!this._finalState && !step.stableIfNotFound) onUnstable(\"field_not_found:\" + step.field);\n\n return undefined;\n } else {\n if (step.assertFieldType !== undefined && field.type !== step.assertFieldType)\n throw new Error(\n `Unexpected field type: expected ${step.assertFieldType} but got ${field.type} for the field name ${step.field}`,\n );\n\n const ret = {} as ValueAndError<SignedResourceId>;\n if (isNotNullSignedResourceId(field.value)) ret.value = field.value;\n if (isNotNullSignedResourceId(field.error)) ret.error = field.error;\n if (ret.value === undefined && ret.error === undefined)\n // this method returns value and error of the field, thus those values are considered to be accessed;\n // any existing but not resolved field here is considered to be unstable, in the sense it is\n // considered to acquire some resolved value eventually\n onUnstable(\"field_not_resolved:\" + step.field);\n field.change.attachWatcher(watcher);\n return ret;\n }\n }\n\n public getInputsLocked(watcher: Watcher): boolean {\n if (!this.inputsLocked)\n // reverse transition can't happen, so there is no reason to wait for value to change\n this.resourceStateChange?.attachWatcher(watcher);\n return this.inputsLocked;\n }\n\n public getOutputsLocked(watcher: Watcher): boolean {\n if (!this.outputsLocked)\n // reverse transition can't happen, so there is no reason to wait for value to change\n this.resourceStateChange?.attachWatcher(watcher);\n return this.outputsLocked;\n }\n\n public get isReadyOrError(): boolean {\n return (\n this.error !== NullSignedResourceId ||\n this.resourceReady ||\n this.originalResourceId !== NullSignedResourceId\n );\n }\n\n public getIsFinal(watcher: Watcher): boolean {\n this.finalChanged?.attachWatcher(watcher);\n return this._finalState;\n }\n\n public getIsReadyOrError(watcher: Watcher): boolean {\n if (!this.isReadyOrError)\n // reverse transition can't happen, so there is no reason to wait for value to change if it is already true\n this.resourceStateChange?.attachWatcher(watcher);\n return this.isReadyOrError;\n }\n\n public getError(watcher: Watcher): SignedResourceId | undefined {\n if (isNullSignedResourceId(this.error)) {\n this.resourceStateChange?.attachWatcher(watcher);\n return undefined;\n } else {\n // reverse transition can't happen, so there is no reason to wait for value to change, if error already set\n return this.error;\n }\n }\n\n public listInputFields(watcher: Watcher): string[] {\n const ret: string[] = [];\n this.fieldsMap.forEach((field, name) => {\n if (field.type === \"Input\" || field.type === \"Service\") ret.push(name);\n });\n if (!this.inputsLocked) this.inputAndServiceFieldListChanged?.attachWatcher(watcher);\n\n return ret;\n }\n\n public listOutputFields(watcher: Watcher): string[] {\n const ret: string[] = [];\n this.fieldsMap.forEach((field, name) => {\n if (field.type === \"Output\") ret.push(name);\n });\n if (!this.outputsLocked) this.outputFieldListChanged?.attachWatcher(watcher);\n\n return ret;\n }\n\n public listDynamicFields(watcher: Watcher): string[] {\n const ret: string[] = [];\n this.fieldsMap.forEach((field, name) => {\n if (field.type !== \"Input\" && field.type !== \"Output\") ret.push(name);\n });\n this.dynamicFieldListChanged?.attachWatcher(watcher);\n\n return ret;\n }\n\n public getKeyValue(watcher: Watcher, key: string): Uint8Array | undefined {\n this.kvChangedPerKey?.attachWatcher(key, watcher);\n return this.kv.get(key);\n }\n\n public getKeyValueString(watcher: Watcher, key: string): string | undefined {\n const bytes = this.getKeyValue(watcher, key);\n if (bytes === undefined) return undefined;\n return cachedDecode(bytes);\n }\n\n public getKeyValueAsJson<T = unknown>(watcher: Watcher, key: string): T | undefined {\n const bytes = this.getKeyValue(watcher, key);\n if (bytes === undefined) return undefined;\n return cachedDeserialize(bytes);\n }\n\n public getDataAsString(): string | undefined {\n if (this.data === undefined) return undefined;\n if (this.dataAsString === undefined) this.dataAsString = cachedDecode(this.data);\n return this.dataAsString;\n }\n\n public getDataAsJson<T = unknown>(): T | undefined {\n if (this.data === undefined) return undefined;\n if (this.dataAsJson === undefined) this.dataAsJson = cachedDeserialize(this.data);\n return this.dataAsJson as T;\n }\n\n verifyReadyState() {\n if (this.resourceReady && !this.inputsLocked)\n throw new Error(\n `ready without input or output lock: ${stringifyWithResourceId(this.basicState)}`,\n );\n }\n\n get basicState(): BasicResourceData {\n return {\n id: this.id,\n kind: this.kind,\n type: this.type,\n data: this.data,\n resourceReady: this.resourceReady,\n inputsLocked: this.inputsLocked,\n outputsLocked: this.outputsLocked,\n error: this.error,\n originalResourceId: this.originalResourceId,\n final: this.finalFlag,\n };\n }\n\n get extendedState(): ExtendedResourceData {\n return {\n ...this.basicState,\n fields: this.fields,\n kv: Array.from(this.kv.entries()).map(([key, value]) => ({ key, value })),\n };\n }\n\n /** Called when {@link FinalResourceDataPredicate} returns true for the state. */\n markFinal() {\n if (this._finalState) return;\n\n this._finalState = true;\n notEmpty(this.finalChanged).markChanged(\"marked final\");\n this.finalChanged = undefined;\n this.resourceStateChange = undefined;\n this.dynamicFieldListChanged = undefined;\n this.inputAndServiceFieldListChanged = undefined;\n this.outputFieldListChanged = undefined;\n this.lockedChange = undefined;\n // this.kvChangedGlobal = undefined;\n this.kvChangedPerKey = undefined;\n }\n\n /** Used for invalidation */\n markAllChanged() {\n this.fieldsMap.forEach((field) => field.change.markChanged(\"marked all changed\"));\n this.finalChanged?.markChanged(\"marked all changed\");\n this.resourceStateChange?.markChanged(\"marked all changed\");\n this.lockedChange?.markChanged(\"marked all changed\");\n this.inputAndServiceFieldListChanged?.markChanged(\"marked all changed\");\n this.outputFieldListChanged?.markChanged(\"marked all changed\");\n this.dynamicFieldListChanged?.markChanged(\"marked all changed\");\n // this.kvChangedGlobal?.markChanged('marked all changed');\n this.kvChangedPerKey?.markAllChanged(\"marked all changed\");\n this.resourceRemoved.markChanged(\"marked all changed\");\n }\n}\n\nexport class PlTreeState {\n /** resource heap */\n private resources: Map<SignedResourceId, PlTreeResource> = new Map();\n private readonly resourcesAdded = new ChangeSource();\n /** Marked when the root set changes (roots discovered or removed), so multi-root\n * accessors that read the set recompute. */\n private readonly rootsChanged = new ChangeSource();\n /** Resets to false if any invalid state transitions are registered,\n * after that tree will produce errors for any read or write operations */\n private _isValid: boolean = true;\n private invalidationMessage?: string;\n\n /** The set of roots — resources protected from GC. Originally a single `root`,\n * generalized to a set so several explicit roots and dynamically-discovered shared\n * roots can coexist in one heap. Mutated through {@link setRoots}. */\n public readonly roots: Set<SignedResourceId>;\n\n constructor(\n /** Resources protected from GC. Accepts a single id (single-root, the original\n * contract) or a set of ids (multi-root). */\n roots: SignedResourceId | Set<SignedResourceId>,\n public readonly isFinalPredicate: FinalResourceDataPredicate,\n ) {\n this.roots = roots instanceof Set ? new Set(roots) : new Set([roots]);\n }\n\n /** Backward-compatible single-root accessor. Returns the sole root and THROWS if the\n * tree has zero or more than one root, so a multi-root tree can never be read as if it\n * had one. Mirrors the {@link entry} guard. */\n public get root(): SignedResourceId {\n if (this.roots.size !== 1)\n throw new Error(\n `single-root accessor used on a tree with ${this.roots.size} roots; use the multi-root API`,\n );\n return this.roots.values().next().value!;\n }\n\n public forEachResource(cb: (res: ResourceDataWithFinalState) => void): void {\n this.resources.forEach((v) => cb(v));\n }\n\n private checkValid() {\n if (!this._isValid) throw new Error(this.invalidationMessage ?? \"tree is in invalid state\");\n }\n\n /** Reactive read of the current root set. Attaches the watcher to {@link rootsChanged}\n * so a Computable recomputes when discovered roots appear or disappear. */\n public getRoots(watcher: Watcher): SignedResourceId[] {\n this.checkValid();\n this.rootsChanged.attachWatcher(watcher);\n return [...this.roots];\n }\n\n public get(watcher: Watcher, rid: SignedResourceId): PlTreeResource {\n this.checkValid();\n const res = this.resources.get(rid);\n if (res === undefined) {\n // to make recovery from resource not found possible, considering some\n // race conditions, where computable is created before tree is updated\n this.resourcesAdded.attachWatcher(watcher);\n throw new Error(`resource ${resourceIdToString(rid)} not found in the tree`);\n }\n res.resourceRemoved.attachWatcher(watcher);\n return res;\n }\n\n updateFromResourceData(resourceData: ExtendedResourceData[], allowOrphanInputs: boolean = false) {\n this.checkValid();\n\n // All resources for which recount should be incremented, first are aggregated in this list\n const incrementRefs: SignedResourceId[] = [];\n const decrementRefs: SignedResourceId[] = [];\n\n // patching / creating resources\n for (const rd of resourceData) {\n let resource = this.resources.get(rd.id);\n\n const statBeforeMutation = resource?.basicState;\n const unexpectedTransitionError = (reason: string): never => {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { fields, ...rdWithoutFields } = rd;\n this.invalidateTree();\n throw new TreeStateUpdateError(\n `Unexpected resource state transition (${reason}): ${stringifyWithResourceId(\n rdWithoutFields,\n )} -> ${stringifyWithResourceId(statBeforeMutation)}`,\n );\n };\n\n if (resource !== undefined) {\n // updating existing resource\n\n if (resource.finalState)\n unexpectedTransitionError(\"resource state can\\t be updated after it is marked as final\");\n\n let changed = false;\n // updating resource version, even if it was not changed\n resource.version += 1;\n\n // duplicate / original\n if (resource.originalResourceId !== rd.originalResourceId) {\n if (resource.originalResourceId !== NullSignedResourceId)\n unexpectedTransitionError(\"originalResourceId can't change after it is set\");\n resource.originalResourceId = rd.originalResourceId;\n // duplicate status of the resource counts as ready for the external observer\n notEmpty(resource.resourceStateChange).markChanged(\n `originalResourceId changed for ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // error\n if (isNotNullSignedResourceId(rd.error) && resource.error !== rd.error) {\n if (isNotNullSignedResourceId(resource.error))\n unexpectedTransitionError(\"resource can't change attached error after it is set\");\n resource.error = rd.error;\n incrementRefs.push(resource.error);\n notEmpty(resource.resourceStateChange).markChanged(\n `error changed for ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // updating fields\n for (const fd of rd.fields) {\n let field = resource.fieldsMap.get(fd.name);\n\n if (!field) {\n // new field\n\n field = new PlTreeField(\n fd.name,\n fd.type,\n fd.value,\n fd.error,\n fd.status,\n fd.valueIsFinal,\n resource.version,\n );\n if (isNotNullSignedResourceId(fd.value)) incrementRefs.push(fd.value);\n if (isNotNullSignedResourceId(fd.error)) incrementRefs.push(fd.error);\n\n if (fd.type === \"Input\" || fd.type === \"Service\") {\n if (resource.inputsLocked)\n unexpectedTransitionError(\n `adding ${fd.type} (${fd.name}) field while inputs locked`,\n );\n notEmpty(resource.inputAndServiceFieldListChanged).markChanged(\n `new ${fd.type} field ${fd.name} added to ${resourceIdToString(resource.id)}`,\n );\n } else if (fd.type === \"Output\") {\n if (resource.outputsLocked)\n unexpectedTransitionError(\n `adding ${fd.type} (${fd.name}) field while outputs locked`,\n );\n notEmpty(resource.outputFieldListChanged).markChanged(\n `new ${fd.type} field ${fd.name} added to ${resourceIdToString(resource.id)}`,\n );\n } else {\n notEmpty(resource.dynamicFieldListChanged).markChanged(\n `new ${fd.type} field ${fd.name} added to ${resourceIdToString(resource.id)}`,\n );\n }\n\n resource.fieldsMap.set(fd.name, field);\n\n changed = true;\n } else {\n // change of old field\n\n // in principle this transition is possible, see assertions below\n if (field.type !== fd.type) {\n if (field.type !== \"Dynamic\")\n unexpectedTransitionError(`field changed type ${field.type} -> ${fd.type}`);\n notEmpty(resource.dynamicFieldListChanged).markChanged(\n `field ${fd.name} changed type from Dynamic to ${fd.type} in ${resourceIdToString(resource.id)}`,\n );\n if (field.type === \"Input\" || field.type === \"Service\") {\n if (resource.inputsLocked)\n unexpectedTransitionError(\n `adding input field \"${fd.name}\", while corresponding list is locked`,\n );\n notEmpty(resource.inputAndServiceFieldListChanged).markChanged(\n `field ${fd.name} changed to type ${fd.type} in ${resourceIdToString(resource.id)}`,\n );\n }\n if (field.type === \"Output\") {\n if (resource.outputsLocked)\n unexpectedTransitionError(\n `adding output field \"${fd.name}\", while corresponding list is locked`,\n );\n notEmpty(resource.outputFieldListChanged).markChanged(\n `field ${fd.name} changed to type ${fd.type} in ${resourceIdToString(resource.id)}`,\n );\n }\n field.type = fd.type;\n field.change.markChanged(\n `field ${fd.name} type changed to ${fd.type} in ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // field value\n if (field.value !== fd.value) {\n if (isNotNullSignedResourceId(field.value)) decrementRefs.push(field.value);\n field.value = fd.value;\n if (isNotNullSignedResourceId(fd.value)) incrementRefs.push(fd.value);\n field.change.markChanged(\n `field ${fd.name} value changed in ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // field error\n if (field.error !== fd.error) {\n if (isNotNullSignedResourceId(field.error)) decrementRefs.push(field.error);\n field.error = fd.error;\n if (isNotNullSignedResourceId(fd.error)) incrementRefs.push(fd.error);\n field.change.markChanged(\n `field ${fd.name} error changed in ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // field status\n if (field.status !== fd.status) {\n field.status = fd.status;\n field.change.markChanged(\n `field ${fd.name} status changed to ${fd.status} in ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // field valueIsFinal flag\n if (field.valueIsFinal !== fd.valueIsFinal) {\n field.valueIsFinal = fd.valueIsFinal;\n field.change.markChanged(\n `field ${fd.name} valueIsFinal changed to ${fd.valueIsFinal} in ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n field.resourceVersion = resource.version;\n }\n }\n\n // detecting removed fields\n resource.fieldsMap.forEach((field, fieldName, fields) => {\n if (field.resourceVersion !== resource!.version) {\n if (field.type === \"Input\" || field.type === \"Service\" || field.type === \"Output\")\n unexpectedTransitionError(`removal of ${field.type} field ${fieldName}`);\n field.change.markChanged(\n `dynamic field ${fieldName} removed from ${resourceIdToString(resource!.id)}`,\n );\n fields.delete(fieldName);\n\n if (isNotNullSignedResourceId(field.value)) decrementRefs.push(field.value);\n if (isNotNullSignedResourceId(field.error)) decrementRefs.push(field.error);\n\n notEmpty(resource!.dynamicFieldListChanged).markChanged(\n `dynamic field ${fieldName} removed from ${resourceIdToString(resource!.id)}`,\n );\n }\n });\n\n // inputsLocked\n if (resource.inputsLocked !== rd.inputsLocked) {\n if (resource.inputsLocked) unexpectedTransitionError(\"inputs unlocking is not permitted\");\n resource.inputsLocked = rd.inputsLocked;\n notEmpty(resource.lockedChange).markChanged(\n `inputs locked for ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // outputsLocked\n if (resource.outputsLocked !== rd.outputsLocked) {\n if (resource.outputsLocked)\n unexpectedTransitionError(\"outputs unlocking is not permitted\");\n resource.outputsLocked = rd.outputsLocked;\n notEmpty(resource.lockedChange).markChanged(\n `outputs locked for ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // ready flag\n if (resource.resourceReady !== rd.resourceReady) {\n const readyStateBefore = resource.resourceReady;\n resource.resourceReady = rd.resourceReady;\n resource.verifyReadyState();\n if (!resource.isReadyOrError)\n unexpectedTransitionError(\n `resource can't lose it's ready or error state (ready state before ${readyStateBefore})`,\n );\n notEmpty(resource.resourceStateChange).markChanged(\n `ready flag changed to ${rd.resourceReady} for ${resourceIdToString(resource.id)}`,\n );\n changed = true;\n }\n\n // syncing kv\n for (const kv of rd.kv) {\n const current = resource.kv.get(kv.key);\n if (current === undefined) {\n resource.kv.set(kv.key, kv.value);\n notEmpty(resource.kvChangedPerKey).markChanged(\n kv.key,\n `kv added for ${resourceIdToString(resource.id)}: ${kv.key}`,\n );\n } else if (Buffer.compare(current, kv.value) !== 0) {\n resource.kv.set(kv.key, kv.value);\n notEmpty(resource.kvChangedPerKey).markChanged(\n kv.key,\n `kv changed for ${resourceIdToString(resource.id)}: ${kv.key}`,\n );\n }\n }\n\n if (resource.kv.size > rd.kv.length) {\n // only it this case it makes sense to check for deletions\n const newStateKeys = new Set(rd.kv.map((kv) => kv.key));\n\n // deleting keys not present in resource anymore\n resource.kv.forEach((_value, key, map) => {\n if (!newStateKeys.has(key)) {\n map.delete(key);\n notEmpty(resource!.kvChangedPerKey).markChanged(\n key,\n `kv deleted for ${resourceIdToString(resource!.id)}: ${key}`,\n );\n }\n });\n }\n\n if (changed) {\n // if resource was changed, updating resource data version\n resource.dataVersion = resource.version;\n if (this.isFinalPredicate(resource)) resource.markFinal();\n }\n } else {\n // creating new resource\n\n resource = new PlTreeResource(rd);\n resource.verifyReadyState();\n if (isNotNullSignedResourceId(resource.error)) incrementRefs.push(resource.error);\n for (const fd of rd.fields) {\n const field = new PlTreeField(\n fd.name,\n fd.type,\n fd.value,\n fd.error,\n fd.status,\n fd.valueIsFinal,\n InitialResourceVersion,\n );\n if (isNotNullSignedResourceId(fd.value)) incrementRefs.push(fd.value);\n if (isNotNullSignedResourceId(fd.error)) incrementRefs.push(fd.error);\n resource.fieldsMap.set(fd.name, field);\n }\n\n // adding kv\n for (const kv of rd.kv) resource.kv.set(kv.key, kv.value);\n\n // checking that resource is final, and if so, marking it\n if (this.isFinalPredicate(resource)) resource.markFinal();\n\n // adding the resource to the heap\n this.resources.set(resource.id, resource);\n this.resourcesAdded.markChanged(`new resource ${resourceIdToString(resource.id)} added`);\n }\n }\n\n // applying refCount increments\n for (const rid of incrementRefs) {\n const res = this.resources.get(rid);\n if (!res) {\n this.invalidateTree();\n throw new TreeStateUpdateError(`orphan resource ${rid}`);\n }\n res.refCount++;\n }\n\n // recursively applying refCount decrements / doing garbage collection\n this.collectGarbage(decrementRefs);\n\n // checking for orphans (maybe removed in the future)\n if (!allowOrphanInputs) {\n for (const rd of resourceData) {\n if (!this.resources.has(rd.id)) {\n this.invalidateTree();\n throw new TreeStateUpdateError(`orphan input resource ${rd.id}`);\n }\n }\n }\n }\n\n /** Runs the refcount-decrement garbage-collection cascade over the given worklist.\n * A resource reaching refCount 0 that is not a root is removed, and its outgoing\n * references are decremented in turn, until the worklist drains. Factored out of\n * {@link updateFromResourceData} so {@link setRoots} can reuse the same cascade. */\n private collectGarbage(decrementRefs: SignedResourceId[]) {\n let currentRefs = decrementRefs;\n while (currentRefs.length > 0) {\n const nextRefs: SignedResourceId[] = [];\n for (const rid of currentRefs) {\n const res = this.resources.get(rid);\n if (!res) {\n this.invalidateTree();\n throw new TreeStateUpdateError(`orphan resource ${rid}`);\n }\n res.refCount--;\n\n // garbage collection\n if (res.refCount === 0 && !this.roots.has(res.id)) {\n // removing fields\n res.fieldsMap.forEach((field) => {\n if (isNotNullSignedResourceId(field.value)) nextRefs.push(field.value);\n if (isNotNullSignedResourceId(field.error)) nextRefs.push(field.error);\n field.change.markChanged(\n `field ${field.name} removed during garbage collection of ${resourceIdToString(res.id)}`,\n );\n });\n if (isNotNullSignedResourceId(res.error)) nextRefs.push(res.error);\n res.resourceRemoved.markChanged(\n `resource removed during garbage collection: ${resourceIdToString(res.id)}`,\n );\n this.resources.delete(rid);\n }\n }\n currentRefs = nextRefs;\n }\n }\n\n /** Replaces the current root set with `newRoots`.\n *\n * Roots that leave the set lose their GC protection: each removed root present in the\n * heap is collected directly (a root sits at refCount 0, so it is never enqueued by an\n * ordinary decrement), and its subtree cascades to collection through the existing\n * refcount GC — the standard removal mechanic, applied to a root. Roots newly added to\n * the set are protected immediately; their resources arrive on the next refresh poll. */\n public setRoots(newRoots: Set<SignedResourceId>) {\n this.checkValid();\n\n const removed: SignedResourceId[] = [];\n for (const rid of this.roots) if (!newRoots.has(rid)) removed.push(rid);\n let added = false;\n for (const rid of newRoots) if (!this.roots.has(rid)) added = true;\n if (removed.length === 0 && !added) return; // no change\n\n // commit the new protected set before collecting, so a removed root is no longer\n // protected while its subtree cascades.\n this.roots.clear();\n for (const rid of newRoots) this.roots.add(rid);\n\n this.rootsChanged.markChanged(\"root set changed\");\n\n for (const rid of removed) {\n const res = this.resources.get(rid);\n if (res === undefined) continue; // root not yet materialized in the heap\n\n // if the (former) root is still referenced by another resource, dropping protection\n // is enough — ordinary refcounting keeps it alive and will collect it later.\n if (res.refCount > 0) continue;\n\n // collect the (now-unprotected) root itself and seed the cascade with the refs it holds\n const seed: SignedResourceId[] = [];\n res.fieldsMap.forEach((field) => {\n if (isNotNullSignedResourceId(field.value)) seed.push(field.value);\n if (isNotNullSignedResourceId(field.error)) seed.push(field.error);\n field.change.markChanged(\n `field ${field.name} removed after root ${resourceIdToString(res.id)} left the root set`,\n );\n });\n if (isNotNullSignedResourceId(res.error)) seed.push(res.error);\n res.resourceRemoved.markChanged(\n `resource removed after leaving the root set: ${resourceIdToString(res.id)}`,\n );\n this.resources.delete(rid);\n\n this.collectGarbage(seed);\n }\n }\n\n /** @deprecated use \"entry\" instead */\n public accessor(rid: SignedResourceId = this.root): PlTreeEntry {\n this.checkValid();\n return this.entry(rid);\n }\n\n public entry(rid: SignedResourceId = this.root): PlTreeEntry {\n this.checkValid();\n return new PlTreeEntry({ treeProvider: () => this }, rid);\n }\n\n public invalidateTree(msg?: string) {\n this._isValid = false;\n this.invalidationMessage = msg;\n this.rootsChanged.markChanged(\"tree invalidated\");\n this.resources.forEach((res) => {\n res.markAllChanged();\n });\n }\n\n public dumpState(): ExtendedResourceData[] {\n return Array.from(this.resources.values()).map((res) => res.extendedState);\n }\n}\n"],"mappings":";;;;;AAgCA,IAAa,uBAAb,cAA0C,MAAM;CAC9C,YAAY,SAAiB;EAC3B,MAAM,OAAO;CACf;AACF;AAEA,IAAM,cAAN,MAAuC;CAInB;CACT;CACA;CACA;CACA;CACA;CAEA;CAVT,SAAkB,IAAIA,2BAAAA,aAAa;CAEnC,YACE,MACA,MACA,OACA,OACA,QACA,cAEA,iBACA;EARgB,KAAA,OAAA;EACT,KAAA,OAAA;EACA,KAAA,QAAA;EACA,KAAA,QAAA;EACA,KAAA,SAAA;EACA,KAAA,eAAA;EAEA,KAAA,kBAAA;CACN;CAEH,IAAI,QAAmB;EACrB,OAAO;GACL,MAAM,KAAK;GACX,MAAM,KAAK;GACX,QAAQ,KAAK;GACb,OAAO,KAAK;GACZ,OAAO,KAAK;GACZ,cAAc,KAAK;EACrB;CACF;AACF;AAEA,MAAM,yBAAyB;;AAO/B,IAAa,iBAAb,MAAkE;;CAEhE,WAAmB;;CAGnB,UAAkB;;CAElB,cAAsB;CAEtB,4BAA+C,IAAI,IAAI;CAEvD,qBAAc,IAAI,IAAwB;CAE1C,kBAA2B,IAAIA,2BAAAA,aAAa;CAI5C,eAAgB,IAAIA,2BAAAA,aAAa;CAEjC,sBAAuB,IAAIA,2BAAAA,aAAa;CAExC,eAAgB,IAAIA,2BAAAA,aAAa;CACjC,kCAAmC,IAAIA,2BAAAA,aAAa;CACpD,yBAA0B,IAAIA,2BAAAA,aAAa;CAC3C,0BAA2B,IAAIA,2BAAAA,aAAa;CAG5C,kBAAmB,IAAIC,2BAAAA,kBAAkB;CAEzC;CACA;CAEA;CACA;CAEA;CACA;CACA;CAEA;CAEA;CACA;CACA;CACA;;CAGA,cAAuB;CAEvB;CAEA,YAAY,cAAiC,QAAmB;EAC9D,KAAK,KAAK,aAAa;EACvB,KAAK,qBAAqB,aAAa;EACvC,KAAK,OAAO,aAAa;EACzB,KAAK,OAAO,aAAa;EACzB,KAAK,OAAO,aAAa;EACzB,KAAK,QAAQ,aAAa;EAC1B,KAAK,eAAe,aAAa;EACjC,KAAK,gBAAgB,aAAa;EAClC,KAAK,gBAAgB,aAAa;EAClC,KAAK,YAAY,aAAa;EAC9B,KAAK,SAAS;CAChB;CAIA,KAAa,KAAa;EACxB,IAAI,KAAK,WAAW,KAAA,GAAW,KAAK,OAAO,KAAK,GAAG;CACrD;CAEA,KAAa,KAAa;EACxB,IAAI,KAAK,WAAW,KAAA,GAAW,KAAK,OAAO,KAAK,GAAG;CACrD;CAEA,IAAI,QAAiB;EACnB,OAAO,KAAK;CACd;CAEA,IAAI,aAAsB;EACxB,OAAO,KAAK;CACd;CAEA,IAAI,SAAsB;EACxB,OAAO,CAAC,GAAG,KAAK,UAAU,OAAO,CAAC;CACpC;CAcA,SACE,SACA,OACA,mBAA6C,CAAC,GACD;EAC7C,MAAM,OAA2B,OAAO,UAAU,WAAW,EAAE,OAAO,MAAM,IAAI;EAEhF,MAAM,QAAQ,KAAK,UAAU,IAAI,KAAK,KAAK;EAC3C,IAAI,UAAU,KAAA,GAAW;GACvB,IAAI,KAAK,wBAAwB,KAAK,oBACpC,MAAM,IAAI,MACR,UAAU,KAAK,MAAM,2BAAA,GAAA,0BAAA,mBAAA,CAA6C,KAAK,EAAE,GAC3E;GAEF,IAAI,CAAC,KAAK,cAAc,KAAK,iCAAiC,cAAc,OAAO;QAC9E,IAAI,KAAK,oBAAoB,aAAa,KAAK,oBAAoB,SACtE,IAAI,KAAK,uBAEP,OAAO,KAAA;QACJ,MAAM,IAAI,MAAM,oCAAoC,KAAK,MAAM,EAAE;GAGxE,IAAI,CAAC,KAAK,eAAe,KAAK,wBAAwB,cAAc,OAAO;QACtE,IAAI,KAAK,oBAAoB,UAChC,IAAI,KAAK,uBAEP,OAAO,KAAA;QACJ,MAAM,IAAI,MAAM,0BAA0B,KAAK,MAAM,EAAE;GAG9D,KAAK,yBAAyB,cAAc,OAAO;GACnD,IAAI,CAAC,KAAK,eAAe,CAAC,KAAK,kBAAkB,WAAW,qBAAqB,KAAK,KAAK;GAE3F;EACF,OAAO;GACL,IAAI,KAAK,oBAAoB,KAAA,KAAa,MAAM,SAAS,KAAK,iBAC5D,MAAM,IAAI,MACR,mCAAmC,KAAK,gBAAgB,WAAW,MAAM,KAAK,sBAAsB,KAAK,OAC3G;GAEF,MAAM,MAAM,CAAC;GACb,KAAA,GAAA,0BAAA,0BAAA,CAA8B,MAAM,KAAK,GAAG,IAAI,QAAQ,MAAM;GAC9D,KAAA,GAAA,0BAAA,0BAAA,CAA8B,MAAM,KAAK,GAAG,IAAI,QAAQ,MAAM;GAC9D,IAAI,IAAI,UAAU,KAAA,KAAa,IAAI,UAAU,KAAA,GAI3C,WAAW,wBAAwB,KAAK,KAAK;GAC/C,MAAM,OAAO,cAAc,OAAO;GAClC,OAAO;EACT;CACF;CAEA,gBAAuB,SAA2B;EAChD,IAAI,CAAC,KAAK,cAER,KAAK,qBAAqB,cAAc,OAAO;EACjD,OAAO,KAAK;CACd;CAEA,iBAAwB,SAA2B;EACjD,IAAI,CAAC,KAAK,eAER,KAAK,qBAAqB,cAAc,OAAO;EACjD,OAAO,KAAK;CACd;CAEA,IAAW,iBAA0B;EACnC,OACE,KAAK,UAAUC,0BAAAA,wBACf,KAAK,iBACL,KAAK,uBAAuBA,0BAAAA;CAEhC;CAEA,WAAkB,SAA2B;EAC3C,KAAK,cAAc,cAAc,OAAO;EACxC,OAAO,KAAK;CACd;CAEA,kBAAyB,SAA2B;EAClD,IAAI,CAAC,KAAK,gBAER,KAAK,qBAAqB,cAAc,OAAO;EACjD,OAAO,KAAK;CACd;CAEA,SAAgB,SAAgD;EAC9D,KAAA,GAAA,0BAAA,uBAAA,CAA2B,KAAK,KAAK,GAAG;GACtC,KAAK,qBAAqB,cAAc,OAAO;GAC/C;EACF,OAEE,OAAO,KAAK;CAEhB;CAEA,gBAAuB,SAA4B;EACjD,MAAM,MAAgB,CAAC;EACvB,KAAK,UAAU,SAAS,OAAO,SAAS;GACtC,IAAI,MAAM,SAAS,WAAW,MAAM,SAAS,WAAW,IAAI,KAAK,IAAI;EACvE,CAAC;EACD,IAAI,CAAC,KAAK,cAAc,KAAK,iCAAiC,cAAc,OAAO;EAEnF,OAAO;CACT;CAEA,iBAAwB,SAA4B;EAClD,MAAM,MAAgB,CAAC;EACvB,KAAK,UAAU,SAAS,OAAO,SAAS;GACtC,IAAI,MAAM,SAAS,UAAU,IAAI,KAAK,IAAI;EAC5C,CAAC;EACD,IAAI,CAAC,KAAK,eAAe,KAAK,wBAAwB,cAAc,OAAO;EAE3E,OAAO;CACT;CAEA,kBAAyB,SAA4B;EACnD,MAAM,MAAgB,CAAC;EACvB,KAAK,UAAU,SAAS,OAAO,SAAS;GACtC,IAAI,MAAM,SAAS,WAAW,MAAM,SAAS,UAAU,IAAI,KAAK,IAAI;EACtE,CAAC;EACD,KAAK,yBAAyB,cAAc,OAAO;EAEnD,OAAO;CACT;CAEA,YAAmB,SAAkB,KAAqC;EACxE,KAAK,iBAAiB,cAAc,KAAK,OAAO;EAChD,OAAO,KAAK,GAAG,IAAI,GAAG;CACxB;CAEA,kBAAyB,SAAkB,KAAiC;EAC1E,MAAM,QAAQ,KAAK,YAAY,SAAS,GAAG;EAC3C,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;EAChC,QAAA,GAAA,2BAAA,aAAA,CAAoB,KAAK;CAC3B;CAEA,kBAAsC,SAAkB,KAA4B;EAClF,MAAM,QAAQ,KAAK,YAAY,SAAS,GAAG;EAC3C,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;EAChC,QAAA,GAAA,2BAAA,kBAAA,CAAyB,KAAK;CAChC;CAEA,kBAA6C;EAC3C,IAAI,KAAK,SAAS,KAAA,GAAW,OAAO,KAAA;EACpC,IAAI,KAAK,iBAAiB,KAAA,GAAW,KAAK,gBAAA,GAAA,2BAAA,aAAA,CAA4B,KAAK,IAAI;EAC/E,OAAO,KAAK;CACd;CAEA,gBAAmD;EACjD,IAAI,KAAK,SAAS,KAAA,GAAW,OAAO,KAAA;EACpC,IAAI,KAAK,eAAe,KAAA,GAAW,KAAK,cAAA,GAAA,2BAAA,kBAAA,CAA+B,KAAK,IAAI;EAChF,OAAO,KAAK;CACd;CAEA,mBAAmB;EACjB,IAAI,KAAK,iBAAiB,CAAC,KAAK,cAC9B,MAAM,IAAI,MACR,wCAAA,GAAA,0BAAA,wBAAA,CAA+D,KAAK,UAAU,GAChF;CACJ;CAEA,IAAI,aAAgC;EAClC,OAAO;GACL,IAAI,KAAK;GACT,MAAM,KAAK;GACX,MAAM,KAAK;GACX,MAAM,KAAK;GACX,eAAe,KAAK;GACpB,cAAc,KAAK;GACnB,eAAe,KAAK;GACpB,OAAO,KAAK;GACZ,oBAAoB,KAAK;GACzB,OAAO,KAAK;EACd;CACF;CAEA,IAAI,gBAAsC;EACxC,OAAO;GACL,GAAG,KAAK;GACR,QAAQ,KAAK;GACb,IAAI,MAAM,KAAK,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,YAAY;IAAE;IAAK;GAAM,EAAE;EAC1E;CACF;;CAGA,YAAY;EACV,IAAI,KAAK,aAAa;EAEtB,KAAK,cAAc;EACnB,CAAA,GAAA,2BAAA,SAAA,CAAS,KAAK,YAAY,CAAC,CAAC,YAAY,cAAc;EACtD,KAAK,eAAe,KAAA;EACpB,KAAK,sBAAsB,KAAA;EAC3B,KAAK,0BAA0B,KAAA;EAC/B,KAAK,kCAAkC,KAAA;EACvC,KAAK,yBAAyB,KAAA;EAC9B,KAAK,eAAe,KAAA;EAEpB,KAAK,kBAAkB,KAAA;CACzB;;CAGA,iBAAiB;EACf,KAAK,UAAU,SAAS,UAAU,MAAM,OAAO,YAAY,oBAAoB,CAAC;EAChF,KAAK,cAAc,YAAY,oBAAoB;EACnD,KAAK,qBAAqB,YAAY,oBAAoB;EAC1D,KAAK,cAAc,YAAY,oBAAoB;EACnD,KAAK,iCAAiC,YAAY,oBAAoB;EACtE,KAAK,wBAAwB,YAAY,oBAAoB;EAC7D,KAAK,yBAAyB,YAAY,oBAAoB;EAE9D,KAAK,iBAAiB,eAAe,oBAAoB;EACzD,KAAK,gBAAgB,YAAY,oBAAoB;CACvD;AACF;AAEA,IAAa,cAAb,MAAyB;CAqBL;;CAnBlB,4BAA2D,IAAI,IAAI;CACnE,iBAAkC,IAAIF,2BAAAA,aAAa;;;CAGnD,eAAgC,IAAIA,2BAAAA,aAAa;;;CAGjD,WAA4B;CAC5B;;;;CAKA;CAEA,YAGE,OACA,kBACA;EADgB,KAAA,mBAAA;EAEhB,KAAK,QAAQ,iBAAiB,MAAM,IAAI,IAAI,KAAK,oBAAI,IAAI,IAAI,CAAC,KAAK,CAAC;CACtE;;;;CAKA,IAAW,OAAyB;EAClC,IAAI,KAAK,MAAM,SAAS,GACtB,MAAM,IAAI,MACR,4CAA4C,KAAK,MAAM,KAAK,+BAC9D;EACF,OAAO,KAAK,MAAM,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC;CACpC;CAEA,gBAAuB,IAAqD;EAC1E,KAAK,UAAU,SAAS,MAAM,GAAG,CAAC,CAAC;CACrC;CAEA,aAAqB;EACnB,IAAI,CAAC,KAAK,UAAU,MAAM,IAAI,MAAM,KAAK,uBAAuB,0BAA0B;CAC5F;;;CAIA,SAAgB,SAAsC;EACpD,KAAK,WAAW;EAChB,KAAK,aAAa,cAAc,OAAO;EACvC,OAAO,CAAC,GAAG,KAAK,KAAK;CACvB;CAEA,IAAW,SAAkB,KAAuC;EAClE,KAAK,WAAW;EAChB,MAAM,MAAM,KAAK,UAAU,IAAI,GAAG;EAClC,IAAI,QAAQ,KAAA,GAAW;GAGrB,KAAK,eAAe,cAAc,OAAO;GACzC,MAAM,IAAI,MAAM,aAAA,GAAA,0BAAA,mBAAA,CAA+B,GAAG,EAAE,uBAAuB;EAC7E;EACA,IAAI,gBAAgB,cAAc,OAAO;EACzC,OAAO;CACT;CAEA,uBAAuB,cAAsC,oBAA6B,OAAO;EAC/F,KAAK,WAAW;EAGhB,MAAM,gBAAoC,CAAC;EAC3C,MAAM,gBAAoC,CAAC;EAG3C,KAAK,MAAM,MAAM,cAAc;GAC7B,IAAI,WAAW,KAAK,UAAU,IAAI,GAAG,EAAE;GAEvC,MAAM,qBAAqB,UAAU;GACrC,MAAM,6BAA6B,WAA0B;IAE3D,MAAM,EAAE,QAAQ,GAAG,oBAAoB;IACvC,KAAK,eAAe;IACpB,MAAM,IAAI,qBACR,yCAAyC,OAAO,MAAA,GAAA,0BAAA,wBAAA,CAC9C,eACF,EAAE,OAAA,GAAA,0BAAA,wBAAA,CAA8B,kBAAkB,GACpD;GACF;GAEA,IAAI,aAAa,KAAA,GAAW;IAG1B,IAAI,SAAS,YACX,0BAA0B,4DAA6D;IAEzF,IAAI,UAAU;IAEd,SAAS,WAAW;IAGpB,IAAI,SAAS,uBAAuB,GAAG,oBAAoB;KACzD,IAAI,SAAS,uBAAuBE,0BAAAA,sBAClC,0BAA0B,iDAAiD;KAC7E,SAAS,qBAAqB,GAAG;KAEjC,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAS,mBAAmB,CAAC,CAAC,YACrC,mCAAA,GAAA,0BAAA,mBAAA,CAAqD,SAAS,EAAE,GAClE;KACA,UAAU;IACZ;IAGA,KAAA,GAAA,0BAAA,0BAAA,CAA8B,GAAG,KAAK,KAAK,SAAS,UAAU,GAAG,OAAO;KACtE,KAAA,GAAA,0BAAA,0BAAA,CAA8B,SAAS,KAAK,GAC1C,0BAA0B,sDAAsD;KAClF,SAAS,QAAQ,GAAG;KACpB,cAAc,KAAK,SAAS,KAAK;KACjC,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAS,mBAAmB,CAAC,CAAC,YACrC,sBAAA,GAAA,0BAAA,mBAAA,CAAwC,SAAS,EAAE,GACrD;KACA,UAAU;IACZ;IAGA,KAAK,MAAM,MAAM,GAAG,QAAQ;KAC1B,IAAI,QAAQ,SAAS,UAAU,IAAI,GAAG,IAAI;KAE1C,IAAI,CAAC,OAAO;MAGV,QAAQ,IAAI,YACV,GAAG,MACH,GAAG,MACH,GAAG,OACH,GAAG,OACH,GAAG,QACH,GAAG,cACH,SAAS,OACX;MACA,KAAA,GAAA,0BAAA,0BAAA,CAA8B,GAAG,KAAK,GAAG,cAAc,KAAK,GAAG,KAAK;MACpE,KAAA,GAAA,0BAAA,0BAAA,CAA8B,GAAG,KAAK,GAAG,cAAc,KAAK,GAAG,KAAK;MAEpE,IAAI,GAAG,SAAS,WAAW,GAAG,SAAS,WAAW;OAChD,IAAI,SAAS,cACX,0BACE,UAAU,GAAG,KAAK,IAAI,GAAG,KAAK,4BAChC;OACF,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAS,+BAA+B,CAAC,CAAC,YACjD,OAAO,GAAG,KAAK,SAAS,GAAG,KAAK,aAAA,GAAA,0BAAA,mBAAA,CAA+B,SAAS,EAAE,GAC5E;MACF,OAAO,IAAI,GAAG,SAAS,UAAU;OAC/B,IAAI,SAAS,eACX,0BACE,UAAU,GAAG,KAAK,IAAI,GAAG,KAAK,6BAChC;OACF,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAS,sBAAsB,CAAC,CAAC,YACxC,OAAO,GAAG,KAAK,SAAS,GAAG,KAAK,aAAA,GAAA,0BAAA,mBAAA,CAA+B,SAAS,EAAE,GAC5E;MACF,OACE,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAS,uBAAuB,CAAC,CAAC,YACzC,OAAO,GAAG,KAAK,SAAS,GAAG,KAAK,aAAA,GAAA,0BAAA,mBAAA,CAA+B,SAAS,EAAE,GAC5E;MAGF,SAAS,UAAU,IAAI,GAAG,MAAM,KAAK;MAErC,UAAU;KACZ,OAAO;MAIL,IAAI,MAAM,SAAS,GAAG,MAAM;OAC1B,IAAI,MAAM,SAAS,WACjB,0BAA0B,sBAAsB,MAAM,KAAK,MAAM,GAAG,MAAM;OAC5E,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAS,uBAAuB,CAAC,CAAC,YACzC,SAAS,GAAG,KAAK,gCAAgC,GAAG,KAAK,OAAA,GAAA,0BAAA,mBAAA,CAAyB,SAAS,EAAE,GAC/F;OACA,IAAI,MAAM,SAAS,WAAW,MAAM,SAAS,WAAW;QACtD,IAAI,SAAS,cACX,0BACE,uBAAuB,GAAG,KAAK,sCACjC;QACF,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAS,+BAA+B,CAAC,CAAC,YACjD,SAAS,GAAG,KAAK,mBAAmB,GAAG,KAAK,OAAA,GAAA,0BAAA,mBAAA,CAAyB,SAAS,EAAE,GAClF;OACF;OACA,IAAI,MAAM,SAAS,UAAU;QAC3B,IAAI,SAAS,eACX,0BACE,wBAAwB,GAAG,KAAK,sCAClC;QACF,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAS,sBAAsB,CAAC,CAAC,YACxC,SAAS,GAAG,KAAK,mBAAmB,GAAG,KAAK,OAAA,GAAA,0BAAA,mBAAA,CAAyB,SAAS,EAAE,GAClF;OACF;OACA,MAAM,OAAO,GAAG;OAChB,MAAM,OAAO,YACX,SAAS,GAAG,KAAK,mBAAmB,GAAG,KAAK,OAAA,GAAA,0BAAA,mBAAA,CAAyB,SAAS,EAAE,GAClF;OACA,UAAU;MACZ;MAGA,IAAI,MAAM,UAAU,GAAG,OAAO;OAC5B,KAAA,GAAA,0BAAA,0BAAA,CAA8B,MAAM,KAAK,GAAG,cAAc,KAAK,MAAM,KAAK;OAC1E,MAAM,QAAQ,GAAG;OACjB,KAAA,GAAA,0BAAA,0BAAA,CAA8B,GAAG,KAAK,GAAG,cAAc,KAAK,GAAG,KAAK;OACpE,MAAM,OAAO,YACX,SAAS,GAAG,KAAK,qBAAA,GAAA,0BAAA,mBAAA,CAAuC,SAAS,EAAE,GACrE;OACA,UAAU;MACZ;MAGA,IAAI,MAAM,UAAU,GAAG,OAAO;OAC5B,KAAA,GAAA,0BAAA,0BAAA,CAA8B,MAAM,KAAK,GAAG,cAAc,KAAK,MAAM,KAAK;OAC1E,MAAM,QAAQ,GAAG;OACjB,KAAA,GAAA,0BAAA,0BAAA,CAA8B,GAAG,KAAK,GAAG,cAAc,KAAK,GAAG,KAAK;OACpE,MAAM,OAAO,YACX,SAAS,GAAG,KAAK,qBAAA,GAAA,0BAAA,mBAAA,CAAuC,SAAS,EAAE,GACrE;OACA,UAAU;MACZ;MAGA,IAAI,MAAM,WAAW,GAAG,QAAQ;OAC9B,MAAM,SAAS,GAAG;OAClB,MAAM,OAAO,YACX,SAAS,GAAG,KAAK,qBAAqB,GAAG,OAAO,OAAA,GAAA,0BAAA,mBAAA,CAAyB,SAAS,EAAE,GACtF;OACA,UAAU;MACZ;MAGA,IAAI,MAAM,iBAAiB,GAAG,cAAc;OAC1C,MAAM,eAAe,GAAG;OACxB,MAAM,OAAO,YACX,SAAS,GAAG,KAAK,2BAA2B,GAAG,aAAa,OAAA,GAAA,0BAAA,mBAAA,CAAyB,SAAS,EAAE,GAClG;OACA,UAAU;MACZ;MAEA,MAAM,kBAAkB,SAAS;KACnC;IACF;IAGA,SAAS,UAAU,SAAS,OAAO,WAAW,WAAW;KACvD,IAAI,MAAM,oBAAoB,SAAU,SAAS;MAC/C,IAAI,MAAM,SAAS,WAAW,MAAM,SAAS,aAAa,MAAM,SAAS,UACvE,0BAA0B,cAAc,MAAM,KAAK,SAAS,WAAW;MACzE,MAAM,OAAO,YACX,iBAAiB,UAAU,iBAAA,GAAA,0BAAA,mBAAA,CAAmC,SAAU,EAAE,GAC5E;MACA,OAAO,OAAO,SAAS;MAEvB,KAAA,GAAA,0BAAA,0BAAA,CAA8B,MAAM,KAAK,GAAG,cAAc,KAAK,MAAM,KAAK;MAC1E,KAAA,GAAA,0BAAA,0BAAA,CAA8B,MAAM,KAAK,GAAG,cAAc,KAAK,MAAM,KAAK;MAE1E,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAU,uBAAuB,CAAC,CAAC,YAC1C,iBAAiB,UAAU,iBAAA,GAAA,0BAAA,mBAAA,CAAmC,SAAU,EAAE,GAC5E;KACF;IACF,CAAC;IAGD,IAAI,SAAS,iBAAiB,GAAG,cAAc;KAC7C,IAAI,SAAS,cAAc,0BAA0B,mCAAmC;KACxF,SAAS,eAAe,GAAG;KAC3B,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAS,YAAY,CAAC,CAAC,YAC9B,sBAAA,GAAA,0BAAA,mBAAA,CAAwC,SAAS,EAAE,GACrD;KACA,UAAU;IACZ;IAGA,IAAI,SAAS,kBAAkB,GAAG,eAAe;KAC/C,IAAI,SAAS,eACX,0BAA0B,oCAAoC;KAChE,SAAS,gBAAgB,GAAG;KAC5B,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAS,YAAY,CAAC,CAAC,YAC9B,uBAAA,GAAA,0BAAA,mBAAA,CAAyC,SAAS,EAAE,GACtD;KACA,UAAU;IACZ;IAGA,IAAI,SAAS,kBAAkB,GAAG,eAAe;KAC/C,MAAM,mBAAmB,SAAS;KAClC,SAAS,gBAAgB,GAAG;KAC5B,SAAS,iBAAiB;KAC1B,IAAI,CAAC,SAAS,gBACZ,0BACE,qEAAqE,iBAAiB,EACxF;KACF,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAS,mBAAmB,CAAC,CAAC,YACrC,yBAAyB,GAAG,cAAc,QAAA,GAAA,0BAAA,mBAAA,CAA0B,SAAS,EAAE,GACjF;KACA,UAAU;IACZ;IAGA,KAAK,MAAM,MAAM,GAAG,IAAI;KACtB,MAAM,UAAU,SAAS,GAAG,IAAI,GAAG,GAAG;KACtC,IAAI,YAAY,KAAA,GAAW;MACzB,SAAS,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK;MAChC,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAS,eAAe,CAAC,CAAC,YACjC,GAAG,KACH,iBAAA,GAAA,0BAAA,mBAAA,CAAmC,SAAS,EAAE,EAAE,IAAI,GAAG,KACzD;KACF,OAAO,IAAI,OAAO,QAAQ,SAAS,GAAG,KAAK,MAAM,GAAG;MAClD,SAAS,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK;MAChC,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAS,eAAe,CAAC,CAAC,YACjC,GAAG,KACH,mBAAA,GAAA,0BAAA,mBAAA,CAAqC,SAAS,EAAE,EAAE,IAAI,GAAG,KAC3D;KACF;IACF;IAEA,IAAI,SAAS,GAAG,OAAO,GAAG,GAAG,QAAQ;KAEnC,MAAM,eAAe,IAAI,IAAI,GAAG,GAAG,KAAK,OAAO,GAAG,GAAG,CAAC;KAGtD,SAAS,GAAG,SAAS,QAAQ,KAAK,QAAQ;MACxC,IAAI,CAAC,aAAa,IAAI,GAAG,GAAG;OAC1B,IAAI,OAAO,GAAG;OACd,CAAA,GAAA,2BAAA,SAAA,CAAS,SAAU,eAAe,CAAC,CAAC,YAClC,KACA,mBAAA,GAAA,0BAAA,mBAAA,CAAqC,SAAU,EAAE,EAAE,IAAI,KACzD;MACF;KACF,CAAC;IACH;IAEA,IAAI,SAAS;KAEX,SAAS,cAAc,SAAS;KAChC,IAAI,KAAK,iBAAiB,QAAQ,GAAG,SAAS,UAAU;IAC1D;GACF,OAAO;IAGL,WAAW,IAAI,eAAe,EAAE;IAChC,SAAS,iBAAiB;IAC1B,KAAA,GAAA,0BAAA,0BAAA,CAA8B,SAAS,KAAK,GAAG,cAAc,KAAK,SAAS,KAAK;IAChF,KAAK,MAAM,MAAM,GAAG,QAAQ;KAC1B,MAAM,QAAQ,IAAI,YAChB,GAAG,MACH,GAAG,MACH,GAAG,OACH,GAAG,OACH,GAAG,QACH,GAAG,cACH,sBACF;KACA,KAAA,GAAA,0BAAA,0BAAA,CAA8B,GAAG,KAAK,GAAG,cAAc,KAAK,GAAG,KAAK;KACpE,KAAA,GAAA,0BAAA,0BAAA,CAA8B,GAAG,KAAK,GAAG,cAAc,KAAK,GAAG,KAAK;KACpE,SAAS,UAAU,IAAI,GAAG,MAAM,KAAK;IACvC;IAGA,KAAK,MAAM,MAAM,GAAG,IAAI,SAAS,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK;IAGxD,IAAI,KAAK,iBAAiB,QAAQ,GAAG,SAAS,UAAU;IAGxD,KAAK,UAAU,IAAI,SAAS,IAAI,QAAQ;IACxC,KAAK,eAAe,YAAY,iBAAA,GAAA,0BAAA,mBAAA,CAAmC,SAAS,EAAE,EAAE,OAAO;GACzF;EACF;EAGA,KAAK,MAAM,OAAO,eAAe;GAC/B,MAAM,MAAM,KAAK,UAAU,IAAI,GAAG;GAClC,IAAI,CAAC,KAAK;IACR,KAAK,eAAe;IACpB,MAAM,IAAI,qBAAqB,mBAAmB,KAAK;GACzD;GACA,IAAI;EACN;EAGA,KAAK,eAAe,aAAa;EAGjC,IAAI,CAAC;QACE,MAAM,MAAM,cACf,IAAI,CAAC,KAAK,UAAU,IAAI,GAAG,EAAE,GAAG;IAC9B,KAAK,eAAe;IACpB,MAAM,IAAI,qBAAqB,yBAAyB,GAAG,IAAI;GACjE;;CAGN;;;;;CAMA,eAAuB,eAAmC;EACxD,IAAI,cAAc;EAClB,OAAO,YAAY,SAAS,GAAG;GAC7B,MAAM,WAA+B,CAAC;GACtC,KAAK,MAAM,OAAO,aAAa;IAC7B,MAAM,MAAM,KAAK,UAAU,IAAI,GAAG;IAClC,IAAI,CAAC,KAAK;KACR,KAAK,eAAe;KACpB,MAAM,IAAI,qBAAqB,mBAAmB,KAAK;IACzD;IACA,IAAI;IAGJ,IAAI,IAAI,aAAa,KAAK,CAAC,KAAK,MAAM,IAAI,IAAI,EAAE,GAAG;KAEjD,IAAI,UAAU,SAAS,UAAU;MAC/B,KAAA,GAAA,0BAAA,0BAAA,CAA8B,MAAM,KAAK,GAAG,SAAS,KAAK,MAAM,KAAK;MACrE,KAAA,GAAA,0BAAA,0BAAA,CAA8B,MAAM,KAAK,GAAG,SAAS,KAAK,MAAM,KAAK;MACrE,MAAM,OAAO,YACX,SAAS,MAAM,KAAK,yCAAA,GAAA,0BAAA,mBAAA,CAA2D,IAAI,EAAE,GACvF;KACF,CAAC;KACD,KAAA,GAAA,0BAAA,0BAAA,CAA8B,IAAI,KAAK,GAAG,SAAS,KAAK,IAAI,KAAK;KACjE,IAAI,gBAAgB,YAClB,gDAAA,GAAA,0BAAA,mBAAA,CAAkE,IAAI,EAAE,GAC1E;KACA,KAAK,UAAU,OAAO,GAAG;IAC3B;GACF;GACA,cAAc;EAChB;CACF;;;;;;;;CASA,SAAgB,UAAiC;EAC/C,KAAK,WAAW;EAEhB,MAAM,UAA8B,CAAC;EACrC,KAAK,MAAM,OAAO,KAAK,OAAO,IAAI,CAAC,SAAS,IAAI,GAAG,GAAG,QAAQ,KAAK,GAAG;EACtE,IAAI,QAAQ;EACZ,KAAK,MAAM,OAAO,UAAU,IAAI,CAAC,KAAK,MAAM,IAAI,GAAG,GAAG,QAAQ;EAC9D,IAAI,QAAQ,WAAW,KAAK,CAAC,OAAO;EAIpC,KAAK,MAAM,MAAM;EACjB,KAAK,MAAM,OAAO,UAAU,KAAK,MAAM,IAAI,GAAG;EAE9C,KAAK,aAAa,YAAY,kBAAkB;EAEhD,KAAK,MAAM,OAAO,SAAS;GACzB,MAAM,MAAM,KAAK,UAAU,IAAI,GAAG;GAClC,IAAI,QAAQ,KAAA,GAAW;GAIvB,IAAI,IAAI,WAAW,GAAG;GAGtB,MAAM,OAA2B,CAAC;GAClC,IAAI,UAAU,SAAS,UAAU;IAC/B,KAAA,GAAA,0BAAA,0BAAA,CAA8B,MAAM,KAAK,GAAG,KAAK,KAAK,MAAM,KAAK;IACjE,KAAA,GAAA,0BAAA,0BAAA,CAA8B,MAAM,KAAK,GAAG,KAAK,KAAK,MAAM,KAAK;IACjE,MAAM,OAAO,YACX,SAAS,MAAM,KAAK,uBAAA,GAAA,0BAAA,mBAAA,CAAyC,IAAI,EAAE,EAAE,mBACvE;GACF,CAAC;GACD,KAAA,GAAA,0BAAA,0BAAA,CAA8B,IAAI,KAAK,GAAG,KAAK,KAAK,IAAI,KAAK;GAC7D,IAAI,gBAAgB,YAClB,iDAAA,GAAA,0BAAA,mBAAA,CAAmE,IAAI,EAAE,GAC3E;GACA,KAAK,UAAU,OAAO,GAAG;GAEzB,KAAK,eAAe,IAAI;EAC1B;CACF;;CAGA,SAAgB,MAAwB,KAAK,MAAmB;EAC9D,KAAK,WAAW;EAChB,OAAO,KAAK,MAAM,GAAG;CACvB;CAEA,MAAa,MAAwB,KAAK,MAAmB;EAC3D,KAAK,WAAW;EAChB,OAAO,IAAIC,kBAAAA,YAAY,EAAE,oBAAoB,KAAK,GAAG,GAAG;CAC1D;CAEA,eAAsB,KAAc;EAClC,KAAK,WAAW;EAChB,KAAK,sBAAsB;EAC3B,KAAK,aAAa,YAAY,kBAAkB;EAChD,KAAK,UAAU,SAAS,QAAQ;GAC9B,IAAI,eAAe;EACrB,CAAC;CACH;CAEA,YAA2C;EACzC,OAAO,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,aAAa;CAC3E;AACF"}
package/dist/state.d.ts CHANGED
@@ -98,23 +98,50 @@ declare class PlTreeResource implements ResourceDataWithFinalState {
98
98
  markAllChanged(): void;
99
99
  }
100
100
  declare class PlTreeState {
101
- /** This will be the only resource not deleted during GC round */
102
- readonly root: SignedResourceId;
103
101
  readonly isFinalPredicate: FinalResourceDataPredicate;
104
102
  /** resource heap */
105
103
  private resources;
106
104
  private readonly resourcesAdded;
105
+ /** Marked when the root set changes (roots discovered or removed), so multi-root
106
+ * accessors that read the set recompute. */
107
+ private readonly rootsChanged;
107
108
  /** Resets to false if any invalid state transitions are registered,
108
109
  * after that tree will produce errors for any read or write operations */
109
110
  private _isValid;
110
111
  private invalidationMessage?;
111
- constructor(/** This will be the only resource not deleted during GC round */
112
+ /** The set of roots — resources protected from GC. Originally a single `root`,
113
+ * generalized to a set so several explicit roots and dynamically-discovered shared
114
+ * roots can coexist in one heap. Mutated through {@link setRoots}. */
115
+ readonly roots: Set<SignedResourceId>;
116
+ constructor(
117
+ /** Resources protected from GC. Accepts a single id (single-root, the original
118
+ * contract) or a set of ids (multi-root). */
112
119
 
113
- root: SignedResourceId, isFinalPredicate: FinalResourceDataPredicate);
120
+ roots: SignedResourceId | Set<SignedResourceId>, isFinalPredicate: FinalResourceDataPredicate);
121
+ /** Backward-compatible single-root accessor. Returns the sole root and THROWS if the
122
+ * tree has zero or more than one root, so a multi-root tree can never be read as if it
123
+ * had one. Mirrors the {@link entry} guard. */
124
+ get root(): SignedResourceId;
114
125
  forEachResource(cb: (res: ResourceDataWithFinalState) => void): void;
115
126
  private checkValid;
127
+ /** Reactive read of the current root set. Attaches the watcher to {@link rootsChanged}
128
+ * so a Computable recomputes when discovered roots appear or disappear. */
129
+ getRoots(watcher: Watcher): SignedResourceId[];
116
130
  get(watcher: Watcher, rid: SignedResourceId): PlTreeResource;
117
131
  updateFromResourceData(resourceData: ExtendedResourceData[], allowOrphanInputs?: boolean): void;
132
+ /** Runs the refcount-decrement garbage-collection cascade over the given worklist.
133
+ * A resource reaching refCount 0 that is not a root is removed, and its outgoing
134
+ * references are decremented in turn, until the worklist drains. Factored out of
135
+ * {@link updateFromResourceData} so {@link setRoots} can reuse the same cascade. */
136
+ private collectGarbage;
137
+ /** Replaces the current root set with `newRoots`.
138
+ *
139
+ * Roots that leave the set lose their GC protection: each removed root present in the
140
+ * heap is collected directly (a root sits at refCount 0, so it is never enqueued by an
141
+ * ordinary decrement), and its subtree cascades to collection through the existing
142
+ * refcount GC — the standard removal mechanic, applied to a root. Roots newly added to
143
+ * the set are protected immediately; their resources arrive on the next refresh poll. */
144
+ setRoots(newRoots: Set<SignedResourceId>): void;
118
145
  /** @deprecated use "entry" instead */
119
146
  accessor(rid?: SignedResourceId): PlTreeEntry;
120
147
  entry(rid?: SignedResourceId): PlTreeEntry;
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","names":[],"sources":["../src/state.ts"],"mappings":"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"}
1
+ {"version":3,"file":"state.d.ts","names":[],"sources":["../src/state.ts"],"mappings":"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"}