{
  "schemaVersion": 1,
  "sensitiveFieldsExcluded": true,
  "generatedAt": "1970-01-01T00:00:00.000Z",
  "packageName": "@happyvertical/smrt-products",
  "packageVersion": "0.42.6",
  "sourceManifestPath": "dist/lib/manifest.json",
  "agentDocPath": "AGENTS.md",
  "sourceHashes": {
    "manifest": "2b49e478d996a7208d1bb9e0e642680c7ca98ff5910915b26b80c14392446465",
    "packageJson": "375735b4236a70f00f7e89d65429e0c531a2202f16be63580c44fb566b105053",
    "agents": "4ddde01c48baf13de773cdb57353a148f3fe3b93d21e99d8ac57677cda809e26"
  },
  "exports": [
    ".",
    "./collections",
    "./components",
    "./generated",
    "./manifest",
    "./manifest.json",
    "./models",
    "./stores",
    "./stores/product-collection",
    "./utils"
  ],
  "dependencies": {
    "@happyvertical/ai": "catalog:",
    "@happyvertical/files": "catalog:",
    "@happyvertical/logger": "catalog:",
    "@happyvertical/smrt-assets": "workspace:*",
    "@happyvertical/smrt-core": "workspace:*",
    "@happyvertical/smrt-scanner": "workspace:*",
    "@happyvertical/smrt-svelte": "workspace:*",
    "@happyvertical/smrt-tenancy": "workspace:*",
    "@happyvertical/smrt-ui": "workspace:*",
    "@happyvertical/smrt-web": "workspace:*",
    "@happyvertical/sql": "catalog:",
    "@happyvertical/utils": "catalog:",
    "cors": "^2.8.6",
    "express": "^5.2.1",
    "@originjs/vite-plugin-federation": "^1.4.1",
    "@sveltejs/package": "^2.5.8",
    "@sveltejs/vite-plugin-svelte": "^7.1.2",
    "@types/cors": "2.8.19",
    "@types/express": "^5.0.6",
    "@types/node": "24.13.2",
    "@happyvertical/smrt-vitest": "workspace:*",
    "concurrently": "^9.2.3",
    "svelte": "^5.56.4",
    "svelte-check": "^4.7.1",
    "typescript": "5.9.3",
    "vite": "8.1.4",
    "vitest": "4.1.10"
  },
  "smrtDependencies": [
    "@happyvertical/smrt-assets",
    "@happyvertical/smrt-core",
    "@happyvertical/smrt-scanner",
    "@happyvertical/smrt-svelte",
    "@happyvertical/smrt-tenancy",
    "@happyvertical/smrt-ui",
    "@happyvertical/smrt-vitest",
    "@happyvertical/smrt-web"
  ],
  "sdkDependencies": [
    "@happyvertical/ai",
    "@happyvertical/files",
    "@happyvertical/logger",
    "@happyvertical/sql",
    "@happyvertical/utils"
  ],
  "tags": [],
  "risks": [],
  "objects": [
    {
      "name": "CategoryCollection",
      "qualifiedName": "@happyvertical/smrt-products:CategoryCollection",
      "collection": "categories",
      "tableName": "category_collections",
      "packageName": "@happyvertical/smrt-products",
      "extends": "SmrtCollection",
      "fields": [],
      "relationships": [],
      "methods": [
        "getRootCategories"
      ],
      "methodSignatures": [
        {
          "name": "getRootCategories",
          "async": true,
          "returns": "Promise<Category[]>"
        }
      ],
      "surfaces": [],
      "relationshipFeatures": [
        "uuidColumns"
      ],
      "tags": [],
      "risks": []
    },
    {
      "name": "MaterialCollection",
      "qualifiedName": "@happyvertical/smrt-products:MaterialCollection",
      "collection": "products",
      "tableName": "products",
      "packageName": "@happyvertical/smrt-products",
      "extends": "ProductCollection",
      "fields": [],
      "relationships": [],
      "methods": [
        "findByKind"
      ],
      "methodSignatures": [
        {
          "name": "findByKind",
          "async": true,
          "params": [
            "materialKind: MaterialKind"
          ],
          "returns": "Promise<Material[]>"
        }
      ],
      "surfaces": [],
      "relationshipFeatures": [
        "uuidColumns"
      ],
      "tags": [],
      "risks": []
    },
    {
      "name": "ProductAssetCollection",
      "qualifiedName": "@happyvertical/smrt-products:ProductAssetCollection",
      "collection": "productassets",
      "tableName": "product_assets",
      "packageName": "@happyvertical/smrt-products",
      "extends": "SmrtJunction",
      "fields": [],
      "relationships": [],
      "methods": [
        "addAsset",
        "attach",
        "byLeft",
        "byRight",
        "detach",
        "getAssets",
        "removeAsset",
        "setLinks"
      ],
      "methodSignatures": [
        {
          "name": "addAsset",
          "async": true,
          "params": [
            "productId: string",
            "asset: Asset",
            "relationship?: any",
            "sortOrder?: any"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "attach",
          "async": true,
          "params": [
            "leftId: string",
            "rightId: string",
            "opts?: JunctionAttachOptions"
          ],
          "returns": "Promise<TItem>"
        },
        {
          "name": "byLeft",
          "async": true,
          "params": [
            "leftId: string",
            "opts?: JunctionFilterOptions"
          ],
          "returns": "Promise<TItem[]>"
        },
        {
          "name": "byRight",
          "async": true,
          "params": [
            "rightId: string",
            "opts?: JunctionFilterOptions"
          ],
          "returns": "Promise<TItem[]>"
        },
        {
          "name": "detach",
          "async": true,
          "params": [
            "leftId: string",
            "rightId: string",
            "opts?: JunctionFilterOptions"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "getAssets",
          "async": true,
          "params": [
            "productId: string",
            "relationship?: string"
          ],
          "returns": "Promise<Asset[]>"
        },
        {
          "name": "removeAsset",
          "async": true,
          "params": [
            "productId: string",
            "assetId: string",
            "relationship?: string"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "setLinks",
          "async": true,
          "params": [
            "leftId: string",
            "rightIds: string[]",
            "opts?: JunctionAttachOptions"
          ],
          "returns": "Promise<void>"
        }
      ],
      "surfaces": [],
      "relationshipFeatures": [
        "SmrtJunction",
        "uuidColumns"
      ],
      "tags": [],
      "risks": []
    },
    {
      "name": "ProductCollection",
      "qualifiedName": "@happyvertical/smrt-products:ProductCollection",
      "collection": "products",
      "tableName": "product_collections",
      "packageName": "@happyvertical/smrt-products",
      "extends": "SmrtCollection",
      "fields": [],
      "relationships": [],
      "methods": [
        "addAsset",
        "findByManufacturer",
        "findInStock",
        "getAssets",
        "removeAsset"
      ],
      "methodSignatures": [
        {
          "name": "addAsset",
          "async": true,
          "params": [
            "productId: string",
            "asset: Asset",
            "relationship?: any",
            "sortOrder?: any"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "findByManufacturer",
          "async": true,
          "params": [
            "manufacturer: string"
          ],
          "returns": "Promise<Product[]>"
        },
        {
          "name": "findInStock",
          "async": true,
          "returns": "Promise<Product[]>"
        },
        {
          "name": "getAssets",
          "async": true,
          "params": [
            "productId: string",
            "relationship?: string"
          ],
          "returns": "Promise<Asset[]>"
        },
        {
          "name": "removeAsset",
          "async": true,
          "params": [
            "productId: string",
            "assetId: string",
            "relationship?: string"
          ],
          "returns": "Promise<void>"
        }
      ],
      "surfaces": [],
      "relationshipFeatures": [
        "uuidColumns"
      ],
      "tags": [],
      "risks": []
    },
    {
      "name": "ProductVariantCollection",
      "qualifiedName": "@happyvertical/smrt-products:ProductVariantCollection",
      "collection": "productvariants",
      "tableName": "product_variants",
      "packageName": "@happyvertical/smrt-products",
      "extends": "SmrtCollection",
      "fields": [],
      "relationships": [],
      "methods": [
        "findAxis",
        "findForProduct"
      ],
      "methodSignatures": [
        {
          "name": "findAxis",
          "async": true,
          "params": [
            "productId: string",
            "axisName: string"
          ],
          "returns": "Promise<ProductVariant | null>"
        },
        {
          "name": "findForProduct",
          "async": true,
          "params": [
            "productId: string"
          ],
          "returns": "Promise<ProductVariant[]>"
        }
      ],
      "surfaces": [],
      "relationshipFeatures": [
        "uuidColumns"
      ],
      "tags": [],
      "risks": []
    },
    {
      "name": "SkuCollection",
      "qualifiedName": "@happyvertical/smrt-products:SkuCollection",
      "collection": "skus",
      "tableName": "product_skus",
      "packageName": "@happyvertical/smrt-products",
      "extends": "SmrtCollection",
      "fields": [],
      "relationships": [],
      "methods": [
        "findActive",
        "findByBarcode",
        "findByCode",
        "findByParent",
        "findByProduct"
      ],
      "methodSignatures": [
        {
          "name": "findActive",
          "async": true,
          "params": [
            "productId?: string"
          ],
          "returns": "Promise<Sku[]>"
        },
        {
          "name": "findByBarcode",
          "async": true,
          "params": [
            "barcode: string"
          ],
          "returns": "Promise<Sku | null>"
        },
        {
          "name": "findByCode",
          "async": true,
          "params": [
            "code: string"
          ],
          "returns": "Promise<Sku | null>"
        },
        {
          "name": "findByParent",
          "async": true,
          "params": [
            "parentSkuId: string"
          ],
          "returns": "Promise<Sku[]>"
        },
        {
          "name": "findByProduct",
          "async": true,
          "params": [
            "productId: string"
          ],
          "returns": "Promise<Sku[]>"
        }
      ],
      "surfaces": [],
      "relationshipFeatures": [
        "uuidColumns"
      ],
      "tags": [],
      "risks": []
    },
    {
      "name": "Category",
      "qualifiedName": "@happyvertical/smrt-products:Category",
      "collection": "categories",
      "tableName": "categories",
      "packageName": "@happyvertical/smrt-products",
      "extends": "SmrtObject",
      "fields": [
        {
          "name": "created_at",
          "type": "datetime",
          "required": false,
          "columnType": "TIMESTAMP"
        },
        {
          "name": "updated_at",
          "type": "datetime",
          "required": false,
          "columnType": "TIMESTAMP"
        },
        {
          "name": "tenantId",
          "type": "text",
          "required": false,
          "columnType": "UUID"
        },
        {
          "name": "name",
          "type": "text",
          "required": false,
          "columnType": "TEXT"
        },
        {
          "name": "description",
          "type": "text",
          "required": false,
          "columnType": "TEXT"
        },
        {
          "name": "parentId",
          "type": "foreignKey",
          "required": false,
          "related": "Category",
          "columnType": "UUID"
        },
        {
          "name": "level",
          "type": "integer",
          "required": true,
          "columnType": "INTEGER",
          "default": 0
        },
        {
          "name": "productCount",
          "type": "integer",
          "required": true,
          "columnType": "INTEGER",
          "default": 0
        },
        {
          "name": "active",
          "type": "boolean",
          "required": true,
          "columnType": "BOOLEAN",
          "default": true
        }
      ],
      "relationships": [
        {
          "name": "parentId",
          "type": "foreignKey",
          "required": false,
          "related": "Category",
          "columnType": "UUID"
        }
      ],
      "methods": [
        "_setLoadedRelationship",
        "classifyConstraintError",
        "clearEmbeddings",
        "delete",
        "describe",
        "destroy",
        "do",
        "executeToolCall",
        "forget",
        "forgetScope",
        "generateEmbeddings",
        "getAiUsageSnapshot",
        "getAvailableTools",
        "getEmbedding",
        "getFields",
        "getId",
        "getRelated",
        "getSavedId",
        "getSlug",
        "hasStaleEmbeddings",
        "initialize",
        "is",
        "isRelatedLoaded",
        "isSaved",
        "listAiUsage",
        "loadDataFromDb",
        "loadFromId",
        "loadFromSlug",
        "loadRelated",
        "loadRelatedMany",
        "markAsPersisted",
        "recall",
        "recallAll",
        "remember",
        "requireInsertOnSave",
        "resetAiUsage",
        "save",
        "summarizeAiUsage",
        "toJSON",
        "toPlainObject",
        "toPublicJSON"
      ],
      "methodSignatures": [
        {
          "name": "_setLoadedRelationship",
          "params": [
            "fieldName: string",
            "value: any"
          ],
          "returns": "void"
        },
        {
          "name": "classifyConstraintError",
          "static": true,
          "params": [
            "message: string"
          ],
          "returns": "'unique' | 'not_null' | null"
        },
        {
          "name": "clearEmbeddings",
          "async": true,
          "returns": "Promise<void>"
        },
        {
          "name": "delete",
          "async": true,
          "returns": "Promise<void>"
        },
        {
          "name": "describe",
          "async": true,
          "params": [
            "options?: AiOperationOptions"
          ],
          "returns": "any"
        },
        {
          "name": "destroy",
          "returns": "void"
        },
        {
          "name": "do",
          "async": true,
          "params": [
            "instructions: string",
            "options?: AiOperationOptions"
          ],
          "returns": "any"
        },
        {
          "name": "executeToolCall",
          "async": true,
          "params": [
            "toolCall: ToolCall"
          ],
          "returns": "Promise<ToolCallResult>"
        },
        {
          "name": "forget",
          "async": true,
          "params": [
            "options: object"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "forgetScope",
          "async": true,
          "params": [
            "options: object"
          ],
          "returns": "Promise<number>"
        },
        {
          "name": "generateEmbeddings",
          "async": true,
          "params": [
            "options?: GenerateEmbeddingsOptions"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "getAiUsageSnapshot",
          "returns": "AiUsageSnapshot | undefined"
        },
        {
          "name": "getAvailableTools",
          "returns": "AITool[]"
        },
        {
          "name": "getEmbedding",
          "async": true,
          "params": [
            "fieldName: string",
            "model?: string"
          ],
          "returns": "Promise<number[] | null>"
        },
        {
          "name": "getFields",
          "async": true,
          "returns": "Promise<any>"
        },
        {
          "name": "getId",
          "async": true,
          "returns": "any"
        },
        {
          "name": "getRelated",
          "async": true,
          "params": [
            "fieldName: string",
            "opts?: LoadRelatedOptions"
          ],
          "returns": "Promise<any>"
        },
        {
          "name": "getSavedId",
          "async": true,
          "returns": "any"
        },
        {
          "name": "getSlug",
          "async": true,
          "returns": "any"
        },
        {
          "name": "hasStaleEmbeddings",
          "async": true,
          "returns": "Promise<boolean>"
        },
        {
          "name": "initialize",
          "async": true,
          "returns": "Promise"
        },
        {
          "name": "is",
          "async": true,
          "params": [
            "criteria: string",
            "options?: AiOperationOptions"
          ],
          "returns": "any"
        },
        {
          "name": "isRelatedLoaded",
          "params": [
            "fieldName: string"
          ],
          "returns": "boolean"
        },
        {
          "name": "isSaved",
          "async": true,
          "returns": "any"
        },
        {
          "name": "listAiUsage",
          "async": true,
          "params": [
            "options?: AiUsageListOptions"
          ],
          "returns": "Promise<SmrtAiUsageRecord[]>"
        },
        {
          "name": "loadDataFromDb",
          "async": true,
          "params": [
            "data: Record<string>"
          ],
          "returns": "any"
        },
        {
          "name": "loadFromId",
          "async": true,
          "returns": "any"
        },
        {
          "name": "loadFromSlug",
          "async": true,
          "returns": "any"
        },
        {
          "name": "loadRelated",
          "async": true,
          "params": [
            "fieldName: string",
            "opts?: LoadRelatedOptions"
          ],
          "returns": "Promise<any>"
        },
        {
          "name": "loadRelatedMany",
          "async": true,
          "params": [
            "fieldName: string",
            "opts?: LoadRelatedOptions"
          ],
          "returns": "Promise<any[]>"
        },
        {
          "name": "markAsPersisted",
          "returns": "void"
        },
        {
          "name": "recall",
          "async": true,
          "params": [
            "options: object"
          ],
          "returns": "Promise"
        },
        {
          "name": "recallAll",
          "async": true,
          "params": [
            "options?: object"
          ],
          "returns": "Promise<Map<string>>"
        },
        {
          "name": "remember",
          "async": true,
          "params": [
            "options: object"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "requireInsertOnSave",
          "returns": "void"
        },
        {
          "name": "resetAiUsage",
          "returns": "void"
        },
        {
          "name": "save",
          "async": true,
          "returns": "any"
        },
        {
          "name": "summarizeAiUsage",
          "async": true,
          "params": [
            "options?: AiUsageSummaryOptions"
          ],
          "returns": "Promise<Record<string, AiUsageStats>>"
        },
        {
          "name": "toJSON",
          "returns": "any"
        },
        {
          "name": "toPlainObject",
          "returns": "Record<string>"
        },
        {
          "name": "toPublicJSON",
          "params": [
            "options?: PublicJsonOptions"
          ],
          "returns": "Record<string>"
        }
      ],
      "tenant": {
        "scoped": true,
        "mode": "optional",
        "field": "tenantId"
      },
      "tableStrategy": "sti",
      "conflictColumns": [
        "tenant_id",
        "slug",
        "context",
        "_meta_type"
      ],
      "surfaces": [
        {
          "kind": "api",
          "name": "categories.list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:Category",
          "path": "/categories",
          "method": "GET"
        },
        {
          "kind": "api",
          "name": "categories.get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:Category",
          "path": "/categories/[id]",
          "method": "GET"
        },
        {
          "kind": "api",
          "name": "categories.create",
          "operation": "create",
          "objectName": "@happyvertical/smrt-products:Category",
          "path": "/categories",
          "method": "POST"
        },
        {
          "kind": "api",
          "name": "categories.update",
          "operation": "update",
          "objectName": "@happyvertical/smrt-products:Category",
          "path": "/categories/[id]",
          "method": "PATCH"
        },
        {
          "kind": "cli",
          "name": "category_list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:Category"
        },
        {
          "kind": "cli",
          "name": "category_get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:Category"
        },
        {
          "kind": "cli",
          "name": "category_create",
          "operation": "create",
          "objectName": "@happyvertical/smrt-products:Category"
        },
        {
          "kind": "cli",
          "name": "category_update",
          "operation": "update",
          "objectName": "@happyvertical/smrt-products:Category"
        },
        {
          "kind": "cli",
          "name": "category_delete",
          "operation": "delete",
          "objectName": "@happyvertical/smrt-products:Category"
        },
        {
          "kind": "mcp",
          "name": "category_list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:Category"
        },
        {
          "kind": "mcp",
          "name": "category_get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:Category"
        }
      ],
      "relationshipFeatures": [
        "foreignKey",
        "uuidColumns"
      ],
      "tags": [],
      "risks": []
    },
    {
      "name": "Material",
      "qualifiedName": "@happyvertical/smrt-products:Material",
      "collection": "products",
      "tableName": "products",
      "packageName": "@happyvertical/smrt-products",
      "extends": "Product",
      "fields": [
        {
          "name": "created_at",
          "type": "datetime",
          "required": false,
          "columnType": "TIMESTAMP"
        },
        {
          "name": "updated_at",
          "type": "datetime",
          "required": false,
          "columnType": "TIMESTAMP"
        },
        {
          "name": "tenantId",
          "type": "text",
          "required": false,
          "columnType": "UUID"
        },
        {
          "name": "productType",
          "type": "text",
          "required": false,
          "columnType": "TEXT"
        },
        {
          "name": "name",
          "type": "text",
          "required": false,
          "columnType": "TEXT"
        },
        {
          "name": "description",
          "type": "text",
          "required": false,
          "columnType": "TEXT"
        },
        {
          "name": "category",
          "type": "text",
          "required": false,
          "columnType": "TEXT"
        },
        {
          "name": "manufacturer",
          "type": "text",
          "required": false,
          "columnType": "TEXT"
        },
        {
          "name": "model",
          "type": "text",
          "required": false,
          "columnType": "TEXT"
        },
        {
          "name": "price",
          "type": "integer",
          "required": true,
          "columnType": "INTEGER",
          "default": 0
        },
        {
          "name": "inStock",
          "type": "boolean",
          "required": true,
          "columnType": "BOOLEAN",
          "default": true
        },
        {
          "name": "specifications",
          "type": "json",
          "required": false,
          "columnType": "JSON",
          "default": {}
        },
        {
          "name": "tags",
          "type": "json",
          "required": false,
          "columnType": "JSON",
          "default": []
        },
        {
          "name": "materialKind",
          "type": "meta",
          "required": false,
          "default": "component"
        },
        {
          "name": "uom",
          "type": "meta",
          "required": false,
          "default": "each"
        },
        {
          "name": "costPerUnit",
          "type": "meta",
          "required": false,
          "default": 0
        }
      ],
      "relationships": [],
      "methods": [
        "_setLoadedRelationship",
        "addAsset",
        "classifyConstraintError",
        "clearEmbeddings",
        "delete",
        "describe",
        "destroy",
        "do",
        "executeToolCall",
        "forget",
        "forgetScope",
        "generateEmbeddings",
        "getAiUsageSnapshot",
        "getAssets",
        "getAvailableTools",
        "getEmbedding",
        "getFields",
        "getId",
        "getRelated",
        "getSavedId",
        "getSlug",
        "getSpecification",
        "hasStaleEmbeddings",
        "initialize",
        "is",
        "isRelatedLoaded",
        "isSaved",
        "listAiUsage",
        "loadDataFromDb",
        "loadFromId",
        "loadFromSlug",
        "loadRelated",
        "loadRelatedMany",
        "markAsPersisted",
        "recall",
        "recallAll",
        "remember",
        "removeAsset",
        "requireInsertOnSave",
        "resetAiUsage",
        "save",
        "summarizeAiUsage",
        "toJSON",
        "toPlainObject",
        "toPublicJSON",
        "updateSpecification"
      ],
      "methodSignatures": [
        {
          "name": "_setLoadedRelationship",
          "params": [
            "fieldName: string",
            "value: any"
          ],
          "returns": "void"
        },
        {
          "name": "addAsset",
          "async": true,
          "params": [
            "asset: Asset",
            "relationship?: any",
            "sortOrder?: any"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "classifyConstraintError",
          "static": true,
          "params": [
            "message: string"
          ],
          "returns": "'unique' | 'not_null' | null"
        },
        {
          "name": "clearEmbeddings",
          "async": true,
          "returns": "Promise<void>"
        },
        {
          "name": "delete",
          "async": true,
          "returns": "Promise<void>"
        },
        {
          "name": "describe",
          "async": true,
          "params": [
            "options?: AiOperationOptions"
          ],
          "returns": "any"
        },
        {
          "name": "destroy",
          "returns": "void"
        },
        {
          "name": "do",
          "async": true,
          "params": [
            "instructions: string",
            "options?: AiOperationOptions"
          ],
          "returns": "any"
        },
        {
          "name": "executeToolCall",
          "async": true,
          "params": [
            "toolCall: ToolCall"
          ],
          "returns": "Promise<ToolCallResult>"
        },
        {
          "name": "forget",
          "async": true,
          "params": [
            "options: object"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "forgetScope",
          "async": true,
          "params": [
            "options: object"
          ],
          "returns": "Promise<number>"
        },
        {
          "name": "generateEmbeddings",
          "async": true,
          "params": [
            "options?: GenerateEmbeddingsOptions"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "getAiUsageSnapshot",
          "returns": "AiUsageSnapshot | undefined"
        },
        {
          "name": "getAssets",
          "async": true,
          "params": [
            "relationship?: string"
          ],
          "returns": "Promise<Asset[]>"
        },
        {
          "name": "getAvailableTools",
          "returns": "AITool[]"
        },
        {
          "name": "getEmbedding",
          "async": true,
          "params": [
            "fieldName: string",
            "model?: string"
          ],
          "returns": "Promise<number[] | null>"
        },
        {
          "name": "getFields",
          "async": true,
          "returns": "Promise<any>"
        },
        {
          "name": "getId",
          "async": true,
          "returns": "any"
        },
        {
          "name": "getRelated",
          "async": true,
          "params": [
            "fieldName: string",
            "opts?: LoadRelatedOptions"
          ],
          "returns": "Promise<any>"
        },
        {
          "name": "getSavedId",
          "async": true,
          "returns": "any"
        },
        {
          "name": "getSlug",
          "async": true,
          "returns": "any"
        },
        {
          "name": "getSpecification",
          "async": true,
          "params": [
            "key: string"
          ],
          "returns": "Promise"
        },
        {
          "name": "hasStaleEmbeddings",
          "async": true,
          "returns": "Promise<boolean>"
        },
        {
          "name": "initialize",
          "async": true,
          "returns": "Promise"
        },
        {
          "name": "is",
          "async": true,
          "params": [
            "criteria: string",
            "options?: AiOperationOptions"
          ],
          "returns": "any"
        },
        {
          "name": "isRelatedLoaded",
          "params": [
            "fieldName: string"
          ],
          "returns": "boolean"
        },
        {
          "name": "isSaved",
          "async": true,
          "returns": "any"
        },
        {
          "name": "listAiUsage",
          "async": true,
          "params": [
            "options?: AiUsageListOptions"
          ],
          "returns": "Promise<SmrtAiUsageRecord[]>"
        },
        {
          "name": "loadDataFromDb",
          "async": true,
          "params": [
            "data: Record<string>"
          ],
          "returns": "any"
        },
        {
          "name": "loadFromId",
          "async": true,
          "returns": "any"
        },
        {
          "name": "loadFromSlug",
          "async": true,
          "returns": "any"
        },
        {
          "name": "loadRelated",
          "async": true,
          "params": [
            "fieldName: string",
            "opts?: LoadRelatedOptions"
          ],
          "returns": "Promise<any>"
        },
        {
          "name": "loadRelatedMany",
          "async": true,
          "params": [
            "fieldName: string",
            "opts?: LoadRelatedOptions"
          ],
          "returns": "Promise<any[]>"
        },
        {
          "name": "markAsPersisted",
          "returns": "void"
        },
        {
          "name": "recall",
          "async": true,
          "params": [
            "options: object"
          ],
          "returns": "Promise"
        },
        {
          "name": "recallAll",
          "async": true,
          "params": [
            "options?: object"
          ],
          "returns": "Promise<Map<string>>"
        },
        {
          "name": "remember",
          "async": true,
          "params": [
            "options: object"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "removeAsset",
          "async": true,
          "params": [
            "assetId: string",
            "relationship?: string"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "requireInsertOnSave",
          "returns": "void"
        },
        {
          "name": "resetAiUsage",
          "returns": "void"
        },
        {
          "name": "save",
          "async": true,
          "returns": "any"
        },
        {
          "name": "summarizeAiUsage",
          "async": true,
          "params": [
            "options?: AiUsageSummaryOptions"
          ],
          "returns": "Promise<Record<string, AiUsageStats>>"
        },
        {
          "name": "toJSON",
          "returns": "any"
        },
        {
          "name": "toPlainObject",
          "returns": "Record<string>"
        },
        {
          "name": "toPublicJSON",
          "params": [
            "options?: PublicJsonOptions"
          ],
          "returns": "Record<string>"
        },
        {
          "name": "updateSpecification",
          "async": true,
          "params": [
            "key: string",
            "value: any"
          ],
          "returns": "Promise<void>"
        }
      ],
      "tenant": {
        "scoped": true,
        "mode": "optional",
        "field": "tenantId"
      },
      "tableStrategy": "sti",
      "surfaces": [
        {
          "kind": "api",
          "name": "products.list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:Material",
          "path": "/products",
          "method": "GET"
        },
        {
          "kind": "api",
          "name": "products.get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:Material",
          "path": "/products/[id]",
          "method": "GET"
        },
        {
          "kind": "api",
          "name": "products.create",
          "operation": "create",
          "objectName": "@happyvertical/smrt-products:Material",
          "path": "/products",
          "method": "POST"
        },
        {
          "kind": "api",
          "name": "products.update",
          "operation": "update",
          "objectName": "@happyvertical/smrt-products:Material",
          "path": "/products/[id]",
          "method": "PATCH"
        },
        {
          "kind": "cli",
          "name": "material_list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:Material"
        },
        {
          "kind": "cli",
          "name": "material_get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:Material"
        },
        {
          "kind": "cli",
          "name": "material_create",
          "operation": "create",
          "objectName": "@happyvertical/smrt-products:Material"
        },
        {
          "kind": "cli",
          "name": "material_update",
          "operation": "update",
          "objectName": "@happyvertical/smrt-products:Material"
        },
        {
          "kind": "cli",
          "name": "material_delete",
          "operation": "delete",
          "objectName": "@happyvertical/smrt-products:Material"
        },
        {
          "kind": "mcp",
          "name": "material_list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:Material"
        },
        {
          "kind": "mcp",
          "name": "material_get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:Material"
        }
      ],
      "relationshipFeatures": [
        "uuidColumns"
      ],
      "tags": [],
      "risks": []
    },
    {
      "name": "Product",
      "qualifiedName": "@happyvertical/smrt-products:Product",
      "collection": "products",
      "tableName": "products",
      "packageName": "@happyvertical/smrt-products",
      "extends": "SmrtObject",
      "fields": [
        {
          "name": "created_at",
          "type": "datetime",
          "required": false,
          "columnType": "TIMESTAMP"
        },
        {
          "name": "updated_at",
          "type": "datetime",
          "required": false,
          "columnType": "TIMESTAMP"
        },
        {
          "name": "tenantId",
          "type": "text",
          "required": false,
          "columnType": "UUID"
        },
        {
          "name": "productType",
          "type": "text",
          "required": false,
          "columnType": "TEXT"
        },
        {
          "name": "name",
          "type": "text",
          "required": false,
          "columnType": "TEXT"
        },
        {
          "name": "description",
          "type": "text",
          "required": false,
          "columnType": "TEXT"
        },
        {
          "name": "category",
          "type": "text",
          "required": false,
          "columnType": "TEXT"
        },
        {
          "name": "manufacturer",
          "type": "text",
          "required": false,
          "columnType": "TEXT"
        },
        {
          "name": "model",
          "type": "text",
          "required": false,
          "columnType": "TEXT"
        },
        {
          "name": "price",
          "type": "integer",
          "required": true,
          "columnType": "INTEGER",
          "default": 0
        },
        {
          "name": "inStock",
          "type": "boolean",
          "required": true,
          "columnType": "BOOLEAN",
          "default": true
        },
        {
          "name": "specifications",
          "type": "json",
          "required": false,
          "columnType": "JSON",
          "default": {}
        },
        {
          "name": "tags",
          "type": "json",
          "required": false,
          "columnType": "JSON",
          "default": []
        }
      ],
      "relationships": [],
      "methods": [
        "_setLoadedRelationship",
        "addAsset",
        "classifyConstraintError",
        "clearEmbeddings",
        "delete",
        "describe",
        "destroy",
        "do",
        "executeToolCall",
        "forget",
        "forgetScope",
        "generateEmbeddings",
        "getAiUsageSnapshot",
        "getAssets",
        "getAvailableTools",
        "getEmbedding",
        "getFields",
        "getId",
        "getRelated",
        "getSavedId",
        "getSlug",
        "getSpecification",
        "hasStaleEmbeddings",
        "initialize",
        "is",
        "isRelatedLoaded",
        "isSaved",
        "listAiUsage",
        "loadDataFromDb",
        "loadFromId",
        "loadFromSlug",
        "loadRelated",
        "loadRelatedMany",
        "markAsPersisted",
        "recall",
        "recallAll",
        "remember",
        "removeAsset",
        "requireInsertOnSave",
        "resetAiUsage",
        "save",
        "summarizeAiUsage",
        "toJSON",
        "toPlainObject",
        "toPublicJSON",
        "updateSpecification"
      ],
      "methodSignatures": [
        {
          "name": "_setLoadedRelationship",
          "params": [
            "fieldName: string",
            "value: any"
          ],
          "returns": "void"
        },
        {
          "name": "addAsset",
          "async": true,
          "params": [
            "asset: Asset",
            "relationship?: any",
            "sortOrder?: any"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "classifyConstraintError",
          "static": true,
          "params": [
            "message: string"
          ],
          "returns": "'unique' | 'not_null' | null"
        },
        {
          "name": "clearEmbeddings",
          "async": true,
          "returns": "Promise<void>"
        },
        {
          "name": "delete",
          "async": true,
          "returns": "Promise<void>"
        },
        {
          "name": "describe",
          "async": true,
          "params": [
            "options?: AiOperationOptions"
          ],
          "returns": "any"
        },
        {
          "name": "destroy",
          "returns": "void"
        },
        {
          "name": "do",
          "async": true,
          "params": [
            "instructions: string",
            "options?: AiOperationOptions"
          ],
          "returns": "any"
        },
        {
          "name": "executeToolCall",
          "async": true,
          "params": [
            "toolCall: ToolCall"
          ],
          "returns": "Promise<ToolCallResult>"
        },
        {
          "name": "forget",
          "async": true,
          "params": [
            "options: object"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "forgetScope",
          "async": true,
          "params": [
            "options: object"
          ],
          "returns": "Promise<number>"
        },
        {
          "name": "generateEmbeddings",
          "async": true,
          "params": [
            "options?: GenerateEmbeddingsOptions"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "getAiUsageSnapshot",
          "returns": "AiUsageSnapshot | undefined"
        },
        {
          "name": "getAssets",
          "async": true,
          "params": [
            "relationship?: string"
          ],
          "returns": "Promise<Asset[]>"
        },
        {
          "name": "getAvailableTools",
          "returns": "AITool[]"
        },
        {
          "name": "getEmbedding",
          "async": true,
          "params": [
            "fieldName: string",
            "model?: string"
          ],
          "returns": "Promise<number[] | null>"
        },
        {
          "name": "getFields",
          "async": true,
          "returns": "Promise<any>"
        },
        {
          "name": "getId",
          "async": true,
          "returns": "any"
        },
        {
          "name": "getRelated",
          "async": true,
          "params": [
            "fieldName: string",
            "opts?: LoadRelatedOptions"
          ],
          "returns": "Promise<any>"
        },
        {
          "name": "getSavedId",
          "async": true,
          "returns": "any"
        },
        {
          "name": "getSlug",
          "async": true,
          "returns": "any"
        },
        {
          "name": "getSpecification",
          "async": true,
          "params": [
            "key: string"
          ],
          "returns": "Promise"
        },
        {
          "name": "hasStaleEmbeddings",
          "async": true,
          "returns": "Promise<boolean>"
        },
        {
          "name": "initialize",
          "async": true,
          "returns": "Promise"
        },
        {
          "name": "is",
          "async": true,
          "params": [
            "criteria: string",
            "options?: AiOperationOptions"
          ],
          "returns": "any"
        },
        {
          "name": "isRelatedLoaded",
          "params": [
            "fieldName: string"
          ],
          "returns": "boolean"
        },
        {
          "name": "isSaved",
          "async": true,
          "returns": "any"
        },
        {
          "name": "listAiUsage",
          "async": true,
          "params": [
            "options?: AiUsageListOptions"
          ],
          "returns": "Promise<SmrtAiUsageRecord[]>"
        },
        {
          "name": "loadDataFromDb",
          "async": true,
          "params": [
            "data: Record<string>"
          ],
          "returns": "any"
        },
        {
          "name": "loadFromId",
          "async": true,
          "returns": "any"
        },
        {
          "name": "loadFromSlug",
          "async": true,
          "returns": "any"
        },
        {
          "name": "loadRelated",
          "async": true,
          "params": [
            "fieldName: string",
            "opts?: LoadRelatedOptions"
          ],
          "returns": "Promise<any>"
        },
        {
          "name": "loadRelatedMany",
          "async": true,
          "params": [
            "fieldName: string",
            "opts?: LoadRelatedOptions"
          ],
          "returns": "Promise<any[]>"
        },
        {
          "name": "markAsPersisted",
          "returns": "void"
        },
        {
          "name": "recall",
          "async": true,
          "params": [
            "options: object"
          ],
          "returns": "Promise"
        },
        {
          "name": "recallAll",
          "async": true,
          "params": [
            "options?: object"
          ],
          "returns": "Promise<Map<string>>"
        },
        {
          "name": "remember",
          "async": true,
          "params": [
            "options: object"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "removeAsset",
          "async": true,
          "params": [
            "assetId: string",
            "relationship?: string"
          ],
          "returns": "Promise<void>"
        },
        {
          "name": "requireInsertOnSave",
          "returns": "void"
        },
        {
          "name": "resetAiUsage",
          "returns": "void"
        },
        {
          "name": "save",
          "async": true,
          "returns": "any"
        },
        {
          "name": "summarizeAiUsage",
          "async": true,
          "params": [
            "options?: AiUsageSummaryOptions"
          ],
          "returns": "Promise<Record<string, AiUsageStats>>"
        },
        {
          "name": "toJSON",
          "returns": "any"
        },
        {
          "name": "toPlainObject",
          "returns": "Record<string>"
        },
        {
          "name": "toPublicJSON",
          "params": [
            "options?: PublicJsonOptions"
          ],
          "returns": "Record<string>"
        },
        {
          "name": "updateSpecification",
          "async": true,
          "params": [
            "key: string",
            "value: any"
          ],
          "returns": "Promise<void>"
        }
      ],
      "tenant": {
        "scoped": true,
        "mode": "optional",
        "field": "tenantId"
      },
      "tableStrategy": "sti",
      "conflictColumns": [
        "tenant_id",
        "slug",
        "context",
        "_meta_type"
      ],
      "surfaces": [
        {
          "kind": "api",
          "name": "products.list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:Product",
          "path": "/products",
          "method": "GET"
        },
        {
          "kind": "api",
          "name": "products.get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:Product",
          "path": "/products/[id]",
          "method": "GET"
        },
        {
          "kind": "api",
          "name": "products.create",
          "operation": "create",
          "objectName": "@happyvertical/smrt-products:Product",
          "path": "/products",
          "method": "POST"
        },
        {
          "kind": "api",
          "name": "products.update",
          "operation": "update",
          "objectName": "@happyvertical/smrt-products:Product",
          "path": "/products/[id]",
          "method": "PATCH"
        },
        {
          "kind": "cli",
          "name": "product_list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:Product"
        },
        {
          "kind": "cli",
          "name": "product_get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:Product"
        },
        {
          "kind": "cli",
          "name": "product_create",
          "operation": "create",
          "objectName": "@happyvertical/smrt-products:Product"
        },
        {
          "kind": "cli",
          "name": "product_update",
          "operation": "update",
          "objectName": "@happyvertical/smrt-products:Product"
        },
        {
          "kind": "cli",
          "name": "product_delete",
          "operation": "delete",
          "objectName": "@happyvertical/smrt-products:Product"
        },
        {
          "kind": "mcp",
          "name": "product_list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:Product"
        },
        {
          "kind": "mcp",
          "name": "product_get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:Product"
        }
      ],
      "relationshipFeatures": [
        "uuidColumns"
      ],
      "tags": [],
      "risks": []
    },
    {
      "name": "ProductAsset",
      "qualifiedName": "@happyvertical/smrt-products:ProductAsset",
      "collection": "productassets",
      "tableName": "product_assets",
      "packageName": "@happyvertical/smrt-products",
      "extends": "SmrtObject",
      "fields": [
        {
          "name": "tenantId",
          "type": "text",
          "required": false,
          "columnType": "UUID"
        },
        {
          "name": "productId",
          "type": "foreignKey",
          "required": true,
          "related": "Product",
          "columnType": "UUID"
        },
        {
          "name": "assetId",
          "type": "crossPackageRef",
          "required": true,
          "related": "@happyvertical/smrt-assets:Asset",
          "columnType": "UUID"
        },
        {
          "name": "relationship",
          "type": "text",
          "required": true,
          "columnType": "TEXT"
        },
        {
          "name": "sortOrder",
          "type": "integer",
          "required": true,
          "columnType": "INTEGER",
          "default": 0
        }
      ],
      "relationships": [
        {
          "name": "productId",
          "type": "foreignKey",
          "required": true,
          "related": "Product",
          "columnType": "UUID"
        },
        {
          "name": "assetId",
          "type": "crossPackageRef",
          "required": true,
          "related": "@happyvertical/smrt-assets:Asset",
          "columnType": "UUID"
        }
      ],
      "methods": [],
      "tenant": {
        "scoped": true,
        "mode": "optional",
        "field": "tenantId"
      },
      "conflictColumns": [
        "product_id",
        "asset_id",
        "relationship",
        "tenant_id"
      ],
      "surfaces": [],
      "relationshipFeatures": [
        "crossPackageRef",
        "foreignKey",
        "uuidColumns"
      ],
      "tags": [],
      "risks": []
    },
    {
      "name": "ProductVariant",
      "qualifiedName": "@happyvertical/smrt-products:ProductVariant",
      "collection": "productvariants",
      "tableName": "product_variants",
      "packageName": "@happyvertical/smrt-products",
      "extends": "SmrtObject",
      "fields": [
        {
          "name": "tenantId",
          "type": "text",
          "required": false,
          "columnType": "UUID"
        },
        {
          "name": "productId",
          "type": "text",
          "required": true,
          "columnType": "TEXT",
          "default": ""
        },
        {
          "name": "axisName",
          "type": "text",
          "required": true,
          "columnType": "TEXT",
          "default": ""
        },
        {
          "name": "label",
          "type": "text",
          "required": false,
          "columnType": "TEXT",
          "default": ""
        },
        {
          "name": "allowedValues",
          "type": "text",
          "required": false,
          "columnType": "TEXT",
          "default": "[]"
        },
        {
          "name": "sortOrder",
          "type": "integer",
          "required": false,
          "columnType": "INTEGER",
          "default": 0
        }
      ],
      "relationships": [],
      "methods": [
        "getValues",
        "setValues"
      ],
      "methodSignatures": [
        {
          "name": "getValues",
          "returns": "string[]"
        },
        {
          "name": "setValues",
          "params": [
            "value: string[] | string"
          ],
          "returns": "void"
        }
      ],
      "tenant": {
        "scoped": true,
        "mode": "optional",
        "field": "tenantId"
      },
      "conflictColumns": [
        "product_id",
        "axis_name",
        "tenant_id"
      ],
      "surfaces": [
        {
          "kind": "api",
          "name": "productvariants.list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:ProductVariant",
          "path": "/productvariants",
          "method": "GET"
        },
        {
          "kind": "api",
          "name": "productvariants.get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:ProductVariant",
          "path": "/productvariants/[id]",
          "method": "GET"
        },
        {
          "kind": "api",
          "name": "productvariants.create",
          "operation": "create",
          "objectName": "@happyvertical/smrt-products:ProductVariant",
          "path": "/productvariants",
          "method": "POST"
        },
        {
          "kind": "api",
          "name": "productvariants.update",
          "operation": "update",
          "objectName": "@happyvertical/smrt-products:ProductVariant",
          "path": "/productvariants/[id]",
          "method": "PATCH"
        },
        {
          "kind": "cli",
          "name": "productvariant_list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:ProductVariant"
        },
        {
          "kind": "cli",
          "name": "productvariant_get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:ProductVariant"
        },
        {
          "kind": "cli",
          "name": "productvariant_create",
          "operation": "create",
          "objectName": "@happyvertical/smrt-products:ProductVariant"
        },
        {
          "kind": "cli",
          "name": "productvariant_update",
          "operation": "update",
          "objectName": "@happyvertical/smrt-products:ProductVariant"
        },
        {
          "kind": "cli",
          "name": "productvariant_delete",
          "operation": "delete",
          "objectName": "@happyvertical/smrt-products:ProductVariant"
        },
        {
          "kind": "mcp",
          "name": "productvariant_list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:ProductVariant"
        },
        {
          "kind": "mcp",
          "name": "productvariant_get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:ProductVariant"
        }
      ],
      "relationshipFeatures": [
        "uuidColumns"
      ],
      "tags": [],
      "risks": []
    },
    {
      "name": "Sku",
      "qualifiedName": "@happyvertical/smrt-products:Sku",
      "collection": "skus",
      "tableName": "product_skus",
      "packageName": "@happyvertical/smrt-products",
      "extends": "SmrtObject",
      "fields": [
        {
          "name": "tenantId",
          "type": "text",
          "required": false,
          "columnType": "UUID"
        },
        {
          "name": "productId",
          "type": "text",
          "required": true,
          "columnType": "TEXT",
          "default": ""
        },
        {
          "name": "code",
          "type": "text",
          "required": true,
          "columnType": "TEXT",
          "default": ""
        },
        {
          "name": "barcode",
          "type": "text",
          "required": false,
          "columnType": "TEXT",
          "default": ""
        },
        {
          "name": "name",
          "type": "text",
          "required": false,
          "columnType": "TEXT",
          "default": ""
        },
        {
          "name": "attributes",
          "type": "text",
          "required": false,
          "columnType": "TEXT",
          "default": "{}"
        },
        {
          "name": "weightGrams",
          "type": "decimal",
          "required": false,
          "columnType": "REAL"
        },
        {
          "name": "parentSkuId",
          "type": "text",
          "required": false,
          "columnType": "TEXT",
          "default": ""
        },
        {
          "name": "active",
          "type": "boolean",
          "required": false,
          "columnType": "BOOLEAN",
          "default": true
        }
      ],
      "relationships": [],
      "methods": [
        "getAttributes",
        "setAttributes"
      ],
      "methodSignatures": [
        {
          "name": "getAttributes",
          "returns": "Record<string>"
        },
        {
          "name": "setAttributes",
          "params": [
            "value: Record<string> | string"
          ],
          "returns": "void"
        }
      ],
      "tenant": {
        "scoped": true,
        "mode": "optional",
        "field": "tenantId"
      },
      "conflictColumns": [
        "code",
        "tenant_id"
      ],
      "surfaces": [
        {
          "kind": "api",
          "name": "skus.list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:Sku",
          "path": "/skus",
          "method": "GET"
        },
        {
          "kind": "api",
          "name": "skus.get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:Sku",
          "path": "/skus/[id]",
          "method": "GET"
        },
        {
          "kind": "api",
          "name": "skus.create",
          "operation": "create",
          "objectName": "@happyvertical/smrt-products:Sku",
          "path": "/skus",
          "method": "POST"
        },
        {
          "kind": "api",
          "name": "skus.update",
          "operation": "update",
          "objectName": "@happyvertical/smrt-products:Sku",
          "path": "/skus/[id]",
          "method": "PATCH"
        },
        {
          "kind": "cli",
          "name": "sku_list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:Sku"
        },
        {
          "kind": "cli",
          "name": "sku_get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:Sku"
        },
        {
          "kind": "cli",
          "name": "sku_create",
          "operation": "create",
          "objectName": "@happyvertical/smrt-products:Sku"
        },
        {
          "kind": "cli",
          "name": "sku_update",
          "operation": "update",
          "objectName": "@happyvertical/smrt-products:Sku"
        },
        {
          "kind": "cli",
          "name": "sku_delete",
          "operation": "delete",
          "objectName": "@happyvertical/smrt-products:Sku"
        },
        {
          "kind": "mcp",
          "name": "sku_list",
          "operation": "list",
          "objectName": "@happyvertical/smrt-products:Sku"
        },
        {
          "kind": "mcp",
          "name": "sku_get",
          "operation": "get",
          "objectName": "@happyvertical/smrt-products:Sku"
        }
      ],
      "relationshipFeatures": [
        "uuidColumns"
      ],
      "tags": [],
      "risks": []
    }
  ],
  "surfaces": [
    {
      "kind": "api",
      "name": "categories.list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:Category",
      "path": "/categories",
      "method": "GET"
    },
    {
      "kind": "api",
      "name": "categories.get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:Category",
      "path": "/categories/[id]",
      "method": "GET"
    },
    {
      "kind": "api",
      "name": "categories.create",
      "operation": "create",
      "objectName": "@happyvertical/smrt-products:Category",
      "path": "/categories",
      "method": "POST"
    },
    {
      "kind": "api",
      "name": "categories.update",
      "operation": "update",
      "objectName": "@happyvertical/smrt-products:Category",
      "path": "/categories/[id]",
      "method": "PATCH"
    },
    {
      "kind": "cli",
      "name": "category_list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:Category"
    },
    {
      "kind": "cli",
      "name": "category_get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:Category"
    },
    {
      "kind": "cli",
      "name": "category_create",
      "operation": "create",
      "objectName": "@happyvertical/smrt-products:Category"
    },
    {
      "kind": "cli",
      "name": "category_update",
      "operation": "update",
      "objectName": "@happyvertical/smrt-products:Category"
    },
    {
      "kind": "cli",
      "name": "category_delete",
      "operation": "delete",
      "objectName": "@happyvertical/smrt-products:Category"
    },
    {
      "kind": "mcp",
      "name": "category_list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:Category"
    },
    {
      "kind": "mcp",
      "name": "category_get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:Category"
    },
    {
      "kind": "api",
      "name": "products.list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:Material",
      "path": "/products",
      "method": "GET"
    },
    {
      "kind": "api",
      "name": "products.get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:Material",
      "path": "/products/[id]",
      "method": "GET"
    },
    {
      "kind": "api",
      "name": "products.create",
      "operation": "create",
      "objectName": "@happyvertical/smrt-products:Material",
      "path": "/products",
      "method": "POST"
    },
    {
      "kind": "api",
      "name": "products.update",
      "operation": "update",
      "objectName": "@happyvertical/smrt-products:Material",
      "path": "/products/[id]",
      "method": "PATCH"
    },
    {
      "kind": "cli",
      "name": "material_list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:Material"
    },
    {
      "kind": "cli",
      "name": "material_get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:Material"
    },
    {
      "kind": "cli",
      "name": "material_create",
      "operation": "create",
      "objectName": "@happyvertical/smrt-products:Material"
    },
    {
      "kind": "cli",
      "name": "material_update",
      "operation": "update",
      "objectName": "@happyvertical/smrt-products:Material"
    },
    {
      "kind": "cli",
      "name": "material_delete",
      "operation": "delete",
      "objectName": "@happyvertical/smrt-products:Material"
    },
    {
      "kind": "mcp",
      "name": "material_list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:Material"
    },
    {
      "kind": "mcp",
      "name": "material_get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:Material"
    },
    {
      "kind": "api",
      "name": "products.list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:Product",
      "path": "/products",
      "method": "GET"
    },
    {
      "kind": "api",
      "name": "products.get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:Product",
      "path": "/products/[id]",
      "method": "GET"
    },
    {
      "kind": "api",
      "name": "products.create",
      "operation": "create",
      "objectName": "@happyvertical/smrt-products:Product",
      "path": "/products",
      "method": "POST"
    },
    {
      "kind": "api",
      "name": "products.update",
      "operation": "update",
      "objectName": "@happyvertical/smrt-products:Product",
      "path": "/products/[id]",
      "method": "PATCH"
    },
    {
      "kind": "cli",
      "name": "product_list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:Product"
    },
    {
      "kind": "cli",
      "name": "product_get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:Product"
    },
    {
      "kind": "cli",
      "name": "product_create",
      "operation": "create",
      "objectName": "@happyvertical/smrt-products:Product"
    },
    {
      "kind": "cli",
      "name": "product_update",
      "operation": "update",
      "objectName": "@happyvertical/smrt-products:Product"
    },
    {
      "kind": "cli",
      "name": "product_delete",
      "operation": "delete",
      "objectName": "@happyvertical/smrt-products:Product"
    },
    {
      "kind": "mcp",
      "name": "product_list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:Product"
    },
    {
      "kind": "mcp",
      "name": "product_get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:Product"
    },
    {
      "kind": "api",
      "name": "productvariants.list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:ProductVariant",
      "path": "/productvariants",
      "method": "GET"
    },
    {
      "kind": "api",
      "name": "productvariants.get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:ProductVariant",
      "path": "/productvariants/[id]",
      "method": "GET"
    },
    {
      "kind": "api",
      "name": "productvariants.create",
      "operation": "create",
      "objectName": "@happyvertical/smrt-products:ProductVariant",
      "path": "/productvariants",
      "method": "POST"
    },
    {
      "kind": "api",
      "name": "productvariants.update",
      "operation": "update",
      "objectName": "@happyvertical/smrt-products:ProductVariant",
      "path": "/productvariants/[id]",
      "method": "PATCH"
    },
    {
      "kind": "cli",
      "name": "productvariant_list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:ProductVariant"
    },
    {
      "kind": "cli",
      "name": "productvariant_get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:ProductVariant"
    },
    {
      "kind": "cli",
      "name": "productvariant_create",
      "operation": "create",
      "objectName": "@happyvertical/smrt-products:ProductVariant"
    },
    {
      "kind": "cli",
      "name": "productvariant_update",
      "operation": "update",
      "objectName": "@happyvertical/smrt-products:ProductVariant"
    },
    {
      "kind": "cli",
      "name": "productvariant_delete",
      "operation": "delete",
      "objectName": "@happyvertical/smrt-products:ProductVariant"
    },
    {
      "kind": "mcp",
      "name": "productvariant_list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:ProductVariant"
    },
    {
      "kind": "mcp",
      "name": "productvariant_get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:ProductVariant"
    },
    {
      "kind": "api",
      "name": "skus.list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:Sku",
      "path": "/skus",
      "method": "GET"
    },
    {
      "kind": "api",
      "name": "skus.get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:Sku",
      "path": "/skus/[id]",
      "method": "GET"
    },
    {
      "kind": "api",
      "name": "skus.create",
      "operation": "create",
      "objectName": "@happyvertical/smrt-products:Sku",
      "path": "/skus",
      "method": "POST"
    },
    {
      "kind": "api",
      "name": "skus.update",
      "operation": "update",
      "objectName": "@happyvertical/smrt-products:Sku",
      "path": "/skus/[id]",
      "method": "PATCH"
    },
    {
      "kind": "cli",
      "name": "sku_list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:Sku"
    },
    {
      "kind": "cli",
      "name": "sku_get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:Sku"
    },
    {
      "kind": "cli",
      "name": "sku_create",
      "operation": "create",
      "objectName": "@happyvertical/smrt-products:Sku"
    },
    {
      "kind": "cli",
      "name": "sku_update",
      "operation": "update",
      "objectName": "@happyvertical/smrt-products:Sku"
    },
    {
      "kind": "cli",
      "name": "sku_delete",
      "operation": "delete",
      "objectName": "@happyvertical/smrt-products:Sku"
    },
    {
      "kind": "mcp",
      "name": "sku_list",
      "operation": "list",
      "objectName": "@happyvertical/smrt-products:Sku"
    },
    {
      "kind": "mcp",
      "name": "sku_get",
      "operation": "get",
      "objectName": "@happyvertical/smrt-products:Sku"
    }
  ],
  "prompts": [],
  "relationshipsV2": {
    "foreignKeyFields": 2,
    "crossPackageRefFields": 1,
    "junctionCollections": 1,
    "hierarchicalObjects": 0,
    "polymorphicAssociations": 0,
    "uuidColumns": 21
  },
  "agentDoc": "# @happyvertical/smrt-products\n\nProduct catalog — reference template for triple-consumption: npm package library, module federation, and standalone REST API server.\n\n## Models\n\n- **Product**: STI base. Tenant-scoped (`@TenantScoped({ mode: 'optional' })`, nullable `tenantId`). Knowledge base product with specs, tags, and the `productType` discriminator. Consumers subclass this with vertical-specific subtypes (apparel `Style`, automotive `Model`, furniture `Design`, etc.).\n- **Material**: STI subtype. Raw input consumed by manufacturing (fabric, trim, thread, packaging, component). Meta fields: `materialKind`, `uom`, `costPerUnit`. Materials are first-class products in the catalog — the SAP/NetSuite pattern. Bills of materials in `@happyvertical/smrt-manufacturing` reference Materials by id.\n- **ProductVariant**: standalone (NOT a Product STI subtype). Declarative axis definition: `productId`, `axisName` (e.g. `'size'`, `'color'`, `'finish'`), `allowedValues` (JSON-stored array), optional `label` and `sortOrder`. Per-SKU value pins live on `Sku.attributes`. Lives in its own `product_variants` table; `conflictColumns: ['product_id', 'axis_name', 'tenant_id']`.\n- **Sku**: standalone. The smallest sellable / countable unit. `productId` points at a `Product` or any of its STI subtypes; `code` is the human-meaningful identifier; `attributes` JSON pins each axis value (`{ size: 'M', color: 'navy' }`). Lives in its own `product_skus` table; `conflictColumns: ['code', 'tenant_id']`. Stock balance and movement history for a Sku live in `@happyvertical/smrt-inventory`.\n- **ProductAsset**: dedicated owned-asset join in `product_assets` with `relationship` and `sortOrder`. Tenant-scoped to match Product.\n- **Category**: hierarchical (parentId, level, productCount). STI base, tenant-scoped.\n\n## Vertical-specific Product subtypes\n\nThis package deliberately ships ONLY the generic primitives. Domain-specific top-level item types live in the consumer's template:\n\n- Apparel: `Style extends Product`, `Makeup extends Product`\n- Furniture: `Design extends Product`, `Configuration extends Product`\n- Automotive: `Model extends Product`, `Trim extends Product`\n- CPG: `Brand extends Product`, `Recipe extends Product`\n\nEach is a small subclass: `@smrt()`, override `productType`, add `@meta()` fields. See `packages/template-apparel-erp` for a worked example.\n\n## Variants — the two concepts\n\nThe framework's variant story uses two distinct primitives that look similar but do different jobs:\n\n- **`ProductVariant`** — *axis declaration*. \"For product X, axis `size` accepts the values `[XS, S, M, L, XL]`.\" Drives form/UI choices.\n- **`Sku.attributes`** — *per-unit value pins*. `{ color: 'navy', size: 'M' }` on each concrete sellable SKU.\n\nBoth live in this package — all catalog shapes are here. Stock motion (where the SKU is, how many, history) lives in `@happyvertical/smrt-inventory`.\n\nThere is deliberately no separate \"catalog grouping above SKU\" row (a la a \"Navy colorway\" row sitting between the Product and its Skus). Group SKUs by axis value via `attributes.color = 'navy'` queries; attach per-axis-value assets via `ProductAsset` rows with relationship metadata. Matches how Shopify, Stripe Products, and most e-commerce platforms model the same shape.\n\n## Collections\n\n- **ProductCollection** — base. Polymorphic queries return the correct subclass instance per row.\n- **MaterialCollection** — STI-filtered subclass. Override `_itemClass`; framework auto-filters by `_meta_type`.\n- **ProductVariantCollection** — standalone collection over `product_variants`. Helpers: `findForProduct(productId)`, `findAxis(productId, axisName)`.\n- **SkuCollection** — standalone collection over `product_skus`. Helpers: `findByCode`, `findByBarcode`, `findByProduct`, `findByParent`, `findActive`.\n- **CategoryCollection** — standard Category CRUD with `getRootCategories()`.\n- **ProductAssetCollection** — direct access to `product_assets` rows and product asset helper wrappers.\n\n## Multi-tenancy\n\nOptional. With `withTenant(id, fn)` (from `@happyvertical/smrt-tenancy`), all queries auto-filter and inserts auto-stamp `tenantId`. Without it, models behave globally (`tenantId = null`). This lets the same package serve both shared reference catalogs and per-merchant SaaS catalogs.\n\n## Triple-Consumption Pattern\n\nSame codebase consumed three ways:\n1. **NPM library**: import classes directly\n2. **Module federation**: runtime component sharing (experimental)\n3. **Standalone API**: `startRestServer([Product, Category])`\n\n## Virtual Modules (Vite)\n\nAuto-generated via Vite plugins: `@happyvertical/smrt-client` (TypeScript client), `@happyvertical/smrt-types`, `@happyvertical/smrt-routes` (Express), `@happyvertical/smrt-mcp`, `@happyvertical/smrt-manifest`.\n\nSvelte 5 stores use runes (`$state`, `$derived`, `$effect`). `product-store.svelte.ts` is the main store (backed by the SMRT client); `product-store.client.svelte.ts` is a virtual-module-free variant for federation builds.\n\n## Client-data runtime — reference store (#1761)\n\nProducts is the reference consumer of the `@happyvertical/smrt-web` browser client-data runtime.\n\n- **Store** — `src/lib/stores/product-collection.ts` (subpath `@happyvertical/smrt-products/stores/product-collection`). `createProductCollection(definition, options)` builds a cached, reactive `SmrtWebCollection<ProductData>` over the generated `/api/v1/products` REST surface via `createSmrtCollection`. It is plugin-agnostic on purpose: the `products` definition is a PARAMETER (not a top-level import), so importing the store never eagerly resolves `@happyvertical/smrt-virt-web` (which exists only under the SMRT Vite plugin) — a unit test / npm consumer supplies its own definition. `productsCollectionDefinition()` lazily resolves the plugin definition (dynamic `import()`; resolved for `tsc` via the `@smrt/web` ambient alias). Deliberately NOT re-exported from the always-loaded `./stores` barrel — importing it is an explicit opt-in to the engine.\n- **Live surface** — `src/lib/components/LiveProductList.svelte` binds the store with `liveCollection` from `@happyvertical/smrt-svelte/web` (live rows + optimistic insert); it takes the definition as a prop. `src/app/pages/LiveProductsPage.svelte` (route `#live`) resolves the component AND the definition via `import()` and passes the definition down.\n- **Code-split (ratified condition ①)** — the ~76 kB TanStack engine must NEVER load on public / smrt-sites pages. `LiveProductsPage` reaches `LiveProductList` and the store ONLY through dynamic `import()`, so the engine lands in a lazily-loaded chunk; the app entry stays engine-free. NEVER import the store or live component statically from an app-root / public entry. `scripts/check-web-engine-code-split.mjs` (wrapped by `src/web-engine-code-split.spec.ts`, `pnpm test:code-split`) proves this against the REAL app graph: it runs the `--mode standalone` vite build and asserts, over the emitted rollup chunk graph, that the entry's static-import closure has zero `@tanstack/*` and the engine is reached only via `dynamicImports`. If the build hits the pre-existing nested-worktree `Tsconfig not found` failure locally, it falls back to a static-import-graph walk of the real `src/app/main.ts` (CI runs the real build).\n\n## Schema migrations (Phase 1 release)\n\nThis package's schema changed shape between the previous release and the Phase 1 apparel-ERP release. Consumers upgrading need to migrate two tables.\n\n### `Sku` rows moved tables\n\nPreviously `Sku` shipped in `@happyvertical/smrt-inventory` under table `inventory_skus`. It now lives here under `product_skus`. Cross-package refs (`StockLevel.skuId`, `BomLine.componentSkuId`) carry plain string ids that still resolve.\n\n**Upgrade procedure** (works on SQLite + Postgres; does NOT rely on `CREATE TABLE AS` which strips constraints):\n\n1. **Boot the new version once** so the framework's lazy `syncSchema` creates `product_skus` with the right PRIMARY KEY, NOT NULL, UNIQUE (`code`, `tenant_id`), and indexes derived from the `Sku` model.\n\n2. **Idempotently copy rows**:\n\n   ```sql\n   BEGIN;\n   INSERT INTO product_skus (\n     id, slug, context, created_at, updated_at,\n     tenant_id, product_id, code, barcode, name,\n     attributes, weight_grams, parent_sku_id, active\n   )\n   SELECT\n     id, slug, context, created_at, updated_at,\n     tenant_id, product_id, code, barcode, name,\n     attributes, weight_grams, parent_sku_id, active\n   FROM inventory_skus\n   WHERE NOT EXISTS (\n     SELECT 1 FROM product_skus p WHERE p.id = inventory_skus.id\n   );\n   COMMIT;\n   ```\n\n3. **Drop the legacy table** once row counts match:\n\n   ```sql\n   DROP TABLE IF EXISTS inventory_skus;\n   ```\n\n### `ProductVariant` changed shape entirely\n\nPreviously a Product STI subtype carrying `parentProductId` + `axisValues` JSON inside `_meta_data` on the shared `products` table (`_meta_type='@happyvertical/smrt-products:ProductVariant'`). It is now a **standalone model** on its own `product_variants` table, with columns `productId`, `axisName`, `allowedValues`, `label`, `sortOrder`.\n\n**There is no automatic data conversion.** The old \"catalog grouping above SKU\" concept doesn't map 1:1 to the new \"per-axis declaration\" concept. Recommended procedure:\n\n1. Inspect the old rows: `SELECT * FROM products WHERE _meta_type = '@happyvertical/smrt-products:ProductVariant';`. Treat them as historical reference.\n2. Re-author axis declarations against the new shape (one `ProductVariant` row per `(productId, axisName)` pair, with `allowedValues` listing the values).\n3. Once the new declarations are populated and verified, remove the legacy rows: `DELETE FROM products WHERE _meta_type = '@happyvertical/smrt-products:ProductVariant';`.\n\nIf you had per-colorway / per-variant images attached via `ProductAsset` rows pointing at old ProductVariant ids, repoint those to the parent Product id; group-by-axis-value queries on `Sku.attributes` cover the same use case at the SKU level.\n\n## Gotchas\n\n- **`ProductVariant` and `Sku` are NOT Product STI subtypes** — they each have their own table (`product_variants`, `product_skus`) because their shapes don't fit the Product schema. Don't try to query them via `ProductCollection`.\n- **`npm run build` emits the published library surface directly**: package consumers read model, collection, and helper exports from `dist/lib`. Cross-package imports from this package should target `/models` or `/collections` subpaths (not the main entry) when the consumer isn't a vite app — the main entry pulls in vite virtual modules.\n- **Use `npm run build:all` only when you need standalone or federation bundles** in addition to the library output\n- **Constructor must explicitly assign all properties**: `Object.assign` doesn't work reliably with decorators\n- **STI subtype-specific fields use `Meta<T>`** — declare them as `fieldName: Meta<FieldType> = defaultValue`. The AST scanner detects the `Meta<T>` type wrapper at build time and routes the field through `_meta_data` JSON storage instead of materializing it as a column on the parent's table. Do **NOT** use the runtime `@meta()` decorator on STI children — it never reaches the manifest, so the schema generator treats the field as an ordinary column on the parent table and the framework's hydration path can't tell it's meta. Override `productType` on each subclass.\n- **Tenant-scoped STI children must repeat `@TenantScoped`** — `@TenantScoped` registers per concrete className, so `Material extends Product` inheriting from a tenant-scoped `Product` is NOT automatically tenant-scoped itself. `MaterialCollection.list/save` passes `'Material'` to the tenant interceptor, which looks up `'Material'` (not `'Product'`) in the per-class registry. Without an explicit `@TenantScoped({ mode: 'optional' })` on `Material`, material rows skip the tenant auto-filter and auto-populate.\n- **STI children must repeat `@smrt({ api, mcp, cli })` generation config (S5 #1406)** — like `@TenantScoped`, the generation config is registered per concrete className and is NOT inherited from the STI parent. An empty `@smrt()` on a child resolves `getConfig(child).api/.mcp` to `undefined`, which the REST and MCP generators treat as \"expose EVERYTHING\" — including `delete` and write-capable MCP tools — even when the parent deliberately restricts its surface. The package's `mcp.ts` generator enumerates the whole registry, so an under-configured child ships a wide-open surface silently. Re-declare the parent's `api`/`mcp`/`cli` posture on every subtype (see `Material`). Consumer subtypes (apparel `Style`/`Makeup`, automotive `Model`/`Trim`, …) must do the same.\n- **Two tenants can share a slug on `Product`/`Category` (smrt#2360)** — a tenant-scoped STI base keys on `(tenant_id, slug, context, _meta_type)` by default, on the schema index and the runtime upsert alike, so no per-tenant slug namespacing and no `conflictColumns` override is needed. Global rows (`tenantId = null`) still dedup among themselves through the SDK's null-aware upsert. Existing databases pick the new key up through `smrt db:migrate` (same-name index swap) — deploy the code and the migration together, since neither version's create binds against the other's index.\n- **`price` is integer minor units** (cents, satoshis) — `$19.99` is `1999`. Money is exact, so `price` initializes `= 0`; writing `19.99` is the bug, and PostgreSQL rejects it with `22P02` while SQLite's affinity stores it and hides it from this package's SQLite suites. `pnpm --filter @happyvertical/smrt-products test:postgres` is the lane that holds the line (#2361). Because `Product` is the STI base, the column is shared by every consumer subtype. `Material.costPerUnit` is a `Meta<number>` in `_meta_data` rather than a column, so it is outside this rule.\n- **Module Federation marked experimental**: may change\n"
}