@open-mercato/core 0.10.1-develop.7975.1.ada24d305c → 0.10.1-develop.7978.1.b4468545b6

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.
@@ -92,6 +92,9 @@ async function loadPersonCompanyLinkSnapshot(em, id, scope) {
92
92
  }
93
93
  );
94
94
  if (!link) return null;
95
+ return snapshotPersonCompanyLink(link);
96
+ }
97
+ function snapshotPersonCompanyLink(link) {
95
98
  const personId = typeof link.person === "string" ? link.person : link.person.id;
96
99
  const companyId = typeof link.company === "string" ? link.company : link.company.id;
97
100
  return {
@@ -150,8 +153,77 @@ async function clearPrimaryFlagsForPerson(em, person) {
150
153
  { isPrimary: false }
151
154
  );
152
155
  }
156
+ async function restoreCreatePersonCompanyLink(ctx, after, before) {
157
+ const em = ctx.container.resolve("em").fork();
158
+ const scope = { tenantId: after.tenantId, organizationId: after.organizationId };
159
+ const link = await findOneWithDecryption(
160
+ em,
161
+ CustomerPersonCompanyLink,
162
+ { id: after.id, ...scope },
163
+ void 0,
164
+ scope
165
+ );
166
+ if (!link) return;
167
+ const person = await requirePersonEntity(em, after.personEntityId, after.tenantId, after.organizationId);
168
+ const profile = await requirePersonProfile(em, person);
169
+ const profileCompanyId = typeof profile.company === "string" ? profile.company : profile.company?.id ?? null;
170
+ const restorePrimaryAssignment = after.isPrimary && link.isPrimary && profileCompanyId === after.companyEntityId;
171
+ const company = restorePrimaryAssignment && before.profileCompanyId ? await requireCompanyEntity(em, before.profileCompanyId, after.tenantId, after.organizationId) : null;
172
+ const primaryLinkIds = before.primaryLinkIds.filter((id) => id !== link.id);
173
+ await withAtomicFlush(em, [
174
+ async () => {
175
+ if (restorePrimaryAssignment) {
176
+ await em.nativeUpdate(
177
+ CustomerPersonCompanyLink,
178
+ { person, ...scope, id: { $ne: link.id }, deletedAt: null, isPrimary: true },
179
+ { isPrimary: false }
180
+ );
181
+ if (primaryLinkIds.length) {
182
+ await em.nativeUpdate(
183
+ CustomerPersonCompanyLink,
184
+ { person, ...scope, id: { $in: primaryLinkIds }, deletedAt: null },
185
+ { isPrimary: true }
186
+ );
187
+ }
188
+ profile.company = company;
189
+ }
190
+ link.isPrimary = before.link?.isPrimary ?? false;
191
+ link.deletedAt = before.link ? before.link.deletedAt ? new Date(before.link.deletedAt) : null : /* @__PURE__ */ new Date();
192
+ }
193
+ ], { transaction: true });
194
+ const dataEngine = ctx.container.resolve("dataEngine");
195
+ await emitCrudUndoSideEffects({
196
+ dataEngine,
197
+ action: link.deletedAt ? "deleted" : "updated",
198
+ entity: link,
199
+ identifiers: getLinkIdentifiers(link),
200
+ syncOrigin: ctx.syncOrigin,
201
+ events: personCompanyLinkCrudEvents,
202
+ indexer: { entityType: "customers:customer_person_company_link" }
203
+ });
204
+ }
153
205
  const createPersonCompanyLinkCommand = {
154
206
  id: "customers.personCompanyLinks.create",
207
+ async prepare(rawInput, ctx) {
208
+ const parsed = personCompanyLinkCreateSchema.parse(rawInput);
209
+ ensureTenantScope(ctx, parsed.tenantId);
210
+ ensureOrganizationScope(ctx, parsed.organizationId);
211
+ const em = ctx.container.resolve("em").fork();
212
+ const person = await requirePersonEntity(em, parsed.personEntityId, parsed.tenantId, parsed.organizationId);
213
+ const company = await requireCompanyEntity(em, parsed.companyEntityId, parsed.tenantId, parsed.organizationId);
214
+ const profile = await requirePersonProfile(em, person);
215
+ const links = await loadPersonCompanyLinks(em, person);
216
+ const link = links.find(
217
+ (entry) => (typeof entry.company === "string" ? entry.company : entry.company.id) === company.id
218
+ ) ?? await findDeletedPersonCompanyLink(em, person, company);
219
+ return {
220
+ before: {
221
+ link: link ? await loadPersonCompanyLinkSnapshot(em, link.id, parsed) : null,
222
+ primaryLinkIds: links.filter((entry) => entry.isPrimary).map((entry) => entry.id),
223
+ profileCompanyId: typeof profile.company === "string" ? profile.company : profile.company?.id ?? null
224
+ }
225
+ };
226
+ },
155
227
  async execute(rawInput, ctx) {
156
228
  const parsed = personCompanyLinkCreateSchema.parse(rawInput);
157
229
  ensureTenantScope(ctx, parsed.tenantId);
@@ -163,8 +235,14 @@ const createPersonCompanyLinkCommand = {
163
235
  const existingLinks = await loadPersonCompanyLinks(em, person);
164
236
  const makePrimary = Boolean(parsed.isPrimary) || existingLinks.length === 0;
165
237
  const existingLive = existingLinks.find((link2) => (typeof link2.company === "string" ? link2.company : link2.company.id) === company.id) ?? null;
238
+ const createBefore = {
239
+ link: existingLive ? snapshotPersonCompanyLink(existingLive) : null,
240
+ primaryLinkIds: existingLinks.filter((link2) => link2.isPrimary).map((link2) => link2.id),
241
+ profileCompanyId: typeof profile.company === "string" ? profile.company : profile.company?.id ?? null
242
+ };
166
243
  if (existingLive) {
167
- if (makePrimary && !existingLive.isPrimary) {
244
+ const changed = makePrimary && !existingLive.isPrimary;
245
+ if (changed) {
168
246
  await withAtomicFlush(em, [
169
247
  () => clearPrimaryFlagsForPerson(em, person),
170
248
  () => {
@@ -173,13 +251,14 @@ const createPersonCompanyLinkCommand = {
173
251
  }
174
252
  ], { transaction: true });
175
253
  }
176
- return { linkId: existingLive.id, created: false, undeleted: false };
254
+ return { linkId: existingLive.id, created: false, undeleted: false, changed, createBefore };
177
255
  }
178
256
  let link;
179
257
  let undeleted = false;
180
258
  await withAtomicFlush(em, [
181
259
  async () => {
182
260
  const deletedLink = await findDeletedPersonCompanyLink(em, person, company);
261
+ if (deletedLink) createBefore.link = snapshotPersonCompanyLink(deletedLink);
183
262
  if (makePrimary) {
184
263
  await clearPrimaryFlagsForPerson(em, person);
185
264
  }
@@ -219,18 +298,22 @@ const createPersonCompanyLinkCommand = {
219
298
  events: personCompanyLinkCrudEvents,
220
299
  indexer: { entityType: "customers:customer_person_company_link" }
221
300
  });
222
- return { linkId: link.id, created: !undeleted, undeleted };
301
+ return { linkId: link.id, created: !undeleted, undeleted, changed: true, createBefore };
223
302
  },
224
303
  captureAfter: async (_input, result, ctx) => {
225
- const em = ctx.container.resolve("em");
304
+ const em = ctx.container.resolve("em").fork();
226
305
  return loadPersonCompanyLinkSnapshot(em, result.linkId, {
227
306
  tenantId: ctx.auth?.tenantId ?? null,
228
307
  organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null
229
308
  });
230
309
  },
231
310
  buildLog: async ({ result, snapshots }) => {
232
- const { translate } = await resolveTranslations();
311
+ const before = result.createBefore;
233
312
  const after = snapshots.after;
313
+ if (!result.changed) {
314
+ return { skipLog: true };
315
+ }
316
+ const { translate } = await resolveTranslations();
234
317
  return {
235
318
  actionLabel: translate("customers.audit.personCompanyLinks.create", "Link company to person"),
236
319
  resourceKind: "customers.personCompanyLink",
@@ -239,10 +322,12 @@ const createPersonCompanyLinkCommand = {
239
322
  parentResourceId: after?.personEntityId ?? null,
240
323
  tenantId: after?.tenantId ?? null,
241
324
  organizationId: after?.organizationId ?? null,
325
+ snapshotBefore: before?.link ?? null,
242
326
  snapshotAfter: after ?? null,
243
327
  payload: {
244
328
  undo: {
245
329
  after: after ?? null,
330
+ ...before ? { createBefore: before } : {},
246
331
  ...result.undeleted ? { before: null } : {}
247
332
  }
248
333
  }
@@ -252,6 +337,10 @@ const createPersonCompanyLinkCommand = {
252
337
  const payload = extractUndoPayload(logEntry);
253
338
  const after = payload?.after;
254
339
  if (!after) return;
340
+ if (payload.createBefore) {
341
+ await restoreCreatePersonCompanyLink(ctx, after, payload.createBefore);
342
+ return;
343
+ }
255
344
  const em = ctx.container.resolve("em").fork();
256
345
  const link = await findOneWithDecryption(
257
346
  em,
@@ -322,6 +411,12 @@ const createPersonCompanyLinkCommand = {
322
411
  void 0,
323
412
  { tenantId: after.tenantId, organizationId: after.organizationId }
324
413
  );
414
+ const existingLinks = await loadPersonCompanyLinks(em, person);
415
+ const createBefore = {
416
+ link: link ? snapshotPersonCompanyLink(link) : null,
417
+ primaryLinkIds: existingLinks.filter((entry) => entry.isPrimary).map((entry) => entry.id),
418
+ profileCompanyId: typeof profile.company === "string" ? profile.company : profile.company?.id ?? null
419
+ };
325
420
  await withAtomicFlush(em, [
326
421
  async () => {
327
422
  if (after.isPrimary) {
@@ -359,7 +454,7 @@ const createPersonCompanyLinkCommand = {
359
454
  events: personCompanyLinkCrudEvents,
360
455
  indexer: { entityType: "customers:customer_person_company_link" }
361
456
  });
362
- return { linkId: link.id, created: true, undeleted: false };
457
+ return { linkId: link.id, created: true, undeleted: false, changed: true, createBefore };
363
458
  }
364
459
  };
365
460
  const updatePersonCompanyLinkCommand = {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/customers/commands/personCompanyLinks.ts"],
4
- "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport { emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n CustomerEntity,\n CustomerPersonCompanyLink,\n CustomerPersonProfile,\n} from '../data/entities'\nimport {\n personCompanyLinkCreateSchema,\n personCompanyLinkDeleteSchema,\n personCompanyLinkUpdateSchema,\n type PersonCompanyLinkCreateInput,\n type PersonCompanyLinkDeleteInput,\n type PersonCompanyLinkUpdateInput,\n} from '../data/validators'\nimport {\n findDeletedPersonCompanyLink,\n loadPersonCompanyLinks,\n promoteFallbackPrimaryLink,\n removePersonCompanyLink,\n} from '../lib/personCompanies'\nimport {\n emitQueryIndexUpsertEvents,\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n type QueryIndexEventEntry,\n} from './shared'\nimport type { CustomersEventId } from '../events'\nimport { E } from '#generated/entities.ids.generated'\nimport type { EventBus } from '@open-mercato/events'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('customers').child({ component: 'personCompanyLinks' })\n\n// Typed against the module's declared event ids so removing or renaming the declaration in\n// `events.ts` fails the build here rather than emitting an undeclared event at runtime.\nconst PROFILE_ONLY_DETACHED_EVENT: CustomersEventId = 'customers.person.company_assignment.detached'\n\ntype PersonCompanyLinkSnapshot = {\n id: string\n personEntityId: string\n companyEntityId: string\n isPrimary: boolean\n tenantId: string\n organizationId: string\n deletedAt: string | null\n}\n\ntype PersonCompanyLinkUndoPayload = {\n before?: PersonCompanyLinkSnapshot | null\n after?: PersonCompanyLinkSnapshot | null\n}\n\n/**\n * Snapshot of a legacy profile-only company assignment \u2014 `customer_person_profiles.company_id`\n * set with no backing link row (#5114). It carries no link id because none exists; `kind`\n * discriminates it from `PersonCompanyLinkSnapshot` in the delete command's undo payload.\n */\ntype PersonCompanyProfileAssignmentSnapshot = {\n kind: 'profile-only'\n personEntityId: string\n companyEntityId: string\n tenantId: string\n organizationId: string\n}\n\ntype PersonCompanyLinkDeleteSnapshot = PersonCompanyLinkSnapshot | PersonCompanyProfileAssignmentSnapshot\n\ntype PersonCompanyLinkDeleteUndoPayload = {\n before?: PersonCompanyLinkDeleteSnapshot | null\n}\n\ntype PersonCompanyLinkDeleteResult = {\n linkId: string | null\n personEntityId: string | null\n companyEntityId: string | null\n}\n\nfunction isProfileAssignmentSnapshot(\n snapshot: PersonCompanyLinkDeleteSnapshot | null | undefined,\n): snapshot is PersonCompanyProfileAssignmentSnapshot {\n return Boolean(snapshot) && (snapshot as PersonCompanyProfileAssignmentSnapshot).kind === 'profile-only'\n}\n\nfunction resolveProfileOnlyTarget(\n parsed: PersonCompanyLinkDeleteInput,\n): { personEntityId: string; companyEntityId: string } | null {\n if (parsed.linkId) return null\n if (!parsed.personEntityId || !parsed.companyEntityId) return null\n return { personEntityId: parsed.personEntityId, companyEntityId: parsed.companyEntityId }\n}\n\nfunction personQueryIndexEntries(\n person: CustomerEntity,\n profile: CustomerPersonProfile,\n): QueryIndexEventEntry[] {\n return [\n {\n entityType: E.customers.customer_entity,\n recordId: person.id,\n tenantId: person.tenantId,\n organizationId: person.organizationId,\n },\n {\n entityType: E.customers.customer_person_profile,\n recordId: profile.id,\n tenantId: profile.tenantId,\n organizationId: profile.organizationId,\n },\n ]\n}\n\nconst personCompanyLinkCrudEvents: CrudEventsConfig = {\n module: 'customers',\n entity: 'person_company_link',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n ...(ctx.entity && typeof ctx.entity === 'object' && 'person' in (ctx.entity as Record<string, unknown>)\n ? {\n personEntityId:\n typeof (ctx.entity as CustomerPersonCompanyLink).person === 'string'\n ? (ctx.entity as any).person\n : (ctx.entity as CustomerPersonCompanyLink).person?.id ?? null,\n companyEntityId:\n typeof (ctx.entity as CustomerPersonCompanyLink).company === 'string'\n ? (ctx.entity as any).company\n : (ctx.entity as CustomerPersonCompanyLink).company?.id ?? null,\n }\n : {}),\n ...(ctx.syncOrigin ? { syncOrigin: ctx.syncOrigin } : {}),\n }),\n}\n\nfunction getLinkIdentifiers(link: CustomerPersonCompanyLink) {\n return {\n id: link.id,\n organizationId: link.organizationId,\n tenantId: link.tenantId,\n }\n}\n\nasync function loadPersonCompanyLinkSnapshot(\n em: EntityManager,\n id: string,\n scope?: { tenantId?: string | null; organizationId?: string | null },\n): Promise<PersonCompanyLinkSnapshot | null> {\n const filter: Record<string, unknown> = { id }\n if (scope?.tenantId) filter.tenantId = scope.tenantId\n if (scope?.organizationId) filter.organizationId = scope.organizationId\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n filter,\n undefined,\n {\n tenantId: scope?.tenantId ?? null,\n organizationId: scope?.organizationId ?? null,\n },\n )\n if (!link) return null\n const personId = typeof link.person === 'string' ? link.person : link.person.id\n const companyId = typeof link.company === 'string' ? link.company : link.company.id\n return {\n id: link.id,\n personEntityId: personId,\n companyEntityId: companyId,\n isPrimary: Boolean(link.isPrimary),\n tenantId: link.tenantId,\n organizationId: link.organizationId,\n deletedAt: link.deletedAt ? link.deletedAt.toISOString() : null,\n }\n}\n\nasync function requirePersonEntity(\n em: EntityManager,\n entityId: string,\n tenantId: string,\n organizationId: string,\n): Promise<CustomerEntity> {\n const person = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: entityId, kind: 'person', tenantId, organizationId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (!person) {\n throw notFound('Person not found')\n }\n return person\n}\n\nasync function requireCompanyEntity(\n em: EntityManager,\n entityId: string,\n tenantId: string,\n organizationId: string,\n): Promise<CustomerEntity> {\n const company = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: entityId, kind: 'company', tenantId, organizationId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (!company) {\n throw notFound('Company not found')\n }\n return company\n}\n\nasync function requirePersonProfile(\n em: EntityManager,\n person: CustomerEntity,\n): Promise<CustomerPersonProfile> {\n const profile = await findOneWithDecryption(\n em,\n CustomerPersonProfile,\n { entity: person },\n { populate: ['company'] },\n { tenantId: person.tenantId, organizationId: person.organizationId },\n )\n if (!profile) {\n throw notFound('Person profile not found')\n }\n return profile\n}\n\nasync function clearPrimaryFlagsForPerson(em: EntityManager, person: CustomerEntity): Promise<void> {\n await em.nativeUpdate(\n CustomerPersonCompanyLink,\n { person, organizationId: person.organizationId, tenantId: person.tenantId, isPrimary: true },\n { isPrimary: false },\n )\n}\n\nconst createPersonCompanyLinkCommand: CommandHandler<PersonCompanyLinkCreateInput, { linkId: string; created: boolean; undeleted: boolean }> = {\n id: 'customers.personCompanyLinks.create',\n async execute(rawInput, ctx) {\n const parsed = personCompanyLinkCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const person = await requirePersonEntity(em, parsed.personEntityId, parsed.tenantId, parsed.organizationId)\n const company = await requireCompanyEntity(em, parsed.companyEntityId, parsed.tenantId, parsed.organizationId)\n const profile = await requirePersonProfile(em, person)\n\n const existingLinks = await loadPersonCompanyLinks(em, person)\n const makePrimary = Boolean(parsed.isPrimary) || existingLinks.length === 0\n const existingLive =\n existingLinks.find((link) => (typeof link.company === 'string' ? link.company : link.company.id) === company.id) ?? null\n\n if (existingLive) {\n if (makePrimary && !existingLive.isPrimary) {\n await withAtomicFlush(em, [\n () => clearPrimaryFlagsForPerson(em, person),\n () => {\n existingLive.isPrimary = true\n profile.company = company\n },\n ], { transaction: true })\n }\n return { linkId: existingLive.id, created: false, undeleted: false }\n }\n\n let link!: CustomerPersonCompanyLink\n let undeleted = false\n await withAtomicFlush(em, [\n async () => {\n const deletedLink = await findDeletedPersonCompanyLink(em, person, company)\n if (makePrimary) {\n await clearPrimaryFlagsForPerson(em, person)\n }\n if (deletedLink) {\n deletedLink.deletedAt = null\n deletedLink.isPrimary = makePrimary\n em.persist(deletedLink)\n link = deletedLink\n undeleted = true\n } else {\n link = em.create(CustomerPersonCompanyLink, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n person,\n company,\n isPrimary: makePrimary,\n })\n em.persist(link)\n }\n },\n () => {\n if (makePrimary) {\n profile.company = company\n } else if (!profile.company && existingLinks.length === 0) {\n profile.company = company\n link.isPrimary = true\n }\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: undeleted ? 'updated' : 'created',\n entity: link,\n identifiers: getLinkIdentifiers(link),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n\n return { linkId: link.id, created: !undeleted, undeleted }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = ctx.container.resolve('em') as EntityManager\n return loadPersonCompanyLinkSnapshot(em, result.linkId, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const after = snapshots.after as PersonCompanyLinkSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.personCompanyLinks.create', 'Link company to person'),\n resourceKind: 'customers.personCompanyLink',\n resourceId: result.linkId,\n parentResourceKind: 'customers.person',\n parentResourceId: after?.personEntityId ?? null,\n tenantId: after?.tenantId ?? null,\n organizationId: after?.organizationId ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: {\n after: after ?? null,\n ...(result.undeleted ? { before: null } : {}),\n } satisfies PersonCompanyLinkUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PersonCompanyLinkUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n { id: after.id },\n undefined,\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (!link) return\n\n let person: CustomerEntity | null = null\n let profile: CustomerPersonProfile | null = null\n let remainingLinks: CustomerPersonCompanyLink[] = []\n\n await withAtomicFlush(em, [\n async () => {\n person = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: after.personEntityId, kind: 'person', tenantId: after.tenantId, organizationId: after.organizationId, deletedAt: null },\n undefined,\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (!person) return\n profile = await findOneWithDecryption(\n em,\n CustomerPersonProfile,\n { entity: person },\n { populate: ['company'] },\n { tenantId: person.tenantId, organizationId: person.organizationId },\n )\n if (!profile) return\n remainingLinks = (await loadPersonCompanyLinks(em, person)).filter((entry) => entry.id !== link.id)\n },\n async () => {\n link.isPrimary = false\n link.deletedAt = new Date()\n if (!person || !profile) return\n if (after.isPrimary) {\n await promoteFallbackPrimaryLink(em, person, profile, remainingLinks, after.companyEntityId)\n } else if (profile.company && typeof profile.company !== 'string' && profile.company.id === after.companyEntityId) {\n profile.company = null\n }\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'deleted',\n entity: link,\n identifiers: getLinkIdentifiers(link),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n },\n redo: async ({ logEntry, ctx }) => {\n const after = resolveRedoSnapshot<PersonCompanyLinkSnapshot>(logEntry)\n if (!after) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for person-company link create' })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const person = await requirePersonEntity(em, after.personEntityId, after.tenantId, after.organizationId)\n const company = await requireCompanyEntity(em, after.companyEntityId, after.tenantId, after.organizationId)\n const profile = await requirePersonProfile(em, person)\n\n let link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n { id: after.id },\n undefined,\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n\n await withAtomicFlush(em, [\n async () => {\n if (after.isPrimary) {\n await clearPrimaryFlagsForPerson(em, person)\n }\n if (!link) {\n link = em.create(CustomerPersonCompanyLink, {\n id: after.id,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n person,\n company,\n isPrimary: after.isPrimary,\n })\n em.persist(link)\n } else {\n link.deletedAt = null\n link.isPrimary = after.isPrimary\n em.persist(link)\n }\n },\n () => {\n if (after.isPrimary) {\n profile.company = company\n }\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: link!,\n identifiers: getLinkIdentifiers(link!),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n\n return { linkId: link!.id, created: true, undeleted: false }\n },\n}\n\nconst updatePersonCompanyLinkCommand: CommandHandler<PersonCompanyLinkUpdateInput, { linkId: string }> = {\n id: 'customers.personCompanyLinks.update',\n async prepare(rawInput, ctx) {\n const parsed = personCompanyLinkUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadPersonCompanyLinkSnapshot(em, parsed.linkId, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = personCompanyLinkUpdateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n {\n id: parsed.linkId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n deletedAt: null,\n },\n undefined,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n if (!link) {\n throw notFound('Company link not found')\n }\n\n const personId = typeof link.person === 'string' ? link.person : link.person.id\n const companyId = typeof link.company === 'string' ? link.company : link.company.id\n const person = await requirePersonEntity(em, personId, parsed.tenantId, parsed.organizationId)\n const profile = await requirePersonProfile(em, person)\n const linkedCompany = await requireCompanyEntity(em, companyId, parsed.tenantId, parsed.organizationId)\n\n const linkWasPrimary = link.isPrimary\n await withAtomicFlush(em, [\n async () => {\n if (parsed.isPrimary) {\n await clearPrimaryFlagsForPerson(em, person)\n link.isPrimary = true\n profile.company = linkedCompany\n } else if (!parsed.isPrimary) {\n link.isPrimary = false\n if (!linkWasPrimary && profile.company && typeof profile.company !== 'string' && profile.company.id === companyId) {\n profile.company = null\n }\n }\n },\n async () => {\n if (!parsed.isPrimary && linkWasPrimary) {\n const remainingLinks = (await loadPersonCompanyLinks(em, person)).filter((entry) => entry.id !== link.id)\n await promoteFallbackPrimaryLink(em, person, profile, remainingLinks, companyId)\n }\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: link,\n identifiers: getLinkIdentifiers(link),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n\n return { linkId: link.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = ctx.container.resolve('em') as EntityManager\n return loadPersonCompanyLinkSnapshot(em, result.linkId, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as PersonCompanyLinkSnapshot | undefined\n const after = snapshots.after as PersonCompanyLinkSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.personCompanyLinks.update', 'Update company link'),\n resourceKind: 'customers.personCompanyLink',\n resourceId: result.linkId,\n parentResourceKind: 'customers.person',\n parentResourceId: after?.personEntityId ?? before?.personEntityId ?? null,\n tenantId: after?.tenantId ?? before?.tenantId ?? null,\n organizationId: after?.organizationId ?? before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: {\n before: before ?? null,\n after: after ?? null,\n } satisfies PersonCompanyLinkUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PersonCompanyLinkUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n { id: before.id },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!link) return\n\n let person: CustomerEntity | null = null\n let profile: CustomerPersonProfile | null = null\n let company: CustomerEntity | null = null\n\n await withAtomicFlush(em, [\n async () => {\n person = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: before.personEntityId, kind: 'person', tenantId: before.tenantId, organizationId: before.organizationId, deletedAt: null },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!person) return\n profile = await findOneWithDecryption(\n em,\n CustomerPersonProfile,\n { entity: person },\n { populate: ['company'] },\n { tenantId: person.tenantId, organizationId: person.organizationId },\n )\n if (!profile || !before.isPrimary) return\n company = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: before.companyEntityId, kind: 'company', tenantId: before.tenantId, organizationId: before.organizationId, deletedAt: null },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n },\n async () => {\n if (!person || !profile) return\n if (before.isPrimary) {\n await clearPrimaryFlagsForPerson(em, person)\n link.isPrimary = true\n if (company) profile.company = company\n } else {\n link.isPrimary = false\n }\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'updated',\n entity: link,\n identifiers: getLinkIdentifiers(link),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n },\n}\n\n/**\n * Detach a legacy profile-only company assignment: `customer_person_profiles.company_id`\n * points at the company but no `customer_person_company_links` row was ever created, so\n * there is no link row for the id-based branch to soft-delete (#5114). Running it as part\n * of the same command keeps the audit entry, the undo token and the CRUD cache\n * invalidation identical to a link-backed detach.\n */\nasync function detachProfileOnlyCompany(\n em: EntityManager,\n ctx: CommandRuntimeContext,\n parsed: PersonCompanyLinkDeleteInput,\n target: { personEntityId: string; companyEntityId: string },\n): Promise<PersonCompanyLinkDeleteResult> {\n const person = await requirePersonEntity(em, target.personEntityId, parsed.tenantId, parsed.organizationId)\n const profile = await requirePersonProfile(em, person)\n const assignedCompany = profile.company\n const assignedCompanyId = typeof assignedCompany === 'string' ? assignedCompany : assignedCompany?.id ?? null\n if (assignedCompanyId !== target.companyEntityId) {\n throw notFound('Company link not found')\n }\n\n await withAtomicFlush(em, [\n () => removePersonCompanyLink(em, person, profile, target.companyEntityId),\n ], { transaction: true })\n\n // There is no link entity to hand to `emitCrudSideEffects`; what changed is the\n // person's own company assignment, so reindex the person and its profile instead.\n await emitQueryIndexUpsertEvents(ctx, personQueryIndexEntries(person, profile))\n await emitProfileOnlyDetachedEvent(ctx, person, target.companyEntityId)\n\n return { linkId: null, personEntityId: person.id, companyEntityId: target.companyEntityId }\n}\n\n/**\n * Live-refresh signal for the company People tab and the person Companies tab, which the\n * link-backed branch gets from `customers.person_company_link.deleted` via `emitCrudSideEffects`.\n * The profile-only branch has no link row to emit that for, so it publishes the sibling\n * `clientBroadcast` event instead (#5114). `tenantId` must travel in the payload: the event bus\n * only forwards a broadcast event cross-process when the payload carries a tenant scope. The\n * write is already committed, so a failed refresh signal must never fail the detach.\n */\nasync function emitProfileOnlyDetachedEvent(\n ctx: CommandRuntimeContext,\n person: CustomerEntity,\n companyEntityId: string,\n): Promise<void> {\n try {\n const bus = ctx.container.resolve<EventBus>('eventBus')\n await bus.emitEvent(\n PROFILE_ONLY_DETACHED_EVENT,\n {\n linkId: null,\n personEntityId: person.id,\n companyEntityId,\n tenantId: person.tenantId,\n organizationId: person.organizationId,\n },\n { tenantId: person.tenantId, organizationId: person.organizationId },\n )\n } catch (err) {\n logger.warn('Profile-only company detach broadcast failed', {\n command: 'customers.personCompanyLinks.delete',\n personEntityId: person.id,\n companyEntityId,\n err,\n })\n }\n}\n\n/**\n * Undo counterpart of `detachProfileOnlyCompany`: re-point the person's legacy\n * `profile.company` at the company it was detached from. The lookups run in the first\n * flush phase and the assignment in the second so the encryption subscriber's\n * re-baseline on find cannot drop the pending change (#2507).\n */\nasync function restoreProfileOnlyCompany(\n ctx: CommandRuntimeContext,\n before: PersonCompanyProfileAssignmentSnapshot,\n): Promise<void> {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let person: CustomerEntity | null = null\n let profile: CustomerPersonProfile | null = null\n let company: CustomerEntity | null = null\n\n await withAtomicFlush(em, [\n async () => {\n person = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: before.personEntityId, kind: 'person', tenantId: before.tenantId, organizationId: before.organizationId, deletedAt: null },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!person) return\n profile = await findOneWithDecryption(\n em,\n CustomerPersonProfile,\n { entity: person },\n { populate: ['company'] },\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!profile) return\n company = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: before.companyEntityId, kind: 'company', tenantId: before.tenantId, organizationId: before.organizationId, deletedAt: null },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n },\n () => {\n if (profile && company) profile.company = company\n },\n ], { transaction: true })\n\n if (person && profile) {\n await emitQueryIndexUpsertEvents(ctx, personQueryIndexEntries(person, profile))\n }\n}\n\nconst deletePersonCompanyLinkCommand: CommandHandler<PersonCompanyLinkDeleteInput, PersonCompanyLinkDeleteResult> = {\n id: 'customers.personCompanyLinks.delete',\n async prepare(rawInput, ctx) {\n const parsed = personCompanyLinkDeleteSchema.parse(rawInput)\n const profileOnlyTarget = resolveProfileOnlyTarget(parsed)\n if (profileOnlyTarget) {\n return {\n before: {\n kind: 'profile-only',\n personEntityId: profileOnlyTarget.personEntityId,\n companyEntityId: profileOnlyTarget.companyEntityId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n } satisfies PersonCompanyProfileAssignmentSnapshot,\n }\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadPersonCompanyLinkSnapshot(em, parsed.linkId as string, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = personCompanyLinkDeleteSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const profileOnlyTarget = resolveProfileOnlyTarget(parsed)\n if (profileOnlyTarget) {\n return await detachProfileOnlyCompany(em, ctx, parsed, profileOnlyTarget)\n }\n\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n {\n id: parsed.linkId as string,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n deletedAt: null,\n },\n undefined,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n if (!link) {\n throw notFound('Company link not found')\n }\n\n const personId = typeof link.person === 'string' ? link.person : link.person.id\n const companyId = typeof link.company === 'string' ? link.company : link.company.id\n const person = await requirePersonEntity(em, personId, parsed.tenantId, parsed.organizationId)\n const profile = await requirePersonProfile(em, person)\n const linkWasPrimary = link.isPrimary\n\n const existingLinks = await loadPersonCompanyLinks(em, person)\n const remainingLinks = existingLinks.filter((entry) => entry.id !== link.id)\n\n await withAtomicFlush(em, [\n () => {\n link.isPrimary = false\n link.deletedAt = new Date()\n },\n async () => {\n if (linkWasPrimary) {\n await promoteFallbackPrimaryLink(em, person, profile, remainingLinks, companyId)\n } else if (profile.company && typeof profile.company !== 'string' && profile.company.id === companyId) {\n const primary = remainingLinks.find((entry) => entry.isPrimary) ?? null\n const primaryCompany = primary && typeof primary.company !== 'string' ? primary.company : null\n if (primaryCompany) {\n profile.company = primaryCompany\n }\n }\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: link,\n identifiers: getLinkIdentifiers(link),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n\n return { linkId: link.id, personEntityId: personId, companyEntityId: companyId }\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as PersonCompanyLinkDeleteSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.personCompanyLinks.delete', 'Remove company link'),\n // Kept as `customers.personCompanyLink` for the profile-only shape too: the company\n // detail cache tags this resource kind, so both detach shapes must invalidate it.\n resourceKind: 'customers.personCompanyLink',\n resourceId: result.linkId,\n parentResourceKind: 'customers.person',\n parentResourceId: before?.personEntityId ?? null,\n tenantId: before?.tenantId ?? null,\n organizationId: before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n payload: {\n undo: {\n before: before ?? null,\n } satisfies PersonCompanyLinkDeleteUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PersonCompanyLinkDeleteUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n\n if (isProfileAssignmentSnapshot(before)) {\n await restoreProfileOnlyCompany(ctx, before)\n return\n }\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n { id: before.id },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!link) return\n\n let person: CustomerEntity | null = null\n let profile: CustomerPersonProfile | null = null\n let company: CustomerEntity | null = null\n\n await withAtomicFlush(em, [\n async () => {\n person = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: before.personEntityId, kind: 'person', tenantId: before.tenantId, organizationId: before.organizationId, deletedAt: null },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!person || !before.isPrimary) return\n profile = await findOneWithDecryption(\n em,\n CustomerPersonProfile,\n { entity: person },\n { populate: ['company'] },\n { tenantId: person.tenantId, organizationId: person.organizationId },\n )\n if (!profile) return\n company = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: before.companyEntityId, kind: 'company', tenantId: before.tenantId, organizationId: before.organizationId, deletedAt: null },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n },\n async () => {\n link.deletedAt = null\n link.isPrimary = before.isPrimary\n if (person && before.isPrimary) {\n await clearPrimaryFlagsForPerson(em, person)\n link.isPrimary = true\n if (profile && company) profile.company = company\n }\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'created',\n entity: link,\n identifiers: getLinkIdentifiers(link),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n },\n}\n\nregisterCommand(createPersonCompanyLinkCommand)\nregisterCommand(updatePersonCompanyLinkCommand)\nregisterCommand(deletePersonCompanyLinkCommand)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport { emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n CustomerEntity,\n CustomerPersonCompanyLink,\n CustomerPersonProfile,\n} from '../data/entities'\nimport {\n personCompanyLinkCreateSchema,\n personCompanyLinkDeleteSchema,\n personCompanyLinkUpdateSchema,\n type PersonCompanyLinkCreateInput,\n type PersonCompanyLinkDeleteInput,\n type PersonCompanyLinkUpdateInput,\n} from '../data/validators'\nimport {\n findDeletedPersonCompanyLink,\n loadPersonCompanyLinks,\n promoteFallbackPrimaryLink,\n removePersonCompanyLink,\n} from '../lib/personCompanies'\nimport {\n emitQueryIndexUpsertEvents,\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n type QueryIndexEventEntry,\n} from './shared'\nimport type { CustomersEventId } from '../events'\nimport { E } from '#generated/entities.ids.generated'\nimport type { EventBus } from '@open-mercato/events'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('customers').child({ component: 'personCompanyLinks' })\n\n// Typed against the module's declared event ids so removing or renaming the declaration in\n// `events.ts` fails the build here rather than emitting an undeclared event at runtime.\nconst PROFILE_ONLY_DETACHED_EVENT: CustomersEventId = 'customers.person.company_assignment.detached'\n\ntype PersonCompanyLinkSnapshot = {\n id: string\n personEntityId: string\n companyEntityId: string\n isPrimary: boolean\n tenantId: string\n organizationId: string\n deletedAt: string | null\n}\n\ntype PersonCompanyLinkUndoPayload = {\n before?: PersonCompanyLinkSnapshot | null\n after?: PersonCompanyLinkSnapshot | null\n createBefore?: PersonCompanyLinkCreateBefore\n}\n\ntype PersonCompanyLinkCreateBefore = {\n link: PersonCompanyLinkSnapshot | null\n primaryLinkIds: string[]\n profileCompanyId: string | null\n}\n\ntype PersonCompanyLinkCreateResult = {\n linkId: string\n created: boolean\n undeleted: boolean\n changed: boolean\n createBefore: PersonCompanyLinkCreateBefore\n}\n\n/**\n * Snapshot of a legacy profile-only company assignment \u2014 `customer_person_profiles.company_id`\n * set with no backing link row (#5114). It carries no link id because none exists; `kind`\n * discriminates it from `PersonCompanyLinkSnapshot` in the delete command's undo payload.\n */\ntype PersonCompanyProfileAssignmentSnapshot = {\n kind: 'profile-only'\n personEntityId: string\n companyEntityId: string\n tenantId: string\n organizationId: string\n}\n\ntype PersonCompanyLinkDeleteSnapshot = PersonCompanyLinkSnapshot | PersonCompanyProfileAssignmentSnapshot\n\ntype PersonCompanyLinkDeleteUndoPayload = {\n before?: PersonCompanyLinkDeleteSnapshot | null\n}\n\ntype PersonCompanyLinkDeleteResult = {\n linkId: string | null\n personEntityId: string | null\n companyEntityId: string | null\n}\n\nfunction isProfileAssignmentSnapshot(\n snapshot: PersonCompanyLinkDeleteSnapshot | null | undefined,\n): snapshot is PersonCompanyProfileAssignmentSnapshot {\n return Boolean(snapshot) && (snapshot as PersonCompanyProfileAssignmentSnapshot).kind === 'profile-only'\n}\n\nfunction resolveProfileOnlyTarget(\n parsed: PersonCompanyLinkDeleteInput,\n): { personEntityId: string; companyEntityId: string } | null {\n if (parsed.linkId) return null\n if (!parsed.personEntityId || !parsed.companyEntityId) return null\n return { personEntityId: parsed.personEntityId, companyEntityId: parsed.companyEntityId }\n}\n\nfunction personQueryIndexEntries(\n person: CustomerEntity,\n profile: CustomerPersonProfile,\n): QueryIndexEventEntry[] {\n return [\n {\n entityType: E.customers.customer_entity,\n recordId: person.id,\n tenantId: person.tenantId,\n organizationId: person.organizationId,\n },\n {\n entityType: E.customers.customer_person_profile,\n recordId: profile.id,\n tenantId: profile.tenantId,\n organizationId: profile.organizationId,\n },\n ]\n}\n\nconst personCompanyLinkCrudEvents: CrudEventsConfig = {\n module: 'customers',\n entity: 'person_company_link',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n ...(ctx.entity && typeof ctx.entity === 'object' && 'person' in (ctx.entity as Record<string, unknown>)\n ? {\n personEntityId:\n typeof (ctx.entity as CustomerPersonCompanyLink).person === 'string'\n ? (ctx.entity as any).person\n : (ctx.entity as CustomerPersonCompanyLink).person?.id ?? null,\n companyEntityId:\n typeof (ctx.entity as CustomerPersonCompanyLink).company === 'string'\n ? (ctx.entity as any).company\n : (ctx.entity as CustomerPersonCompanyLink).company?.id ?? null,\n }\n : {}),\n ...(ctx.syncOrigin ? { syncOrigin: ctx.syncOrigin } : {}),\n }),\n}\n\nfunction getLinkIdentifiers(link: CustomerPersonCompanyLink) {\n return {\n id: link.id,\n organizationId: link.organizationId,\n tenantId: link.tenantId,\n }\n}\n\nasync function loadPersonCompanyLinkSnapshot(\n em: EntityManager,\n id: string,\n scope?: { tenantId?: string | null; organizationId?: string | null },\n): Promise<PersonCompanyLinkSnapshot | null> {\n const filter: Record<string, unknown> = { id }\n if (scope?.tenantId) filter.tenantId = scope.tenantId\n if (scope?.organizationId) filter.organizationId = scope.organizationId\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n filter,\n undefined,\n {\n tenantId: scope?.tenantId ?? null,\n organizationId: scope?.organizationId ?? null,\n },\n )\n if (!link) return null\n return snapshotPersonCompanyLink(link)\n}\n\nfunction snapshotPersonCompanyLink(link: CustomerPersonCompanyLink): PersonCompanyLinkSnapshot {\n const personId = typeof link.person === 'string' ? link.person : link.person.id\n const companyId = typeof link.company === 'string' ? link.company : link.company.id\n return {\n id: link.id,\n personEntityId: personId,\n companyEntityId: companyId,\n isPrimary: Boolean(link.isPrimary),\n tenantId: link.tenantId,\n organizationId: link.organizationId,\n deletedAt: link.deletedAt ? link.deletedAt.toISOString() : null,\n }\n}\n\nasync function requirePersonEntity(\n em: EntityManager,\n entityId: string,\n tenantId: string,\n organizationId: string,\n): Promise<CustomerEntity> {\n const person = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: entityId, kind: 'person', tenantId, organizationId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (!person) {\n throw notFound('Person not found')\n }\n return person\n}\n\nasync function requireCompanyEntity(\n em: EntityManager,\n entityId: string,\n tenantId: string,\n organizationId: string,\n): Promise<CustomerEntity> {\n const company = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: entityId, kind: 'company', tenantId, organizationId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (!company) {\n throw notFound('Company not found')\n }\n return company\n}\n\nasync function requirePersonProfile(\n em: EntityManager,\n person: CustomerEntity,\n): Promise<CustomerPersonProfile> {\n const profile = await findOneWithDecryption(\n em,\n CustomerPersonProfile,\n { entity: person },\n { populate: ['company'] },\n { tenantId: person.tenantId, organizationId: person.organizationId },\n )\n if (!profile) {\n throw notFound('Person profile not found')\n }\n return profile\n}\n\nasync function clearPrimaryFlagsForPerson(em: EntityManager, person: CustomerEntity): Promise<void> {\n await em.nativeUpdate(\n CustomerPersonCompanyLink,\n { person, organizationId: person.organizationId, tenantId: person.tenantId, isPrimary: true },\n { isPrimary: false },\n )\n}\n\nasync function restoreCreatePersonCompanyLink(\n ctx: CommandRuntimeContext,\n after: PersonCompanyLinkSnapshot,\n before: PersonCompanyLinkCreateBefore,\n): Promise<void> {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = { tenantId: after.tenantId, organizationId: after.organizationId }\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n { id: after.id, ...scope },\n undefined,\n scope,\n )\n if (!link) return\n const person = await requirePersonEntity(em, after.personEntityId, after.tenantId, after.organizationId)\n const profile = await requirePersonProfile(em, person)\n const profileCompanyId = typeof profile.company === 'string' ? profile.company : profile.company?.id ?? null\n const restorePrimaryAssignment = after.isPrimary && link.isPrimary && profileCompanyId === after.companyEntityId\n const company = restorePrimaryAssignment && before.profileCompanyId\n ? await requireCompanyEntity(em, before.profileCompanyId, after.tenantId, after.organizationId)\n : null\n const primaryLinkIds = before.primaryLinkIds.filter((id) => id !== link.id)\n\n await withAtomicFlush(em, [\n async () => {\n if (restorePrimaryAssignment) {\n await em.nativeUpdate(\n CustomerPersonCompanyLink,\n { person, ...scope, id: { $ne: link.id }, deletedAt: null, isPrimary: true },\n { isPrimary: false },\n )\n if (primaryLinkIds.length) {\n await em.nativeUpdate(\n CustomerPersonCompanyLink,\n { person, ...scope, id: { $in: primaryLinkIds }, deletedAt: null },\n { isPrimary: true },\n )\n }\n profile.company = company\n }\n link.isPrimary = before.link?.isPrimary ?? false\n link.deletedAt = before.link\n ? before.link.deletedAt ? new Date(before.link.deletedAt) : null\n : new Date()\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: link.deletedAt ? 'deleted' : 'updated',\n entity: link,\n identifiers: getLinkIdentifiers(link),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n}\n\nconst createPersonCompanyLinkCommand: CommandHandler<PersonCompanyLinkCreateInput, PersonCompanyLinkCreateResult> = {\n id: 'customers.personCompanyLinks.create',\n async prepare(rawInput, ctx) {\n const parsed = personCompanyLinkCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const person = await requirePersonEntity(em, parsed.personEntityId, parsed.tenantId, parsed.organizationId)\n const company = await requireCompanyEntity(em, parsed.companyEntityId, parsed.tenantId, parsed.organizationId)\n const profile = await requirePersonProfile(em, person)\n const links = await loadPersonCompanyLinks(em, person)\n const link = links.find((entry) =>\n (typeof entry.company === 'string' ? entry.company : entry.company.id) === company.id,\n ) ?? await findDeletedPersonCompanyLink(em, person, company)\n return {\n before: {\n link: link ? await loadPersonCompanyLinkSnapshot(em, link.id, parsed) : null,\n primaryLinkIds: links.filter((entry) => entry.isPrimary).map((entry) => entry.id),\n profileCompanyId: typeof profile.company === 'string' ? profile.company : profile.company?.id ?? null,\n } satisfies PersonCompanyLinkCreateBefore,\n }\n },\n async execute(rawInput, ctx) {\n const parsed = personCompanyLinkCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const person = await requirePersonEntity(em, parsed.personEntityId, parsed.tenantId, parsed.organizationId)\n const company = await requireCompanyEntity(em, parsed.companyEntityId, parsed.tenantId, parsed.organizationId)\n const profile = await requirePersonProfile(em, person)\n\n const existingLinks = await loadPersonCompanyLinks(em, person)\n const makePrimary = Boolean(parsed.isPrimary) || existingLinks.length === 0\n const existingLive =\n existingLinks.find((link) => (typeof link.company === 'string' ? link.company : link.company.id) === company.id) ?? null\n // This state must come from execute's decision, not prepare's earlier read: another\n // request may have created the link between prepare and execute.\n const createBefore: PersonCompanyLinkCreateBefore = {\n link: existingLive ? snapshotPersonCompanyLink(existingLive) : null,\n primaryLinkIds: existingLinks.filter((link) => link.isPrimary).map((link) => link.id),\n profileCompanyId: typeof profile.company === 'string' ? profile.company : profile.company?.id ?? null,\n }\n\n if (existingLive) {\n const changed = makePrimary && !existingLive.isPrimary\n if (changed) {\n await withAtomicFlush(em, [\n () => clearPrimaryFlagsForPerson(em, person),\n () => {\n existingLive.isPrimary = true\n profile.company = company\n },\n ], { transaction: true })\n }\n return { linkId: existingLive.id, created: false, undeleted: false, changed, createBefore }\n }\n\n let link!: CustomerPersonCompanyLink\n let undeleted = false\n await withAtomicFlush(em, [\n async () => {\n const deletedLink = await findDeletedPersonCompanyLink(em, person, company)\n if (deletedLink) createBefore.link = snapshotPersonCompanyLink(deletedLink)\n if (makePrimary) {\n await clearPrimaryFlagsForPerson(em, person)\n }\n if (deletedLink) {\n deletedLink.deletedAt = null\n deletedLink.isPrimary = makePrimary\n em.persist(deletedLink)\n link = deletedLink\n undeleted = true\n } else {\n link = em.create(CustomerPersonCompanyLink, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n person,\n company,\n isPrimary: makePrimary,\n })\n em.persist(link)\n }\n },\n () => {\n if (makePrimary) {\n profile.company = company\n } else if (!profile.company && existingLinks.length === 0) {\n profile.company = company\n link.isPrimary = true\n }\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: undeleted ? 'updated' : 'created',\n entity: link,\n identifiers: getLinkIdentifiers(link),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n\n return { linkId: link.id, created: !undeleted, undeleted, changed: true, createBefore }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadPersonCompanyLinkSnapshot(em, result.linkId, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n },\n buildLog: async ({ result, snapshots }) => {\n const before = result.createBefore\n const after = snapshots.after as PersonCompanyLinkSnapshot | undefined\n if (!result.changed) {\n return { skipLog: true }\n }\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('customers.audit.personCompanyLinks.create', 'Link company to person'),\n resourceKind: 'customers.personCompanyLink',\n resourceId: result.linkId,\n parentResourceKind: 'customers.person',\n parentResourceId: after?.personEntityId ?? null,\n tenantId: after?.tenantId ?? null,\n organizationId: after?.organizationId ?? null,\n snapshotBefore: before?.link ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: {\n after: after ?? null,\n ...(before ? { createBefore: before } : {}),\n ...(result.undeleted ? { before: null } : {}),\n } satisfies PersonCompanyLinkUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PersonCompanyLinkUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n\n if (payload.createBefore) {\n await restoreCreatePersonCompanyLink(ctx, after, payload.createBefore)\n return\n }\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n { id: after.id },\n undefined,\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (!link) return\n\n let person: CustomerEntity | null = null\n let profile: CustomerPersonProfile | null = null\n let remainingLinks: CustomerPersonCompanyLink[] = []\n\n await withAtomicFlush(em, [\n async () => {\n person = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: after.personEntityId, kind: 'person', tenantId: after.tenantId, organizationId: after.organizationId, deletedAt: null },\n undefined,\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (!person) return\n profile = await findOneWithDecryption(\n em,\n CustomerPersonProfile,\n { entity: person },\n { populate: ['company'] },\n { tenantId: person.tenantId, organizationId: person.organizationId },\n )\n if (!profile) return\n remainingLinks = (await loadPersonCompanyLinks(em, person)).filter((entry) => entry.id !== link.id)\n },\n async () => {\n link.isPrimary = false\n link.deletedAt = new Date()\n if (!person || !profile) return\n if (after.isPrimary) {\n await promoteFallbackPrimaryLink(em, person, profile, remainingLinks, after.companyEntityId)\n } else if (profile.company && typeof profile.company !== 'string' && profile.company.id === after.companyEntityId) {\n profile.company = null\n }\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'deleted',\n entity: link,\n identifiers: getLinkIdentifiers(link),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n },\n redo: async ({ logEntry, ctx }) => {\n const after = resolveRedoSnapshot<PersonCompanyLinkSnapshot>(logEntry)\n if (!after) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for person-company link create' })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const person = await requirePersonEntity(em, after.personEntityId, after.tenantId, after.organizationId)\n const company = await requireCompanyEntity(em, after.companyEntityId, after.tenantId, after.organizationId)\n const profile = await requirePersonProfile(em, person)\n\n let link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n { id: after.id },\n undefined,\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n const existingLinks = await loadPersonCompanyLinks(em, person)\n const createBefore: PersonCompanyLinkCreateBefore = {\n link: link ? snapshotPersonCompanyLink(link) : null,\n primaryLinkIds: existingLinks.filter((entry) => entry.isPrimary).map((entry) => entry.id),\n profileCompanyId: typeof profile.company === 'string' ? profile.company : profile.company?.id ?? null,\n }\n\n await withAtomicFlush(em, [\n async () => {\n if (after.isPrimary) {\n await clearPrimaryFlagsForPerson(em, person)\n }\n if (!link) {\n link = em.create(CustomerPersonCompanyLink, {\n id: after.id,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n person,\n company,\n isPrimary: after.isPrimary,\n })\n em.persist(link)\n } else {\n link.deletedAt = null\n link.isPrimary = after.isPrimary\n em.persist(link)\n }\n },\n () => {\n if (after.isPrimary) {\n profile.company = company\n }\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: link!,\n identifiers: getLinkIdentifiers(link!),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n\n return { linkId: link!.id, created: true, undeleted: false, changed: true, createBefore }\n },\n}\n\nconst updatePersonCompanyLinkCommand: CommandHandler<PersonCompanyLinkUpdateInput, { linkId: string }> = {\n id: 'customers.personCompanyLinks.update',\n async prepare(rawInput, ctx) {\n const parsed = personCompanyLinkUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadPersonCompanyLinkSnapshot(em, parsed.linkId, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = personCompanyLinkUpdateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n {\n id: parsed.linkId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n deletedAt: null,\n },\n undefined,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n if (!link) {\n throw notFound('Company link not found')\n }\n\n const personId = typeof link.person === 'string' ? link.person : link.person.id\n const companyId = typeof link.company === 'string' ? link.company : link.company.id\n const person = await requirePersonEntity(em, personId, parsed.tenantId, parsed.organizationId)\n const profile = await requirePersonProfile(em, person)\n const linkedCompany = await requireCompanyEntity(em, companyId, parsed.tenantId, parsed.organizationId)\n\n const linkWasPrimary = link.isPrimary\n await withAtomicFlush(em, [\n async () => {\n if (parsed.isPrimary) {\n await clearPrimaryFlagsForPerson(em, person)\n link.isPrimary = true\n profile.company = linkedCompany\n } else if (!parsed.isPrimary) {\n link.isPrimary = false\n if (!linkWasPrimary && profile.company && typeof profile.company !== 'string' && profile.company.id === companyId) {\n profile.company = null\n }\n }\n },\n async () => {\n if (!parsed.isPrimary && linkWasPrimary) {\n const remainingLinks = (await loadPersonCompanyLinks(em, person)).filter((entry) => entry.id !== link.id)\n await promoteFallbackPrimaryLink(em, person, profile, remainingLinks, companyId)\n }\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: link,\n identifiers: getLinkIdentifiers(link),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n\n return { linkId: link.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = ctx.container.resolve('em') as EntityManager\n return loadPersonCompanyLinkSnapshot(em, result.linkId, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as PersonCompanyLinkSnapshot | undefined\n const after = snapshots.after as PersonCompanyLinkSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.personCompanyLinks.update', 'Update company link'),\n resourceKind: 'customers.personCompanyLink',\n resourceId: result.linkId,\n parentResourceKind: 'customers.person',\n parentResourceId: after?.personEntityId ?? before?.personEntityId ?? null,\n tenantId: after?.tenantId ?? before?.tenantId ?? null,\n organizationId: after?.organizationId ?? before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: {\n before: before ?? null,\n after: after ?? null,\n } satisfies PersonCompanyLinkUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PersonCompanyLinkUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n { id: before.id },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!link) return\n\n let person: CustomerEntity | null = null\n let profile: CustomerPersonProfile | null = null\n let company: CustomerEntity | null = null\n\n await withAtomicFlush(em, [\n async () => {\n person = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: before.personEntityId, kind: 'person', tenantId: before.tenantId, organizationId: before.organizationId, deletedAt: null },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!person) return\n profile = await findOneWithDecryption(\n em,\n CustomerPersonProfile,\n { entity: person },\n { populate: ['company'] },\n { tenantId: person.tenantId, organizationId: person.organizationId },\n )\n if (!profile || !before.isPrimary) return\n company = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: before.companyEntityId, kind: 'company', tenantId: before.tenantId, organizationId: before.organizationId, deletedAt: null },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n },\n async () => {\n if (!person || !profile) return\n if (before.isPrimary) {\n await clearPrimaryFlagsForPerson(em, person)\n link.isPrimary = true\n if (company) profile.company = company\n } else {\n link.isPrimary = false\n }\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'updated',\n entity: link,\n identifiers: getLinkIdentifiers(link),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n },\n}\n\n/**\n * Detach a legacy profile-only company assignment: `customer_person_profiles.company_id`\n * points at the company but no `customer_person_company_links` row was ever created, so\n * there is no link row for the id-based branch to soft-delete (#5114). Running it as part\n * of the same command keeps the audit entry, the undo token and the CRUD cache\n * invalidation identical to a link-backed detach.\n */\nasync function detachProfileOnlyCompany(\n em: EntityManager,\n ctx: CommandRuntimeContext,\n parsed: PersonCompanyLinkDeleteInput,\n target: { personEntityId: string; companyEntityId: string },\n): Promise<PersonCompanyLinkDeleteResult> {\n const person = await requirePersonEntity(em, target.personEntityId, parsed.tenantId, parsed.organizationId)\n const profile = await requirePersonProfile(em, person)\n const assignedCompany = profile.company\n const assignedCompanyId = typeof assignedCompany === 'string' ? assignedCompany : assignedCompany?.id ?? null\n if (assignedCompanyId !== target.companyEntityId) {\n throw notFound('Company link not found')\n }\n\n await withAtomicFlush(em, [\n () => removePersonCompanyLink(em, person, profile, target.companyEntityId),\n ], { transaction: true })\n\n // There is no link entity to hand to `emitCrudSideEffects`; what changed is the\n // person's own company assignment, so reindex the person and its profile instead.\n await emitQueryIndexUpsertEvents(ctx, personQueryIndexEntries(person, profile))\n await emitProfileOnlyDetachedEvent(ctx, person, target.companyEntityId)\n\n return { linkId: null, personEntityId: person.id, companyEntityId: target.companyEntityId }\n}\n\n/**\n * Live-refresh signal for the company People tab and the person Companies tab, which the\n * link-backed branch gets from `customers.person_company_link.deleted` via `emitCrudSideEffects`.\n * The profile-only branch has no link row to emit that for, so it publishes the sibling\n * `clientBroadcast` event instead (#5114). `tenantId` must travel in the payload: the event bus\n * only forwards a broadcast event cross-process when the payload carries a tenant scope. The\n * write is already committed, so a failed refresh signal must never fail the detach.\n */\nasync function emitProfileOnlyDetachedEvent(\n ctx: CommandRuntimeContext,\n person: CustomerEntity,\n companyEntityId: string,\n): Promise<void> {\n try {\n const bus = ctx.container.resolve<EventBus>('eventBus')\n await bus.emitEvent(\n PROFILE_ONLY_DETACHED_EVENT,\n {\n linkId: null,\n personEntityId: person.id,\n companyEntityId,\n tenantId: person.tenantId,\n organizationId: person.organizationId,\n },\n { tenantId: person.tenantId, organizationId: person.organizationId },\n )\n } catch (err) {\n logger.warn('Profile-only company detach broadcast failed', {\n command: 'customers.personCompanyLinks.delete',\n personEntityId: person.id,\n companyEntityId,\n err,\n })\n }\n}\n\n/**\n * Undo counterpart of `detachProfileOnlyCompany`: re-point the person's legacy\n * `profile.company` at the company it was detached from. The lookups run in the first\n * flush phase and the assignment in the second so the encryption subscriber's\n * re-baseline on find cannot drop the pending change (#2507).\n */\nasync function restoreProfileOnlyCompany(\n ctx: CommandRuntimeContext,\n before: PersonCompanyProfileAssignmentSnapshot,\n): Promise<void> {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let person: CustomerEntity | null = null\n let profile: CustomerPersonProfile | null = null\n let company: CustomerEntity | null = null\n\n await withAtomicFlush(em, [\n async () => {\n person = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: before.personEntityId, kind: 'person', tenantId: before.tenantId, organizationId: before.organizationId, deletedAt: null },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!person) return\n profile = await findOneWithDecryption(\n em,\n CustomerPersonProfile,\n { entity: person },\n { populate: ['company'] },\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!profile) return\n company = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: before.companyEntityId, kind: 'company', tenantId: before.tenantId, organizationId: before.organizationId, deletedAt: null },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n },\n () => {\n if (profile && company) profile.company = company\n },\n ], { transaction: true })\n\n if (person && profile) {\n await emitQueryIndexUpsertEvents(ctx, personQueryIndexEntries(person, profile))\n }\n}\n\nconst deletePersonCompanyLinkCommand: CommandHandler<PersonCompanyLinkDeleteInput, PersonCompanyLinkDeleteResult> = {\n id: 'customers.personCompanyLinks.delete',\n async prepare(rawInput, ctx) {\n const parsed = personCompanyLinkDeleteSchema.parse(rawInput)\n const profileOnlyTarget = resolveProfileOnlyTarget(parsed)\n if (profileOnlyTarget) {\n return {\n before: {\n kind: 'profile-only',\n personEntityId: profileOnlyTarget.personEntityId,\n companyEntityId: profileOnlyTarget.companyEntityId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n } satisfies PersonCompanyProfileAssignmentSnapshot,\n }\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadPersonCompanyLinkSnapshot(em, parsed.linkId as string, {\n tenantId: ctx.auth?.tenantId ?? null,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,\n })\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = personCompanyLinkDeleteSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const profileOnlyTarget = resolveProfileOnlyTarget(parsed)\n if (profileOnlyTarget) {\n return await detachProfileOnlyCompany(em, ctx, parsed, profileOnlyTarget)\n }\n\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n {\n id: parsed.linkId as string,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n deletedAt: null,\n },\n undefined,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n if (!link) {\n throw notFound('Company link not found')\n }\n\n const personId = typeof link.person === 'string' ? link.person : link.person.id\n const companyId = typeof link.company === 'string' ? link.company : link.company.id\n const person = await requirePersonEntity(em, personId, parsed.tenantId, parsed.organizationId)\n const profile = await requirePersonProfile(em, person)\n const linkWasPrimary = link.isPrimary\n\n const existingLinks = await loadPersonCompanyLinks(em, person)\n const remainingLinks = existingLinks.filter((entry) => entry.id !== link.id)\n\n await withAtomicFlush(em, [\n () => {\n link.isPrimary = false\n link.deletedAt = new Date()\n },\n async () => {\n if (linkWasPrimary) {\n await promoteFallbackPrimaryLink(em, person, profile, remainingLinks, companyId)\n } else if (profile.company && typeof profile.company !== 'string' && profile.company.id === companyId) {\n const primary = remainingLinks.find((entry) => entry.isPrimary) ?? null\n const primaryCompany = primary && typeof primary.company !== 'string' ? primary.company : null\n if (primaryCompany) {\n profile.company = primaryCompany\n }\n }\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: link,\n identifiers: getLinkIdentifiers(link),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n\n return { linkId: link.id, personEntityId: personId, companyEntityId: companyId }\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as PersonCompanyLinkDeleteSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.personCompanyLinks.delete', 'Remove company link'),\n // Kept as `customers.personCompanyLink` for the profile-only shape too: the company\n // detail cache tags this resource kind, so both detach shapes must invalidate it.\n resourceKind: 'customers.personCompanyLink',\n resourceId: result.linkId,\n parentResourceKind: 'customers.person',\n parentResourceId: before?.personEntityId ?? null,\n tenantId: before?.tenantId ?? null,\n organizationId: before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n payload: {\n undo: {\n before: before ?? null,\n } satisfies PersonCompanyLinkDeleteUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PersonCompanyLinkDeleteUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n\n if (isProfileAssignmentSnapshot(before)) {\n await restoreProfileOnlyCompany(ctx, before)\n return\n }\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n { id: before.id },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!link) return\n\n let person: CustomerEntity | null = null\n let profile: CustomerPersonProfile | null = null\n let company: CustomerEntity | null = null\n\n await withAtomicFlush(em, [\n async () => {\n person = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: before.personEntityId, kind: 'person', tenantId: before.tenantId, organizationId: before.organizationId, deletedAt: null },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!person || !before.isPrimary) return\n profile = await findOneWithDecryption(\n em,\n CustomerPersonProfile,\n { entity: person },\n { populate: ['company'] },\n { tenantId: person.tenantId, organizationId: person.organizationId },\n )\n if (!profile) return\n company = await findOneWithDecryption(\n em,\n CustomerEntity,\n { id: before.companyEntityId, kind: 'company', tenantId: before.tenantId, organizationId: before.organizationId, deletedAt: null },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n },\n async () => {\n link.deletedAt = null\n link.isPrimary = before.isPrimary\n if (person && before.isPrimary) {\n await clearPrimaryFlagsForPerson(em, person)\n link.isPrimary = true\n if (profile && company) profile.company = company\n }\n },\n ], { transaction: true })\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'created',\n entity: link,\n identifiers: getLinkIdentifiers(link),\n syncOrigin: ctx.syncOrigin,\n events: personCompanyLinkCrudEvents,\n indexer: { entityType: 'customers:customer_person_company_link' },\n })\n },\n}\n\nregisterCommand(createPersonCompanyLinkCommand)\nregisterCommand(updatePersonCompanyLinkCommand)\nregisterCommand(deletePersonCompanyLinkCommand)\n"],
5
+ "mappings": "AAAA,SAAS,uBAAuB;AAGhC,SAAS,qBAAqB,+BAA+B;AAC7D,SAAS,eAAe,gBAAgB;AACxC,SAAS,2BAA2B;AACpC,SAAS,6BAA6B;AAGtC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAEP,SAAS,SAAS;AAElB,SAAS,uBAAuB;AAChC,SAAS,2BAA2B;AACpC,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,WAAW,EAAE,MAAM,EAAE,WAAW,qBAAqB,CAAC;AAIlF,MAAM,8BAAgD;AAyDtD,SAAS,4BACP,UACoD;AACpD,SAAO,QAAQ,QAAQ,KAAM,SAAoD,SAAS;AAC5F;AAEA,SAAS,yBACP,QAC4D;AAC5D,MAAI,OAAO,OAAQ,QAAO;AAC1B,MAAI,CAAC,OAAO,kBAAkB,CAAC,OAAO,gBAAiB,QAAO;AAC9D,SAAO,EAAE,gBAAgB,OAAO,gBAAgB,iBAAiB,OAAO,gBAAgB;AAC1F;AAEA,SAAS,wBACP,QACA,SACwB;AACxB,SAAO;AAAA,IACL;AAAA,MACE,YAAY,EAAE,UAAU;AAAA,MACxB,UAAU,OAAO;AAAA,MACjB,UAAU,OAAO;AAAA,MACjB,gBAAgB,OAAO;AAAA,IACzB;AAAA,IACA;AAAA,MACE,YAAY,EAAE,UAAU;AAAA,MACxB,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,MAClB,gBAAgB,QAAQ;AAAA,IAC1B;AAAA,EACF;AACF;AAEA,MAAM,8BAAgD;AAAA,EACpD,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,cAAc,CAAC,SAAS;AAAA,IACtB,IAAI,IAAI,YAAY;AAAA,IACpB,gBAAgB,IAAI,YAAY;AAAA,IAChC,UAAU,IAAI,YAAY;AAAA,IAC1B,GAAI,IAAI,UAAU,OAAO,IAAI,WAAW,YAAY,YAAa,IAAI,SACjE;AAAA,MACE,gBACE,OAAQ,IAAI,OAAqC,WAAW,WACvD,IAAI,OAAe,SACnB,IAAI,OAAqC,QAAQ,MAAM;AAAA,MAC9D,iBACE,OAAQ,IAAI,OAAqC,YAAY,WACxD,IAAI,OAAe,UACnB,IAAI,OAAqC,SAAS,MAAM;AAAA,IACjE,IACA,CAAC;AAAA,IACL,GAAI,IAAI,aAAa,EAAE,YAAY,IAAI,WAAW,IAAI,CAAC;AAAA,EACzD;AACF;AAEA,SAAS,mBAAmB,MAAiC;AAC3D,SAAO;AAAA,IACL,IAAI,KAAK;AAAA,IACT,gBAAgB,KAAK;AAAA,IACrB,UAAU,KAAK;AAAA,EACjB;AACF;AAEA,eAAe,8BACb,IACA,IACA,OAC2C;AAC3C,QAAM,SAAkC,EAAE,GAAG;AAC7C,MAAI,OAAO,SAAU,QAAO,WAAW,MAAM;AAC7C,MAAI,OAAO,eAAgB,QAAO,iBAAiB,MAAM;AACzD,QAAM,OAAO,MAAM;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,MACE,UAAU,OAAO,YAAY;AAAA,MAC7B,gBAAgB,OAAO,kBAAkB;AAAA,IAC3C;AAAA,EACF;AACA,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,0BAA0B,IAAI;AACvC;AAEA,SAAS,0BAA0B,MAA4D;AAC7F,QAAM,WAAW,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS,KAAK,OAAO;AAC7E,QAAM,YAAY,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,KAAK,QAAQ;AACjF,SAAO;AAAA,IACL,IAAI,KAAK;AAAA,IACT,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,WAAW,QAAQ,KAAK,SAAS;AAAA,IACjC,UAAU,KAAK;AAAA,IACf,gBAAgB,KAAK;AAAA,IACrB,WAAW,KAAK,YAAY,KAAK,UAAU,YAAY,IAAI;AAAA,EAC7D;AACF;AAEA,eAAe,oBACb,IACA,UACA,UACA,gBACyB;AACzB,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IACA;AAAA,IACA,EAAE,IAAI,UAAU,MAAM,UAAU,UAAU,gBAAgB,WAAW,KAAK;AAAA,IAC1E;AAAA,IACA,EAAE,UAAU,eAAe;AAAA,EAC7B;AACA,MAAI,CAAC,QAAQ;AACX,UAAM,SAAS,kBAAkB;AAAA,EACnC;AACA,SAAO;AACT;AAEA,eAAe,qBACb,IACA,UACA,UACA,gBACyB;AACzB,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,IACA;AAAA,IACA,EAAE,IAAI,UAAU,MAAM,WAAW,UAAU,gBAAgB,WAAW,KAAK;AAAA,IAC3E;AAAA,IACA,EAAE,UAAU,eAAe;AAAA,EAC7B;AACA,MAAI,CAAC,SAAS;AACZ,UAAM,SAAS,mBAAmB;AAAA,EACpC;AACA,SAAO;AACT;AAEA,eAAe,qBACb,IACA,QACgC;AAChC,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,IACA;AAAA,IACA,EAAE,QAAQ,OAAO;AAAA,IACjB,EAAE,UAAU,CAAC,SAAS,EAAE;AAAA,IACxB,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,EACrE;AACA,MAAI,CAAC,SAAS;AACZ,UAAM,SAAS,0BAA0B;AAAA,EAC3C;AACA,SAAO;AACT;AAEA,eAAe,2BAA2B,IAAmB,QAAuC;AAClG,QAAM,GAAG;AAAA,IACP;AAAA,IACA,EAAE,QAAQ,gBAAgB,OAAO,gBAAgB,UAAU,OAAO,UAAU,WAAW,KAAK;AAAA,IAC5F,EAAE,WAAW,MAAM;AAAA,EACrB;AACF;AAEA,eAAe,+BACb,KACA,OACA,QACe;AACf,QAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,QAAM,QAAQ,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAC/E,QAAM,OAAO,MAAM;AAAA,IACjB;AAAA,IACA;AAAA,IACA,EAAE,IAAI,MAAM,IAAI,GAAG,MAAM;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AACA,MAAI,CAAC,KAAM;AACX,QAAM,SAAS,MAAM,oBAAoB,IAAI,MAAM,gBAAgB,MAAM,UAAU,MAAM,cAAc;AACvG,QAAM,UAAU,MAAM,qBAAqB,IAAI,MAAM;AACrD,QAAM,mBAAmB,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,QAAQ,SAAS,MAAM;AACxG,QAAM,2BAA2B,MAAM,aAAa,KAAK,aAAa,qBAAqB,MAAM;AACjG,QAAM,UAAU,4BAA4B,OAAO,mBAC/C,MAAM,qBAAqB,IAAI,OAAO,kBAAkB,MAAM,UAAU,MAAM,cAAc,IAC5F;AACJ,QAAM,iBAAiB,OAAO,eAAe,OAAO,CAAC,OAAO,OAAO,KAAK,EAAE;AAE1E,QAAM,gBAAgB,IAAI;AAAA,IACxB,YAAY;AACV,UAAI,0BAA0B;AAC5B,cAAM,GAAG;AAAA,UACP;AAAA,UACA,EAAE,QAAQ,GAAG,OAAO,IAAI,EAAE,KAAK,KAAK,GAAG,GAAG,WAAW,MAAM,WAAW,KAAK;AAAA,UAC3E,EAAE,WAAW,MAAM;AAAA,QACrB;AACA,YAAI,eAAe,QAAQ;AACzB,gBAAM,GAAG;AAAA,YACP;AAAA,YACA,EAAE,QAAQ,GAAG,OAAO,IAAI,EAAE,KAAK,eAAe,GAAG,WAAW,KAAK;AAAA,YACjE,EAAE,WAAW,KAAK;AAAA,UACpB;AAAA,QACF;AACA,gBAAQ,UAAU;AAAA,MACpB;AACA,WAAK,YAAY,OAAO,MAAM,aAAa;AAC3C,WAAK,YAAY,OAAO,OACpB,OAAO,KAAK,YAAY,IAAI,KAAK,OAAO,KAAK,SAAS,IAAI,OAC1D,oBAAI,KAAK;AAAA,IACf;AAAA,EACF,GAAG,EAAE,aAAa,KAAK,CAAC;AAExB,QAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,QAAM,wBAAwB;AAAA,IAC5B;AAAA,IACA,QAAQ,KAAK,YAAY,YAAY;AAAA,IACrC,QAAQ;AAAA,IACR,aAAa,mBAAmB,IAAI;AAAA,IACpC,YAAY,IAAI;AAAA,IAChB,QAAQ;AAAA,IACR,SAAS,EAAE,YAAY,yCAAyC;AAAA,EAClE,CAAC;AACH;AAEA,MAAM,iCAA8G;AAAA,EAClH,IAAI;AAAA,EACJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,8BAA8B,MAAM,QAAQ;AAC3D,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAClD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,SAAS,MAAM,oBAAoB,IAAI,OAAO,gBAAgB,OAAO,UAAU,OAAO,cAAc;AAC1G,UAAM,UAAU,MAAM,qBAAqB,IAAI,OAAO,iBAAiB,OAAO,UAAU,OAAO,cAAc;AAC7G,UAAM,UAAU,MAAM,qBAAqB,IAAI,MAAM;AACrD,UAAM,QAAQ,MAAM,uBAAuB,IAAI,MAAM;AACrD,UAAM,OAAO,MAAM;AAAA,MAAK,CAAC,WACtB,OAAO,MAAM,YAAY,WAAW,MAAM,UAAU,MAAM,QAAQ,QAAQ,QAAQ;AAAA,IACrF,KAAK,MAAM,6BAA6B,IAAI,QAAQ,OAAO;AAC3D,WAAO;AAAA,MACL,QAAQ;AAAA,QACN,MAAM,OAAO,MAAM,8BAA8B,IAAI,KAAK,IAAI,MAAM,IAAI;AAAA,QACxE,gBAAgB,MAAM,OAAO,CAAC,UAAU,MAAM,SAAS,EAAE,IAAI,CAAC,UAAU,MAAM,EAAE;AAAA,QAChF,kBAAkB,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,QAAQ,SAAS,MAAM;AAAA,MACnG;AAAA,IACF;AAAA,EACF;AAAA,EACA,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,8BAA8B,MAAM,QAAQ;AAC3D,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAElD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,SAAS,MAAM,oBAAoB,IAAI,OAAO,gBAAgB,OAAO,UAAU,OAAO,cAAc;AAC1G,UAAM,UAAU,MAAM,qBAAqB,IAAI,OAAO,iBAAiB,OAAO,UAAU,OAAO,cAAc;AAC7G,UAAM,UAAU,MAAM,qBAAqB,IAAI,MAAM;AAErD,UAAM,gBAAgB,MAAM,uBAAuB,IAAI,MAAM;AAC7D,UAAM,cAAc,QAAQ,OAAO,SAAS,KAAK,cAAc,WAAW;AAC1E,UAAM,eACJ,cAAc,KAAK,CAACA,WAAU,OAAOA,MAAK,YAAY,WAAWA,MAAK,UAAUA,MAAK,QAAQ,QAAQ,QAAQ,EAAE,KAAK;AAGtH,UAAM,eAA8C;AAAA,MAClD,MAAM,eAAe,0BAA0B,YAAY,IAAI;AAAA,MAC/D,gBAAgB,cAAc,OAAO,CAACA,UAASA,MAAK,SAAS,EAAE,IAAI,CAACA,UAASA,MAAK,EAAE;AAAA,MACpF,kBAAkB,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,QAAQ,SAAS,MAAM;AAAA,IACnG;AAEA,QAAI,cAAc;AAChB,YAAM,UAAU,eAAe,CAAC,aAAa;AAC7C,UAAI,SAAS;AACX,cAAM,gBAAgB,IAAI;AAAA,UACxB,MAAM,2BAA2B,IAAI,MAAM;AAAA,UAC3C,MAAM;AACJ,yBAAa,YAAY;AACzB,oBAAQ,UAAU;AAAA,UACpB;AAAA,QACF,GAAG,EAAE,aAAa,KAAK,CAAC;AAAA,MAC1B;AACA,aAAO,EAAE,QAAQ,aAAa,IAAI,SAAS,OAAO,WAAW,OAAO,SAAS,aAAa;AAAA,IAC5F;AAEA,QAAI;AACJ,QAAI,YAAY;AAChB,UAAM,gBAAgB,IAAI;AAAA,MACxB,YAAY;AACV,cAAM,cAAc,MAAM,6BAA6B,IAAI,QAAQ,OAAO;AAC1E,YAAI,YAAa,cAAa,OAAO,0BAA0B,WAAW;AAC1E,YAAI,aAAa;AACf,gBAAM,2BAA2B,IAAI,MAAM;AAAA,QAC7C;AACA,YAAI,aAAa;AACf,sBAAY,YAAY;AACxB,sBAAY,YAAY;AACxB,aAAG,QAAQ,WAAW;AACtB,iBAAO;AACP,sBAAY;AAAA,QACd,OAAO;AACL,iBAAO,GAAG,OAAO,2BAA2B;AAAA,YAC1C,gBAAgB,OAAO;AAAA,YACvB,UAAU,OAAO;AAAA,YACjB;AAAA,YACA;AAAA,YACA,WAAW;AAAA,UACb,CAAC;AACD,aAAG,QAAQ,IAAI;AAAA,QACjB;AAAA,MACF;AAAA,MACA,MAAM;AACJ,YAAI,aAAa;AACf,kBAAQ,UAAU;AAAA,QACpB,WAAW,CAAC,QAAQ,WAAW,cAAc,WAAW,GAAG;AACzD,kBAAQ,UAAU;AAClB,eAAK,YAAY;AAAA,QACnB;AAAA,MACF;AAAA,IACF,GAAG,EAAE,aAAa,KAAK,CAAC;AAExB,UAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,UAAM,oBAAoB;AAAA,MACxB;AAAA,MACA,QAAQ,YAAY,YAAY;AAAA,MAChC,QAAQ;AAAA,MACR,aAAa,mBAAmB,IAAI;AAAA,MACpC,YAAY,IAAI;AAAA,MAChB,QAAQ;AAAA,MACR,SAAS,EAAE,YAAY,yCAAyC;AAAA,IAClE,CAAC;AAED,WAAO,EAAE,QAAQ,KAAK,IAAI,SAAS,CAAC,WAAW,WAAW,SAAS,MAAM,aAAa;AAAA,EACxF;AAAA,EACA,cAAc,OAAO,QAAQ,QAAQ,QAAQ;AAC3C,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,WAAO,8BAA8B,IAAI,OAAO,QAAQ;AAAA,MACtD,UAAU,IAAI,MAAM,YAAY;AAAA,MAChC,gBAAgB,IAAI,0BAA0B,IAAI,MAAM,SAAS;AAAA,IACnE,CAAC;AAAA,EACH;AAAA,EACA,UAAU,OAAO,EAAE,QAAQ,UAAU,MAAM;AACzC,UAAM,SAAS,OAAO;AACtB,UAAM,QAAQ,UAAU;AACxB,QAAI,CAAC,OAAO,SAAS;AACnB,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AACA,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,WAAO;AAAA,MACL,aAAa,UAAU,6CAA6C,wBAAwB;AAAA,MAC5F,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,oBAAoB;AAAA,MACpB,kBAAkB,OAAO,kBAAkB;AAAA,MAC3C,UAAU,OAAO,YAAY;AAAA,MAC7B,gBAAgB,OAAO,kBAAkB;AAAA,MACzC,gBAAgB,QAAQ,QAAQ;AAAA,MAChC,eAAe,SAAS;AAAA,MACxB,SAAS;AAAA,QACP,MAAM;AAAA,UACJ,OAAO,SAAS;AAAA,UAChB,GAAI,SAAS,EAAE,cAAc,OAAO,IAAI,CAAC;AAAA,UACzC,GAAI,OAAO,YAAY,EAAE,QAAQ,KAAK,IAAI,CAAC;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,UAAU,mBAAiD,QAAQ;AACzE,UAAM,QAAQ,SAAS;AACvB,QAAI,CAAC,MAAO;AAEZ,QAAI,QAAQ,cAAc;AACxB,YAAM,+BAA+B,KAAK,OAAO,QAAQ,YAAY;AACrE;AAAA,IACF;AAEA,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,MACA,EAAE,IAAI,MAAM,GAAG;AAAA,MACf;AAAA,MACA,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAAA,IACnE;AACA,QAAI,CAAC,KAAM;AAEX,QAAI,SAAgC;AACpC,QAAI,UAAwC;AAC5C,QAAI,iBAA8C,CAAC;AAEnD,UAAM,gBAAgB,IAAI;AAAA,MACxB,YAAY;AACV,iBAAS,MAAM;AAAA,UACb;AAAA,UACA;AAAA,UACA,EAAE,IAAI,MAAM,gBAAgB,MAAM,UAAU,UAAU,MAAM,UAAU,gBAAgB,MAAM,gBAAgB,WAAW,KAAK;AAAA,UAC5H;AAAA,UACA,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAAA,QACnE;AACA,YAAI,CAAC,OAAQ;AACb,kBAAU,MAAM;AAAA,UACd;AAAA,UACA;AAAA,UACA,EAAE,QAAQ,OAAO;AAAA,UACjB,EAAE,UAAU,CAAC,SAAS,EAAE;AAAA,UACxB,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,QACrE;AACA,YAAI,CAAC,QAAS;AACd,0BAAkB,MAAM,uBAAuB,IAAI,MAAM,GAAG,OAAO,CAAC,UAAU,MAAM,OAAO,KAAK,EAAE;AAAA,MACpG;AAAA,MACA,YAAY;AACV,aAAK,YAAY;AACjB,aAAK,YAAY,oBAAI,KAAK;AAC1B,YAAI,CAAC,UAAU,CAAC,QAAS;AACzB,YAAI,MAAM,WAAW;AACnB,gBAAM,2BAA2B,IAAI,QAAQ,SAAS,gBAAgB,MAAM,eAAe;AAAA,QAC7F,WAAW,QAAQ,WAAW,OAAO,QAAQ,YAAY,YAAY,QAAQ,QAAQ,OAAO,MAAM,iBAAiB;AACjH,kBAAQ,UAAU;AAAA,QACpB;AAAA,MACF;AAAA,IACF,GAAG,EAAE,aAAa,KAAK,CAAC;AAExB,UAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,UAAM,wBAAwB;AAAA,MAC5B;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa,mBAAmB,IAAI;AAAA,MACpC,YAAY,IAAI;AAAA,MAChB,QAAQ;AAAA,MACR,SAAS,EAAE,YAAY,yCAAyC;AAAA,IAClE,CAAC;AAAA,EACH;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,QAAQ,oBAA+C,QAAQ;AACrE,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,cAAc,KAAK,EAAE,OAAO,sEAAsE,CAAC;AAAA,IAC/G;AACA,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,SAAS,MAAM,oBAAoB,IAAI,MAAM,gBAAgB,MAAM,UAAU,MAAM,cAAc;AACvG,UAAM,UAAU,MAAM,qBAAqB,IAAI,MAAM,iBAAiB,MAAM,UAAU,MAAM,cAAc;AAC1G,UAAM,UAAU,MAAM,qBAAqB,IAAI,MAAM;AAErD,QAAI,OAAO,MAAM;AAAA,MACf;AAAA,MACA;AAAA,MACA,EAAE,IAAI,MAAM,GAAG;AAAA,MACf;AAAA,MACA,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAAA,IACnE;AACA,UAAM,gBAAgB,MAAM,uBAAuB,IAAI,MAAM;AAC7D,UAAM,eAA8C;AAAA,MAClD,MAAM,OAAO,0BAA0B,IAAI,IAAI;AAAA,MAC/C,gBAAgB,cAAc,OAAO,CAAC,UAAU,MAAM,SAAS,EAAE,IAAI,CAAC,UAAU,MAAM,EAAE;AAAA,MACxF,kBAAkB,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,QAAQ,SAAS,MAAM;AAAA,IACnG;AAEA,UAAM,gBAAgB,IAAI;AAAA,MACxB,YAAY;AACV,YAAI,MAAM,WAAW;AACnB,gBAAM,2BAA2B,IAAI,MAAM;AAAA,QAC7C;AACA,YAAI,CAAC,MAAM;AACT,iBAAO,GAAG,OAAO,2BAA2B;AAAA,YAC1C,IAAI,MAAM;AAAA,YACV,gBAAgB,MAAM;AAAA,YACtB,UAAU,MAAM;AAAA,YAChB;AAAA,YACA;AAAA,YACA,WAAW,MAAM;AAAA,UACnB,CAAC;AACD,aAAG,QAAQ,IAAI;AAAA,QACjB,OAAO;AACL,eAAK,YAAY;AACjB,eAAK,YAAY,MAAM;AACvB,aAAG,QAAQ,IAAI;AAAA,QACjB;AAAA,MACF;AAAA,MACA,MAAM;AACJ,YAAI,MAAM,WAAW;AACnB,kBAAQ,UAAU;AAAA,QACpB;AAAA,MACF;AAAA,IACF,GAAG,EAAE,aAAa,KAAK,CAAC;AAExB,UAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,UAAM,oBAAoB;AAAA,MACxB;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa,mBAAmB,IAAK;AAAA,MACrC,YAAY,IAAI;AAAA,MAChB,QAAQ;AAAA,MACR,SAAS,EAAE,YAAY,yCAAyC;AAAA,IAClE,CAAC;AAED,WAAO,EAAE,QAAQ,KAAM,IAAI,SAAS,MAAM,WAAW,OAAO,SAAS,MAAM,aAAa;AAAA,EAC1F;AACF;AAEA,MAAM,iCAAmG;AAAA,EACvG,IAAI;AAAA,EACJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,8BAA8B,MAAM,QAAQ;AAC3D,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,WAAW,MAAM,8BAA8B,IAAI,OAAO,QAAQ;AAAA,MACtE,UAAU,IAAI,MAAM,YAAY;AAAA,MAChC,gBAAgB,IAAI,0BAA0B,IAAI,MAAM,SAAS;AAAA,IACnE,CAAC;AACD,WAAO,WAAW,EAAE,QAAQ,SAAS,IAAI,CAAC;AAAA,EAC5C;AAAA,EACA,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,8BAA8B,MAAM,QAAQ;AAC3D,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAElD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,QACE,IAAI,OAAO;AAAA,QACX,UAAU,OAAO;AAAA,QACjB,gBAAgB,OAAO;AAAA,QACvB,WAAW;AAAA,MACb;AAAA,MACA;AAAA,MACA,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,IACrE;AACA,QAAI,CAAC,MAAM;AACT,YAAM,SAAS,wBAAwB;AAAA,IACzC;AAEA,UAAM,WAAW,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS,KAAK,OAAO;AAC7E,UAAM,YAAY,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,KAAK,QAAQ;AACjF,UAAM,SAAS,MAAM,oBAAoB,IAAI,UAAU,OAAO,UAAU,OAAO,cAAc;AAC7F,UAAM,UAAU,MAAM,qBAAqB,IAAI,MAAM;AACrD,UAAM,gBAAgB,MAAM,qBAAqB,IAAI,WAAW,OAAO,UAAU,OAAO,cAAc;AAEtG,UAAM,iBAAiB,KAAK;AAC5B,UAAM,gBAAgB,IAAI;AAAA,MACxB,YAAY;AACV,YAAI,OAAO,WAAW;AACpB,gBAAM,2BAA2B,IAAI,MAAM;AAC3C,eAAK,YAAY;AACjB,kBAAQ,UAAU;AAAA,QACpB,WAAW,CAAC,OAAO,WAAW;AAC5B,eAAK,YAAY;AACjB,cAAI,CAAC,kBAAkB,QAAQ,WAAW,OAAO,QAAQ,YAAY,YAAY,QAAQ,QAAQ,OAAO,WAAW;AACjH,oBAAQ,UAAU;AAAA,UACpB;AAAA,QACF;AAAA,MACF;AAAA,MACA,YAAY;AACV,YAAI,CAAC,OAAO,aAAa,gBAAgB;AACvC,gBAAM,kBAAkB,MAAM,uBAAuB,IAAI,MAAM,GAAG,OAAO,CAAC,UAAU,MAAM,OAAO,KAAK,EAAE;AACxG,gBAAM,2BAA2B,IAAI,QAAQ,SAAS,gBAAgB,SAAS;AAAA,QACjF;AAAA,MACF;AAAA,IACF,GAAG,EAAE,aAAa,KAAK,CAAC;AAExB,UAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,UAAM,oBAAoB;AAAA,MACxB;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa,mBAAmB,IAAI;AAAA,MACpC,YAAY,IAAI;AAAA,MAChB,QAAQ;AAAA,MACR,SAAS,EAAE,YAAY,yCAAyC;AAAA,IAClE,CAAC;AAED,WAAO,EAAE,QAAQ,KAAK,GAAG;AAAA,EAC3B;AAAA,EACA,cAAc,OAAO,QAAQ,QAAQ,QAAQ;AAC3C,UAAM,KAAK,IAAI,UAAU,QAAQ,IAAI;AACrC,WAAO,8BAA8B,IAAI,OAAO,QAAQ;AAAA,MACtD,UAAU,IAAI,MAAM,YAAY;AAAA,MAChC,gBAAgB,IAAI,0BAA0B,IAAI,MAAM,SAAS;AAAA,IACnE,CAAC;AAAA,EACH;AAAA,EACA,UAAU,OAAO,EAAE,QAAQ,UAAU,MAAM;AACzC,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,UAAM,SAAS,UAAU;AACzB,UAAM,QAAQ,UAAU;AACxB,WAAO;AAAA,MACL,aAAa,UAAU,6CAA6C,qBAAqB;AAAA,MACzF,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,oBAAoB;AAAA,MACpB,kBAAkB,OAAO,kBAAkB,QAAQ,kBAAkB;AAAA,MACrE,UAAU,OAAO,YAAY,QAAQ,YAAY;AAAA,MACjD,gBAAgB,OAAO,kBAAkB,QAAQ,kBAAkB;AAAA,MACnE,gBAAgB,UAAU;AAAA,MAC1B,eAAe,SAAS;AAAA,MACxB,SAAS;AAAA,QACP,MAAM;AAAA,UACJ,QAAQ,UAAU;AAAA,UAClB,OAAO,SAAS;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,UAAU,mBAAiD,QAAQ;AACzE,UAAM,SAAS,SAAS;AACxB,QAAI,CAAC,OAAQ;AAEb,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,MACA,EAAE,IAAI,OAAO,GAAG;AAAA,MAChB;AAAA,MACA,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,IACrE;AACA,QAAI,CAAC,KAAM;AAEX,QAAI,SAAgC;AACpC,QAAI,UAAwC;AAC5C,QAAI,UAAiC;AAErC,UAAM,gBAAgB,IAAI;AAAA,MACxB,YAAY;AACV,iBAAS,MAAM;AAAA,UACb;AAAA,UACA;AAAA,UACA,EAAE,IAAI,OAAO,gBAAgB,MAAM,UAAU,UAAU,OAAO,UAAU,gBAAgB,OAAO,gBAAgB,WAAW,KAAK;AAAA,UAC/H;AAAA,UACA,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,QACrE;AACA,YAAI,CAAC,OAAQ;AACb,kBAAU,MAAM;AAAA,UACd;AAAA,UACA;AAAA,UACA,EAAE,QAAQ,OAAO;AAAA,UACjB,EAAE,UAAU,CAAC,SAAS,EAAE;AAAA,UACxB,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,QACrE;AACA,YAAI,CAAC,WAAW,CAAC,OAAO,UAAW;AACnC,kBAAU,MAAM;AAAA,UACd;AAAA,UACA;AAAA,UACA,EAAE,IAAI,OAAO,iBAAiB,MAAM,WAAW,UAAU,OAAO,UAAU,gBAAgB,OAAO,gBAAgB,WAAW,KAAK;AAAA,UACjI;AAAA,UACA,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,QACrE;AAAA,MACF;AAAA,MACA,YAAY;AACV,YAAI,CAAC,UAAU,CAAC,QAAS;AACzB,YAAI,OAAO,WAAW;AACpB,gBAAM,2BAA2B,IAAI,MAAM;AAC3C,eAAK,YAAY;AACjB,cAAI,QAAS,SAAQ,UAAU;AAAA,QACjC,OAAO;AACL,eAAK,YAAY;AAAA,QACnB;AAAA,MACF;AAAA,IACF,GAAG,EAAE,aAAa,KAAK,CAAC;AAExB,UAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,UAAM,wBAAwB;AAAA,MAC5B;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa,mBAAmB,IAAI;AAAA,MACpC,YAAY,IAAI;AAAA,MAChB,QAAQ;AAAA,MACR,SAAS,EAAE,YAAY,yCAAyC;AAAA,IAClE,CAAC;AAAA,EACH;AACF;AASA,eAAe,yBACb,IACA,KACA,QACA,QACwC;AACxC,QAAM,SAAS,MAAM,oBAAoB,IAAI,OAAO,gBAAgB,OAAO,UAAU,OAAO,cAAc;AAC1G,QAAM,UAAU,MAAM,qBAAqB,IAAI,MAAM;AACrD,QAAM,kBAAkB,QAAQ;AAChC,QAAM,oBAAoB,OAAO,oBAAoB,WAAW,kBAAkB,iBAAiB,MAAM;AACzG,MAAI,sBAAsB,OAAO,iBAAiB;AAChD,UAAM,SAAS,wBAAwB;AAAA,EACzC;AAEA,QAAM,gBAAgB,IAAI;AAAA,IACxB,MAAM,wBAAwB,IAAI,QAAQ,SAAS,OAAO,eAAe;AAAA,EAC3E,GAAG,EAAE,aAAa,KAAK,CAAC;AAIxB,QAAM,2BAA2B,KAAK,wBAAwB,QAAQ,OAAO,CAAC;AAC9E,QAAM,6BAA6B,KAAK,QAAQ,OAAO,eAAe;AAEtE,SAAO,EAAE,QAAQ,MAAM,gBAAgB,OAAO,IAAI,iBAAiB,OAAO,gBAAgB;AAC5F;AAUA,eAAe,6BACb,KACA,QACA,iBACe;AACf,MAAI;AACF,UAAM,MAAM,IAAI,UAAU,QAAkB,UAAU;AACtD,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,QACE,QAAQ;AAAA,QACR,gBAAgB,OAAO;AAAA,QACvB;AAAA,QACA,UAAU,OAAO;AAAA,QACjB,gBAAgB,OAAO;AAAA,MACzB;AAAA,MACA,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,IACrE;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,KAAK,gDAAgD;AAAA,MAC1D,SAAS;AAAA,MACT,gBAAgB,OAAO;AAAA,MACvB;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAQA,eAAe,0BACb,KACA,QACe;AACf,QAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,MAAI,SAAgC;AACpC,MAAI,UAAwC;AAC5C,MAAI,UAAiC;AAErC,QAAM,gBAAgB,IAAI;AAAA,IACxB,YAAY;AACV,eAAS,MAAM;AAAA,QACb;AAAA,QACA;AAAA,QACA,EAAE,IAAI,OAAO,gBAAgB,MAAM,UAAU,UAAU,OAAO,UAAU,gBAAgB,OAAO,gBAAgB,WAAW,KAAK;AAAA,QAC/H;AAAA,QACA,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,MACrE;AACA,UAAI,CAAC,OAAQ;AACb,gBAAU,MAAM;AAAA,QACd;AAAA,QACA;AAAA,QACA,EAAE,QAAQ,OAAO;AAAA,QACjB,EAAE,UAAU,CAAC,SAAS,EAAE;AAAA,QACxB,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,MACrE;AACA,UAAI,CAAC,QAAS;AACd,gBAAU,MAAM;AAAA,QACd;AAAA,QACA;AAAA,QACA,EAAE,IAAI,OAAO,iBAAiB,MAAM,WAAW,UAAU,OAAO,UAAU,gBAAgB,OAAO,gBAAgB,WAAW,KAAK;AAAA,QACjI;AAAA,QACA,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,MACrE;AAAA,IACF;AAAA,IACA,MAAM;AACJ,UAAI,WAAW,QAAS,SAAQ,UAAU;AAAA,IAC5C;AAAA,EACF,GAAG,EAAE,aAAa,KAAK,CAAC;AAExB,MAAI,UAAU,SAAS;AACrB,UAAM,2BAA2B,KAAK,wBAAwB,QAAQ,OAAO,CAAC;AAAA,EAChF;AACF;AAEA,MAAM,iCAA8G;AAAA,EAClH,IAAI;AAAA,EACJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,8BAA8B,MAAM,QAAQ;AAC3D,UAAM,oBAAoB,yBAAyB,MAAM;AACzD,QAAI,mBAAmB;AACrB,aAAO;AAAA,QACL,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,gBAAgB,kBAAkB;AAAA,UAClC,iBAAiB,kBAAkB;AAAA,UACnC,UAAU,OAAO;AAAA,UACjB,gBAAgB,OAAO;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AACA,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,WAAW,MAAM,8BAA8B,IAAI,OAAO,QAAkB;AAAA,MAChF,UAAU,IAAI,MAAM,YAAY;AAAA,MAChC,gBAAgB,IAAI,0BAA0B,IAAI,MAAM,SAAS;AAAA,IACnE,CAAC;AACD,WAAO,WAAW,EAAE,QAAQ,SAAS,IAAI,CAAC;AAAA,EAC5C;AAAA,EACA,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,8BAA8B,MAAM,QAAQ;AAC3D,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAElD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,oBAAoB,yBAAyB,MAAM;AACzD,QAAI,mBAAmB;AACrB,aAAO,MAAM,yBAAyB,IAAI,KAAK,QAAQ,iBAAiB;AAAA,IAC1E;AAEA,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,QACE,IAAI,OAAO;AAAA,QACX,UAAU,OAAO;AAAA,QACjB,gBAAgB,OAAO;AAAA,QACvB,WAAW;AAAA,MACb;AAAA,MACA;AAAA,MACA,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,IACrE;AACA,QAAI,CAAC,MAAM;AACT,YAAM,SAAS,wBAAwB;AAAA,IACzC;AAEA,UAAM,WAAW,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS,KAAK,OAAO;AAC7E,UAAM,YAAY,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,KAAK,QAAQ;AACjF,UAAM,SAAS,MAAM,oBAAoB,IAAI,UAAU,OAAO,UAAU,OAAO,cAAc;AAC7F,UAAM,UAAU,MAAM,qBAAqB,IAAI,MAAM;AACrD,UAAM,iBAAiB,KAAK;AAE5B,UAAM,gBAAgB,MAAM,uBAAuB,IAAI,MAAM;AAC7D,UAAM,iBAAiB,cAAc,OAAO,CAAC,UAAU,MAAM,OAAO,KAAK,EAAE;AAE3E,UAAM,gBAAgB,IAAI;AAAA,MACxB,MAAM;AACJ,aAAK,YAAY;AACjB,aAAK,YAAY,oBAAI,KAAK;AAAA,MAC5B;AAAA,MACA,YAAY;AACV,YAAI,gBAAgB;AAClB,gBAAM,2BAA2B,IAAI,QAAQ,SAAS,gBAAgB,SAAS;AAAA,QACjF,WAAW,QAAQ,WAAW,OAAO,QAAQ,YAAY,YAAY,QAAQ,QAAQ,OAAO,WAAW;AACrG,gBAAM,UAAU,eAAe,KAAK,CAAC,UAAU,MAAM,SAAS,KAAK;AACnE,gBAAM,iBAAiB,WAAW,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU;AAC1F,cAAI,gBAAgB;AAClB,oBAAQ,UAAU;AAAA,UACpB;AAAA,QACF;AAAA,MACF;AAAA,IACF,GAAG,EAAE,aAAa,KAAK,CAAC;AAExB,UAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,UAAM,oBAAoB;AAAA,MACxB;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa,mBAAmB,IAAI;AAAA,MACpC,YAAY,IAAI;AAAA,MAChB,QAAQ;AAAA,MACR,SAAS,EAAE,YAAY,yCAAyC;AAAA,IAClE,CAAC;AAED,WAAO,EAAE,QAAQ,KAAK,IAAI,gBAAgB,UAAU,iBAAiB,UAAU;AAAA,EACjF;AAAA,EACA,UAAU,OAAO,EAAE,QAAQ,UAAU,MAAM;AACzC,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,UAAM,SAAS,UAAU;AACzB,WAAO;AAAA,MACL,aAAa,UAAU,6CAA6C,qBAAqB;AAAA;AAAA;AAAA,MAGzF,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,oBAAoB;AAAA,MACpB,kBAAkB,QAAQ,kBAAkB;AAAA,MAC5C,UAAU,QAAQ,YAAY;AAAA,MAC9B,gBAAgB,QAAQ,kBAAkB;AAAA,MAC1C,gBAAgB,UAAU;AAAA,MAC1B,SAAS;AAAA,QACP,MAAM;AAAA,UACJ,QAAQ,UAAU;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,UAAU,mBAAuD,QAAQ;AAC/E,UAAM,SAAS,SAAS;AACxB,QAAI,CAAC,OAAQ;AAEb,QAAI,4BAA4B,MAAM,GAAG;AACvC,YAAM,0BAA0B,KAAK,MAAM;AAC3C;AAAA,IACF;AAEA,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,MACA,EAAE,IAAI,OAAO,GAAG;AAAA,MAChB;AAAA,MACA,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,IACrE;AACA,QAAI,CAAC,KAAM;AAEX,QAAI,SAAgC;AACpC,QAAI,UAAwC;AAC5C,QAAI,UAAiC;AAErC,UAAM,gBAAgB,IAAI;AAAA,MACxB,YAAY;AACV,iBAAS,MAAM;AAAA,UACb;AAAA,UACA;AAAA,UACA,EAAE,IAAI,OAAO,gBAAgB,MAAM,UAAU,UAAU,OAAO,UAAU,gBAAgB,OAAO,gBAAgB,WAAW,KAAK;AAAA,UAC/H;AAAA,UACA,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,QACrE;AACA,YAAI,CAAC,UAAU,CAAC,OAAO,UAAW;AAClC,kBAAU,MAAM;AAAA,UACd;AAAA,UACA;AAAA,UACA,EAAE,QAAQ,OAAO;AAAA,UACjB,EAAE,UAAU,CAAC,SAAS,EAAE;AAAA,UACxB,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,QACrE;AACA,YAAI,CAAC,QAAS;AACd,kBAAU,MAAM;AAAA,UACd;AAAA,UACA;AAAA,UACA,EAAE,IAAI,OAAO,iBAAiB,MAAM,WAAW,UAAU,OAAO,UAAU,gBAAgB,OAAO,gBAAgB,WAAW,KAAK;AAAA,UACjI;AAAA,UACA,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe;AAAA,QACrE;AAAA,MACF;AAAA,MACA,YAAY;AACV,aAAK,YAAY;AACjB,aAAK,YAAY,OAAO;AACxB,YAAI,UAAU,OAAO,WAAW;AAC9B,gBAAM,2BAA2B,IAAI,MAAM;AAC3C,eAAK,YAAY;AACjB,cAAI,WAAW,QAAS,SAAQ,UAAU;AAAA,QAC5C;AAAA,MACF;AAAA,IACF,GAAG,EAAE,aAAa,KAAK,CAAC;AAExB,UAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,UAAM,wBAAwB;AAAA,MAC5B;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa,mBAAmB,IAAI;AAAA,MACpC,YAAY,IAAI;AAAA,MAChB,QAAQ;AAAA,MACR,SAAS,EAAE,YAAY,yCAAyC;AAAA,IAClE,CAAC;AAAA,EACH;AACF;AAEA,gBAAgB,8BAA8B;AAC9C,gBAAgB,8BAA8B;AAC9C,gBAAgB,8BAA8B;",
6
6
  "names": ["link"]
7
7
  }