@happyvertical/smrt-cli 0.51.15 → 0.51.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/AGENTS.md +1 -0
  2. package/dist/ApiKey-BZmbOTnL-D3HXUD48.js +157 -0
  3. package/dist/ApiKeyCollection-Bfb_nw81-iisJ_4LE.js +2 -0
  4. package/dist/AuditLogCollection-B1YonCAP-BSaKxHp3.js +2 -0
  5. package/dist/NostrIdentity-n70E0vck-jJyb_ar3.js +4189 -0
  6. package/dist/NostrIdentityCollection-Ca74dkaL-M4K0-Bkw.js +2 -0
  7. package/dist/OidcIdentity-CChQnYNH-Cnye-7CI.js +117 -0
  8. package/dist/OidcIdentityCollection-D3L0WYbM-BOje5aiS.js +2 -0
  9. package/dist/ProfileAssetCollection-V8u4wqSL-DDnGXiJl.js +2 -0
  10. package/dist/ProfileCollection-BvhD2cfL-P9hC9GcP.js +1753 -0
  11. package/dist/ProfileMetadataCollection-DxX_BJKV-ZbSkGI11.js +2 -0
  12. package/dist/ProfileMetafieldCollection-CMKhVi2I-BrAonTjE.js +2 -0
  13. package/dist/ProfileRelationshipCollection-DUVgaIqf-0E090hxE.js +2 -0
  14. package/dist/ProfileRelationshipTermCollection-DtA9OM23-EGZ4UVpV.js +2 -0
  15. package/dist/ProfileRelationshipType-BRiRka6t-W3qx1WVa.js +101 -0
  16. package/dist/ProfileRelationshipTypeCollection-BdXwd7Kf-mvIAf7RC.js +2 -0
  17. package/dist/{commands-BhDS-TVS.js → commands-C3O2NOMh.js} +96 -22
  18. package/dist/{config-DfBo4hHU.js → config-hqNo4lzH.js} +1 -13
  19. package/dist/dist-A0mO7r3F.js +142 -0
  20. package/dist/dist-DNf1dFwn.js +1487 -0
  21. package/dist/dist-DrGZRXfi.js +3712 -0
  22. package/dist/index.js +14 -14
  23. package/dist/{json-validator-CjX8fHx9.js → json-validator-oEN7eUI3.js} +1 -1
  24. package/dist/oidcProvisioningPrimitives-CjOkg3Zd-BtqRL7sX.js +161 -0
  25. package/dist/resolveIdentity-73HQnTlT-C4CQBrRn.js +2 -0
  26. package/dist/rolldown-runtime-8H4AJuhK.js +14 -0
  27. package/package.json +8 -7
