@happyvertical/smrt-products 0.30.0
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.
- package/AGENTS.md +122 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +7 -0
- package/README.md +115 -0
- package/dist/lib/__smrt-register__.d.ts +2 -0
- package/dist/lib/__smrt-register__.d.ts.map +1 -0
- package/dist/lib/app/main.d.ts +6 -0
- package/dist/lib/app/main.d.ts.map +1 -0
- package/dist/lib/chunks/ProductAssetCollection-DFPXN43q.js +64 -0
- package/dist/lib/chunks/ProductAssetCollection-DFPXN43q.js.map +1 -0
- package/dist/lib/chunks/ProductForm-DHeb2L24.js +371 -0
- package/dist/lib/chunks/ProductForm-DHeb2L24.js.map +1 -0
- package/dist/lib/chunks/Sku-DUKtbYWT.js +511 -0
- package/dist/lib/chunks/Sku-DUKtbYWT.js.map +1 -0
- package/dist/lib/chunks/SkuCollection-C0tdkEdL.js +160 -0
- package/dist/lib/chunks/SkuCollection-C0tdkEdL.js.map +1 -0
- package/dist/lib/chunks/__smrt-register__-BIgFaVKn.js +5 -0
- package/dist/lib/chunks/__smrt-register__-BIgFaVKn.js.map +1 -0
- package/dist/lib/chunks/index-i3-ci1FB.js +6 -0
- package/dist/lib/chunks/index-i3-ci1FB.js.map +1 -0
- package/dist/lib/chunks/product-store.svelte-Dayd5n3W.js +132 -0
- package/dist/lib/chunks/product-store.svelte-Dayd5n3W.js.map +1 -0
- package/dist/lib/client.d.ts +9 -0
- package/dist/lib/client.d.ts.map +1 -0
- package/dist/lib/collections.d.ts +2 -0
- package/dist/lib/collections.d.ts.map +1 -0
- package/dist/lib/collections.js +12 -0
- package/dist/lib/collections.js.map +1 -0
- package/dist/lib/components.d.ts +2 -0
- package/dist/lib/components.d.ts.map +1 -0
- package/dist/lib/components.js +6 -0
- package/dist/lib/components.js.map +1 -0
- package/dist/lib/generated.d.ts +2 -0
- package/dist/lib/generated.d.ts.map +1 -0
- package/dist/lib/generated.js +5 -0
- package/dist/lib/generated.js.map +1 -0
- package/dist/lib/index.d.ts +14 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +228 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/lib/collections/CategoryCollection.d.ts +20 -0
- package/dist/lib/lib/collections/CategoryCollection.d.ts.map +1 -0
- package/dist/lib/lib/collections/MaterialCollection.d.ts +20 -0
- package/dist/lib/lib/collections/MaterialCollection.d.ts.map +1 -0
- package/dist/lib/lib/collections/ProductAssetCollection.d.ts +16 -0
- package/dist/lib/lib/collections/ProductAssetCollection.d.ts.map +1 -0
- package/dist/lib/lib/collections/ProductCollection.d.ts +12 -0
- package/dist/lib/lib/collections/ProductCollection.d.ts.map +1 -0
- package/dist/lib/lib/collections/ProductVariantCollection.d.ts +10 -0
- package/dist/lib/lib/collections/ProductVariantCollection.d.ts.map +1 -0
- package/dist/lib/lib/collections/SkuCollection.d.ts +31 -0
- package/dist/lib/lib/collections/SkuCollection.d.ts.map +1 -0
- package/dist/lib/lib/collections/index.d.ts +7 -0
- package/dist/lib/lib/collections/index.d.ts.map +1 -0
- package/dist/lib/lib/components/ProductCard.svelte +173 -0
- package/dist/lib/lib/components/ProductCard.svelte.d.ts +10 -0
- package/dist/lib/lib/components/ProductCard.svelte.d.ts.map +1 -0
- package/dist/lib/lib/components/ProductForm.svelte +289 -0
- package/dist/lib/lib/components/ProductForm.svelte.d.ts +11 -0
- package/dist/lib/lib/components/ProductForm.svelte.d.ts.map +1 -0
- package/dist/lib/lib/components/TestComponent.svelte +25 -0
- package/dist/lib/lib/components/TestComponent.svelte.d.ts +7 -0
- package/dist/lib/lib/components/TestComponent.svelte.d.ts.map +1 -0
- package/dist/lib/lib/components/auto-generated/AutoForm.svelte +240 -0
- package/dist/lib/lib/components/auto-generated/AutoForm.svelte.d.ts +13 -0
- package/dist/lib/lib/components/auto-generated/AutoForm.svelte.d.ts.map +1 -0
- package/dist/lib/lib/components/auto-generated/FieldRenderer.svelte +205 -0
- package/dist/lib/lib/components/auto-generated/FieldRenderer.svelte.d.ts +14 -0
- package/dist/lib/lib/components/auto-generated/FieldRenderer.svelte.d.ts.map +1 -0
- package/dist/lib/lib/components/index.d.ts +12 -0
- package/dist/lib/lib/components/index.d.ts.map +1 -0
- package/dist/lib/lib/components/index.js +11 -0
- package/dist/lib/lib/features/CategoryManager.svelte +80 -0
- package/dist/lib/lib/features/CategoryManager.svelte.d.ts +7 -0
- package/dist/lib/lib/features/CategoryManager.svelte.d.ts.map +1 -0
- package/dist/lib/lib/features/ProductCatalog.svelte +299 -0
- package/dist/lib/lib/features/ProductCatalog.svelte.d.ts +8 -0
- package/dist/lib/lib/features/ProductCatalog.svelte.d.ts.map +1 -0
- package/dist/lib/lib/federation-entry.d.ts +11 -0
- package/dist/lib/lib/federation-entry.d.ts.map +1 -0
- package/dist/lib/lib/generated/index.d.ts +2 -0
- package/dist/lib/lib/generated/index.d.ts.map +1 -0
- package/dist/lib/lib/i18n.d.ts +79 -0
- package/dist/lib/lib/i18n.d.ts.map +1 -0
- package/dist/lib/lib/index.d.ts +20 -0
- package/dist/lib/lib/index.d.ts.map +1 -0
- package/dist/lib/lib/mock-smrt-client.d.ts +40 -0
- package/dist/lib/lib/mock-smrt-client.d.ts.map +1 -0
- package/dist/lib/lib/mock-smrt-client.js +129 -0
- package/dist/lib/lib/mock-smrt-client.js.map +1 -0
- package/dist/lib/lib/models/Category.d.ts +38 -0
- package/dist/lib/lib/models/Category.d.ts.map +1 -0
- package/dist/lib/lib/models/Material.d.ts +22 -0
- package/dist/lib/lib/models/Material.d.ts.map +1 -0
- package/dist/lib/lib/models/Product.d.ts +57 -0
- package/dist/lib/lib/models/Product.d.ts.map +1 -0
- package/dist/lib/lib/models/ProductAsset.d.ts +17 -0
- package/dist/lib/lib/models/ProductAsset.d.ts.map +1 -0
- package/dist/lib/lib/models/ProductVariant.d.ts +51 -0
- package/dist/lib/lib/models/ProductVariant.d.ts.map +1 -0
- package/dist/lib/lib/models/Sku.d.ts +79 -0
- package/dist/lib/lib/models/Sku.d.ts.map +1 -0
- package/dist/lib/lib/models/index.d.ts +15 -0
- package/dist/lib/lib/models/index.d.ts.map +1 -0
- package/dist/lib/lib/models/types.d.ts +41 -0
- package/dist/lib/lib/models/types.d.ts.map +1 -0
- package/dist/lib/lib/stores/index.d.ts +8 -0
- package/dist/lib/lib/stores/index.d.ts.map +1 -0
- package/dist/lib/lib/stores/index.js +7 -0
- package/dist/lib/lib/stores/product-store.client.svelte.d.ts +45 -0
- package/dist/lib/lib/stores/product-store.client.svelte.d.ts.map +1 -0
- package/dist/lib/lib/stores/product-store.client.svelte.js +147 -0
- package/dist/lib/lib/stores/product-store.svelte.d.ts +29 -0
- package/dist/lib/lib/stores/product-store.svelte.d.ts.map +1 -0
- package/dist/lib/lib/stores/product-store.svelte.js +144 -0
- package/dist/lib/lib/types.d.ts +43 -0
- package/dist/lib/lib/types.d.ts.map +1 -0
- package/dist/lib/lib/utils/index.d.ts +10 -0
- package/dist/lib/lib/utils/index.d.ts.map +1 -0
- package/dist/lib/main.d.ts +5 -0
- package/dist/lib/main.d.ts.map +1 -0
- package/dist/lib/manifest.json +3758 -0
- package/dist/lib/mcp.d.ts +14 -0
- package/dist/lib/mcp.d.ts.map +1 -0
- package/dist/lib/models.d.ts +2 -0
- package/dist/lib/models.d.ts.map +1 -0
- package/dist/lib/models.js +12 -0
- package/dist/lib/models.js.map +1 -0
- package/dist/lib/native-api-server.d.ts +7 -0
- package/dist/lib/native-api-server.d.ts.map +1 -0
- package/dist/lib/server.d.ts +11 -0
- package/dist/lib/server.d.ts.map +1 -0
- package/dist/lib/simple-api-server.d.ts +7 -0
- package/dist/lib/simple-api-server.d.ts.map +1 -0
- package/dist/lib/simple-server.d.ts +6 -0
- package/dist/lib/simple-server.d.ts.map +1 -0
- package/dist/lib/smrt-knowledge.json +1584 -0
- package/dist/lib/smrt-products.css +233 -0
- package/dist/lib/stores.d.ts +2 -0
- package/dist/lib/stores.d.ts.map +1 -0
- package/dist/lib/stores.js +6 -0
- package/dist/lib/stores.js.map +1 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +27 -0
- package/dist/lib/utils.js.map +1 -0
- package/package.json +127 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the products package.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Discriminator for Product STI subtypes.
|
|
8
|
+
*
|
|
9
|
+
* Industry-vertical templates extend `Product` with their own STI subtypes
|
|
10
|
+
* (apparel uses `Style`/`Makeup`; furniture might use `Design`/`Finish`;
|
|
11
|
+
* automotive `Model`/`Trim`) — the upstream package only ships the truly
|
|
12
|
+
* generic primitives:
|
|
13
|
+
*
|
|
14
|
+
* - {@link ProductType.PRODUCT} — plain catalog item (base)
|
|
15
|
+
* - {@link ProductType.MATERIAL} — raw input consumed by manufacturing
|
|
16
|
+
*
|
|
17
|
+
* The axis-declaration concept ("this product varies along `size` with
|
|
18
|
+
* values `[XS, S, M, L, XL]`") is NOT a Product STI subtype — it lives in
|
|
19
|
+
* its own model, {@link ProductVariant}, with a separate table. Per-SKU
|
|
20
|
+
* value pins live on `Sku.attributes` (also in this package — `Sku` was
|
|
21
|
+
* relocated from `@happyvertical/smrt-inventory` to here in Phase 1 so
|
|
22
|
+
* every catalog primitive lives under one roof; inventory only holds
|
|
23
|
+
* stock levels and movements now).
|
|
24
|
+
*/
|
|
25
|
+
export declare enum ProductType {
|
|
26
|
+
/** Generic catalog item (default). */
|
|
27
|
+
PRODUCT = "product",
|
|
28
|
+
/** A raw input — fabric, trim, packaging, etc. — consumed by manufacturing. */
|
|
29
|
+
MATERIAL = "material"
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* High-level classification of a {@link ProductType.MATERIAL} item.
|
|
33
|
+
*
|
|
34
|
+
* Open string so consumers can extend with vertical-specific kinds without
|
|
35
|
+
* an enum change. The `(string & {})` branch preserves the literal-string
|
|
36
|
+
* autocomplete suggestions in IDEs — a bare `| string` would collapse the
|
|
37
|
+
* whole union to `string` and erase the named hints (same pattern as
|
|
38
|
+
* `StockMovementReason` in `@happyvertical/smrt-inventory`).
|
|
39
|
+
*/
|
|
40
|
+
export type MaterialKind = 'fabric' | 'trim' | 'thread' | 'label' | 'packaging' | 'component' | (string & {});
|
|
41
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/lib/models/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,oBAAY,WAAW;IACrB,sCAAsC;IACtC,OAAO,YAAY;IACnB,+EAA+E;IAC/E,QAAQ,aAAa;CACtB;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GACpB,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,OAAO,GACP,WAAW,GACX,WAAW,GACX,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMRT Template Stores
|
|
3
|
+
*
|
|
4
|
+
* Svelte 5 rune-based state management for SMRT objects.
|
|
5
|
+
* These stores integrate with auto-generated SMRT clients.
|
|
6
|
+
*/
|
|
7
|
+
export { ProductStoreClass, productStore } from './product-store.svelte';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/stores/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product Store - Client-only version for federation builds
|
|
3
|
+
*
|
|
4
|
+
* This version provides the same interface as the full product store
|
|
5
|
+
* but uses mock data and doesn't depend on SMRT virtual modules.
|
|
6
|
+
*/
|
|
7
|
+
import type { ProductData } from '../types';
|
|
8
|
+
export declare class ProductStoreClass {
|
|
9
|
+
private data;
|
|
10
|
+
get items(): ProductData[];
|
|
11
|
+
get loading(): boolean;
|
|
12
|
+
get error(): string | null;
|
|
13
|
+
get selectedProduct(): ProductData | null;
|
|
14
|
+
get inStockCount(): number;
|
|
15
|
+
get totalValue(): number;
|
|
16
|
+
get categories(): (string | undefined)[];
|
|
17
|
+
loadProducts(): Promise<void>;
|
|
18
|
+
createProduct(productData: Partial<ProductData>): Promise<{
|
|
19
|
+
data: ProductData;
|
|
20
|
+
}>;
|
|
21
|
+
updateProduct(id: string, updates: Partial<ProductData>): Promise<{
|
|
22
|
+
data: {
|
|
23
|
+
updated_at: string;
|
|
24
|
+
id?: string;
|
|
25
|
+
created_at?: string;
|
|
26
|
+
name?: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
category?: string;
|
|
29
|
+
manufacturer?: string;
|
|
30
|
+
model?: string;
|
|
31
|
+
price?: number;
|
|
32
|
+
inStock?: boolean;
|
|
33
|
+
specifications?: Record<string, any>;
|
|
34
|
+
tags?: string[];
|
|
35
|
+
};
|
|
36
|
+
}>;
|
|
37
|
+
deleteProduct(id: string): Promise<void>;
|
|
38
|
+
selectProduct(product: ProductData | null): void;
|
|
39
|
+
clearError(): void;
|
|
40
|
+
filterByCategory(category: string): ProductData[];
|
|
41
|
+
filterInStock(): ProductData[];
|
|
42
|
+
searchProducts(query: string): ProductData[];
|
|
43
|
+
}
|
|
44
|
+
export declare const productStore: ProductStoreClass;
|
|
45
|
+
//# sourceMappingURL=product-store.client.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product-store.client.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/stores/product-store.client.svelte.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAS5C,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,IAAI,CAiBT;IAGH,IAAI,KAAK,kBAER;IACD,IAAI,OAAO,YAEV;IACD,IAAI,KAAK,kBAER;IACD,IAAI,eAAe,uBAElB;IAGD,IAAI,YAAY,WAEf;IAED,IAAI,UAAU,WAKb;IAED,IAAI,UAAU,2BAKb;IAGK,YAAY;IAUZ,aAAa,CAAC,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC;;;IAuB/C,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC;;;;;;;;;;;;;;;;IA8BvD,aAAa,CAAC,EAAE,EAAE,MAAM;IAmB9B,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIzC,UAAU;IAKV,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE;IAIjD,aAAa,IAAI,WAAW,EAAE;IAI9B,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE;CAS7C;AAGD,eAAO,MAAM,YAAY,mBAA0B,CAAC"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product Store - Client-only version for federation builds
|
|
3
|
+
*
|
|
4
|
+
* This version provides the same interface as the full product store
|
|
5
|
+
* but uses mock data and doesn't depend on SMRT virtual modules.
|
|
6
|
+
*/
|
|
7
|
+
export class ProductStoreClass {
|
|
8
|
+
data = $state({
|
|
9
|
+
items: [
|
|
10
|
+
{
|
|
11
|
+
id: '1',
|
|
12
|
+
name: 'Sample Product',
|
|
13
|
+
description: 'This is a sample product for demonstration',
|
|
14
|
+
price: 29.99,
|
|
15
|
+
inStock: true,
|
|
16
|
+
category: 'Electronics',
|
|
17
|
+
tags: ['sample', 'demo'],
|
|
18
|
+
created_at: new Date().toISOString(),
|
|
19
|
+
updated_at: new Date().toISOString(),
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
loading: false,
|
|
23
|
+
error: null,
|
|
24
|
+
selectedProduct: null,
|
|
25
|
+
});
|
|
26
|
+
// Reactive getters
|
|
27
|
+
get items() {
|
|
28
|
+
return this.data.items;
|
|
29
|
+
}
|
|
30
|
+
get loading() {
|
|
31
|
+
return this.data.loading;
|
|
32
|
+
}
|
|
33
|
+
get error() {
|
|
34
|
+
return this.data.error;
|
|
35
|
+
}
|
|
36
|
+
get selectedProduct() {
|
|
37
|
+
return this.data.selectedProduct;
|
|
38
|
+
}
|
|
39
|
+
// Derived state
|
|
40
|
+
get inStockCount() {
|
|
41
|
+
return this.data.items.filter((p) => p.inStock).length;
|
|
42
|
+
}
|
|
43
|
+
get totalValue() {
|
|
44
|
+
return this.data.items.reduce((sum, product) => sum + (product.price || 0), 0);
|
|
45
|
+
}
|
|
46
|
+
get categories() {
|
|
47
|
+
const categorySet = new Set(this.data.items.map((p) => p.category).filter(Boolean));
|
|
48
|
+
return Array.from(categorySet);
|
|
49
|
+
}
|
|
50
|
+
// Actions (mock implementations)
|
|
51
|
+
async loadProducts() {
|
|
52
|
+
this.data.loading = true;
|
|
53
|
+
this.data.error = null;
|
|
54
|
+
// Simulate API call
|
|
55
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
56
|
+
this.data.loading = false;
|
|
57
|
+
}
|
|
58
|
+
async createProduct(productData) {
|
|
59
|
+
this.data.loading = true;
|
|
60
|
+
this.data.error = null;
|
|
61
|
+
try {
|
|
62
|
+
const newProduct = {
|
|
63
|
+
id: String(Date.now()),
|
|
64
|
+
created_at: new Date().toISOString(),
|
|
65
|
+
updated_at: new Date().toISOString(),
|
|
66
|
+
...productData,
|
|
67
|
+
};
|
|
68
|
+
this.data.items.push(newProduct);
|
|
69
|
+
return { data: newProduct };
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
this.data.error =
|
|
73
|
+
err instanceof Error ? err.message : 'Failed to create product';
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
this.data.loading = false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async updateProduct(id, updates) {
|
|
81
|
+
this.data.loading = true;
|
|
82
|
+
this.data.error = null;
|
|
83
|
+
try {
|
|
84
|
+
const index = this.data.items.findIndex((p) => p.id === id);
|
|
85
|
+
if (index !== -1) {
|
|
86
|
+
const updatedProduct = {
|
|
87
|
+
...this.data.items[index],
|
|
88
|
+
...updates,
|
|
89
|
+
updated_at: new Date().toISOString(),
|
|
90
|
+
};
|
|
91
|
+
this.data.items[index] = updatedProduct;
|
|
92
|
+
if (this.data.selectedProduct?.id === id) {
|
|
93
|
+
this.data.selectedProduct = updatedProduct;
|
|
94
|
+
}
|
|
95
|
+
return { data: updatedProduct };
|
|
96
|
+
}
|
|
97
|
+
throw new Error('Product not found');
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
this.data.error =
|
|
101
|
+
err instanceof Error ? err.message : 'Failed to update product';
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
this.data.loading = false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async deleteProduct(id) {
|
|
109
|
+
this.data.loading = true;
|
|
110
|
+
this.data.error = null;
|
|
111
|
+
try {
|
|
112
|
+
this.data.items = this.data.items.filter((p) => p.id !== id);
|
|
113
|
+
if (this.data.selectedProduct?.id === id) {
|
|
114
|
+
this.data.selectedProduct = null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
this.data.error =
|
|
119
|
+
err instanceof Error ? err.message : 'Failed to delete product';
|
|
120
|
+
throw err;
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
this.data.loading = false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
selectProduct(product) {
|
|
127
|
+
this.data.selectedProduct = product;
|
|
128
|
+
}
|
|
129
|
+
clearError() {
|
|
130
|
+
this.data.error = null;
|
|
131
|
+
}
|
|
132
|
+
// Filter methods
|
|
133
|
+
filterByCategory(category) {
|
|
134
|
+
return this.data.items.filter((p) => p.category === category);
|
|
135
|
+
}
|
|
136
|
+
filterInStock() {
|
|
137
|
+
return this.data.items.filter((p) => p.inStock);
|
|
138
|
+
}
|
|
139
|
+
searchProducts(query) {
|
|
140
|
+
const lowercaseQuery = query.toLowerCase();
|
|
141
|
+
return this.data.items.filter((product) => product.name?.toLowerCase().includes(lowercaseQuery) ||
|
|
142
|
+
product.description?.toLowerCase().includes(lowercaseQuery) ||
|
|
143
|
+
product.tags?.some((tag) => tag.toLowerCase().includes(lowercaseQuery)));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Export singleton instance
|
|
147
|
+
export const productStore = new ProductStoreClass();
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product Store - Svelte 5 Runes State Management
|
|
3
|
+
*
|
|
4
|
+
* Reactive store for managing product state with SMRT auto-generated client.
|
|
5
|
+
* Uses Svelte 5 runes for reactive state management.
|
|
6
|
+
*/
|
|
7
|
+
import { type ProductData } from '../mock-smrt-client';
|
|
8
|
+
export declare class ProductStoreClass {
|
|
9
|
+
private data;
|
|
10
|
+
private api;
|
|
11
|
+
get items(): ProductData[];
|
|
12
|
+
get loading(): boolean;
|
|
13
|
+
get error(): string | null;
|
|
14
|
+
get selectedProduct(): ProductData | null;
|
|
15
|
+
get inStockCount(): number;
|
|
16
|
+
get totalValue(): number;
|
|
17
|
+
get categories(): string[];
|
|
18
|
+
loadProducts(): Promise<void>;
|
|
19
|
+
createProduct(productData: Partial<ProductData>): Promise<import("../mock-smrt-client").ApiResponse<ProductData>>;
|
|
20
|
+
updateProduct(id: string, updates: Partial<ProductData>): Promise<import("../mock-smrt-client").ApiResponse<ProductData>>;
|
|
21
|
+
deleteProduct(id: string): Promise<void>;
|
|
22
|
+
selectProduct(product: ProductData | null): void;
|
|
23
|
+
clearError(): void;
|
|
24
|
+
filterByCategory(category: string): ProductData[];
|
|
25
|
+
filterInStock(): ProductData[];
|
|
26
|
+
searchProducts(query: string): ProductData[];
|
|
27
|
+
}
|
|
28
|
+
export declare const productStore: ProductStoreClass;
|
|
29
|
+
//# sourceMappingURL=product-store.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product-store.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/stores/product-store.svelte.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AASrE,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,IAAI,CAKT;IAEH,OAAO,CAAC,GAAG,CAA2B;IAGtC,IAAI,KAAK,kBAER;IACD,IAAI,OAAO,YAEV;IACD,IAAI,KAAK,kBAER;IACD,IAAI,eAAe,uBAElB;IAGD,IAAI,YAAY,WAEf;IAED,IAAI,UAAU,WAKb;IAED,IAAI,UAAU,aAKb;IAGK,YAAY;IAiBZ,aAAa,CAAC,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC;IAmB/C,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC;IA2BvD,aAAa,CAAC,EAAE,EAAE,MAAM;IAqB9B,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIzC,UAAU;IAKV,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE;IAIjD,aAAa,IAAI,WAAW,EAAE;IAI9B,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE;CAS7C;AAGD,eAAO,MAAM,YAAY,mBAA0B,CAAC"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product Store - Svelte 5 Runes State Management
|
|
3
|
+
*
|
|
4
|
+
* Reactive store for managing product state with SMRT auto-generated client.
|
|
5
|
+
* Uses Svelte 5 runes for reactive state management.
|
|
6
|
+
*/
|
|
7
|
+
import { createClient } from '../mock-smrt-client';
|
|
8
|
+
export class ProductStoreClass {
|
|
9
|
+
data = $state({
|
|
10
|
+
items: [],
|
|
11
|
+
loading: false,
|
|
12
|
+
error: null,
|
|
13
|
+
selectedProduct: null,
|
|
14
|
+
});
|
|
15
|
+
api = createClient('/api/v1');
|
|
16
|
+
// Reactive getters
|
|
17
|
+
get items() {
|
|
18
|
+
return this.data.items;
|
|
19
|
+
}
|
|
20
|
+
get loading() {
|
|
21
|
+
return this.data.loading;
|
|
22
|
+
}
|
|
23
|
+
get error() {
|
|
24
|
+
return this.data.error;
|
|
25
|
+
}
|
|
26
|
+
get selectedProduct() {
|
|
27
|
+
return this.data.selectedProduct;
|
|
28
|
+
}
|
|
29
|
+
// Derived state
|
|
30
|
+
get inStockCount() {
|
|
31
|
+
return this.data.items.filter((p) => p.inStock).length;
|
|
32
|
+
}
|
|
33
|
+
get totalValue() {
|
|
34
|
+
return this.data.items.reduce((sum, product) => sum + (product.price || 0), 0);
|
|
35
|
+
}
|
|
36
|
+
get categories() {
|
|
37
|
+
const categorySet = new Set(this.data.items.map((p) => p.category).filter(Boolean));
|
|
38
|
+
return Array.from(categorySet);
|
|
39
|
+
}
|
|
40
|
+
// Actions
|
|
41
|
+
async loadProducts() {
|
|
42
|
+
this.data.loading = true;
|
|
43
|
+
this.data.error = null;
|
|
44
|
+
try {
|
|
45
|
+
const response = await this.api.products.list();
|
|
46
|
+
if (response.data) {
|
|
47
|
+
this.data.items = response.data;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
this.data.error =
|
|
52
|
+
err instanceof Error ? err.message : 'Failed to load products';
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
this.data.loading = false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async createProduct(productData) {
|
|
59
|
+
this.data.loading = true;
|
|
60
|
+
this.data.error = null;
|
|
61
|
+
try {
|
|
62
|
+
const response = await this.api.products.create(productData);
|
|
63
|
+
if (response.data) {
|
|
64
|
+
this.data.items.push(response.data);
|
|
65
|
+
}
|
|
66
|
+
return response;
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
this.data.error =
|
|
70
|
+
err instanceof Error ? err.message : 'Failed to create product';
|
|
71
|
+
throw err;
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
this.data.loading = false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async updateProduct(id, updates) {
|
|
78
|
+
this.data.loading = true;
|
|
79
|
+
this.data.error = null;
|
|
80
|
+
try {
|
|
81
|
+
const response = await this.api.products.update(id, updates);
|
|
82
|
+
if (response.data) {
|
|
83
|
+
const index = this.data.items.findIndex((p) => p.id === id);
|
|
84
|
+
if (index !== -1) {
|
|
85
|
+
this.data.items[index] = response.data;
|
|
86
|
+
}
|
|
87
|
+
// Update selected product if it's the one being updated
|
|
88
|
+
if (this.data.selectedProduct?.id === id) {
|
|
89
|
+
this.data.selectedProduct = response.data;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return response;
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
this.data.error =
|
|
96
|
+
err instanceof Error ? err.message : 'Failed to update product';
|
|
97
|
+
throw err;
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
this.data.loading = false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async deleteProduct(id) {
|
|
104
|
+
this.data.loading = true;
|
|
105
|
+
this.data.error = null;
|
|
106
|
+
try {
|
|
107
|
+
await this.api.products.delete(id);
|
|
108
|
+
this.data.items = this.data.items.filter((p) => p.id !== id);
|
|
109
|
+
// Clear selection if deleted product was selected
|
|
110
|
+
if (this.data.selectedProduct?.id === id) {
|
|
111
|
+
this.data.selectedProduct = null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
this.data.error =
|
|
116
|
+
err instanceof Error ? err.message : 'Failed to delete product';
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
this.data.loading = false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
selectProduct(product) {
|
|
124
|
+
this.data.selectedProduct = product;
|
|
125
|
+
}
|
|
126
|
+
clearError() {
|
|
127
|
+
this.data.error = null;
|
|
128
|
+
}
|
|
129
|
+
// Filter methods (return derived arrays, don't mutate state)
|
|
130
|
+
filterByCategory(category) {
|
|
131
|
+
return this.data.items.filter((p) => p.category === category);
|
|
132
|
+
}
|
|
133
|
+
filterInStock() {
|
|
134
|
+
return this.data.items.filter((p) => p.inStock);
|
|
135
|
+
}
|
|
136
|
+
searchProducts(query) {
|
|
137
|
+
const lowercaseQuery = query.toLowerCase();
|
|
138
|
+
return this.data.items.filter((product) => product.name?.toLowerCase().includes(lowercaseQuery) ||
|
|
139
|
+
product.description?.toLowerCase().includes(lowercaseQuery) ||
|
|
140
|
+
product.tags?.some((tag) => tag.toLowerCase().includes(lowercaseQuery)));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Export singleton instance
|
|
144
|
+
export const productStore = new ProductStoreClass();
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic type definitions for UI components
|
|
3
|
+
* These are standalone types that don't depend on SMRT virtual modules
|
|
4
|
+
* to avoid Node.js dependency issues in federation builds
|
|
5
|
+
*/
|
|
6
|
+
export interface ProductData {
|
|
7
|
+
id?: string;
|
|
8
|
+
created_at?: string;
|
|
9
|
+
updated_at?: string;
|
|
10
|
+
name?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
category?: string;
|
|
13
|
+
manufacturer?: string;
|
|
14
|
+
model?: string;
|
|
15
|
+
price?: number;
|
|
16
|
+
inStock?: boolean;
|
|
17
|
+
specifications?: Record<string, any>;
|
|
18
|
+
tags?: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface CategoryData {
|
|
21
|
+
id?: string;
|
|
22
|
+
created_at?: string;
|
|
23
|
+
updated_at?: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
slug?: string;
|
|
27
|
+
parentId?: string;
|
|
28
|
+
level?: number;
|
|
29
|
+
productCount?: number;
|
|
30
|
+
active?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface Request {
|
|
33
|
+
params: Record<string, string>;
|
|
34
|
+
query: Record<string, any>;
|
|
35
|
+
json(): Promise<any>;
|
|
36
|
+
}
|
|
37
|
+
export interface Response {
|
|
38
|
+
json(data: any, init?: {
|
|
39
|
+
status?: number;
|
|
40
|
+
}): Response;
|
|
41
|
+
status(code: number): Response;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,QAAQ,CAAC;IACtD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;CAChC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMRT Template Utilities
|
|
3
|
+
*
|
|
4
|
+
* Shared utility functions for product management functionality.
|
|
5
|
+
*/
|
|
6
|
+
export declare function formatPrice(price: number): string;
|
|
7
|
+
export declare function formatDate(date: string | Date): string;
|
|
8
|
+
export declare function slugify(text: string): string;
|
|
9
|
+
export declare function generateId(): string;
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/utils/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAOtD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK5C;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/main.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|