{
  "version": 3,
  "sources": ["../../../src/Obj.ts"],
  "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\n// @import-as-namespace\n\nimport * as Effect from 'effect/Effect';\nimport * as Equal from 'effect/Equal';\nimport * as Function from 'effect/Function';\nimport * as Option from 'effect/Option';\nimport * as Schema from 'effect/Schema';\nimport * as Utils from 'effect/Utils';\n\nimport type { ForeignKey } from '@dxos/echo-protocol';\nimport { SchemaEx } from '@dxos/effect';\nimport { assertArgument, invariant } from '@dxos/invariant';\nimport { EntityId, type URI } from '@dxos/keys';\nimport { assumeType, deepMapValues } from '@dxos/util';\n\nimport type * as Database from './Database';\nimport * as Entity from './Entity';\nimport * as Err from './Err';\nimport * as internal from './internal';\nimport { getProxyTarget, isProxy } from './internal/common/proxy/proxy-utils';\nimport * as objInternal from './internal/Obj';\nimport * as Ref from './Ref';\nimport type * as Tag from './Tag';\nimport * as Type from './Type';\n\n/**\n * Base type for all ECHO objects.\n */\ninterface BaseObj extends internal.AnyEntity, Entity.OfKind<typeof Entity.Kind.Object> {}\n\n/**\n * Object type with specific properties.\n */\nexport type OfShape<Props> = BaseObj & Props;\n\n/**\n * Object with no known properties beyond id and kind.\n * Use this when the object's schema/properties are not known.\n * For objects with arbitrary properties, use `Obj.AnyProps`.\n *\n * NOTE: This is a TypeScript type only, not a schema.\n * To validate that a value is an ECHO object, use `Schema.is(Type.Obj)`.\n */\nexport interface Unknown extends BaseObj {}\n\n/**\n * Runtime Effect schema for any ECHO object.\n * Use for validation, parsing, or as a reference target for collections.\n *\n * NOTE: `Schema.is(Type.Obj)` does STRUCTURAL validation only (checks for `id` field).\n * Use `Obj.isObject()` for proper ECHO instance type guards that check the KindId brand.\n *\n * @example\n * ```ts\n * // Structural type guard (accepts any object with id field)\n * if (Schema.is(Type.Obj)(unknownValue)) { ... }\n *\n * // ECHO instance type guard (checks KindId brand)\n * if (Obj.isObject(unknownValue)) { ... }\n *\n * // Reference to any object type\n * const Collection = Schema.Struct({\n *   objects: Schema.Array(Ref.Ref(Obj.Unknown)),\n * }).pipe(Type.makeObject(DXN.make('com.example.type.collection', '0.1.0')));\n * ```\n */\n// TODO(wittjosiah): Investigate if Schema.filter can validate KindId on ECHO instances.\n//   Effect Schema normalizes proxy objects to plain objects before calling filter predicates.\n//   Possible approaches: custom Schema.declare, AST manipulation, or upstream contribution.\nexport const Unknown: internal.UnknownTypeSchema<Unknown, typeof Entity.Kind.Object> = Schema.Struct({\n  id: Schema.String,\n}).pipe(\n  Schema.extend(Schema.Record({ key: Schema.String, value: Schema.Unknown })),\n  Schema.annotations({\n    [internal.TypeAnnotationId]: {\n      kind: Entity.Kind.Object,\n      typename: internal.ANY_OBJECT_TYPENAME,\n      version: internal.ANY_OBJECT_VERSION,\n    },\n  }),\n) as unknown as internal.UnknownTypeSchema<Unknown, typeof Entity.Kind.Object>;\n\n/**\n * Object with arbitrary properties.\n *\n * NOTE: Due to how TypeScript works, this type is not assignable to a specific schema type.\n * In that case, use `Obj.instanceOf` to check if an object is of a specific type.\n *\n * Prefer using `Obj.Unknown` when you don't need to access arbitrary properties.\n */\nexport interface Any extends BaseObj, internal.AnyProperties {}\n\n/**\n * Base type for snapshot objects (has SnapshotKindId instead of KindId).\n */\ninterface BaseSnapshot extends internal.AnyEntity {\n  readonly [Entity.SnapshotKindId]: typeof Entity.Kind.Object;\n  readonly id: EntityId;\n}\n\n/**\n * Immutable snapshot of an ECHO object.\n * Branded with SnapshotKindId (not KindId).\n * Property values are frozen at the time the snapshot was created.\n * Returned by getSnapshot() and hooks like useObject().\n *\n * Snapshots are structurally identical to reactive objects but have a different brand,\n * making them distinguishable at the TypeScript level. Neither is assignable to the other.\n */\nexport type Snapshot<T extends Unknown = Unknown> = Omit<T, Entity.KindId> & BaseSnapshot;\n\n/**\n * JSON-encoded properties for objects.\n */\nexport interface BaseObjJson {\n  id: string;\n}\n\n// Factory (not a shared const): each object must get its own `keys`/`tags`/`annotations` containers,\n// otherwise mutating one object's meta would leak into every other object via the shared references.\nconst defaultMeta = (): internal.EntityMeta => ({\n  keys: [],\n  tags: [],\n  annotations: {},\n});\n\n// TODO(burdon): Should we allow the caller to set the id?\n/**\n * Props type for object creation with a given type. Accepts a `Type.AnyObj`\n * entity and derives the instance shape via `Type.InstanceType`. Relation-kind\n * entities are rejected at the type level — use `Relation.MakeProps` for those.\n *\n * When the schema is the unconstrained `Type.AnyObj` (`Obj<unknown>` — e.g. a\n * dynamic type from `schemaRegistry.register`), the instance shape is not\n * statically known, so data props widen to `Record<string, unknown>` and the\n * caller can pass arbitrary fields without a cast.\n */\nexport type MakeProps<S extends Type.AnyObj> = {\n  id?: EntityId;\n  [Meta]?: Partial<internal.EntityMeta>;\n  [Parent]?: Unknown;\n  // When the resolved instance has no known data keys, widen to a permissive\n  // record (the `Obj<unknown>` case); otherwise use the precise property shape.\n  // `[keyof …] extends [never]` is wrapped in tuples so the check is\n  // non-distributive — a `never` instance type (e.g. when narrowing collapses\n  // the schema) stays a single branch instead of distributing to `never`.\n} & ([keyof Entity.Properties<Type.InstanceType<S>>] extends [never]\n  ? Record<string, unknown>\n  : Entity.Properties<Type.InstanceType<S>>);\n\n/**\n * Creates a new echo object of the given schema or `Type.Type`.\n *\n * @param typeOrSchema - A static object schema (`Type.makeObject(...)`) or a\n *   `Type.Type` entity (e.g. one returned by `db.addType(schemaEntity)`).\n * @param props - Object properties.\n *\n * Meta can be passed as a symbol in `props`.\n *\n * Example:\n * ```ts\n * const obj = Obj.make(Person, { [Obj.Meta]: { keys: [...] }, name: 'John' });\n * ```\n *\n * Note: Only accepts object schemas / object-kind types, not relation schemas.\n * Use `Relation.make` for relations.\n */\nexport function make<T extends Type.AnyObj>(type: T, props: NoInfer<MakeProps<T>>): OfShape<Type.InstanceType<T>>;\nexport function make(input: Type.AnyObj, props: any): OfShape<any> {\n  // `Type.Type` entities aren't `Schema.Schema` themselves; derive the Effect\n  // Schema via `Type.getSchema(...)`. Pass the entity through to `makeObject`\n  // so subsequent schema mutations (`Type.addFields`, etc.) propagate.\n  const schema = Type.getSchema(input);\n  assertArgument(\n    internal.getTypeAnnotation(schema)?.kind === Entity.Kind.Object,\n    'schema',\n    'Expected an object schema',\n  );\n\n  let meta: internal.EntityMeta | undefined = undefined;\n\n  // Set default fields on meta on creation.\n  if (props[internal.MetaId] != null) {\n    meta = { ...defaultMeta(), ...props[internal.MetaId] };\n    delete props[internal.MetaId];\n  }\n\n  // Filter undefined values (Object.entries only returns string-keyed properties).\n  const filterUndefined: any = Object.fromEntries(Object.entries(props).filter(([_, v]) => v !== undefined));\n\n  // Copy symbol properties (like ParentId) that Object.entries doesn't include.\n  for (const sym of Object.getOwnPropertySymbols(props)) {\n    const value = (props as any)[sym];\n    if (value !== undefined) {\n      filterUndefined[sym] = value;\n    }\n  }\n\n  return internal.makeObject(\n    schema,\n    filterUndefined,\n    {\n      ...defaultMeta(),\n      ...meta,\n    },\n    input,\n  );\n}\n\n/**\n * Determine if object is an ECHO object.\n */\nexport const isObject = (obj: unknown): obj is Unknown => {\n  assumeType<internal.InternalObjectProps>(obj);\n  return typeof obj === 'object' && obj !== null && obj[Entity.KindId] === Entity.Kind.Object;\n};\n\nexport const isSnapshot = (obj: unknown): obj is Snapshot => {\n  assumeType<internal.InternalObjectProps>(obj);\n  return typeof obj === 'object' && obj !== null && (obj as any)[Entity.SnapshotKindId] === Entity.Kind.Object;\n};\n\n/**\n * Subscribe to object updates.\n * The callback is called synchronously when the object is modified.\n * Only accepts reactive objects (not snapshots).\n * @returns Unsubscribe function.\n */\nexport const subscribe = (obj: Unknown, callback: () => void): (() => void) => {\n  return internal.subscribe(obj, callback);\n};\n\n//\n// Snapshot\n//\n\n/**\n * Returns an immutable snapshot of an object.\n * The snapshot is branded with SnapshotKindId instead of KindId,\n * making it distinguishable from the reactive object at the type level.\n */\nexport const getSnapshot: <T extends Unknown>(obj: T) => Snapshot<T> = objInternal.getSnapshot as any;\n\n/**\n * Returns the reactive version of an object from the database, given its snapshot.\n * Inverse of `Obj.getSnapshot`.\n *\n * Uses `Obj.getDatabase` internally to get the database from the snapshot,\n * then resolves the reactive object by ID.\n *\n * @param snapshot - A snapshot of the object (from `Obj.getSnapshot`).\n * @returns Effect that succeeds with the reactive object, or fails with `GetReactiveError`.\n * @example\n * ```ts\n * const snapshot = Obj.getSnapshot(obj);\n * const reactive = Obj.getReactive(snapshot).pipe(\n *   Effect.runSync\n * );\n * ```\n */\nexport const getReactive = <T extends Unknown>(snapshot: Snapshot<T>): Effect.Effect<T, Err.GetReactiveError> =>\n  Effect.gen(function* () {\n    const db = internal.getDatabase(snapshot);\n    if (!db) {\n      return yield* Effect.fail(new Err.GetReactiveError({ reason: 'no-database', snapshotId: snapshot.id }));\n    }\n    const obj = db.getObjectById(snapshot.id);\n    if (!obj) {\n      return yield* Effect.fail(new Err.GetReactiveError({ reason: 'object-not-found', snapshotId: snapshot.id }));\n    }\n    return obj as T;\n  });\n\n/**\n * Like `Obj.getReactive` but returns `Option.none()` instead of failing when the object\n * cannot be resolved (no database, object not found).\n *\n * @param snapshot - A snapshot of the object (from `Obj.getSnapshot`).\n * @returns Effect that succeeds with `Option.some(reactive)` or `Option.none()`.\n */\nexport const getReactiveOption = <T extends Unknown>(snapshot: Snapshot<T>): Effect.Effect<Option.Option<T>, never> =>\n  getReactive(snapshot).pipe(\n    Effect.map(Option.some),\n    Effect.catchAll(() => Effect.succeed(Option.none())),\n  );\n\n/**\n * Synchronous version of `Obj.getReactive`. Returns the reactive object or throws\n * `GetReactiveError` when the object cannot be resolved (no database, object not found).\n *\n * @param snapshot - A snapshot of the object (from `Obj.getSnapshot`).\n * @returns The reactive object.\n * @throws {Err.GetReactiveError} When the object cannot be resolved.\n */\nexport const getReactiveOrThrow = <T extends Unknown>(snapshot: Snapshot<T>): T =>\n  Effect.runSync(getReactive(snapshot));\n\nexport type CloneOptions = {\n  /**\n   * Retain the original object's ID.\n   * @default false\n   */\n  retainId?: boolean;\n\n  /**\n   * Recursively clone referenced objects.\n   * @default false\n   */\n  deep?: boolean;\n};\n\n/**\n * Clones an object or relation.\n * This does not clone referenced objects, only the properties in the object.\n * @returns A new object with the same schema and properties.\n */\nexport const clone: <T extends Unknown>(obj: T, opts?: CloneOptions) => T = objInternal.clone;\n\n//\n// Change\n//\n\n/**\n * Makes all properties mutable recursively.\n * Used to provide a mutable view of an object within `Obj.update`.\n */\nexport type Mutable<T> = internal.Mutable<T>;\n\n/**\n * Perform mutations on an echo object within a controlled context.\n *\n * All mutations within the callback are batched and trigger a single notification\n * when the callback completes. Direct mutations outside of `Obj.update` will throw\n * an error for echo objects.\n *\n * This function also works with nested objects within echo objects (e.g., Template structs)\n * that are reactive at runtime.\n *\n * @param obj - The echo object to mutate. Use `Relation.update` for relations.\n * @param callback - The callback that performs mutations on the object.\n *\n * @example\n * ```ts\n * const person = Obj.make(Person, { name: 'John', age: 25 });\n *\n * // Mutate within Obj.update\n * Obj.update(person, (obj) => {\n *   obj.name = 'Jane';\n *   obj.age = 30;\n * });\n * // ONE notification fires here\n *\n * // Direct mutation throws\n * person.name = 'Bob'; // Error: Cannot modify outside Obj.update()\n * ```\n *\n * Note: Only accepts objects. Use `Relation.update` for relations.\n */\nexport const update = <T extends Unknown>(obj: T, callback: internal.ChangeCallback<T>): void => {\n  internal.change(obj, callback);\n};\n\n/**\n * Get a deeply nested property from an object.\n *\n * Similar to lodash.get and getDeep from @dxos/util.\n * This is the complementary function to setValue.\n * Accepts both reactive objects and snapshots.\n *\n * @param obj - The ECHO object to get the property from.\n * @param path - Path to the property (array of keys).\n * @returns The value at the path, or undefined if not found.\n *\n * @example\n * ```ts\n * const person = Obj.make(Person, {\n *   name: 'John',\n *   addresses: [{ street: '123 Main St' }]\n * });\n *\n * Obj.getValue(person, ['addresses', 0, 'street']); // '123 Main St'\n * Obj.getValue(person, ['addresses', 1, 'street']); // undefined\n * ```\n */\nexport const getValue = (obj: Unknown | Snapshot, path: readonly (string | number)[]): any => {\n  return SchemaEx.getValue(obj, SchemaEx.createJsonPath(path));\n};\n\n/**\n * Set a deeply nested property on an object, using the object's schema to determine\n * whether to initialize nested data as an empty object or array.\n *\n * Similar to lodash.set and setDeep from @dxos/util, but schema-aware.\n * Must be called within an `Obj.update` callback.\n *\n * NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`\n * parameters, so there is no compile-time error. Enforcement is runtime-only.\n *\n * @param obj - The mutable ECHO object to set the property on.\n * @param path - Path to the property (array of keys).\n * @param value - Value to set.\n * @returns The value that was set.\n *\n * @example\n * ```ts\n * const person = Obj.make(Person, { name: 'John' });\n * // Person schema has: addresses: Schema.Array(Address)\n * Obj.update(person, (obj) => {\n *   Obj.setValue(obj, ['addresses', 0, 'street'], '123 Main St');\n * });\n * // Creates: person.addresses = [{ street: '123 Main St' }]\n * ```\n */\n// TODO(wittjosiah): Compute possible path values + type value based on generic object type.\nexport const setValue: (obj: Mutable<Unknown>, path: readonly (string | number)[], value: any) => void =\n  objInternal.setValue as any;\n\n//\n// Type\n//\n\nexport const ID = EntityId;\nexport type ID = EntityId;\n\n/**\n * Test if an object is an instance of a given object type.\n *\n * @example\n * ```ts\n * const john = Obj.make(Person, { name: 'John' });\n * const isPerson = Obj.instanceOf(Person);\n * if (isPerson(john)) {\n *   // john is Person\n * }\n * ```\n *\n * Only accepts `Type.AnyObj` — use `Relation.instanceOf` for relations and\n * `Type.isType(value)` to test for `Type.Type` meta-schema entities.\n */\nexport const instanceOf: {\n  // Reject `Type.Type` at the type level — those are meta-schema entities, not\n  // object instances. Use `Type.isType(value)` instead.\n  <T extends Type.Type>(\n    type: T,\n    _hint?: never,\n    // eslint-disable-next-line @typescript-eslint/unified-signatures\n    ..._error: ['ERROR: Obj.instanceOf does not accept Type.Type; use Type.isType(value) instead']\n  ): never;\n  // Reject relation types — use `Relation.instanceOf` instead.\n  <R extends Type.AnyRelation>(\n    type: R,\n    _hint?: never,\n    // eslint-disable-next-line @typescript-eslint/unified-signatures\n    ..._error: ['ERROR: Obj.instanceOf does not accept relation types; use Relation.instanceOf instead']\n  ): never;\n  <S extends Type.AnyObj>(schema: S): (value: unknown) => value is Type.InstanceType<S>;\n  <S extends Type.AnyObj>(schema: S, value: unknown): value is Type.InstanceType<S>;\n} = ((...args: [schema: Type.AnyEntity, value?: unknown]) => {\n  if (args.length === 1) {\n    return (entity: unknown) => internal.isInstanceOf(args[0], entity);\n  }\n\n  return internal.isInstanceOf(args[0], args[1]);\n}) as any;\n\n/**\n * Test if a snapshot is an instance of a schema.\n * Mirrors `instanceOf` but only accepts values branded with SnapshotKindId.\n * Use when the value is known to be a snapshot (e.g. from `getSnapshot` or `useObject`).\n *\n * @example\n * ```ts\n * const snapshot = Obj.getSnapshot(person);\n * if (Obj.snapshotOf(Person, snapshot)) {\n *   // snapshot is Obj.Snapshot<Person>\n * }\n * ```\n */\nexport const snapshotOf: {\n  <S extends Type.AnyObj>(schema: S): (value: unknown) => value is Snapshot<Type.InstanceType<S>>;\n  <S extends Type.AnyObj>(schema: S, value: unknown): value is Snapshot<Type.InstanceType<S>>;\n} = ((...args: [schema: Type.AnyObj, value: unknown] | [schema: Type.AnyObj]) => {\n  const check = (entity: unknown) =>\n    entity != null &&\n    typeof entity === 'object' &&\n    Entity.SnapshotKindId in entity &&\n    internal.isInstanceOf(args[0], entity);\n\n  if (args.length === 1) {\n    return (entity: unknown) => check(entity);\n  }\n\n  return check(args[1]);\n}) as any;\n\nexport type { GetURIOptions } from './internal';\n\n// TODO(dmaretskyi): Allow returning undefined.\n/**\n * Get the URI of the object.\n * Accepts both reactive objects and snapshots.\n *\n * @param options.prefer - Controls the URI form (see {@link GetURIOptions}).\n */\nexport const getURI = (entity: Unknown | Snapshot, options?: internal.GetURIOptions): URI.URI => {\n  assertArgument(!Schema.isSchema(entity), 'obj', 'Object should not be a schema.');\n  return internal.getUri(entity, options);\n};\n\n/**\n * @returns The DXN of the object's type.\n * @example dxn:com.example.type.person:1.0.0\n * @throws If the object is missing its type (corrupted object).\n */\nexport const getTypeURI = (obj: Unknown | Snapshot): URI.URI => {\n  const type = internal.getTypeURI(obj);\n  invariant(type != null, 'Corrupted object: missing type.');\n  return type;\n};\n\n/**\n * Get the type entity (`Type.AnyObj`) the object was created from.\n *\n * Returns `undefined` when the object's type isn't registered in this runtime\n * (e.g. a freshly deserialized snapshot whose type entity hasn't been wired\n * up yet, or an object loaded from storage before its schema is known). To\n * get the Effect Schema from the returned entity, use `Type.getSchema(...)`.\n */\nexport const getType = (obj: Unknown | Snapshot): Type.AnyObj | undefined =>\n  internal.getType(obj) as Type.AnyObj | undefined;\n\n/**\n * @returns The typename of the object's type.\n * Accepts both reactive objects and snapshots.\n * @example `com.example.type.person`\n */\nexport const getTypename = (entity: Unknown | Snapshot): string | undefined => internal.getTypename(entity);\n\n//\n// Database\n//\n\n/**\n * Get the database the object belongs to.\n * Accepts both reactive objects and snapshots.\n *\n * @idiom org.dxos.echo.objGetDatabase\n *   applies: Reaching an object's database — to query, add, or remove — when the surrounding Space is not otherwise needed\n *   instead-of: `getSpace(obj)?.db` (resolving the whole Space just to read its `.db`)\n *   uses: {@link getDatabase}\n */\nexport const getDatabase = (entity: Entity.Unknown | Entity.Snapshot): Database.Database | undefined =>\n  internal.getDatabase(entity);\n\n//\n// Meta\n//\n\n/**\n * Property that accesses metadata for an entity.\n *\n * Alias for `Entity.Meta`.\n */\nexport const Meta = internal.MetaId;\n\n/**\n * Deeply read-only version of EntityMeta.\n * Prevents mutation at all nesting levels (e.g., `meta.keys.push()` is a TypeScript error).\n */\nexport type ReadonlyMeta = internal.ReadonlyMeta;\n\n/**\n * Mutable meta type returned by `Obj.getMeta` inside an `Obj.update` callback.\n */\nexport type Meta = internal.Meta;\n\n// TODO(burdon): Narrow type.\n// TODO(dmaretskyi): Allow returning undefined.\n/**\n * Get the metadata for an object.\n * Returns mutable meta when passed a mutable object (inside `Obj.update` callback).\n * Returns read-only meta when passed a regular object or snapshot.\n *\n * @example\n * ```ts\n * // Read-only access outside change callback\n * const meta = Obj.getMeta(person);  // ReadonlyMeta\n *\n * // Mutable access inside change callback\n * Obj.update(person, (obj) => {\n *   const meta = Obj.getMeta(obj);     // EntityMeta (mutable)\n *   meta.tags.push(Ref.make(tag));     // tags are refs to Tag objects\n * });\n * ```\n */\n// TODO(wittjosiah): When passed a Snapshot, should return a snapshot of meta, not the live meta proxy.\nexport function getMeta(entity: Mutable<Unknown>): Meta;\nexport function getMeta(entity: Unknown | Snapshot): ReadonlyMeta;\nexport function getMeta(entity: Unknown | Snapshot | Mutable<Unknown>): Meta | ReadonlyMeta {\n  return internal.getMetaChecked(entity);\n}\n\n/**\n * @returns Foreign keys for the object from the specified source.\n * Accepts both reactive objects and snapshots.\n */\nexport const getKeys: {\n  (entity: Unknown | Snapshot, source: string): ForeignKey[];\n  (source: string): (entity: Unknown | Snapshot) => ForeignKey[];\n} = Function.dual(2, (entity: Unknown | Snapshot, source?: string): ForeignKey[] => internal.getKeys(entity, source!));\n\n/**\n * Delete all keys from the object for the specified source.\n * Must be called within an `Obj.update` callback.\n *\n * NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`\n * parameters, so there is no compile-time error. Enforcement is runtime-only.\n */\nexport const deleteKeys = (entity: Mutable<Unknown>, source: string): void => internal.deleteKeys(entity, source);\n\n/**\n * Add a tag to the object.\n * Must be called within an `Obj.update` callback.\n *\n * NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`\n * parameters, so there is no compile-time error. Enforcement is runtime-only.\n */\nexport const addTag = (entity: Mutable<Unknown>, tag: Ref.Ref<Tag.Tag>): void => internal.addTag(entity, tag);\n\n/**\n * Remove a tag from the object.\n * Must be called within an `Obj.update` callback.\n *\n * NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`\n * parameters, so there is no compile-time error. Enforcement is runtime-only.\n */\nexport const removeTag = (entity: Mutable<Unknown>, tag: Ref.Ref<Tag.Tag>): void => internal.removeTag(entity, tag);\n\n/**\n * Check if the object is deleted.\n * Accepts both reactive objects and snapshots.\n */\n// TODO(dmaretskyi): Default to `false`.\nexport const isDeleted = (entity: Unknown | Snapshot): boolean => objInternal.isDeleted(entity);\n\n//\n// Annotations\n//\n\n/**\n * Get the label of the object.\n * Accepts both reactive objects and snapshots.\n *\n * @param options.fallback `'typename'` returns the object's typename when no\n *   label is set (e.g. `org.dxos.type.table`).\n */\nexport const getLabel = (entity: Unknown | Snapshot, options?: internal.GetLabelOptions): string | undefined =>\n  internal.getLabel(entity, options);\n\n/**\n * Set the label of the object.\n * Must be called within an `Obj.update` callback.\n *\n * NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`\n * parameters, so there is no compile-time error. Enforcement is runtime-only.\n */\nexport const setLabel = (entity: Mutable<Unknown>, label: string): void => internal.setLabel(entity, label);\n\n/**\n * Get the description of the object.\n * Accepts both reactive objects and snapshots.\n */\nexport const getDescription = (entity: Unknown | Snapshot): string | undefined => internal.getDescription(entity);\n\n/**\n * Get the icon annotation for the object (or any entity), resolved via its type-level\n * `IconAnnotation`. Accepts both reactive entities and snapshots, and either Objects or\n * Relations — the underlying schema-based lookup works for both.\n *\n * Returns the full `{ icon, hue }` annotation; callers wanting just the icon name typically\n * write `Obj.getIcon(obj)?.icon ?? 'ph--cube--regular'`.\n */\nexport const getIcon = (entity: Entity.Unknown | Entity.Snapshot): internal.IconAnnotation | undefined =>\n  internal.getIcon(entity);\n\n/**\n * Set the description of the object.\n * Must be called within an `Obj.update` callback.\n *\n * NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`\n * parameters, so there is no compile-time error. Enforcement is runtime-only.\n */\nexport const setDescription = (entity: Mutable<Unknown>, description: string): void =>\n  internal.setDescription(entity, description);\n\n/**\n * Symbol to set parent when creating objects with `Obj.make`.\n * @example\n * ```ts\n * Obj.make(TestSchema.Person, {\n *   [Obj.Parent]: parentObject,\n *   name: 'John',\n * })\n * ```\n */\nexport const Parent: unique symbol = internal.ParentId as any;\n\n/**\n * Get the parent of an object.\n * The parent is always loaded together with the object.\n * Only objects are allowed to have a parent\n * @returns The parent object, or undefined if the object has no parent.\n */\nexport const getParent = (entity: Unknown | Snapshot): Unknown | undefined => {\n  assertArgument(isObject(entity) || isSnapshot(entity), 'Expected an object');\n  assumeType<internal.InternalObjectProps>(entity);\n  return entity[internal.ParentId] as Unknown | undefined;\n};\n\n/**\n * Sets the parent of an object.\n * If a parent (or any transitive parent) is deleted, the object will be deleted.\n * Only objects are allowed to have a parent.\n */\nexport const setParent = (entity: Unknown, parent: Any | undefined) => {\n  assertArgument(isObject(entity), 'Expected an object');\n  assertArgument(parent === undefined || isObject(parent), 'Expected an object');\n  assumeType<internal.InternalObjectProps>(entity);\n  assumeType<internal.InternalObjectProps | undefined>(parent);\n  entity[internal.ParentId] = parent;\n  return entity;\n};\n\ninterface UpdateFromOptions<T> {\n  exclude?: (keyof T)[];\n  include?: (keyof T)[];\n}\n\nconst valuesEqual = (left: unknown, right: unknown): boolean => {\n  if (left === right) {\n    return true;\n  }\n  if (left === null || right === null) {\n    return left === right;\n  }\n  if (typeof left !== 'object' || typeof right !== 'object') {\n    return Utils.structuralRegion(() => Equal.equals(left, right));\n  }\n  if (Ref.isRef(left) && Ref.isRef(right)) {\n    return left.uri === right.uri;\n  }\n  if (Ref.isRef(left) || Ref.isRef(right)) {\n    return false;\n  }\n  if (Array.isArray(left) && Array.isArray(right)) {\n    if (left.length !== right.length) {\n      return false;\n    }\n    for (let index = 0; index < left.length; index++) {\n      if (!valuesEqual(left[index], right[index])) {\n        return false;\n      }\n    }\n    return true;\n  }\n  if (Array.isArray(left) || Array.isArray(right)) {\n    return false;\n  }\n  const leftRecord = left as Record<string, unknown>;\n  const rightRecord = right as Record<string, unknown>;\n  const keys = new Set([\n    ...Object.keys(leftRecord).filter((key) => key !== 'id'),\n    ...Object.keys(rightRecord).filter((key) => key !== 'id'),\n  ]);\n  for (const key of keys) {\n    const leftHas = Object.hasOwn(leftRecord, key);\n    const rightHas = Object.hasOwn(rightRecord, key);\n    const leftValue = leftHas ? leftRecord[key] : undefined;\n    const rightValue = rightHas ? rightRecord[key] : undefined;\n    if (!valuesEqual(leftValue, rightValue)) {\n      return false;\n    }\n  }\n  return true;\n};\n\n/**\n * Breaks reactive proxies on assigned values so echo-db assignment accepts nested structs (same idea as link assignment).\n */\nconst prepareAssignValue = (value: unknown): unknown =>\n  deepMapValues(value, (nested, recurse) => {\n    if (nested === null || typeof nested !== 'object') {\n      return nested;\n    }\n    if (Ref.isRef(nested)) {\n      return nested;\n    }\n    if (Array.isArray(nested)) {\n      return recurse(nested);\n    }\n    if (isProxy(nested)) {\n      return recurse({ ...getProxyTarget(nested) });\n    }\n    return recurse(nested);\n  });\n\n/**\n * For each key present on `source` (except `id`), assigns `target[key]` when the current value differs.\n * References are compared by target DXN; other values use Effect `Equal.equals` inside a structural region,\n * with recursive comparison for arrays and plain object-shaped property bags (excluding `id`).\n *\n * Must be called within an `Obj.update` callback.\n *\n * @returns Whether any property was updated.\n */\nexport const updateFrom = <T extends Unknown>(\n  target: Mutable<T>,\n  source: T,\n  options?: UpdateFromOptions<T>,\n): boolean => {\n  assertArgument(isObject(target), 'Expected an echo object target.');\n  assertArgument(isObject(source), 'Expected an echo object source.');\n  let keys = Object.keys(source as Record<string, unknown>).filter((key) => key !== 'id');\n  if (options?.include !== undefined) {\n    const include = new Set(options.include.map((key) => String(key)));\n    keys = keys.filter((key) => include.has(key));\n  }\n  if (options?.exclude !== undefined) {\n    const exclude = new Set(options.exclude.map((key) => String(key)));\n    keys = keys.filter((key) => !exclude.has(key));\n  }\n  let updated = false;\n  const sourceRecord = source as Record<string, unknown>;\n  const targetRecord = target as Record<string, unknown>;\n  for (const key of keys) {\n    if (!Object.hasOwn(sourceRecord, key)) {\n      continue;\n    }\n    const nextValue = sourceRecord[key];\n    const prevValue = Object.hasOwn(targetRecord, key) ? targetRecord[key] : undefined;\n    if (valuesEqual(prevValue, nextValue)) {\n      continue;\n    }\n    targetRecord[key] = prepareAssignValue(nextValue) as never;\n    updated = true;\n  }\n  return updated;\n};\n\n//\n// JSON\n//\n\n/**\n * JSON representation of an object.\n */\nexport type JSON = internal.ObjectJSON;\n\n/**\n * Converts object to its JSON representation.\n * Accepts both reactive objects and snapshots.\n *\n * The same algorithm is used when calling the standard `JSON.stringify(obj)` function.\n */\nexport const toJSON = (entity: Unknown | Snapshot): JSON => objInternal.objectToJSON(entity);\n\n/**\n * Creates an object from its json representation, performing schema validation.\n * References and schemas will be resolvable if the `refResolver` is provided.\n *\n * The function must be async to support resolving the schema as well as the relation endpoints.\n *\n * @param options.refResolver - Resolver for references. Produces hydrated references that can be resolved.\n * @param options.uri - Override object URI. Changes the result of `Obj.getURI`.\n * @param options.database - Database to associate with the object.\n */\nexport const fromJSON: (\n  json: unknown,\n  options?: { refResolver?: Ref.Resolver; uri?: URI.URI; database?: Database.Database; parent?: Unknown },\n) => Promise<Unknown> = objInternal.objectFromJSON as any;\n\n/**\n * Comparator function type for sorting objects.\n * Accepts both reactive objects and snapshots.\n */\nexport type Comparator = internal.Comparator<Unknown | Snapshot>;\n\nexport const sortByLabel: Comparator = internal.sortByLabel as Comparator;\nexport const sortByTypename: Comparator = internal.sortByTypename as Comparator;\nexport const sort = (...comparators: Comparator[]): Comparator => internal.sort(...comparators) as Comparator;\n\n//\n// Version\n//\n\nexport const VersionTypeId = internal.VersionTypeId;\nexport type VersionCompareResult = internal.VersionCompareResult;\n\n/**\n * Represent object version.\n * May be backed by Automerge.\n * Objects with no history are not versioned.\n */\nexport type Version = internal.EntityVersion;\n\nexport const isVersion = internal.isVersion;\nexport const versionValid = internal.versionValid;\nexport const compareVersions = internal.compareVersions;\nexport const encodeVersion = internal.encodeVersion;\nexport const decodeVersion = internal.decodeVersion;\n\n/**\n * Returns the version of the object.\n * Accepts both reactive objects and snapshots.\n */\nexport const version = (entity: Unknown | Snapshot): Version => internal.version(entity);\n\n//\n// Atoms\n//\n\nexport const atom = objInternal.makeAtom;\nexport const atomReactive = objInternal.makeWithReactive;\nexport const atomProperty = objInternal.makeProperty;\n"],
  "mappings": "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",
  "names": ["Unknown", "VersionTypeId", "addTag", "clone", "compareVersions", "decodeVersion", "deleteKeys", "encodeVersion", "getDatabase", "getDescription", "getIcon", "getKeys", "getLabel", "getSnapshot", "getType", "getTypeURI", "getTypename", "isDeleted", "isVersion", "removeTag", "setDescription", "setLabel", "setValue", "sort", "sortByLabel", "sortByTypename", "subscribe", "version", "versionValid", "Effect", "Equal", "Function", "Option", "Schema", "Utils", "SchemaEx", "assertArgument", "invariant", "EntityId", "assumeType", "deepMapValues", "Schema", "Record", "key", "annotations", "TypeAnnotationId", "kind", "Kind", "typename", "ANY_OBJECT_TYPENAME", "version", "internal", "ANY_OBJECT_VERSION", "input", "meta", "undefined", "props", "defaultMeta", "MetaId", "Object", "getOwnPropertySymbols", "value", "filterUndefined", "sym", "isSnapshot", "obj", "subscribe", "Effect", "GetReactiveError", "reason", "snapshotId", "snapshot", "id", "setValue", "entity", "isInstanceOf", "args", "length", "check", "options", "invariant", "type", "getTypename", "getDatabase", "getMetaChecked", "isDeleted", "assumeType", "ParentId", "assertArgument", "parent", "isObject", "valuesEqual", "left", "Ref", "right", "isRef", "Array", "isArray", "index", "leftRecord", "keys", "Set", "rightRecord", "rightHas", "leftValue", "leftHas", "rightValue", "nested", "isProxy", "getProxyTarget", "source", "filter", "include", "map", "String", "exclude", "updated", "targetRecord", "hasOwn", "prevValue", "nextValue", "sortByTypename", "sort", "comparators", "versionValid", "compareVersions", "encodeVersion", "decodeVersion", "atomProperty", "objInternal"]
}