@@ -0,0 +1,1487 @@
1
+ import { i as queryWithGlobals, n as tenantId, r as queryGlobal, s as withSystemContext, t as TenantScoped } from "./dist-A0mO7r3F.js";
2
+ import { ObjectRegistry, SmrtCollection, SmrtHierarchical, SmrtJunction, SmrtObject, SmrtPolymorphicAssociation, crossPackageRef, field, foreignKey, smrt } from "@happyvertical/smrt-core";
3
+ //#region ../tags/dist/index.js
4
+ var __defProp$2$1 = Object.defineProperty;
5
+ var __exportAll = (all, no_symbols) => {
6
+ let target = {};
7
+ for (var name in all) __defProp$2$1(target, name, {
8
+ get: all[name],
9
+ enumerable: true
10
+ });
11
+ if (!no_symbols) __defProp$2$1(target, Symbol.toStringTag, { value: "Module" });
12
+ return target;
13
+ };
14
+ ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-tags\",\"packageVersion\":\"0.51.17\",\"objects\":{\"@happyvertical/smrt-tags:TagAlias\":{\"name\":\"tagalias\",\"className\":\"TagAlias\",\"qualifiedName\":\"@happyvertical/smrt-tags:TagAlias\",\"collection\":\"tagaliases\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/tags/src/tag-alias.ts\",\"packageName\":\"@happyvertical/smrt-tags\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tagSlug\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"alias\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"language\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"createdAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"getTag\":{\"name\":\"getTag\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Tag | null>\",\"isStatic\":false,\"isPublic\":true},\"searchByAlias\":{\"name\":\"searchByAlias\",\"async\":true,\"parameters\":[{\"name\":\"_alias\",\"type\":\"string\",\"optional\":false},{\"name\":\"_language\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Tag[]>\",\"isStatic\":true,\"isPublic\":true},\"getAliasesForTag\":{\"name\":\"getAliasesForTag\",\"async\":true,\"parameters\":[{\"name\":\"_tagSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<TagAlias[]>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"]},\"extends\":\"SmrtObject\",\"exportName\":\"TagAlias\",\"collectionExportName\":\"TagAliasCollection\",\"validationRules\":[{\"field\":\"alias\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"tag_aliases\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"tag_aliases\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tag_slug\\\" TEXT DEFAULT '',\\n \\\"alias\\\" TEXT DEFAULT '',\\n \\\"language\\\" TEXT DEFAULT '',\\n \\\"tenant_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tag_slug\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"alias\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"language\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false}},\"indexes\":[{\"name\":\"tag_aliases_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"tag_aliases_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"tag_aliases_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"95a4bc18\"},\"importPath\":\"@happyvertical/smrt-tags\"},\"@happyvertical/smrt-tags:TagAliasCollection\":{\"name\":\"tagaliascollection\",\"className\":\"TagAliasCollection\",\"qualifiedName\":\"@happyvertical/smrt-tags:TagAliasCollection\",\"collection\":\"tagaliases\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/tags/src/tag-aliases.ts\",\"packageName\":\"@happyvertical/smrt-tags\",\"fields\":{},\"methods\":{\"addAlias\":{\"name\":\"addAlias\",\"async\":true,\"parameters\":[{\"name\":\"tagSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"alias\",\"type\":\"string\",\"optional\":false},{\"name\":\"language\",\"type\":\"string\",\"optional\":true},{\"name\":\"context\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<TagAlias>\",\"isStatic\":false,\"isPublic\":true},\"searchByAlias\":{\"name\":\"searchByAlias\",\"async\":true,\"parameters\":[{\"name\":\"alias\",\"type\":\"string\",\"optional\":false},{\"name\":\"language\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Tag[]>\",\"isStatic\":false,\"isPublic\":true},\"getAliasesForTag\":{\"name\":\"getAliasesForTag\",\"async\":true,\"parameters\":[{\"name\":\"tagSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"language\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<TagAlias[]>\",\"isStatic\":false,\"isPublic\":true},\"removeAlias\":{\"name\":\"removeAlias\",\"async\":true,\"parameters\":[{\"name\":\"aliasId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"bulkAddAliases\":{\"name\":\"bulkAddAliases\",\"async\":true,\"parameters\":[{\"name\":\"tagSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"aliases\",\"type\":\"Array<object>\",\"optional\":false,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<TagAlias[]>\",\"isStatic\":false,\"isPublic\":true},\"getAliasesByLanguage\":{\"name\":\"getAliasesByLanguage\",\"async\":true,\"parameters\":[{\"name\":\"tagSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Map<string, string[]>>\",\"isStatic\":false,\"isPublic\":true},\"findMatchingAliases\":{\"name\":\"findMatchingAliases\",\"async\":true,\"parameters\":[{\"name\":\"query\",\"type\":\"string\",\"optional\":false},{\"name\":\"language\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<TagAlias[]>\",\"isStatic\":false,\"isPublic\":true},\"findByTenant\":{\"name\":\"findByTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<TagAlias[]>\",\"isStatic\":false,\"isPublic\":true},\"findGlobal\":{\"name\":\"findGlobal\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<TagAlias[]>\",\"isStatic\":false,\"isPublic\":true},\"findWithGlobals\":{\"name\":\"findWithGlobals\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<TagAlias[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"TagAlias\",\"exportName\":\"TagAliasCollection\",\"collectionExportName\":\"TagAliasCollectionCollection\",\"schema\":{\"tableName\":\"tag_aliases\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"tag_aliases\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tag_slug\\\" TEXT DEFAULT '',\\n \\\"alias\\\" TEXT DEFAULT '',\\n \\\"language\\\" TEXT DEFAULT '',\\n \\\"tenant_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tag_slug\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"alias\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"language\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false}},\"indexes\":[{\"name\":\"tag_aliases_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"tag_aliases_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"tag_aliases_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"95a4bc18\"},\"importPath\":\"@happyvertical/smrt-tags\"},\"@happyvertical/smrt-tags:Tag\":{\"name\":\"tag\",\"className\":\"Tag\",\"qualifiedName\":\"@happyvertical/smrt-tags:Tag\",\"collection\":\"tags\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/tags/src/tag.ts\",\"packageName\":\"@happyvertical/smrt-tags\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"parentId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Tag\",\"_meta\":{\"nullable\":true}},\"name\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"level\":{\"type\":\"integer\",\"required\":false,\"default\":0},\"description\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"metadata\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"createdAt\":{\"type\":\"datetime\",\"required\":false},\"updatedAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"getParent\":{\"name\":\"getParent\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this | null>\",\"isStatic\":false,\"isPublic\":true},\"getChildren\":{\"name\":\"getChildren\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this[]>\",\"isStatic\":false,\"isPublic\":true},\"getAncestors\":{\"name\":\"getAncestors\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this[]>\",\"isStatic\":false,\"isPublic\":true},\"getDescendants\":{\"name\":\"getDescendants\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this[]>\",\"isStatic\":false,\"isPublic\":true},\"getHierarchy\":{\"name\":\"getHierarchy\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<HierarchyView<this>>\",\"isStatic\":false,\"isPublic\":true},\"moveTo\":{\"name\":\"moveTo\",\"async\":true,\"parameters\":[{\"name\":\"newParent\",\"type\":\"this | string | null\",\"optional\":false,\"unionBranches\":[{\"type\":\"this\"},{\"type\":\"string\"},{\"type\":\"null\"}]}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"TagMetadata\",\"isStatic\":false,\"isPublic\":true},\"setMetadata\":{\"name\":\"setMetadata\",\"async\":false,\"parameters\":[{\"name\":\"data\",\"type\":\"TagMetadata\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"updateMetadata\":{\"name\":\"updateMetadata\",\"async\":false,\"parameters\":[{\"name\":\"updates\",\"type\":\"Partial<TagMetadata>\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"getBySlug\":{\"name\":\"getBySlug\",\"async\":true,\"parameters\":[{\"name\":\"_slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"_context\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Tag | null>\",\"isStatic\":true,\"isPublic\":true},\"getRootTags\":{\"name\":\"getRootTags\",\"async\":true,\"parameters\":[{\"name\":\"_context\",\"type\":\"string\",\"optional\":true,\"default\":\"global\"}],\"returnType\":\"Promise<Tag[]>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"]},\"extends\":\"SmrtHierarchical\",\"exportName\":\"Tag\",\"collectionExportName\":\"TagCollection\",\"validationRules\":[{\"field\":\"name\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"tags\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"tags\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"parent_id\\\" UUID,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"level\\\" INTEGER DEFAULT 0,\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"metadata\\\" TEXT DEFAULT '',\\n \\\"tenant_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"parent_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"tags\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"level\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false}},\"indexes\":[{\"name\":\"tags_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"tags_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"tags_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"tags_parent_id_idx\",\"columns\":[\"parent_id\"]}],\"version\":\"4da9de3e\"},\"importPath\":\"@happyvertical/smrt-tags\"},\"@happyvertical/smrt-tags:TagCollection\":{\"name\":\"tagcollection\",\"className\":\"TagCollection\",\"qualifiedName\":\"@happyvertical/smrt-tags:TagCollection\",\"collection\":\"tags\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/tags/src/tags.ts\",\"packageName\":\"@happyvertical/smrt-tags\",\"fields\":{},\"methods\":{\"getOrCreate\":{\"name\":\"getOrCreate\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"context\",\"type\":\"string\",\"optional\":true,\"default\":\"global\"}],\"returnType\":\"Promise<Tag>\",\"isStatic\":false,\"isPublic\":true},\"listByContext\":{\"name\":\"listByContext\",\"async\":true,\"parameters\":[{\"name\":\"context\",\"type\":\"string\",\"optional\":false},{\"name\":\"parentSlug\",\"type\":\"string | null\",\"optional\":true,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"null\"}]}],\"returnType\":\"Promise<Tag[]>\",\"isStatic\":false,\"isPublic\":true},\"getRootTags\":{\"name\":\"getRootTags\",\"async\":true,\"parameters\":[{\"name\":\"context\",\"type\":\"string\",\"optional\":true,\"default\":\"global\"}],\"returnType\":\"Promise<Tag[]>\",\"isStatic\":false,\"isPublic\":true},\"getChildren\":{\"name\":\"getChildren\",\"async\":true,\"parameters\":[{\"name\":\"parentSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"context\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Tag[]>\",\"isStatic\":false,\"isPublic\":true},\"getHierarchy\":{\"name\":\"getHierarchy\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"context\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<TagHierarchy>\",\"isStatic\":false,\"isPublic\":true},\"moveTag\":{\"name\":\"moveTag\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"newParentSlug\",\"type\":\"string | null\",\"optional\":false,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"null\"}]},{\"name\":\"context\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"mergeTag\":{\"name\":\"mergeTag\",\"async\":true,\"parameters\":[{\"name\":\"fromSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"toSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"context\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"cleanupUnused\":{\"name\":\"cleanupUnused\",\"async\":true,\"parameters\":[{\"name\":\"context\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"calculateLevel\":{\"name\":\"calculateLevel\",\"async\":true,\"parameters\":[{\"name\":\"parentSlug\",\"type\":\"string | null\",\"optional\":false,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"null\"}]},{\"name\":\"context\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"findByTenant\":{\"name\":\"findByTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Tag[]>\",\"isStatic\":false,\"isPublic\":true},\"findGlobal\":{\"name\":\"findGlobal\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Tag[]>\",\"isStatic\":false,\"isPublic\":true},\"findWithGlobals\":{\"name\":\"findWithGlobals\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Tag[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"Tag\",\"exportName\":\"TagCollection\",\"collectionExportName\":\"TagCollectionCollection\",\"schema\":{\"tableName\":\"tags\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"tags\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"parent_id\\\" UUID,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"level\\\" INTEGER DEFAULT 0,\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"metadata\\\" TEXT DEFAULT '',\\n \\\"tenant_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"parent_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"tags\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"level\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false}},\"indexes\":[{\"name\":\"tags_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"tags_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"tags_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"tags_parent_id_idx\",\"columns\":[\"parent_id\"]}],\"version\":\"4da9de3e\"},\"importPath\":\"@happyvertical/smrt-tags\"}},\"moduleType\":\"smrt\",\"smrtDependencies\":[\"@happyvertical/smrt-core\",\"@happyvertical/smrt-tenancy\"]}"));
15
+ var __defProp$1$1 = Object.defineProperty;
16
+ var __getOwnPropDesc$1$1 = Object.getOwnPropertyDescriptor;
17
+ var __decorateClass$1$1 = (decorators, target, key, kind) => {
18
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1$1(target, key) : target;
19
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
20
+ if (kind && result) __defProp$1$1(target, key, result);
21
+ return result;
22
+ };
23
+ var Tag = class extends SmrtHierarchical {
24
+ _slug = "";
25
+ _context = "global";
26
+ get slug() {
27
+ return this._slug;
28
+ }
29
+ set slug(value) {
30
+ this._slug = value;
31
+ }
32
+ get context() {
33
+ return this._context;
34
+ }
35
+ set context(value) {
36
+ this._context = value;
37
+ }
38
+ name = "";
39
+ level = 0;
40
+ description = "";
41
+ metadata = "";
42
+ tenantId = null;
43
+ createdAt = /* @__PURE__ */ new Date();
44
+ updatedAt = /* @__PURE__ */ new Date();
45
+ constructor(options = {}) {
46
+ super(options);
47
+ if (options.name) this.name = options.name;
48
+ if (options.parentId !== void 0) this.parentId = options.parentId ?? null;
49
+ if (options.slug) this._slug = options.slug;
50
+ if (options.context !== void 0) this._context = options.context;
51
+ if (options.level !== void 0) this.level = options.level;
52
+ if (options.description !== void 0) this.description = options.description;
53
+ if (options.metadata !== void 0) if (typeof options.metadata === "string") this.metadata = options.metadata;
54
+ else this.metadata = JSON.stringify(options.metadata);
55
+ }
56
+ /**
57
+ * Get metadata as parsed object
58
+ *
59
+ * @returns Parsed metadata object or empty object if no metadata
60
+ */
61
+ getMetadata() {
62
+ const metadataValue = String(this.metadata || "");
63
+ if (!metadataValue) return {};
64
+ try {
65
+ return JSON.parse(metadataValue);
66
+ } catch {
67
+ return {};
68
+ }
69
+ }
70
+ /**
71
+ * Set metadata from object
72
+ *
73
+ * @param data - Metadata object to store
74
+ */
75
+ setMetadata(data) {
76
+ this.metadata = JSON.stringify(data);
77
+ }
78
+ /**
79
+ * Update metadata by merging with existing values
80
+ *
81
+ * @param updates - Partial metadata to merge
82
+ */
83
+ updateMetadata(updates) {
84
+ const current = this.getMetadata();
85
+ this.setMetadata({
86
+ ...current,
87
+ ...updates
88
+ });
89
+ }
90
+ /**
91
+ * Convenience method for slug-based lookup
92
+ *
93
+ * @param slug - The slug to search for
94
+ * @param context - Optional context filter
95
+ * @returns Tag instance or null if not found
96
+ */
97
+ static async getBySlug(_slug, _context) {
98
+ return null;
99
+ }
100
+ /**
101
+ * Get root tags (no parent) for a context
102
+ *
103
+ * @param context - The context to filter by
104
+ * @returns Array of root tags
105
+ */
106
+ static async getRootTags(_context = "global") {
107
+ return [];
108
+ }
109
+ };
110
+ __decorateClass$1$1([field({ required: true })], Tag.prototype, "name", 2);
111
+ __decorateClass$1$1([tenantId({ nullable: true })], Tag.prototype, "tenantId", 2);
112
+ Tag = __decorateClass$1$1([TenantScoped({ mode: "optional" }), smrt({
113
+ tableStrategy: "sti",
114
+ api: { include: [
115
+ "list",
116
+ "get",
117
+ "create",
118
+ "update",
119
+ "delete"
120
+ ] },
121
+ mcp: { include: [
122
+ "list",
123
+ "get",
124
+ "create",
125
+ "update"
126
+ ] },
127
+ cli: { skipApiCheck: true }
128
+ })], Tag);
129
+ var __defProp$7 = Object.defineProperty;
130
+ var __getOwnPropDesc$7 = Object.getOwnPropertyDescriptor;
131
+ var __decorateClass$7 = (decorators, target, key, kind) => {
132
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$7(target, key) : target;
133
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
134
+ if (kind && result) __defProp$7(target, key, result);
135
+ return result;
136
+ };
137
+ var TagAlias = class extends SmrtObject {
138
+ tagSlug = "";
139
+ alias = "";
140
+ language = "";
141
+ _context = "";
142
+ get context() {
143
+ return this._context;
144
+ }
145
+ set context(value) {
146
+ this._context = value;
147
+ }
148
+ tenantId = null;
149
+ createdAt = /* @__PURE__ */ new Date();
150
+ constructor(options = {}) {
151
+ super(options);
152
+ if (options.tagSlug !== void 0) this.tagSlug = options.tagSlug;
153
+ if (options.alias) this.alias = options.alias;
154
+ if (options.language !== void 0) this.language = options.language;
155
+ if (options.context !== void 0) this._context = options.context;
156
+ }
157
+ /**
158
+ * Get the tag this alias belongs to
159
+ *
160
+ * @returns Tag instance or null if not found
161
+ */
162
+ async getTag() {
163
+ const { TagCollection } = await Promise.resolve().then(() => tags_exports);
164
+ return await (await TagCollection.create(this.options)).get({ slug: this.tagSlug });
165
+ }
166
+ /**
167
+ * Search tags by alias
168
+ *
169
+ * @param alias - The alias to search for
170
+ * @param language - Optional language filter
171
+ * @returns Array of matching tags
172
+ */
173
+ static async searchByAlias(_alias, _language) {
174
+ return [];
175
+ }
176
+ /**
177
+ * Get all aliases for a tag
178
+ *
179
+ * @param tagSlug - The tag slug to get aliases for
180
+ * @returns Array of TagAlias instances
181
+ */
182
+ static async getAliasesForTag(_tagSlug) {
183
+ return [];
184
+ }
185
+ };
186
+ __decorateClass$7([field({ required: true })], TagAlias.prototype, "alias", 2);
187
+ __decorateClass$7([tenantId({ nullable: true })], TagAlias.prototype, "tenantId", 2);
188
+ TagAlias = __decorateClass$7([TenantScoped({ mode: "optional" }), smrt({
189
+ tableStrategy: "sti",
190
+ api: { include: [
191
+ "list",
192
+ "get",
193
+ "create",
194
+ "update",
195
+ "delete"
196
+ ] },
197
+ mcp: { include: [
198
+ "list",
199
+ "get",
200
+ "create"
201
+ ] },
202
+ cli: { skipApiCheck: true }
203
+ })], TagAlias);
204
+ var tag_aliases_exports = /* @__PURE__ */ __exportAll({ TagAliasCollection: () => TagAliasCollection });
205
+ var TagAliasCollection = class extends SmrtCollection {
206
+ static _itemClass = TagAlias;
207
+ /**
208
+ * Add an alias to a tag (get or create)
209
+ *
210
+ * @param tagSlug - The tag slug
211
+ * @param alias - The alias text
212
+ * @param language - Optional language code
213
+ * @param context - Optional context
214
+ * @returns TagAlias instance
215
+ */
216
+ async addAlias(tagSlug, alias, language, context) {
217
+ const where = {
218
+ tagSlug,
219
+ alias
220
+ };
221
+ if (language) where.language = language;
222
+ if (context) where.context = context;
223
+ const existing = await this.list({
224
+ where,
225
+ limit: 1
226
+ });
227
+ if (existing.length > 0) return existing[0];
228
+ return await this.create({
229
+ tagSlug,
230
+ alias,
231
+ language,
232
+ context
233
+ });
234
+ }
235
+ /**
236
+ * Search tags by alias
237
+ *
238
+ * @param alias - The alias to search for
239
+ * @param language - Optional language filter
240
+ * @returns Array of matching tags
241
+ */
242
+ async searchByAlias(alias, language) {
243
+ const where = { alias };
244
+ if (language) where.language = language;
245
+ const aliases = await this.list({ where });
246
+ const tagSlugs = [...new Set(aliases.map((a) => a.tagSlug))];
247
+ const { TagCollection } = await Promise.resolve().then(() => tags_exports);
248
+ const tagCollection = await TagCollection.create(this.options);
249
+ const tags = [];
250
+ for (const slug of tagSlugs) {
251
+ const tag = await tagCollection.get({ slug });
252
+ if (tag) tags.push(tag);
253
+ }
254
+ return tags;
255
+ }
256
+ /**
257
+ * Get all aliases for a tag
258
+ *
259
+ * @param tagSlug - The tag slug
260
+ * @param language - Optional language filter
261
+ * @returns Array of TagAlias instances
262
+ */
263
+ async getAliasesForTag(tagSlug, language) {
264
+ const where = { tagSlug };
265
+ if (language) where.language = language;
266
+ return await this.list({ where });
267
+ }
268
+ /**
269
+ * Remove an alias by ID
270
+ *
271
+ * @param aliasId - The alias UUID
272
+ */
273
+ async removeAlias(aliasId) {
274
+ const alias = await this.get({ id: aliasId });
275
+ if (alias) await alias.delete();
276
+ }
277
+ /**
278
+ * Bulk add aliases to a tag
279
+ *
280
+ * @param tagSlug - The tag slug
281
+ * @param aliases - Array of alias configurations
282
+ * @returns Array of created TagAlias instances
283
+ */
284
+ async bulkAddAliases(tagSlug, aliases) {
285
+ const created = [];
286
+ for (const aliasData of aliases) {
287
+ const tagAlias = await this.addAlias(tagSlug, aliasData.alias, aliasData.language, aliasData.context);
288
+ created.push(tagAlias);
289
+ }
290
+ return created;
291
+ }
292
+ /**
293
+ * Get aliases grouped by language
294
+ *
295
+ * @param tagSlug - The tag slug
296
+ * @returns Map of language code to array of aliases
297
+ */
298
+ async getAliasesByLanguage(tagSlug) {
299
+ const aliases = await this.getAliasesForTag(tagSlug);
300
+ const grouped = /* @__PURE__ */ new Map();
301
+ for (const alias of aliases) {
302
+ const lang = String(alias.language || "default");
303
+ if (!grouped.has(lang)) grouped.set(lang, []);
304
+ grouped.get(lang)?.push(String(alias.alias));
305
+ }
306
+ return grouped;
307
+ }
308
+ /**
309
+ * Find matching aliases (case-insensitive partial match)
310
+ *
311
+ * Note: This is a simple implementation. For production use,
312
+ * consider using full-text search or fuzzy matching.
313
+ *
314
+ * @param query - The search query
315
+ * @param language - Optional language filter
316
+ * @returns Array of matching TagAlias instances
317
+ */
318
+ async findMatchingAliases(query, language) {
319
+ const where = {};
320
+ if (language) where.language = language;
321
+ const all = await this.list({ where });
322
+ const queryLower = query.toLowerCase();
323
+ return all.filter((alias) => String(alias.alias).toLowerCase().includes(queryLower));
324
+ }
325
+ /**
326
+ * Find all tag aliases belonging to a specific tenant
327
+ *
328
+ * @param tenantId - The tenant ID to filter by
329
+ * @returns Array of tag aliases for the specified tenant
330
+ */
331
+ async findByTenant(tenantId) {
332
+ return this.list({ where: { tenantId } });
333
+ }
334
+ /**
335
+ * Find all global (tenant-less) tag aliases.
336
+ *
337
+ * Routes through the shared tenant-global helper so it does not throw under
338
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
339
+ * flagged as an isolation violation). (#1600)
340
+ *
341
+ * @returns Array of global tag aliases with null tenantId
342
+ */
343
+ async findGlobal() {
344
+ return queryGlobal(this);
345
+ }
346
+ /**
347
+ * Find tag aliases for a tenant including global aliases.
348
+ *
349
+ * Fails closed if an active tenant context requests a different tenant's
350
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
351
+ *
352
+ * @param tenantId - The tenant ID to filter by
353
+ * @returns Array of tag aliases for the tenant plus all global aliases
354
+ */
355
+ async findWithGlobals(tenantId) {
356
+ return queryWithGlobals(this, tenantId, "TagAlias.findWithGlobals");
357
+ }
358
+ };
359
+ var tags_exports = /* @__PURE__ */ __exportAll({ TagCollection: () => TagCollection });
360
+ var TagCollection = class extends SmrtCollection {
361
+ static _itemClass = Tag;
362
+ /**
363
+ * Get or create a tag with context
364
+ *
365
+ * @param slug - Tag slug
366
+ * @param context - Tag context (default: 'global')
367
+ * @returns Tag instance
368
+ */
369
+ async getOrCreate(slug, context = "global") {
370
+ const existing = await this.list({
371
+ where: {
372
+ slug,
373
+ context
374
+ },
375
+ limit: 1
376
+ });
377
+ if (existing.length > 0) return existing[0];
378
+ return await this.create({
379
+ slug,
380
+ name: slug.replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
381
+ context,
382
+ level: 0
383
+ });
384
+ }
385
+ /**
386
+ * Resolve a tag by slug, optionally scoped to a context.
387
+ *
388
+ * Tags are identified by `(slug, context)`. When `context` is omitted
389
+ * and the slug exists in more than one context, this throws a clear
390
+ * ambiguity error rather than silently picking the first matching row.
391
+ * Callers that know their context should pass it; callers that work in
392
+ * a single-context world can leave it off.
393
+ *
394
+ * @returns The matching Tag, or `null` if nothing matches.
395
+ * @throws Error if `context` is omitted and the slug is ambiguous.
396
+ */
397
+ async resolveBySlug(slug, context) {
398
+ const where = { slug };
399
+ if (context !== void 0) where.context = context;
400
+ const matches = await this.list({
401
+ where,
402
+ limit: 2
403
+ });
404
+ if (matches.length === 0) return null;
405
+ if (matches.length > 1) throw new Error(`Tag slug '${slug}' is ambiguous: resolves to ${matches.length}+ rows across contexts. Pass an explicit \`context\` argument.`);
406
+ return matches[0];
407
+ }
408
+ /**
409
+ * List tags by context with optional parent filtering by slug.
410
+ *
411
+ * @param context - The context to filter by
412
+ * @param parentSlug - Optional parent slug to filter children. Pass an
413
+ * empty string or `null` to find root tags; pass a slug to find that
414
+ * tag's immediate children. Typed as `string | null` so TypeScript
415
+ * callers can pass `null` without a cast — the `null` and `''` paths
416
+ * are both treated as "roots only".
417
+ * @returns Array of matching tags
418
+ */
419
+ async listByContext(context, parentSlug) {
420
+ const where = { context };
421
+ if (parentSlug === "" || parentSlug === null) where.parentId = null;
422
+ else if (parentSlug !== void 0) {
423
+ const parent = await this.get({
424
+ slug: parentSlug,
425
+ context
426
+ });
427
+ if (!parent?.id) return [];
428
+ where.parentId = parent.id;
429
+ }
430
+ return await this.list({ where });
431
+ }
432
+ /**
433
+ * Get root tags (no parent) for a context
434
+ *
435
+ * @param context - The context to filter by (default: 'global')
436
+ * @returns Array of root tags
437
+ */
438
+ async getRootTags(context = "global") {
439
+ return await this.list({ where: {
440
+ context,
441
+ parentId: null
442
+ } });
443
+ }
444
+ /**
445
+ * Get immediate children of a parent tag, looked up by slug.
446
+ *
447
+ * @param parentSlug - The parent tag slug
448
+ * @param context - Optional context for the parent lookup. When omitted,
449
+ * the parent slug must be unambiguous across contexts (throws if not).
450
+ * @returns Array of child tags, or `[]` if the parent slug doesn't
451
+ * resolve. Children are filtered to the resolved parent's context so
452
+ * cross-context children don't leak in.
453
+ */
454
+ async getChildren(parentSlug, context) {
455
+ const parent = await this.resolveBySlug(parentSlug, context);
456
+ if (!parent?.id) return [];
457
+ return await this.list({ where: {
458
+ parentId: parent.id,
459
+ context: parent.context
460
+ } });
461
+ }
462
+ /**
463
+ * Get tag hierarchy (all ancestors and descendants)
464
+ *
465
+ * @param slug - The tag slug
466
+ * @param context - Optional context for the slug lookup. When omitted,
467
+ * the slug must be unambiguous across contexts.
468
+ * @returns Object with ancestors, current tag, and descendants
469
+ */
470
+ async getHierarchy(slug, context) {
471
+ const tag = await this.resolveBySlug(slug, context);
472
+ if (!tag) throw new Error(`Tag '${slug}' not found`);
473
+ const [ancestors, descendants] = await Promise.all([tag.getAncestors(), tag.getDescendants()]);
474
+ return {
475
+ ancestors,
476
+ current: tag,
477
+ descendants
478
+ };
479
+ }
480
+ /**
481
+ * Move a tag to a new parent. Slug-based API; UUIDs resolved internally.
482
+ *
483
+ * Cycle detection is inlined here (mirroring `SmrtHierarchical.moveTo`'s
484
+ * self-loop + descendant checks) so that both `parentId` and the
485
+ * denormalised `level` field can be persisted in a single `save()`.
486
+ * Delegating to `moveTo` would write `parentId` first and `level` in a
487
+ * second save — if the second save failed, the tag would be left with
488
+ * the new parent but a stale level, breaking the depth cache.
489
+ *
490
+ * After the moved tag persists, descendant levels are recalculated
491
+ * recursively via `updateDescendantLevels`.
492
+ *
493
+ * @param slug - The tag to move
494
+ * @param newParentSlug - The new parent slug (null for root)
495
+ * @param context - Optional context. When provided, both source and new
496
+ * parent are resolved within it. When omitted, both slugs must be
497
+ * unambiguous across contexts; the resolver throws otherwise.
498
+ * @throws Error if either slug fails to resolve, if either slug is
499
+ * ambiguous across contexts (no context provided), if source and new
500
+ * parent live in different contexts, or if the move would create a
501
+ * cycle.
502
+ */
503
+ async moveTag(slug, newParentSlug, context) {
504
+ const tag = await this.resolveBySlug(slug, context);
505
+ if (!tag) throw new Error(`Tag '${slug}' not found`);
506
+ let newParent = null;
507
+ if (newParentSlug) {
508
+ newParent = await this.resolveBySlug(newParentSlug, context ?? tag.context);
509
+ if (!newParent) throw new Error(`Tag '${newParentSlug}' not found`);
510
+ if (newParent.context !== tag.context) throw new Error(`Cannot move Tag '${slug}' (context '${tag.context}') under '${newParentSlug}' (context '${newParent.context}') \u2014 contexts must match.`);
511
+ }
512
+ const newParentId = newParent?.id ?? null;
513
+ if (newParentId !== null && newParentId === tag.id) throw new Error(`Cannot move Tag ${tag.id} to itself.`);
514
+ if (newParentId !== null) {
515
+ if ((await tag.getDescendants()).some((d) => d.id === newParentId)) throw new Error(`Cannot move Tag ${tag.id} under one of its own descendants (${newParentId}) \u2014 would create a cycle.`);
516
+ }
517
+ tag.parentId = newParentId;
518
+ tag.level = newParent ? newParent.level + 1 : 0;
519
+ await tag.save();
520
+ await this.updateDescendantLevels(tag);
521
+ }
522
+ /**
523
+ * Merge one tag into another (updates all references)
524
+ *
525
+ * Reparents `fromTag`'s direct children onto `toTag` and recalculates
526
+ * their `level` field plus the level of every descendant — without
527
+ * this, children moved from a different depth would carry stale
528
+ * levels relative to their new parent. `TagAlias.tagSlug` references
529
+ * are also rewritten, then `fromTag` is deleted.
530
+ *
531
+ * Note: Consuming packages are responsible for updating their own
532
+ * join tables (e.g. `asset_tags`).
533
+ *
534
+ * @param fromSlug - The tag to merge from
535
+ * @param toSlug - The tag to merge into
536
+ * @param context - Optional context. When provided, both tags are
537
+ * resolved within it. When omitted, both slugs must be unambiguous
538
+ * across contexts.
539
+ * @throws Error if either slug fails to resolve, if either slug is
540
+ * ambiguous, or if the two tags live in different contexts.
541
+ */
542
+ async mergeTag(fromSlug, toSlug, context) {
543
+ const fromTag = await this.resolveBySlug(fromSlug, context);
544
+ const toTag = await this.resolveBySlug(toSlug, context ?? fromTag?.context);
545
+ if (!fromTag) throw new Error(`Source tag '${fromSlug}' not found`);
546
+ if (!toTag) throw new Error(`Target tag '${toSlug}' not found`);
547
+ if (!fromTag.id) throw new Error(`Source tag '${fromSlug}' has no id`);
548
+ if (!toTag.id) throw new Error(`Target tag '${toSlug}' has no id`);
549
+ if (fromTag.context !== toTag.context) throw new Error(`Cannot merge '${fromSlug}' (context '${fromTag.context}') into '${toSlug}' (context '${toTag.context}') \u2014 contexts must match.`);
550
+ if (fromTag.id === toTag.id) throw new Error(`Cannot merge tag '${fromSlug}' into itself.`);
551
+ if ((await fromTag.getDescendants()).some((d) => d.id === toTag.id)) throw new Error(`Cannot merge '${fromSlug}' into '${toSlug}' \u2014 target is a descendant of source (would create a cycle).`);
552
+ const children = await this.list({ where: { parentId: fromTag.id } });
553
+ const newChildLevel = toTag.level + 1;
554
+ for (const child of children) {
555
+ child.parentId = toTag.id;
556
+ child.level = newChildLevel;
557
+ await child.save();
558
+ await this.updateDescendantLevels(child);
559
+ }
560
+ const { TagAliasCollection } = await Promise.resolve().then(() => tag_aliases_exports);
561
+ const aliasCollection = await TagAliasCollection.create(this.options);
562
+ const aliasContexts = [fromTag.context];
563
+ if (fromTag.context === "global") aliasContexts.push("");
564
+ const aliases = await aliasCollection.list({ where: {
565
+ tagSlug: fromSlug,
566
+ context: aliasContexts
567
+ } });
568
+ for (const alias of aliases) {
569
+ alias.tagSlug = toSlug;
570
+ await alias.save();
571
+ }
572
+ await fromTag.delete();
573
+ }
574
+ /**
575
+ * Remove tags with no references (cleanup unused tags)
576
+ *
577
+ * Note: This requires consuming packages to provide usage information.
578
+ * By default, only removes tags with no children and no aliases.
579
+ *
580
+ * @param context - Optional context to filter cleanup
581
+ */
582
+ async cleanupUnused(context) {
583
+ const where = {};
584
+ if (context) where.context = context;
585
+ const tags = await this.list({ where });
586
+ const { TagAliasCollection } = await Promise.resolve().then(() => tag_aliases_exports);
587
+ const aliasCollection = await TagAliasCollection.create(this.options);
588
+ let deletedCount = 0;
589
+ for (const tag of tags) {
590
+ if (!tag.id) continue;
591
+ if ((await this.list({
592
+ where: { parentId: tag.id },
593
+ limit: 1
594
+ })).length > 0) continue;
595
+ if ((await aliasCollection.list({
596
+ where: { tagSlug: tag.slug },
597
+ limit: 1
598
+ })).length > 0) continue;
599
+ await tag.delete();
600
+ deletedCount++;
601
+ }
602
+ return deletedCount;
603
+ }
604
+ /**
605
+ * Calculate hierarchy level for a tag, looking the parent up by slug.
606
+ *
607
+ * @param parentSlug - The parent tag slug (null/empty for root)
608
+ * @param context - Optional context for the parent lookup. When
609
+ * omitted, the parent slug must be unambiguous across contexts.
610
+ * @returns The calculated level (root parent → 1, missing parent → 0)
611
+ */
612
+ async calculateLevel(parentSlug, context) {
613
+ if (!parentSlug) return 0;
614
+ const parent = await this.resolveBySlug(parentSlug, context);
615
+ if (!parent) return 0;
616
+ return parent.level + 1;
617
+ }
618
+ /**
619
+ * Update levels for all descendants after moving a tag
620
+ *
621
+ * @param tag - The tag that was moved
622
+ */
623
+ async updateDescendantLevels(tag) {
624
+ if (!tag.id) return;
625
+ const children = await this.list({ where: { parentId: tag.id } });
626
+ for (const child of children) {
627
+ child.level = tag.level + 1;
628
+ await child.save();
629
+ await this.updateDescendantLevels(child);
630
+ }
631
+ }
632
+ /**
633
+ * Find all tags belonging to a specific tenant
634
+ *
635
+ * @param tenantId - The tenant ID to filter by
636
+ * @returns Array of tags for the specified tenant
637
+ */
638
+ async findByTenant(tenantId) {
639
+ return this.list({ where: { tenantId } });
640
+ }
641
+ /**
642
+ * Find all global (tenant-less) tags.
643
+ *
644
+ * Routes through the shared tenant-global helper so it does not throw under
645
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
646
+ * flagged as an isolation violation). (#1600)
647
+ *
648
+ * @returns Array of global tags with null tenantId
649
+ */
650
+ async findGlobal() {
651
+ return queryGlobal(this);
652
+ }
653
+ /**
654
+ * Find tags for a tenant including global tags.
655
+ *
656
+ * Fails closed if an active tenant context requests a different tenant's
657
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
658
+ *
659
+ * @param tenantId - The tenant ID to filter by
660
+ * @returns Array of tags for the tenant plus all global tags
661
+ */
662
+ async findWithGlobals(tenantId) {
663
+ return queryWithGlobals(this, tenantId, "Tag.findWithGlobals");
664
+ }
665
+ };
666
+ //#endregion
667
+ //#region ../assets/dist/index.js
668
+ ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-assets\",\"packageVersion\":\"0.51.17\",\"objects\":{\"@happyvertical/smrt-assets:AssetAssociation\":{\"name\":\"assetassociation\",\"className\":\"AssetAssociation\",\"qualifiedName\":\"@happyvertical/smrt-assets:AssetAssociation\",\"collection\":\"assetassociations\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/assets/src/asset-association.ts\",\"packageName\":\"@happyvertical/smrt-assets\",\"fields\":{\"metaType\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"metaId\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"role\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"sortOrder\":{\"type\":\"integer\",\"required\":false,\"default\":0},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"assetId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Asset\",\"_meta\":{\"required\":true}}},\"methods\":{\"hydrate\":{\"name\":\"hydrate\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<T | null>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"conflictColumns\":[\"asset_id\",\"meta_type\",\"meta_id\",\"role\"],\"api\":{\"include\":[\"list\",\"get\",\"create\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtPolymorphicAssociation\",\"exportName\":\"AssetAssociation\",\"collectionExportName\":\"AssetAssociationCollection\",\"validationRules\":[{\"field\":\"metaType\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"metaId\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"role\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"assetId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"asset_associations\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"asset_associations\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"meta_type\\\" TEXT NOT NULL,\\n \\\"meta_id\\\" TEXT NOT NULL,\\n \\\"role\\\" TEXT NOT NULL,\\n \\\"sort_order\\\" INTEGER DEFAULT 0,\\n \\\"tenant_id\\\" UUID,\\n \\\"asset_id\\\" UUID NOT NULL\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"meta_type\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"meta_id\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"role\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"sort_order\":{\"type\":\"INTEGER\",\"notNull\":false,\"unique\":false,\"default\":0},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"asset_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"assets\",\"column\":\"id\",\"onDelete\":\"CASCADE\",\"onUpdate\":\"CASCADE\"}}},\"indexes\":[{\"name\":\"asset_associations_asset_id_meta_type_idx\",\"columns\":[\"asset_id\",\"meta_type\",\"meta_id\",\"role\"],\"unique\":true},{\"name\":\"asset_associations_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"asset_associations_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"asset_associations_meta_type_meta_id_idx\",\"columns\":[\"meta_type\",\"meta_id\"]}],\"version\":\"faa13cea\"},\"importPath\":\"@happyvertical/smrt-assets\"},\"@happyvertical/smrt-assets:AssetAssociationCollection\":{\"name\":\"assetassociationcollection\",\"className\":\"AssetAssociationCollection\",\"qualifiedName\":\"@happyvertical/smrt-assets:AssetAssociationCollection\",\"collection\":\"assetassociations\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/assets/src/asset-associations.ts\",\"packageName\":\"@happyvertical/smrt-assets\",\"fields\":{},\"methods\":{\"byLeft\":{\"name\":\"byLeft\",\"async\":true,\"parameters\":[{\"name\":\"metaType\",\"type\":\"string\",\"optional\":false},{\"name\":\"metaId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionFilterOptions\",\"optional\":true}],\"returnType\":\"Promise<AssetAssociation[]>\",\"isStatic\":false,\"isPublic\":true},\"byRight\":{\"name\":\"byRight\",\"async\":true,\"parameters\":[{\"name\":\"rightId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionFilterOptions\",\"optional\":true}],\"returnType\":\"Promise<TItem[]>\",\"isStatic\":false,\"isPublic\":true},\"attach\":{\"name\":\"attach\",\"async\":true,\"parameters\":[{\"name\":\"metaType\",\"type\":\"string\",\"optional\":false},{\"name\":\"metaId\",\"type\":\"string\",\"optional\":false},{\"name\":\"assetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionAttachOptions\",\"optional\":true}],\"returnType\":\"Promise<AssetAssociation>\",\"isStatic\":false,\"isPublic\":true},\"detach\":{\"name\":\"detach\",\"async\":true,\"parameters\":[{\"name\":\"metaType\",\"type\":\"string\",\"optional\":false},{\"name\":\"metaId\",\"type\":\"string\",\"optional\":false},{\"name\":\"assetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionFilterOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"setLinks\":{\"name\":\"setLinks\",\"async\":true,\"parameters\":[{\"name\":\"metaType\",\"type\":\"string\",\"optional\":false},{\"name\":\"metaId\",\"type\":\"string\",\"optional\":false},{\"name\":\"assetIds\",\"type\":\"string[]\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionAttachOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtJunction\",\"extendsTypeArg\":\"AssetAssociation\",\"exportName\":\"AssetAssociationCollection\",\"collectionExportName\":\"AssetAssociationCollectionCollection\",\"schema\":{\"tableName\":\"asset_associations\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"asset_associations\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"meta_type\\\" TEXT NOT NULL,\\n \\\"meta_id\\\" TEXT NOT NULL,\\n \\\"role\\\" TEXT NOT NULL,\\n \\\"sort_order\\\" INTEGER DEFAULT 0,\\n \\\"tenant_id\\\" UUID,\\n \\\"asset_id\\\" UUID NOT NULL\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"meta_type\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"meta_id\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"role\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"sort_order\":{\"type\":\"INTEGER\",\"notNull\":false,\"unique\":false,\"default\":0},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"asset_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"assets\",\"column\":\"id\",\"onDelete\":\"CASCADE\",\"onUpdate\":\"CASCADE\"}}},\"indexes\":[{\"name\":\"asset_associations_asset_id_meta_type_idx\",\"columns\":[\"asset_id\",\"meta_type\",\"meta_id\",\"role\"],\"unique\":true},{\"name\":\"asset_associations_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"asset_associations_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"asset_associations_meta_type_meta_id_idx\",\"columns\":[\"meta_type\",\"meta_id\"]}],\"version\":\"faa13cea\"},\"importPath\":\"@happyvertical/smrt-assets\"},\"@happyvertical/smrt-assets:AssetMetafield\":{\"name\":\"assetmetafield\",\"className\":\"AssetMetafield\",\"qualifiedName\":\"@happyvertical/smrt-assets:AssetMetafield\",\"collection\":\"assetmetafields\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/assets/src/asset-metafield.ts\",\"packageName\":\"@happyvertical/smrt-assets\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"name\":{\"type\":\"text\",\"required\":false},\"validation\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getValidation\":{\"name\":\"getValidation\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"setValidation\":{\"name\":\"setValidation\",\"async\":false,\"parameters\":[{\"name\":\"rules\",\"type\":\"Record<string, unknown>\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"getBySlug\":{\"name\":\"getBySlug\",\"async\":true,\"parameters\":[{\"name\":\"_slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<AssetMetafield | null>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\"]},\"cli\":{\"skipApiCheck\":true}},\"extends\":\"SmrtObject\",\"exportName\":\"AssetMetafield\",\"collectionExportName\":\"AssetMetafieldCollection\",\"schema\":{\"tableName\":\"asset_metafields\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"asset_metafields\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"name\\\" TEXT,\\n \\\"validation\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false},\"validation\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"asset_metafields_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"asset_metafields_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"asset_metafields_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"7393718c\"},\"importPath\":\"@happyvertical/smrt-assets\"},\"@happyvertical/smrt-assets:AssetMetafieldCollection\":{\"name\":\"assetmetafieldcollection\",\"className\":\"AssetMetafieldCollection\",\"qualifiedName\":\"@happyvertical/smrt-assets:AssetMetafieldCollection\",\"collection\":\"assetmetafields\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/assets/src/asset-metafields.ts\",\"packageName\":\"@happyvertical/smrt-assets\",\"fields\":{},\"methods\":{\"getOrCreate\":{\"name\":\"getOrCreate\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"name\",\"type\":\"string\",\"optional\":true},{\"name\":\"validation\",\"type\":\"string | Record<string, unknown>\",\"optional\":true,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"Record<string, unknown>\"}]}],\"returnType\":\"Promise<AssetMetafield>\",\"isStatic\":false,\"isPublic\":true},\"initializeCommonMetafields\":{\"name\":\"initializeCommonMetafields\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"AssetMetafield\",\"exportName\":\"AssetMetafieldCollection\",\"collectionExportName\":\"AssetMetafieldCollectionCollection\",\"schema\":{\"tableName\":\"asset_metafields\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"asset_metafields\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"name\\\" TEXT,\\n \\\"validation\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false},\"validation\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"asset_metafields_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"asset_metafields_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"asset_metafields_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"7393718c\"},\"importPath\":\"@happyvertical/smrt-assets\"},\"@happyvertical/smrt-assets:AssetStatus\":{\"name\":\"assetstatus\",\"className\":\"AssetStatus\",\"qualifiedName\":\"@happyvertical/smrt-assets:AssetStatus\",\"collection\":\"assetstatuses\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/assets/src/asset-status.ts\",\"packageName\":\"@happyvertical/smrt-assets\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"name\":{\"type\":\"text\",\"required\":false},\"description\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getBySlug\":{\"name\":\"getBySlug\",\"async\":true,\"parameters\":[{\"name\":\"_slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<AssetStatus | null>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\"]},\"cli\":{\"skipApiCheck\":true}},\"extends\":\"SmrtObject\",\"exportName\":\"AssetStatus\",\"collectionExportName\":\"AssetStatusCollection\",\"schema\":{\"tableName\":\"asset_statuses\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"asset_statuses\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"name\\\" TEXT,\\n \\\"description\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"asset_statuses_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"asset_statuses_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"asset_statuses_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"8251a52f\"},\"importPath\":\"@happyvertical/smrt-assets\"},\"@happyvertical/smrt-assets:AssetStatusCollection\":{\"name\":\"assetstatuscollection\",\"className\":\"AssetStatusCollection\",\"qualifiedName\":\"@happyvertical/smrt-assets:AssetStatusCollection\",\"collection\":\"assetstatuses\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/assets/src/asset-statuses.ts\",\"packageName\":\"@happyvertical/smrt-assets\",\"fields\":{},\"methods\":{\"getOrCreate\":{\"name\":\"getOrCreate\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"name\",\"type\":\"string\",\"optional\":true},{\"name\":\"description\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<AssetStatus>\",\"isStatic\":false,\"isPublic\":true},\"initializeCommonStatuses\":{\"name\":\"initializeCommonStatuses\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"AssetStatus\",\"exportName\":\"AssetStatusCollection\",\"collectionExportName\":\"AssetStatusCollectionCollection\",\"schema\":{\"tableName\":\"asset_statuses\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"asset_statuses\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"name\\\" TEXT,\\n \\\"description\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"asset_statuses_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"asset_statuses_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"asset_statuses_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"8251a52f\"},\"importPath\":\"@happyvertical/smrt-assets\"},\"@happyvertical/smrt-assets:AssetType\":{\"name\":\"assettype\",\"className\":\"AssetType\",\"qualifiedName\":\"@happyvertical/smrt-assets:AssetType\",\"collection\":\"assettypes\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/assets/src/asset-type.ts\",\"packageName\":\"@happyvertical/smrt-assets\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"name\":{\"type\":\"text\",\"required\":false},\"description\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getBySlug\":{\"name\":\"getBySlug\",\"async\":true,\"parameters\":[{\"name\":\"_slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<AssetType | null>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\"]},\"cli\":{\"skipApiCheck\":true}},\"extends\":\"SmrtObject\",\"exportName\":\"AssetType\",\"collectionExportName\":\"AssetTypeCollection\",\"schema\":{\"tableName\":\"asset_types\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"asset_types\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"name\\\" TEXT,\\n \\\"description\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"asset_types_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"asset_types_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"asset_types_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"a9c93be2\"},\"importPath\":\"@happyvertical/smrt-assets\"},\"@happyvertical/smrt-assets:AssetTypeCollection\":{\"name\":\"assettypecollection\",\"className\":\"AssetTypeCollection\",\"qualifiedName\":\"@happyvertical/smrt-assets:AssetTypeCollection\",\"collection\":\"assettypes\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/assets/src/asset-types.ts\",\"packageName\":\"@happyvertical/smrt-assets\",\"fields\":{},\"methods\":{\"getOrCreate\":{\"name\":\"getOrCreate\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"name\",\"type\":\"string\",\"optional\":true},{\"name\":\"description\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<AssetType>\",\"isStatic\":false,\"isPublic\":true},\"initializeCommonTypes\":{\"name\":\"initializeCommonTypes\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"AssetType\",\"exportName\":\"AssetTypeCollection\",\"collectionExportName\":\"AssetTypeCollectionCollection\",\"schema\":{\"tableName\":\"asset_types\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"asset_types\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"name\\\" TEXT,\\n \\\"description\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"asset_types_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"asset_types_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"asset_types_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"a9c93be2\"},\"importPath\":\"@happyvertical/smrt-assets\"},\"@happyvertical/smrt-assets:Asset\":{\"name\":\"asset\",\"className\":\"Asset\",\"qualifiedName\":\"@happyvertical/smrt-assets:Asset\",\"collection\":\"assets\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/assets/src/asset.ts\",\"packageName\":\"@happyvertical/smrt-assets\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"name\":{\"type\":\"text\",\"required\":false},\"sourceUri\":{\"type\":\"text\",\"required\":false},\"mimeType\":{\"type\":\"text\",\"required\":false},\"description\":{\"type\":\"text\",\"required\":false},\"metadata\":{\"type\":\"text\",\"required\":false},\"version\":{\"type\":\"integer\",\"required\":true,\"default\":1},\"primaryVersionId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Asset\"},\"typeSlug\":{\"type\":\"text\",\"required\":false},\"statusSlug\":{\"type\":\"text\",\"required\":false},\"ownerProfileId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-profiles:Profile\"},\"sourceAssetId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Asset\"},\"folderId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Folder\"},\"sourceType\":{\"type\":\"text\",\"required\":false},\"externalId\":{\"type\":\"text\",\"required\":false},\"externalRefs\":{\"type\":\"text\",\"required\":false},\"createdAt\":{\"type\":\"text\",\"required\":false},\"updatedAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"setMetadata\":{\"name\":\"setMetadata\",\"async\":false,\"parameters\":[{\"name\":\"metadata\",\"type\":\"Record<string, unknown>\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"mergeMetadata\":{\"name\":\"mergeMetadata\",\"async\":false,\"parameters\":[{\"name\":\"metadata\",\"type\":\"Record<string, unknown>\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"getExternalRefs\":{\"name\":\"getExternalRefs\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, AssetExternalReference>\",\"isStatic\":false,\"isPublic\":true},\"getExternalRef\":{\"name\":\"getExternalRef\",\"async\":false,\"parameters\":[{\"name\":\"provider\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"AssetExternalReference | null\",\"isStatic\":false,\"isPublic\":true},\"setExternalRef\":{\"name\":\"setExternalRef\",\"async\":false,\"parameters\":[{\"name\":\"provider\",\"type\":\"string\",\"optional\":false},{\"name\":\"reference\",\"type\":\"any\",\"optional\":false,\"typeUnresolved\":true}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"getTags\":{\"name\":\"getTags\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Tag[]>\",\"isStatic\":false,\"isPublic\":true},\"hasTag\":{\"name\":\"hasTag\",\"async\":true,\"parameters\":[{\"name\":\"tagSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"getSource\":{\"name\":\"getSource\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Asset | null>\",\"isStatic\":false,\"isPublic\":true},\"getDerivatives\":{\"name\":\"getDerivatives\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"getType\":{\"name\":\"getType\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<AssetType | null>\",\"isStatic\":false,\"isPublic\":true},\"getStatus\":{\"name\":\"getStatus\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<AssetStatus | null>\",\"isStatic\":false,\"isPublic\":true},\"getAssociations\":{\"name\":\"getAssociations\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<AssetAssociation[]>\",\"isStatic\":false,\"isPublic\":true},\"associateWith\":{\"name\":\"associateWith\",\"async\":true,\"parameters\":[{\"name\":\"metaType\",\"type\":\"string\",\"optional\":false},{\"name\":\"metaId\",\"type\":\"string\",\"optional\":false},{\"name\":\"role\",\"type\":\"any\",\"optional\":true,\"default\":\"default\"}],\"returnType\":\"Promise<AssetAssociation>\",\"isStatic\":false,\"isPublic\":true},\"getBySlug\":{\"name\":\"getBySlug\",\"async\":true,\"parameters\":[{\"name\":\"_slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Asset | null>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"]},\"extends\":\"SmrtObject\",\"exportName\":\"Asset\",\"collectionExportName\":\"AssetCollection\",\"validationRules\":[{\"field\":\"version\",\"rule\":\"required\",\"fieldType\":\"integer\"}],\"schema\":{\"tableName\":\"assets\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"assets\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"name\\\" TEXT,\\n \\\"source_uri\\\" TEXT,\\n \\\"mime_type\\\" TEXT,\\n \\\"description\\\" TEXT,\\n \\\"metadata\\\" TEXT,\\n \\\"version\\\" INTEGER DEFAULT 1,\\n \\\"primary_version_id\\\" UUID,\\n \\\"type_slug\\\" TEXT,\\n \\\"status_slug\\\" TEXT,\\n \\\"owner_profile_id\\\" UUID,\\n \\\"source_asset_id\\\" UUID,\\n \\\"folder_id\\\" UUID,\\n \\\"source_type\\\" TEXT,\\n \\\"external_id\\\" TEXT,\\n \\\"external_refs\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false},\"source_uri\":{\"type\":\"TEXT\",\"notNull\":false},\"mime_type\":{\"type\":\"TEXT\",\"notNull\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false},\"version\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":1},\"primary_version_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"assets\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"type_slug\":{\"type\":\"TEXT\",\"notNull\":false},\"status_slug\":{\"type\":\"TEXT\",\"notNull\":false},\"owner_profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false},\"source_asset_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"assets\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"folder_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"folders\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"source_type\":{\"type\":\"TEXT\",\"notNull\":false},\"external_id\":{\"type\":\"TEXT\",\"notNull\":false},\"external_refs\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"assets_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"assets_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"assets_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"assets_primary_version_id_idx\",\"columns\":[\"primary_version_id\"]},{\"name\":\"assets_owner_profile_id_idx\",\"columns\":[\"owner_profile_id\"]},{\"name\":\"assets_source_asset_id_idx\",\"columns\":[\"source_asset_id\"]},{\"name\":\"assets_folder_id_idx\",\"columns\":[\"folder_id\"]}],\"version\":\"16d6c152\"},\"importPath\":\"@happyvertical/smrt-assets\"},\"@happyvertical/smrt-assets:AssetCollection\":{\"name\":\"assetcollection\",\"className\":\"AssetCollection\",\"qualifiedName\":\"@happyvertical/smrt-assets:AssetCollection\",\"collection\":\"assets\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/assets/src/assets.ts\",\"packageName\":\"@happyvertical/smrt-assets\",\"fields\":{},\"methods\":{\"findByTenant\":{\"name\":\"findByTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"findGlobal\":{\"name\":\"findGlobal\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"findWithGlobals\":{\"name\":\"findWithGlobals\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"addTag\":{\"name\":\"addTag\",\"async\":true,\"parameters\":[{\"name\":\"assetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"tagSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeTag\":{\"name\":\"removeTag\",\"async\":true,\"parameters\":[{\"name\":\"assetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"tagSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getByTag\":{\"name\":\"getByTag\",\"async\":true,\"parameters\":[{\"name\":\"tagSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"getByType\":{\"name\":\"getByType\",\"async\":true,\"parameters\":[{\"name\":\"typeSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"getByStatus\":{\"name\":\"getByStatus\",\"async\":true,\"parameters\":[{\"name\":\"statusSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"getByOwner\":{\"name\":\"getByOwner\",\"async\":true,\"parameters\":[{\"name\":\"ownerProfileId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"createNewVersion\":{\"name\":\"createNewVersion\",\"async\":true,\"parameters\":[{\"name\":\"primaryVersionId\",\"type\":\"string\",\"optional\":false},{\"name\":\"newSourceUri\",\"type\":\"string\",\"optional\":false},{\"name\":\"updates\",\"type\":\"Partial<Asset>\",\"optional\":true}],\"returnType\":\"Promise<Asset>\",\"isStatic\":false,\"isPublic\":true},\"getLatestVersion\":{\"name\":\"getLatestVersion\",\"async\":true,\"parameters\":[{\"name\":\"primaryVersionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Asset | null>\",\"isStatic\":false,\"isPublic\":true},\"listVersions\":{\"name\":\"listVersions\",\"async\":true,\"parameters\":[{\"name\":\"primaryVersionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"getDerivatives\":{\"name\":\"getDerivatives\",\"async\":true,\"parameters\":[{\"name\":\"sourceAssetId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"getByMimeType\":{\"name\":\"getByMimeType\",\"async\":true,\"parameters\":[{\"name\":\"mimePattern\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"rollbackToVersion\":{\"name\":\"rollbackToVersion\",\"async\":true,\"parameters\":[{\"name\":\"primaryVersionId\",\"type\":\"string\",\"optional\":false},{\"name\":\"targetVersion\",\"type\":\"number\",\"optional\":false}],\"returnType\":\"Promise<Asset>\",\"isStatic\":false,\"isPublic\":true},\"getByFolder\":{\"name\":\"getByFolder\",\"async\":true,\"parameters\":[{\"name\":\"folderId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"Asset\",\"exportName\":\"AssetCollection\",\"collectionExportName\":\"AssetCollectionCollection\",\"schema\":{\"tableName\":\"assets\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"assets\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"name\\\" TEXT,\\n \\\"source_uri\\\" TEXT,\\n \\\"mime_type\\\" TEXT,\\n \\\"description\\\" TEXT,\\n \\\"metadata\\\" TEXT,\\n \\\"version\\\" INTEGER DEFAULT 1,\\n \\\"primary_version_id\\\" UUID,\\n \\\"type_slug\\\" TEXT,\\n \\\"status_slug\\\" TEXT,\\n \\\"owner_profile_id\\\" UUID,\\n \\\"source_asset_id\\\" UUID,\\n \\\"folder_id\\\" UUID,\\n \\\"source_type\\\" TEXT,\\n \\\"external_id\\\" TEXT,\\n \\\"external_refs\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false},\"source_uri\":{\"type\":\"TEXT\",\"notNull\":false},\"mime_type\":{\"type\":\"TEXT\",\"notNull\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false},\"version\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":1},\"primary_version_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"assets\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"type_slug\":{\"type\":\"TEXT\",\"notNull\":false},\"status_slug\":{\"type\":\"TEXT\",\"notNull\":false},\"owner_profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false},\"source_asset_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"assets\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"folder_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"folders\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"source_type\":{\"type\":\"TEXT\",\"notNull\":false},\"external_id\":{\"type\":\"TEXT\",\"notNull\":false},\"external_refs\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"assets_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"assets_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"assets_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"assets_primary_version_id_idx\",\"columns\":[\"primary_version_id\"]},{\"name\":\"assets_owner_profile_id_idx\",\"columns\":[\"owner_profile_id\"]},{\"name\":\"assets_source_asset_id_idx\",\"columns\":[\"source_asset_id\"]},{\"name\":\"assets_folder_id_idx\",\"columns\":[\"folder_id\"]}],\"version\":\"16d6c152\"},\"importPath\":\"@happyvertical/smrt-assets\"},\"@happyvertical/smrt-assets:Folder\":{\"name\":\"folder\",\"className\":\"Folder\",\"qualifiedName\":\"@happyvertical/smrt-assets:Folder\",\"collection\":\"folders\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/assets/src/folder.ts\",\"packageName\":\"@happyvertical/smrt-assets\",\"fields\":{\"parentId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Folder\",\"_meta\":{\"nullable\":true}},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"name\":{\"type\":\"text\",\"required\":false},\"description\":{\"type\":\"text\",\"required\":false},\"ownerProfileId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-profiles:Profile\"},\"createdAt\":{\"type\":\"text\",\"required\":false},\"updatedAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getParent\":{\"name\":\"getParent\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this | null>\",\"isStatic\":false,\"isPublic\":true},\"getChildren\":{\"name\":\"getChildren\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this[]>\",\"isStatic\":false,\"isPublic\":true},\"getAncestors\":{\"name\":\"getAncestors\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this[]>\",\"isStatic\":false,\"isPublic\":true},\"getDescendants\":{\"name\":\"getDescendants\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this[]>\",\"isStatic\":false,\"isPublic\":true},\"getHierarchy\":{\"name\":\"getHierarchy\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<HierarchyView<this>>\",\"isStatic\":false,\"isPublic\":true},\"moveTo\":{\"name\":\"moveTo\",\"async\":true,\"parameters\":[{\"name\":\"newParent\",\"type\":\"this | string | null\",\"optional\":false,\"unionBranches\":[{\"type\":\"this\"},{\"type\":\"string\"},{\"type\":\"null\"}]}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getBySlug\":{\"name\":\"getBySlug\",\"async\":true,\"parameters\":[{\"name\":\"_slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Folder | null>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\"]},\"extends\":\"SmrtHierarchical\",\"exportName\":\"Folder\",\"collectionExportName\":\"FolderCollection\",\"schema\":{\"tableName\":\"folders\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"folders\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"parent_id\\\" UUID,\\n \\\"tenant_id\\\" UUID,\\n \\\"name\\\" TEXT,\\n \\\"description\\\" TEXT,\\n \\\"owner_profile_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"parent_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"folders\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"owner_profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"folders_slug_context_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"folders_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"folders_parent_id_idx\",\"columns\":[\"parent_id\"]},{\"name\":\"folders_owner_profile_id_idx\",\"columns\":[\"owner_profile_id\"]}],\"version\":\"1d0b1fcb\"},\"importPath\":\"@happyvertical/smrt-assets\"},\"@happyvertical/smrt-assets:FolderCollection\":{\"name\":\"foldercollection\",\"className\":\"FolderCollection\",\"qualifiedName\":\"@happyvertical/smrt-assets:FolderCollection\",\"collection\":\"folders\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/assets/src/folders.ts\",\"packageName\":\"@happyvertical/smrt-assets\",\"fields\":{},\"methods\":{\"getTree\":{\"name\":\"getTree\",\"async\":true,\"parameters\":[{\"name\":\"rootId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Folder[]>\",\"isStatic\":false,\"isPublic\":true},\"getPath\":{\"name\":\"getPath\",\"async\":true,\"parameters\":[{\"name\":\"folderId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Folder[]>\",\"isStatic\":false,\"isPublic\":true},\"getContents\":{\"name\":\"getContents\",\"async\":true,\"parameters\":[{\"name\":\"folderId\",\"type\":\"string\",\"optional\":false},{\"name\":\"assetCollection\",\"type\":\"AssetCollection\",\"optional\":false}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"moveAsset\":{\"name\":\"moveAsset\",\"async\":true,\"parameters\":[{\"name\":\"asset\",\"type\":\"Asset\",\"optional\":false},{\"name\":\"folderId\",\"type\":\"string | null\",\"optional\":false,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"null\"}]}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"Folder\",\"exportName\":\"FolderCollection\",\"collectionExportName\":\"FolderCollectionCollection\",\"schema\":{\"tableName\":\"folders\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"folders\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"parent_id\\\" UUID,\\n \\\"tenant_id\\\" UUID,\\n \\\"name\\\" TEXT,\\n \\\"description\\\" TEXT,\\n \\\"owner_profile_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"parent_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"folders\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"owner_profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"folders_slug_context_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"folders_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"folders_parent_id_idx\",\"columns\":[\"parent_id\"]},{\"name\":\"folders_owner_profile_id_idx\",\"columns\":[\"owner_profile_id\"]}],\"version\":\"1d0b1fcb\"},\"importPath\":\"@happyvertical/smrt-assets\"}},\"moduleType\":\"smrt\",\"smrtDependencies\":[\"@happyvertical/smrt-core\",\"@happyvertical/smrt-tags\",\"@happyvertical/smrt-tenancy\"]}"));
669
+ var __defProp$6 = Object.defineProperty;
670
+ var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
671
+ var __decorateClass$6 = (decorators, target, key, kind) => {
672
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
673
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
674
+ if (kind && result) __defProp$6(target, key, result);
675
+ return result;
676
+ };
677
+ var AssetAssociation = class extends SmrtPolymorphicAssociation {
678
+ tenantId = null;
679
+ assetId = "";
680
+ constructor(options = {}) {
681
+ super(options);
682
+ if (options.assetId) this.assetId = options.assetId;
683
+ if (options.tenantId !== void 0) this.tenantId = options.tenantId;
684
+ }
685
+ };
686
+ __decorateClass$6([tenantId({ nullable: true })], AssetAssociation.prototype, "tenantId", 2);
687
+ __decorateClass$6([foreignKey("Asset", { required: true })], AssetAssociation.prototype, "assetId", 2);
688
+ AssetAssociation = __decorateClass$6([TenantScoped({ mode: "optional" }), smrt({
689
+ conflictColumns: [
690
+ "asset_id",
691
+ "meta_type",
692
+ "meta_id",
693
+ "role"
694
+ ],
695
+ api: { include: [
696
+ "list",
697
+ "get",
698
+ "create",
699
+ "delete"
700
+ ] },
701
+ mcp: { include: [
702
+ "list",
703
+ "get",
704
+ "create"
705
+ ] },
706
+ cli: { skipApiCheck: true }
707
+ })], AssetAssociation);
708
+ var __defProp$5 = Object.defineProperty;
709
+ var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
710
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp$5(obj, key, {
711
+ enumerable: true,
712
+ configurable: true,
713
+ writable: true,
714
+ value
715
+ }) : obj[key] = value;
716
+ var __decorateClass$5 = (decorators, target, key, kind) => {
717
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
718
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
719
+ if (kind && result) __defProp$5(target, key, result);
720
+ return result;
721
+ };
722
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
723
+ var AssetAssociationCollection = class extends SmrtJunction {
724
+ leftField = "metaId";
725
+ rightField = "assetId";
726
+ /**
727
+ * List associations for a polymorphic owner.
728
+ *
729
+ * Composite left key — pass both halves.
730
+ */
731
+ async byLeft(metaType, metaId, opts = {}) {
732
+ return await this.list({
733
+ where: {
734
+ ...opts,
735
+ metaType,
736
+ metaId
737
+ },
738
+ orderBy: "sort_order ASC"
739
+ });
740
+ }
741
+ /**
742
+ * Create an association. Composite left (metaType, metaId) precedes right (assetId).
743
+ */
744
+ async attach(metaType, metaId, assetId, opts = {}) {
745
+ return await this.create({
746
+ ...opts,
747
+ assetId,
748
+ metaType,
749
+ metaId
750
+ });
751
+ }
752
+ /**
753
+ * Delete matching associations. Composite left (metaType, metaId) precedes right (assetId).
754
+ */
755
+ async detach(metaType, metaId, assetId, opts = {}) {
756
+ const links = await this.list({ where: {
757
+ ...opts,
758
+ metaType,
759
+ metaId,
760
+ assetId
761
+ } });
762
+ for (const link of links) await link.delete();
763
+ }
764
+ /**
765
+ * Replace all associations for a polymorphic owner with the given asset IDs.
766
+ * Not transactional — see `SmrtJunction.setLinks` for caveats.
767
+ */
768
+ async setLinks(metaType, metaId, assetIds, opts = {}) {
769
+ const snapshotOpts = { ...opts };
770
+ delete snapshotOpts.assetId;
771
+ const existing = await this.list({ where: {
772
+ ...snapshotOpts,
773
+ metaType,
774
+ metaId
775
+ } });
776
+ for (const link of existing) await link.delete();
777
+ const positionKey = this.positionField;
778
+ for (let i = 0; i < assetIds.length; i++) {
779
+ const rowOpts = { ...opts };
780
+ if (positionKey && rowOpts[positionKey] === void 0) rowOpts[positionKey] = i;
781
+ await this.attach(metaType, metaId, assetIds[i], rowOpts);
782
+ }
783
+ }
784
+ };
785
+ __publicField(AssetAssociationCollection, "_itemClass", AssetAssociation);
786
+ AssetAssociationCollection = __decorateClass$5([smrt()], AssetAssociationCollection);
787
+ var __defProp$4 = Object.defineProperty;
788
+ var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
789
+ var __decorateClass$4 = (decorators, target, key, kind) => {
790
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
791
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
792
+ if (kind && result) __defProp$4(target, key, result);
793
+ return result;
794
+ };
795
+ var AssetStatus = class extends SmrtObject {
796
+ name = "";
797
+ description = "";
798
+ constructor(options = {}) {
799
+ super(options);
800
+ if (options.slug) this.slug = options.slug;
801
+ if (options.name) this.name = options.name;
802
+ if (options.description) this.description = options.description;
803
+ }
804
+ /**
805
+ * Get asset status by slug
806
+ *
807
+ * @param slug - The slug to search for
808
+ * @returns AssetStatus instance or null
809
+ */
810
+ static async getBySlug(_slug) {
811
+ return null;
812
+ }
813
+ };
814
+ AssetStatus = __decorateClass$4([smrt({
815
+ tableStrategy: "sti",
816
+ api: { include: [
817
+ "list",
818
+ "get",
819
+ "create",
820
+ "update",
821
+ "delete"
822
+ ] },
823
+ mcp: { include: [
824
+ "list",
825
+ "get",
826
+ "create"
827
+ ] },
828
+ cli: { skipApiCheck: true }
829
+ })], AssetStatus);
830
+ var __defProp$3 = Object.defineProperty;
831
+ var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
832
+ var __decorateClass$3 = (decorators, target, key, kind) => {
833
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
834
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
835
+ if (kind && result) __defProp$3(target, key, result);
836
+ return result;
837
+ };
838
+ var AssetType = class extends SmrtObject {
839
+ name = "";
840
+ description = "";
841
+ constructor(options = {}) {
842
+ super(options);
843
+ if (options.slug) this.slug = options.slug;
844
+ if (options.name) this.name = options.name;
845
+ if (options.description) this.description = options.description;
846
+ }
847
+ /**
848
+ * Get asset type by slug
849
+ *
850
+ * @param slug - The slug to search for
851
+ * @returns AssetType instance or null
852
+ */
853
+ static async getBySlug(_slug) {
854
+ return null;
855
+ }
856
+ };
857
+ AssetType = __decorateClass$3([smrt({
858
+ tableStrategy: "sti",
859
+ api: { include: [
860
+ "list",
861
+ "get",
862
+ "create",
863
+ "update",
864
+ "delete"
865
+ ] },
866
+ mcp: { include: [
867
+ "list",
868
+ "get",
869
+ "create"
870
+ ] },
871
+ cli: { skipApiCheck: true }
872
+ })], AssetType);
873
+ var __defProp$2 = Object.defineProperty;
874
+ var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
875
+ var __decorateClass$2 = (decorators, target, key, kind) => {
876
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
877
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
878
+ if (kind && result) __defProp$2(target, key, result);
879
+ return result;
880
+ };
881
+ function parseAssetRecord(value) {
882
+ if (!value) return {};
883
+ if (typeof value !== "string") return value;
884
+ if (!value.trim()) return {};
885
+ try {
886
+ const parsed = JSON.parse(value);
887
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
888
+ } catch {
889
+ return {};
890
+ }
891
+ }
892
+ function stringifyAssetRecord(value) {
893
+ if (!value || Object.keys(value).length === 0) return "";
894
+ return JSON.stringify(value);
895
+ }
896
+ var Asset = class extends SmrtObject {
897
+ tenantId = null;
898
+ name = "";
899
+ sourceUri = "";
900
+ mimeType = "";
901
+ description = "";
902
+ metadata = "";
903
+ version = 1;
904
+ primaryVersionId = null;
905
+ typeSlug = "";
906
+ statusSlug = "";
907
+ ownerProfileId = null;
908
+ sourceAssetId = null;
909
+ folderId = null;
910
+ sourceType = "";
911
+ externalId = "";
912
+ externalRefs = "";
913
+ createdAt = /* @__PURE__ */ new Date();
914
+ updatedAt = /* @__PURE__ */ new Date();
915
+ constructor(options = {}) {
916
+ super(options);
917
+ if (options.name) this.name = options.name;
918
+ if (options.slug) this.slug = options.slug;
919
+ if (options.sourceUri) this.sourceUri = options.sourceUri;
920
+ if (options.mimeType) this.mimeType = options.mimeType;
921
+ if (options.description) this.description = options.description;
922
+ if (options.metadata !== void 0) this.metadata = typeof options.metadata === "string" ? options.metadata : stringifyAssetRecord(options.metadata);
923
+ if (options.version !== void 0) this.version = options.version;
924
+ if (options.primaryVersionId !== void 0) this.primaryVersionId = options.primaryVersionId;
925
+ if (options.typeSlug) this.typeSlug = options.typeSlug;
926
+ if (options.statusSlug) this.statusSlug = options.statusSlug;
927
+ if (options.ownerProfileId !== void 0) this.ownerProfileId = options.ownerProfileId;
928
+ if (options.sourceAssetId !== void 0) this.sourceAssetId = options.sourceAssetId;
929
+ if (options.folderId !== void 0) this.folderId = options.folderId;
930
+ if (options.sourceType) this.sourceType = options.sourceType;
931
+ if (options.externalId) this.externalId = options.externalId;
932
+ if (options.externalRefs !== void 0) this.externalRefs = typeof options.externalRefs === "string" ? options.externalRefs : stringifyAssetRecord(options.externalRefs);
933
+ if (options.tenantId !== void 0) this.tenantId = options.tenantId;
934
+ if (options.createdAt) this.createdAt = options.createdAt;
935
+ if (options.updatedAt) this.updatedAt = options.updatedAt;
936
+ }
937
+ getMetadata() {
938
+ return parseAssetRecord(this.metadata);
939
+ }
940
+ setMetadata(metadata) {
941
+ this.metadata = stringifyAssetRecord(metadata);
942
+ }
943
+ mergeMetadata(metadata) {
944
+ this.setMetadata({
945
+ ...this.getMetadata(),
946
+ ...metadata
947
+ });
948
+ }
949
+ getExternalRefs() {
950
+ const refs = parseAssetRecord(this.externalRefs);
951
+ const normalized = {};
952
+ for (const [provider, value] of Object.entries(refs)) if (value && typeof value === "object" && !Array.isArray(value)) normalized[provider] = {
953
+ ...value,
954
+ provider
955
+ };
956
+ return normalized;
957
+ }
958
+ getExternalRef(provider) {
959
+ return this.getExternalRefs()[provider] ?? null;
960
+ }
961
+ setExternalRef(provider, reference) {
962
+ this.externalRefs = stringifyAssetRecord({
963
+ ...this.getExternalRefs(),
964
+ [provider]: {
965
+ ...this.getExternalRef(provider) ?? {},
966
+ ...reference,
967
+ provider: reference.provider ?? provider
968
+ }
969
+ });
970
+ }
971
+ /**
972
+ * Get all tags for this asset from @happyvertical/smrt-tags
973
+ *
974
+ * @returns Array of Tag instances from @happyvertical/smrt-tags package
975
+ */
976
+ async getTags() {
977
+ const rows = await this.db.list("asset_tags", { where: { asset_id: this.id } });
978
+ const tags = [];
979
+ for (const row of rows) {
980
+ const tag = await Tag.getBySlug(row.tag_slug);
981
+ if (tag) tags.push(tag);
982
+ }
983
+ return tags;
984
+ }
985
+ /**
986
+ * Check if this asset has a specific tag
987
+ *
988
+ * @param tagSlug - The slug of the tag to check
989
+ * @returns True if the asset has this tag
990
+ */
991
+ async hasTag(tagSlug) {
992
+ return (await this.db.list("asset_tags", { where: {
993
+ asset_id: this.id,
994
+ tag_slug: tagSlug
995
+ } })).length > 0;
996
+ }
997
+ /**
998
+ * Resolve the AssetCollection lazily. Going through `ObjectRegistry`
999
+ * mirrors the pattern used by `SmrtHierarchical._hierarchyCollection`
1000
+ * so source/derivative lookups inherit tenant scoping and ORM
1001
+ * hydration without hard-coding an import of `./assets` (which would
1002
+ * create a module-import cycle).
1003
+ *
1004
+ * The return type is `SmrtCollection<Asset>` (the framework base, type-
1005
+ * only import from core) rather than the concrete `AssetCollection` —
1006
+ * importing the concrete class is what would create the cycle, but the
1007
+ * base-class shape gives callers full `.get()` / `.list()` type
1008
+ * safety here.
1009
+ *
1010
+ * R5-canon: hardcode the base Asset's qualified key so a different
1011
+ * package also registering a class called `Asset` can't be picked
1012
+ * by `findClass`'s multi-strategy fallback. Crucially we DON'T
1013
+ * resolve via `this.constructor._smrtQualifiedName` — for an STI
1014
+ * subclass like `Image`, that would yield the Image collection
1015
+ * (which auto-filters `_meta_type = '...:Image'` on `get`/`list`),
1016
+ * and `getSource()` / `getDerivatives()` would miss cross-type
1017
+ * derivation links (Image derived from a plain Asset, etc.).
1018
+ * `sourceAssetId` is a base-table derivation link, so it always
1019
+ * resolves through the base Asset collection.
1020
+ */
1021
+ async _assetCollection() {
1022
+ return await ObjectRegistry.getCollection("@happyvertical/smrt-assets:Asset", this.options);
1023
+ }
1024
+ /**
1025
+ * Get the source asset this one was derived from, if any.
1026
+ *
1027
+ * Renamed from `getParent` in R3-D. The relationship is "I was produced
1028
+ * from that asset" (e.g. a thumbnail's source is its original image),
1029
+ * not a structural-hierarchy parent.
1030
+ *
1031
+ * Goes through the AssetCollection so tenant interceptors and ORM
1032
+ * hydration apply — important because a tenant-scoped consumer with
1033
+ * cross-tenant derivative chains would otherwise return assets from
1034
+ * tenants the caller cannot see, and a raw `db.get` returns
1035
+ * snake_case rows that leave camelCase props (e.g. `sourceUri`) at
1036
+ * their constructor defaults.
1037
+ *
1038
+ * @returns Source Asset instance, or null if this asset has no source
1039
+ */
1040
+ async getSource() {
1041
+ if (!this.sourceAssetId) return null;
1042
+ return await (await this._assetCollection()).get({ id: this.sourceAssetId });
1043
+ }
1044
+ /**
1045
+ * Get all assets derived from this one (e.g. thumbnails, variants,
1046
+ * transcodes, AI edits).
1047
+ *
1048
+ * Renamed from `getChildren` in R3-D to match the derivation
1049
+ * semantics. Goes through the AssetCollection so tenant interceptors
1050
+ * and ORM hydration apply (see `getSource` for why this matters —
1051
+ * the pre-R3-D `getChildren` used raw `db.list`, which both bypassed
1052
+ * tenant scoping and dropped camelCase property hydration; that
1053
+ * latent breakage is fixed here).
1054
+ *
1055
+ * @returns Array of derivative Asset instances
1056
+ */
1057
+ async getDerivatives() {
1058
+ if (!this.id) return [];
1059
+ return await (await this._assetCollection()).list({ where: { sourceAssetId: this.id } });
1060
+ }
1061
+ /**
1062
+ * Get the type of this asset
1063
+ *
1064
+ * @returns AssetType instance or null
1065
+ */
1066
+ async getType() {
1067
+ if (!this.typeSlug) return null;
1068
+ return await AssetType.getBySlug(this.typeSlug);
1069
+ }
1070
+ /**
1071
+ * Get the status of this asset
1072
+ *
1073
+ * @returns AssetStatus instance or null
1074
+ */
1075
+ async getStatus() {
1076
+ if (!this.statusSlug) return null;
1077
+ return await AssetStatus.getBySlug(this.statusSlug);
1078
+ }
1079
+ /**
1080
+ * Get all associations for this asset
1081
+ *
1082
+ * @returns Array of AssetAssociation instances
1083
+ */
1084
+ async getAssociations() {
1085
+ return await (await AssetAssociationCollection.create({ db: this.db })).byRight(this.id);
1086
+ }
1087
+ /**
1088
+ * Associate this asset with a target object
1089
+ *
1090
+ * @param metaType - Target class name or qualified name (e.g., 'Article' or '@pkg:Article')
1091
+ * @param metaId - Target object ID
1092
+ * @param role - Association role (default: 'default')
1093
+ * @returns The created AssetAssociation
1094
+ */
1095
+ async associateWith(metaType, metaId, role = "default") {
1096
+ return await (await AssetAssociationCollection.create({ db: this.db })).attach(metaType, metaId, this.id, { role });
1097
+ }
1098
+ /**
1099
+ * Get asset by slug
1100
+ *
1101
+ * @param slug - The slug to search for
1102
+ * @returns Asset instance or null
1103
+ */
1104
+ static async getBySlug(_slug) {
1105
+ return null;
1106
+ }
1107
+ };
1108
+ __decorateClass$2([tenantId({ nullable: true })], Asset.prototype, "tenantId", 2);
1109
+ __decorateClass$2([foreignKey("Asset")], Asset.prototype, "primaryVersionId", 2);
1110
+ __decorateClass$2([crossPackageRef("@happyvertical/smrt-profiles:Profile")], Asset.prototype, "ownerProfileId", 2);
1111
+ __decorateClass$2([foreignKey("Asset")], Asset.prototype, "sourceAssetId", 2);
1112
+ __decorateClass$2([foreignKey("Folder")], Asset.prototype, "folderId", 2);
1113
+ Asset = __decorateClass$2([TenantScoped({ mode: "optional" }), smrt({
1114
+ tableStrategy: "sti",
1115
+ api: { include: [
1116
+ "list",
1117
+ "get",
1118
+ "create",
1119
+ "update",
1120
+ "delete"
1121
+ ] },
1122
+ mcp: { include: [
1123
+ "list",
1124
+ "get",
1125
+ "create",
1126
+ "update"
1127
+ ] },
1128
+ cli: { skipApiCheck: true }
1129
+ })], Asset);
1130
+ var __defProp$1 = Object.defineProperty;
1131
+ var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
1132
+ var __decorateClass$1 = (decorators, target, key, kind) => {
1133
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
1134
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
1135
+ if (kind && result) __defProp$1(target, key, result);
1136
+ return result;
1137
+ };
1138
+ var AssetMetafield = class extends SmrtObject {
1139
+ name = "";
1140
+ validation = "";
1141
+ constructor(options = {}) {
1142
+ super(options);
1143
+ if (options.slug) this.slug = options.slug;
1144
+ if (options.name) this.name = options.name;
1145
+ if (options.validation) this.validation = options.validation;
1146
+ }
1147
+ /**
1148
+ * Get validation rules as parsed object
1149
+ *
1150
+ * @returns Parsed validation object or empty object if no validation
1151
+ */
1152
+ getValidation() {
1153
+ if (!this.validation) return {};
1154
+ try {
1155
+ return JSON.parse(this.validation);
1156
+ } catch {
1157
+ return {};
1158
+ }
1159
+ }
1160
+ /**
1161
+ * Set validation rules from object
1162
+ *
1163
+ * @param rules - Validation rules object
1164
+ */
1165
+ setValidation(rules) {
1166
+ this.validation = JSON.stringify(rules);
1167
+ }
1168
+ /**
1169
+ * Get asset metafield by slug
1170
+ *
1171
+ * @param slug - The slug to search for
1172
+ * @returns AssetMetafield instance or null
1173
+ */
1174
+ static async getBySlug(_slug) {
1175
+ return null;
1176
+ }
1177
+ };
1178
+ AssetMetafield = __decorateClass$1([smrt({
1179
+ tableStrategy: "sti",
1180
+ api: { include: [
1181
+ "list",
1182
+ "get",
1183
+ "create",
1184
+ "update",
1185
+ "delete"
1186
+ ] },
1187
+ mcp: { include: [
1188
+ "list",
1189
+ "get",
1190
+ "create"
1191
+ ] },
1192
+ cli: { skipApiCheck: true }
1193
+ })], AssetMetafield);
1194
+ var AssetCollection = class extends SmrtCollection {
1195
+ static _itemClass = Asset;
1196
+ /**
1197
+ * Find all assets belonging to a specific tenant
1198
+ *
1199
+ * @param tenantId - The tenant ID to filter by
1200
+ * @returns Array of assets belonging to this tenant
1201
+ */
1202
+ async findByTenant(tenantId) {
1203
+ return await this.list({ where: { tenantId } });
1204
+ }
1205
+ /**
1206
+ * Find all global assets (assets without a tenant).
1207
+ *
1208
+ * Routes through the shared tenant-global helper so it does not throw under
1209
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
1210
+ * flagged as an isolation violation). (#1600)
1211
+ *
1212
+ * @returns Array of global assets
1213
+ */
1214
+ async findGlobal() {
1215
+ return queryGlobal(this);
1216
+ }
1217
+ /**
1218
+ * Find assets belonging to a tenant plus all global assets.
1219
+ *
1220
+ * Fails closed if an active tenant context requests a different tenant's
1221
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
1222
+ *
1223
+ * @param tenantId - The tenant ID to include
1224
+ * @returns Array of tenant-specific and global assets
1225
+ */
1226
+ async findWithGlobals(tenantId) {
1227
+ return queryWithGlobals(this, tenantId, "Asset.findWithGlobals");
1228
+ }
1229
+ /**
1230
+ * Add a tag to an asset (uses @smrt/tags)
1231
+ *
1232
+ * @param assetId - The asset ID to tag
1233
+ * @param tagSlug - The tag slug from @smrt/tags
1234
+ */
1235
+ async addTag(assetId, tagSlug) {
1236
+ await this.db.upsert("asset_tags", ["asset_id", "tag_slug"], {
1237
+ asset_id: assetId,
1238
+ tag_slug: tagSlug,
1239
+ created_at: (/* @__PURE__ */ new Date()).toISOString()
1240
+ });
1241
+ }
1242
+ /**
1243
+ * Remove a tag from an asset
1244
+ *
1245
+ * @param assetId - The asset ID
1246
+ * @param tagSlug - The tag slug to remove
1247
+ */
1248
+ async removeTag(assetId, tagSlug) {
1249
+ await this.db.delete("asset_tags", {
1250
+ asset_id: assetId,
1251
+ tag_slug: tagSlug
1252
+ });
1253
+ }
1254
+ /**
1255
+ * Get all assets with a specific tag
1256
+ *
1257
+ * @param tagSlug - The tag slug to filter by
1258
+ * @returns Array of assets with this tag
1259
+ */
1260
+ async getByTag(tagSlug) {
1261
+ const rows = await this.db.list("asset_tags", { tag_slug: tagSlug });
1262
+ const assets = [];
1263
+ for (const row of rows) {
1264
+ const asset = await this.get({ id: row.asset_id });
1265
+ if (asset) assets.push(asset);
1266
+ }
1267
+ return assets;
1268
+ }
1269
+ /**
1270
+ * Get assets by type
1271
+ *
1272
+ * @param typeSlug - The asset type slug (e.g., 'image', 'video')
1273
+ * @returns Array of assets matching the type
1274
+ */
1275
+ async getByType(typeSlug) {
1276
+ return await this.list({ where: { typeSlug } });
1277
+ }
1278
+ /**
1279
+ * Get assets by status
1280
+ *
1281
+ * @param statusSlug - The asset status slug (e.g., 'published', 'draft')
1282
+ * @returns Array of assets matching the status
1283
+ */
1284
+ async getByStatus(statusSlug) {
1285
+ return await this.list({ where: { statusSlug } });
1286
+ }
1287
+ /**
1288
+ * Get assets by owner
1289
+ *
1290
+ * @param ownerProfileId - The profile ID of the owner
1291
+ * @returns Array of assets owned by this profile
1292
+ */
1293
+ async getByOwner(ownerProfileId) {
1294
+ return await this.list({ where: { ownerProfileId } });
1295
+ }
1296
+ /**
1297
+ * Create a new version of an existing asset
1298
+ *
1299
+ * @param primaryVersionId - The primary version ID (first version's ID)
1300
+ * @param newSourceUri - The new source URI for this version
1301
+ * @param updates - Optional additional updates
1302
+ * @returns The newly created asset version
1303
+ */
1304
+ async createNewVersion(primaryVersionId, newSourceUri, updates = {}) {
1305
+ const versions = await this.listVersions(primaryVersionId);
1306
+ if (versions.length === 0) throw new Error(`No asset found with primary version ID: ${primaryVersionId}`);
1307
+ versions.sort((a, b) => b.version - a.version);
1308
+ const latestVersion = versions[0];
1309
+ const newVersionNumber = latestVersion.version + 1;
1310
+ const primary = versions.find((v) => v.id === primaryVersionId) ?? versions[versions.length - 1];
1311
+ const baseSlug = String(primary?.slug ?? "") || "asset";
1312
+ const takenInChain = new Set(versions.map((v) => v.slug).filter(Boolean));
1313
+ let candidate = `${baseSlug}-v${newVersionNumber}`;
1314
+ for (let attempt = 1;; attempt += 1) {
1315
+ if (!(takenInChain.has(candidate) || await this.get({ slug: candidate }) !== null)) break;
1316
+ candidate = `${baseSlug}-v${newVersionNumber}-${attempt}`;
1317
+ }
1318
+ return await this.create({
1319
+ ...latestVersion,
1320
+ id: void 0,
1321
+ slug: candidate,
1322
+ sourceUri: newSourceUri,
1323
+ version: newVersionNumber,
1324
+ primaryVersionId,
1325
+ createdAt: /* @__PURE__ */ new Date(),
1326
+ updatedAt: /* @__PURE__ */ new Date(),
1327
+ ...updates
1328
+ });
1329
+ }
1330
+ /**
1331
+ * Get the latest version of an asset
1332
+ *
1333
+ * @param primaryVersionId - The primary version ID
1334
+ * @returns The latest version or null
1335
+ */
1336
+ async getLatestVersion(primaryVersionId) {
1337
+ const versions = await this.listVersions(primaryVersionId);
1338
+ if (versions.length === 0) return null;
1339
+ versions.sort((a, b) => b.version - a.version);
1340
+ return versions[0];
1341
+ }
1342
+ /**
1343
+ * List all versions of an asset
1344
+ *
1345
+ * @param primaryVersionId - The primary version ID
1346
+ * @returns Array of all asset versions, ordered by version number
1347
+ */
1348
+ async listVersions(primaryVersionId) {
1349
+ const [chained, primary] = await Promise.all([this.list({ where: { primaryVersionId } }), this.get({ id: primaryVersionId })]);
1350
+ const byId = /* @__PURE__ */ new Map();
1351
+ for (const asset of [...primary ? [primary] : [], ...chained]) if (asset?.id) byId.set(asset.id, asset);
1352
+ const assets = Array.from(byId.values());
1353
+ assets.sort((a, b) => a.version - b.version);
1354
+ return assets;
1355
+ }
1356
+ /**
1357
+ * Get derivative assets of a source asset.
1358
+ *
1359
+ * Renamed from `getChildren(parentId)` in R3-D to match the rename of
1360
+ * the underlying column (`parent_id` → `source_asset_id`) and method
1361
+ * (`Asset.getChildren` → `Asset.getDerivatives`).
1362
+ *
1363
+ * @param sourceAssetId - The source asset ID
1364
+ * @returns Array of derivative assets
1365
+ */
1366
+ async getDerivatives(sourceAssetId) {
1367
+ return await this.list({ where: { sourceAssetId } });
1368
+ }
1369
+ /**
1370
+ * Get assets by MIME type pattern
1371
+ *
1372
+ * @param mimePattern - MIME type pattern (e.g., 'image/*', 'video/mp4')
1373
+ * @returns Array of matching assets
1374
+ */
1375
+ async getByMimeType(mimePattern) {
1376
+ const pattern = mimePattern.replace("*", "%");
1377
+ return await this.list({ where: { "mimeType like": pattern } });
1378
+ }
1379
+ /**
1380
+ * Rollback to a previous version by creating a new version with the target's content.
1381
+ * Does NOT delete intermediate versions (safe rollback).
1382
+ *
1383
+ * @param primaryVersionId - The primary version ID of the version chain
1384
+ * @param targetVersion - The version number to rollback to
1385
+ * @returns The newly created asset version with content copied from target
1386
+ */
1387
+ async rollbackToVersion(primaryVersionId, targetVersion) {
1388
+ const target = (await this.listVersions(primaryVersionId)).find((v) => v.version === targetVersion);
1389
+ if (!target) throw new Error(`Version ${targetVersion} not found for asset ${primaryVersionId}`);
1390
+ return await this.createNewVersion(primaryVersionId, target.sourceUri, { description: `Rollback to version ${targetVersion}` });
1391
+ }
1392
+ /**
1393
+ * Get assets in a specific folder
1394
+ *
1395
+ * @param folderId - The folder ID to list contents for
1396
+ * @returns Array of assets in this folder
1397
+ */
1398
+ async getByFolder(folderId) {
1399
+ return await this.list({ where: { folderId } });
1400
+ }
1401
+ };
1402
+ var __defProp = Object.defineProperty;
1403
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
1404
+ var __decorateClass = (decorators, target, key, kind) => {
1405
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
1406
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
1407
+ if (kind && result) __defProp(target, key, result);
1408
+ return result;
1409
+ };
1410
+ var Folder = class extends SmrtHierarchical {
1411
+ tenantId = null;
1412
+ name = "";
1413
+ description = "";
1414
+ ownerProfileId = null;
1415
+ createdAt = /* @__PURE__ */ new Date();
1416
+ updatedAt = /* @__PURE__ */ new Date();
1417
+ constructor(options = {}) {
1418
+ super(options);
1419
+ if (options.name !== void 0) this.name = options.name;
1420
+ if (options.slug !== void 0) this.slug = options.slug;
1421
+ if (options.description !== void 0) this.description = options.description;
1422
+ if (options.parentId !== void 0) this.parentId = options.parentId ?? null;
1423
+ if (options.ownerProfileId !== void 0) this.ownerProfileId = options.ownerProfileId;
1424
+ if (options.tenantId !== void 0) this.tenantId = options.tenantId;
1425
+ if (options.createdAt) this.createdAt = options.createdAt;
1426
+ if (options.updatedAt) this.updatedAt = options.updatedAt;
1427
+ }
1428
+ /**
1429
+ * Look up a folder by slug.
1430
+ */
1431
+ static async getBySlug(_slug) {
1432
+ return null;
1433
+ }
1434
+ };
1435
+ __decorateClass([tenantId({ nullable: true })], Folder.prototype, "tenantId", 2);
1436
+ __decorateClass([crossPackageRef("@happyvertical/smrt-profiles:Profile")], Folder.prototype, "ownerProfileId", 2);
1437
+ Folder = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
1438
+ api: { include: [
1439
+ "list",
1440
+ "get",
1441
+ "create",
1442
+ "update",
1443
+ "delete"
1444
+ ] },
1445
+ mcp: { include: [
1446
+ "list",
1447
+ "get",
1448
+ "create",
1449
+ "update"
1450
+ ] },
1451
+ cli: { skipApiCheck: true }
1452
+ })], Folder);
1453
+ var OWNED_ASSET_RELATIONSHIP_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
1454
+ function assertValidOwnedAssetRelationship(relationship) {
1455
+ if (!OWNED_ASSET_RELATIONSHIP_PATTERN.test(relationship)) throw new Error(`Invalid relationship type "${relationship}"; must start with a letter or underscore and contain only letters, digits, and underscores`);
1456
+ }
1457
+ function assertValidOwnedAssetSortOrder(sortOrder) {
1458
+ if (!Number.isInteger(sortOrder) || sortOrder < 0 || sortOrder > 2147483647) throw new Error(`Invalid sortOrder "${sortOrder}"; must be a non-negative integer`);
1459
+ }
1460
+ async function resolveOwnedAssetsById(db, assetIds, tenantId) {
1461
+ if (assetIds.length === 0) return [];
1462
+ const assets = await AssetCollection.create({ db });
1463
+ const resolved = tenantId ? await withSystemContext(async () => assets.listByIds(assetIds)) : await assets.listByIds(assetIds);
1464
+ const visibleAssets = tenantId ? resolved.filter((asset) => asset.tenantId === tenantId || asset.tenantId === null) : resolved;
1465
+ const assetsById = new Map(visibleAssets.filter((asset) => asset.id).map((asset) => [asset.id, asset]));
1466
+ return assetIds.map((assetId) => assetsById.get(assetId)).filter(Boolean);
1467
+ }
1468
+ async function getOwnerRecord(collection, ownerId) {
1469
+ return collection.get({ id: ownerId });
1470
+ }
1471
+ async function getOwnedAssetsFromCollection(collection, ownerId, relationship) {
1472
+ const owner = await getOwnerRecord(collection, ownerId);
1473
+ if (!owner) return [];
1474
+ return owner.getAssets(relationship);
1475
+ }
1476
+ async function addOwnedAssetFromCollection(collection, ownerType, ownerId, asset, relationship = "attachment", sortOrder = 0) {
1477
+ const owner = await getOwnerRecord(collection, ownerId);
1478
+ if (!owner) throw new Error(`${ownerType} '${ownerId}' not found`);
1479
+ await owner.addAsset(asset, relationship, sortOrder);
1480
+ }
1481
+ async function removeOwnedAssetFromCollection(collection, ownerType, ownerId, assetId, relationship) {
1482
+ const owner = await getOwnerRecord(collection, ownerId);
1483
+ if (!owner) throw new Error(`${ownerType} '${ownerId}' not found`);
1484
+ await owner.removeAsset(assetId, relationship);
1485
+ }
1486
+ //#endregion
1487
+ export { removeOwnedAssetFromCollection as a, getOwnedAssetsFromCollection as i, assertValidOwnedAssetRelationship as n, resolveOwnedAssetsById as o, assertValidOwnedAssetSortOrder as r, addOwnedAssetFromCollection as t };