@unifiedcommerce/core 0.1.0 → 0.1.1
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/package.json +1 -2
- package/src/adapters/console-email.ts +0 -43
- package/src/auth/access.ts +0 -187
- package/src/auth/auth-schema.ts +0 -139
- package/src/auth/middleware.ts +0 -161
- package/src/auth/org.ts +0 -41
- package/src/auth/permissions.ts +0 -28
- package/src/auth/setup.ts +0 -169
- package/src/auth/system-actor.ts +0 -19
- package/src/auth/types.ts +0 -10
- package/src/config/defaults.ts +0 -82
- package/src/config/define-config.ts +0 -53
- package/src/config/types.ts +0 -299
- package/src/generated/plugin-capabilities.d.ts +0 -20
- package/src/generated/plugin-manifest.ts +0 -23
- package/src/generated/plugin-repositories.d.ts +0 -20
- package/src/hooks/checkout-completion.ts +0 -262
- package/src/hooks/checkout.ts +0 -677
- package/src/hooks/order-emails.ts +0 -62
- package/src/index.ts +0 -214
- package/src/interfaces/mcp/agent-prompt.ts +0 -174
- package/src/interfaces/mcp/context-enrichment.ts +0 -177
- package/src/interfaces/mcp/server.ts +0 -617
- package/src/interfaces/mcp/transport.ts +0 -68
- package/src/interfaces/rest/customer-portal.ts +0 -299
- package/src/interfaces/rest/index.ts +0 -74
- package/src/interfaces/rest/router.ts +0 -334
- package/src/interfaces/rest/routes/admin-jobs.ts +0 -58
- package/src/interfaces/rest/routes/audit.ts +0 -50
- package/src/interfaces/rest/routes/carts.ts +0 -89
- package/src/interfaces/rest/routes/catalog.ts +0 -493
- package/src/interfaces/rest/routes/checkout.ts +0 -283
- package/src/interfaces/rest/routes/inventory.ts +0 -70
- package/src/interfaces/rest/routes/media.ts +0 -86
- package/src/interfaces/rest/routes/orders.ts +0 -78
- package/src/interfaces/rest/routes/payments.ts +0 -60
- package/src/interfaces/rest/routes/pricing.ts +0 -57
- package/src/interfaces/rest/routes/promotions.ts +0 -92
- package/src/interfaces/rest/routes/search.ts +0 -71
- package/src/interfaces/rest/routes/webhooks.ts +0 -46
- package/src/interfaces/rest/schemas/admin-jobs.ts +0 -40
- package/src/interfaces/rest/schemas/audit.ts +0 -46
- package/src/interfaces/rest/schemas/carts.ts +0 -125
- package/src/interfaces/rest/schemas/catalog.ts +0 -450
- package/src/interfaces/rest/schemas/checkout.ts +0 -66
- package/src/interfaces/rest/schemas/customer-portal.ts +0 -195
- package/src/interfaces/rest/schemas/inventory.ts +0 -138
- package/src/interfaces/rest/schemas/media.ts +0 -75
- package/src/interfaces/rest/schemas/orders.ts +0 -104
- package/src/interfaces/rest/schemas/pricing.ts +0 -80
- package/src/interfaces/rest/schemas/promotions.ts +0 -110
- package/src/interfaces/rest/schemas/responses.ts +0 -85
- package/src/interfaces/rest/schemas/search.ts +0 -58
- package/src/interfaces/rest/schemas/shared.ts +0 -62
- package/src/interfaces/rest/schemas/webhooks.ts +0 -68
- package/src/interfaces/rest/utils.ts +0 -104
- package/src/interfaces/rest/webhook-router.ts +0 -50
- package/src/kernel/compensation/executor.ts +0 -61
- package/src/kernel/compensation/types.ts +0 -26
- package/src/kernel/database/adapter.ts +0 -13
- package/src/kernel/database/drizzle-db.ts +0 -56
- package/src/kernel/database/migrate.ts +0 -76
- package/src/kernel/database/plugin-types.ts +0 -34
- package/src/kernel/database/schema.ts +0 -49
- package/src/kernel/database/scoped-db.ts +0 -68
- package/src/kernel/database/tx-context.ts +0 -46
- package/src/kernel/error-mapper.ts +0 -15
- package/src/kernel/errors.ts +0 -89
- package/src/kernel/factory/repository-factory.ts +0 -242
- package/src/kernel/hooks/create-context.ts +0 -43
- package/src/kernel/hooks/executor.ts +0 -88
- package/src/kernel/hooks/registry.ts +0 -74
- package/src/kernel/hooks/types.ts +0 -52
- package/src/kernel/http-error.ts +0 -44
- package/src/kernel/jobs/adapter.ts +0 -36
- package/src/kernel/jobs/drizzle-adapter.ts +0 -58
- package/src/kernel/jobs/runner.ts +0 -153
- package/src/kernel/jobs/schema.ts +0 -46
- package/src/kernel/jobs/types.ts +0 -30
- package/src/kernel/local-api.ts +0 -185
- package/src/kernel/plugin/manifest.ts +0 -253
- package/src/kernel/query/executor.ts +0 -184
- package/src/kernel/query/registry.ts +0 -46
- package/src/kernel/result.ts +0 -33
- package/src/kernel/schema/extra-columns.ts +0 -37
- package/src/kernel/service-registry.ts +0 -76
- package/src/kernel/service-timing.ts +0 -89
- package/src/kernel/state-machine/machine.ts +0 -101
- package/src/modules/analytics/drizzle-adapter.ts +0 -426
- package/src/modules/analytics/hooks.ts +0 -11
- package/src/modules/analytics/models.ts +0 -125
- package/src/modules/analytics/repository/index.ts +0 -6
- package/src/modules/analytics/service.ts +0 -245
- package/src/modules/analytics/types.ts +0 -180
- package/src/modules/audit/hooks.ts +0 -78
- package/src/modules/audit/schema.ts +0 -33
- package/src/modules/audit/service.ts +0 -151
- package/src/modules/cart/access.ts +0 -27
- package/src/modules/cart/matcher.ts +0 -26
- package/src/modules/cart/repository/index.ts +0 -234
- package/src/modules/cart/schema.ts +0 -42
- package/src/modules/cart/schemas.ts +0 -38
- package/src/modules/cart/service.ts +0 -541
- package/src/modules/catalog/repository/index.ts +0 -772
- package/src/modules/catalog/schema.ts +0 -203
- package/src/modules/catalog/schemas.ts +0 -104
- package/src/modules/catalog/service.ts +0 -1544
- package/src/modules/customers/repository/index.ts +0 -327
- package/src/modules/customers/schema.ts +0 -64
- package/src/modules/customers/service.ts +0 -171
- package/src/modules/fulfillment/repository/index.ts +0 -426
- package/src/modules/fulfillment/schema.ts +0 -101
- package/src/modules/fulfillment/service.ts +0 -555
- package/src/modules/fulfillment/types.ts +0 -59
- package/src/modules/inventory/repository/index.ts +0 -509
- package/src/modules/inventory/schema.ts +0 -94
- package/src/modules/inventory/schemas.ts +0 -38
- package/src/modules/inventory/service.ts +0 -490
- package/src/modules/media/adapter.ts +0 -17
- package/src/modules/media/repository/index.ts +0 -274
- package/src/modules/media/schema.ts +0 -41
- package/src/modules/media/service.ts +0 -151
- package/src/modules/orders/repository/index.ts +0 -287
- package/src/modules/orders/schema.ts +0 -66
- package/src/modules/orders/service.ts +0 -619
- package/src/modules/orders/stale-order-cleanup.ts +0 -76
- package/src/modules/organization/service.ts +0 -191
- package/src/modules/payments/adapter.ts +0 -47
- package/src/modules/payments/repository/index.ts +0 -6
- package/src/modules/payments/service.ts +0 -107
- package/src/modules/pricing/repository/index.ts +0 -291
- package/src/modules/pricing/schema.ts +0 -71
- package/src/modules/pricing/schemas.ts +0 -38
- package/src/modules/pricing/service.ts +0 -494
- package/src/modules/promotions/repository/index.ts +0 -325
- package/src/modules/promotions/schema.ts +0 -62
- package/src/modules/promotions/schemas.ts +0 -38
- package/src/modules/promotions/service.ts +0 -598
- package/src/modules/search/adapter.ts +0 -57
- package/src/modules/search/hooks.ts +0 -12
- package/src/modules/search/repository/index.ts +0 -6
- package/src/modules/search/service.ts +0 -315
- package/src/modules/shipping/calculator.ts +0 -188
- package/src/modules/shipping/repository/index.ts +0 -6
- package/src/modules/shipping/service.ts +0 -51
- package/src/modules/tax/adapter.ts +0 -60
- package/src/modules/tax/repository/index.ts +0 -6
- package/src/modules/tax/service.ts +0 -53
- package/src/modules/webhooks/hook.ts +0 -34
- package/src/modules/webhooks/repository/index.ts +0 -278
- package/src/modules/webhooks/schema.ts +0 -56
- package/src/modules/webhooks/service.ts +0 -117
- package/src/modules/webhooks/signing.ts +0 -6
- package/src/modules/webhooks/ssrf-guard.ts +0 -71
- package/src/modules/webhooks/tasks.ts +0 -52
- package/src/modules/webhooks/worker.ts +0 -134
- package/src/runtime/commerce.ts +0 -145
- package/src/runtime/kernel.ts +0 -419
- package/src/runtime/logger.ts +0 -36
- package/src/runtime/server.ts +0 -349
- package/src/runtime/shutdown.ts +0 -43
- package/src/test-utils/create-pglite-adapter.ts +0 -129
- package/src/test-utils/create-plugin-test-app.ts +0 -128
- package/src/test-utils/create-repository-test-harness.ts +0 -16
- package/src/test-utils/create-test-config.ts +0 -190
- package/src/test-utils/create-test-kernel.ts +0 -7
- package/src/test-utils/create-test-plugin-context.ts +0 -75
- package/src/test-utils/rest-api-test-utils.ts +0 -265
- package/src/test-utils/test-actors.ts +0 -62
- package/src/test-utils/typed-hooks.ts +0 -54
- package/src/types/commerce-types.ts +0 -34
- package/src/utils/id.ts +0 -3
- package/src/utils/logger.ts +0 -18
- package/src/utils/pagination.ts +0 -22
|
@@ -1,772 +0,0 @@
|
|
|
1
|
-
import { eq, and, inArray, type SQL } from "drizzle-orm";
|
|
2
|
-
import type { TxContext } from "../../../kernel/database/tx-context.js";
|
|
3
|
-
import type {
|
|
4
|
-
DrizzleDatabase,
|
|
5
|
-
DbOrTx,
|
|
6
|
-
} from "../../../kernel/database/drizzle-db.js";
|
|
7
|
-
import {
|
|
8
|
-
sellableEntities,
|
|
9
|
-
sellableAttributes,
|
|
10
|
-
sellableCustomFields,
|
|
11
|
-
categories,
|
|
12
|
-
entityCategories,
|
|
13
|
-
brands,
|
|
14
|
-
entityBrands,
|
|
15
|
-
optionTypes,
|
|
16
|
-
optionValues,
|
|
17
|
-
variants,
|
|
18
|
-
variantOptionValues,
|
|
19
|
-
} from "../schema.js";
|
|
20
|
-
|
|
21
|
-
// Infer types from Drizzle schema
|
|
22
|
-
export type SellableEntity = typeof sellableEntities.$inferSelect;
|
|
23
|
-
export type SellableEntityInsert = typeof sellableEntities.$inferInsert;
|
|
24
|
-
export type SellableAttribute = typeof sellableAttributes.$inferSelect;
|
|
25
|
-
export type SellableAttributeInsert = typeof sellableAttributes.$inferInsert;
|
|
26
|
-
export type SellableCustomField = typeof sellableCustomFields.$inferSelect;
|
|
27
|
-
export type SellableCustomFieldInsert =
|
|
28
|
-
typeof sellableCustomFields.$inferInsert;
|
|
29
|
-
export type Category = typeof categories.$inferSelect;
|
|
30
|
-
export type CategoryInsert = typeof categories.$inferInsert;
|
|
31
|
-
export type EntityCategory = typeof entityCategories.$inferSelect;
|
|
32
|
-
export type EntityCategoryInsert = typeof entityCategories.$inferInsert;
|
|
33
|
-
export type Brand = typeof brands.$inferSelect;
|
|
34
|
-
export type BrandInsert = typeof brands.$inferInsert;
|
|
35
|
-
export type EntityBrand = typeof entityBrands.$inferSelect;
|
|
36
|
-
export type EntityBrandInsert = typeof entityBrands.$inferInsert;
|
|
37
|
-
export type OptionType = typeof optionTypes.$inferSelect;
|
|
38
|
-
export type OptionTypeInsert = typeof optionTypes.$inferInsert;
|
|
39
|
-
export type OptionValue = typeof optionValues.$inferSelect;
|
|
40
|
-
export type OptionValueInsert = typeof optionValues.$inferInsert;
|
|
41
|
-
export type Variant = typeof variants.$inferSelect;
|
|
42
|
-
export type VariantInsert = typeof variants.$inferInsert;
|
|
43
|
-
export type VariantOptionValue = typeof variantOptionValues.$inferSelect;
|
|
44
|
-
export type VariantOptionValueInsert = typeof variantOptionValues.$inferInsert;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* CatalogRepository provides type-safe database operations for catalog entities.
|
|
48
|
-
*
|
|
49
|
-
* This repository uses Drizzle ORM with PostgresJsDatabase for full type inference.
|
|
50
|
-
* Transaction context is passed through TxContext when needed for transactional writes.
|
|
51
|
-
*
|
|
52
|
-
* All methods support an optional TxContext parameter for transaction participation.
|
|
53
|
-
* When ctx is provided, operations run within that transaction; otherwise they use the main db.
|
|
54
|
-
*/
|
|
55
|
-
export class CatalogRepository {
|
|
56
|
-
constructor(private readonly db: DrizzleDatabase) {}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Returns the appropriate database context - either a transaction or the main db.
|
|
60
|
-
* Both DrizzleDatabase and DrizzleTx have the same query builder interface.
|
|
61
|
-
*/
|
|
62
|
-
private getDb(ctx?: TxContext): DbOrTx {
|
|
63
|
-
return (ctx?.tx as DbOrTx | undefined) ?? this.db;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
67
|
-
// Sellable Entities
|
|
68
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
69
|
-
|
|
70
|
-
async findEntityById(
|
|
71
|
-
id: string,
|
|
72
|
-
ctx?: TxContext,
|
|
73
|
-
): Promise<SellableEntity | undefined> {
|
|
74
|
-
const db = this.getDb(ctx);
|
|
75
|
-
const rows = await db
|
|
76
|
-
.select()
|
|
77
|
-
.from(sellableEntities)
|
|
78
|
-
.where(eq(sellableEntities.id, id));
|
|
79
|
-
return rows[0];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async findEntityBySlug(
|
|
83
|
-
orgId: string,
|
|
84
|
-
slug: string,
|
|
85
|
-
ctx?: TxContext,
|
|
86
|
-
): Promise<SellableEntity | undefined> {
|
|
87
|
-
const db = this.getDb(ctx);
|
|
88
|
-
const rows = await db
|
|
89
|
-
.select()
|
|
90
|
-
.from(sellableEntities)
|
|
91
|
-
.where(
|
|
92
|
-
and(
|
|
93
|
-
eq(sellableEntities.organizationId, orgId),
|
|
94
|
-
eq(sellableEntities.slug, slug),
|
|
95
|
-
),
|
|
96
|
-
);
|
|
97
|
-
return rows[0];
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async findEntities(
|
|
101
|
-
orgId: string,
|
|
102
|
-
filter?: {
|
|
103
|
-
type?: string;
|
|
104
|
-
status?: string;
|
|
105
|
-
ids?: string[];
|
|
106
|
-
},
|
|
107
|
-
ctx?: TxContext,
|
|
108
|
-
): Promise<SellableEntity[]> {
|
|
109
|
-
const db = this.getDb(ctx);
|
|
110
|
-
const conditions: SQL[] = [eq(sellableEntities.organizationId, orgId)];
|
|
111
|
-
|
|
112
|
-
if (filter?.type) {
|
|
113
|
-
conditions.push(eq(sellableEntities.type, filter.type));
|
|
114
|
-
}
|
|
115
|
-
if (filter?.status) {
|
|
116
|
-
conditions.push(
|
|
117
|
-
eq(sellableEntities.status, filter.status as SellableEntity["status"]),
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
if (filter?.ids && filter.ids.length > 0) {
|
|
121
|
-
conditions.push(inArray(sellableEntities.id, filter.ids));
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return db
|
|
125
|
-
.select()
|
|
126
|
-
.from(sellableEntities)
|
|
127
|
-
.where(conditions.length === 1 ? conditions[0] : and(...conditions));
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
async createEntity(
|
|
131
|
-
data: SellableEntityInsert,
|
|
132
|
-
ctx?: TxContext,
|
|
133
|
-
): Promise<SellableEntity> {
|
|
134
|
-
const db = this.getDb(ctx);
|
|
135
|
-
const rows = await db.insert(sellableEntities).values(data).returning();
|
|
136
|
-
return rows[0]!;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
async updateEntity(
|
|
140
|
-
id: string,
|
|
141
|
-
data: Partial<Omit<SellableEntityInsert, "id">>,
|
|
142
|
-
ctx?: TxContext,
|
|
143
|
-
): Promise<SellableEntity | undefined> {
|
|
144
|
-
const db = this.getDb(ctx);
|
|
145
|
-
const rows = await db
|
|
146
|
-
.update(sellableEntities)
|
|
147
|
-
.set({ ...data, updatedAt: new Date() })
|
|
148
|
-
.where(eq(sellableEntities.id, id))
|
|
149
|
-
.returning();
|
|
150
|
-
return rows[0];
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
async deleteEntity(id: string, ctx?: TxContext): Promise<boolean> {
|
|
154
|
-
const db = this.getDb(ctx);
|
|
155
|
-
const result = await db
|
|
156
|
-
.delete(sellableEntities)
|
|
157
|
-
.where(eq(sellableEntities.id, id))
|
|
158
|
-
.returning();
|
|
159
|
-
return result.length > 0;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
163
|
-
// Sellable Attributes
|
|
164
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
165
|
-
|
|
166
|
-
async findAttributesByEntityId(
|
|
167
|
-
entityId: string,
|
|
168
|
-
ctx?: TxContext,
|
|
169
|
-
): Promise<SellableAttribute[]> {
|
|
170
|
-
const db = this.getDb(ctx);
|
|
171
|
-
return db
|
|
172
|
-
.select()
|
|
173
|
-
.from(sellableAttributes)
|
|
174
|
-
.where(eq(sellableAttributes.entityId, entityId));
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
async findAttributeByLocale(
|
|
178
|
-
entityId: string,
|
|
179
|
-
locale: string,
|
|
180
|
-
ctx?: TxContext,
|
|
181
|
-
): Promise<SellableAttribute | undefined> {
|
|
182
|
-
const db = this.getDb(ctx);
|
|
183
|
-
const rows = await db
|
|
184
|
-
.select()
|
|
185
|
-
.from(sellableAttributes)
|
|
186
|
-
.where(
|
|
187
|
-
and(
|
|
188
|
-
eq(sellableAttributes.entityId, entityId),
|
|
189
|
-
eq(sellableAttributes.locale, locale),
|
|
190
|
-
),
|
|
191
|
-
);
|
|
192
|
-
return rows[0];
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
async createAttribute(
|
|
196
|
-
data: SellableAttributeInsert,
|
|
197
|
-
ctx?: TxContext,
|
|
198
|
-
): Promise<SellableAttribute> {
|
|
199
|
-
const db = this.getDb(ctx);
|
|
200
|
-
const rows = await db.insert(sellableAttributes).values(data).returning();
|
|
201
|
-
return rows[0]!;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
async updateAttribute(
|
|
205
|
-
id: string,
|
|
206
|
-
data: Partial<Omit<SellableAttributeInsert, "id">>,
|
|
207
|
-
ctx?: TxContext,
|
|
208
|
-
): Promise<SellableAttribute | undefined> {
|
|
209
|
-
const db = this.getDb(ctx);
|
|
210
|
-
const rows = await db
|
|
211
|
-
.update(sellableAttributes)
|
|
212
|
-
.set(data)
|
|
213
|
-
.where(eq(sellableAttributes.id, id))
|
|
214
|
-
.returning();
|
|
215
|
-
return rows[0];
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
async upsertAttribute(
|
|
219
|
-
entityId: string,
|
|
220
|
-
locale: string,
|
|
221
|
-
data: Omit<SellableAttributeInsert, "entityId" | "locale">,
|
|
222
|
-
ctx?: TxContext,
|
|
223
|
-
): Promise<SellableAttribute> {
|
|
224
|
-
const existing = await this.findAttributeByLocale(entityId, locale, ctx);
|
|
225
|
-
if (existing) {
|
|
226
|
-
const updated = await this.updateAttribute(existing.id, data, ctx);
|
|
227
|
-
return updated!;
|
|
228
|
-
}
|
|
229
|
-
return this.createAttribute({ ...data, entityId, locale }, ctx);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
async deleteAttributesByEntityId(
|
|
233
|
-
entityId: string,
|
|
234
|
-
ctx?: TxContext,
|
|
235
|
-
): Promise<void> {
|
|
236
|
-
const db = this.getDb(ctx);
|
|
237
|
-
await db
|
|
238
|
-
.delete(sellableAttributes)
|
|
239
|
-
.where(eq(sellableAttributes.entityId, entityId));
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
243
|
-
// Custom Fields
|
|
244
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
245
|
-
|
|
246
|
-
async findCustomFieldsByEntityId(
|
|
247
|
-
entityId: string,
|
|
248
|
-
ctx?: TxContext,
|
|
249
|
-
): Promise<SellableCustomField[]> {
|
|
250
|
-
const db = this.getDb(ctx);
|
|
251
|
-
return db
|
|
252
|
-
.select()
|
|
253
|
-
.from(sellableCustomFields)
|
|
254
|
-
.where(eq(sellableCustomFields.entityId, entityId));
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
async createCustomField(
|
|
258
|
-
data: SellableCustomFieldInsert,
|
|
259
|
-
ctx?: TxContext,
|
|
260
|
-
): Promise<SellableCustomField> {
|
|
261
|
-
const db = this.getDb(ctx);
|
|
262
|
-
const rows = await db.insert(sellableCustomFields).values(data).returning();
|
|
263
|
-
return rows[0]!;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
async deleteCustomFieldsByEntityId(
|
|
267
|
-
entityId: string,
|
|
268
|
-
ctx?: TxContext,
|
|
269
|
-
): Promise<void> {
|
|
270
|
-
const db = this.getDb(ctx);
|
|
271
|
-
await db
|
|
272
|
-
.delete(sellableCustomFields)
|
|
273
|
-
.where(eq(sellableCustomFields.entityId, entityId));
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
277
|
-
// Categories
|
|
278
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
279
|
-
|
|
280
|
-
async findCategoryById(
|
|
281
|
-
id: string,
|
|
282
|
-
ctx?: TxContext,
|
|
283
|
-
): Promise<Category | undefined> {
|
|
284
|
-
const db = this.getDb(ctx);
|
|
285
|
-
const rows = await db
|
|
286
|
-
.select()
|
|
287
|
-
.from(categories)
|
|
288
|
-
.where(eq(categories.id, id));
|
|
289
|
-
return rows[0];
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
async findCategoryBySlug(
|
|
293
|
-
orgId: string,
|
|
294
|
-
slug: string,
|
|
295
|
-
ctx?: TxContext,
|
|
296
|
-
): Promise<Category | undefined> {
|
|
297
|
-
const db = this.getDb(ctx);
|
|
298
|
-
const rows = await db
|
|
299
|
-
.select()
|
|
300
|
-
.from(categories)
|
|
301
|
-
.where(
|
|
302
|
-
and(
|
|
303
|
-
eq(categories.organizationId, orgId),
|
|
304
|
-
eq(categories.slug, slug),
|
|
305
|
-
),
|
|
306
|
-
);
|
|
307
|
-
return rows[0];
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
async findAllCategories(
|
|
311
|
-
orgId: string,
|
|
312
|
-
ctx?: TxContext,
|
|
313
|
-
): Promise<Category[]> {
|
|
314
|
-
const db = this.getDb(ctx);
|
|
315
|
-
return db
|
|
316
|
-
.select()
|
|
317
|
-
.from(categories)
|
|
318
|
-
.where(eq(categories.organizationId, orgId));
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
async createCategory(
|
|
322
|
-
data: CategoryInsert,
|
|
323
|
-
ctx?: TxContext,
|
|
324
|
-
): Promise<Category> {
|
|
325
|
-
const db = this.getDb(ctx);
|
|
326
|
-
const rows = await db.insert(categories).values(data).returning();
|
|
327
|
-
return rows[0]!;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
async updateCategory(
|
|
331
|
-
id: string,
|
|
332
|
-
data: Partial<Omit<CategoryInsert, "id">>,
|
|
333
|
-
ctx?: TxContext,
|
|
334
|
-
): Promise<Category | undefined> {
|
|
335
|
-
const db = this.getDb(ctx);
|
|
336
|
-
const rows = await db
|
|
337
|
-
.update(categories)
|
|
338
|
-
.set(data)
|
|
339
|
-
.where(eq(categories.id, id))
|
|
340
|
-
.returning();
|
|
341
|
-
return rows[0];
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
async deleteCategory(id: string, ctx?: TxContext): Promise<boolean> {
|
|
345
|
-
const db = this.getDb(ctx);
|
|
346
|
-
const result = await db
|
|
347
|
-
.delete(categories)
|
|
348
|
-
.where(eq(categories.id, id))
|
|
349
|
-
.returning();
|
|
350
|
-
return result.length > 0;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
354
|
-
// Entity Categories (Join Table)
|
|
355
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
356
|
-
|
|
357
|
-
async findEntityCategories(
|
|
358
|
-
entityId: string,
|
|
359
|
-
ctx?: TxContext,
|
|
360
|
-
): Promise<EntityCategory[]> {
|
|
361
|
-
const db = this.getDb(ctx);
|
|
362
|
-
return db
|
|
363
|
-
.select()
|
|
364
|
-
.from(entityCategories)
|
|
365
|
-
.where(eq(entityCategories.entityId, entityId));
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
async findEntitiesByCategory(
|
|
369
|
-
categoryId: string,
|
|
370
|
-
ctx?: TxContext,
|
|
371
|
-
): Promise<string[]> {
|
|
372
|
-
const db = this.getDb(ctx);
|
|
373
|
-
const rows = await db
|
|
374
|
-
.select()
|
|
375
|
-
.from(entityCategories)
|
|
376
|
-
.where(eq(entityCategories.categoryId, categoryId));
|
|
377
|
-
return rows.map((r) => r.entityId);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
async addEntityToCategory(
|
|
381
|
-
entityId: string,
|
|
382
|
-
categoryId: string,
|
|
383
|
-
sortOrder = 0,
|
|
384
|
-
ctx?: TxContext,
|
|
385
|
-
): Promise<void> {
|
|
386
|
-
const db = this.getDb(ctx);
|
|
387
|
-
await db
|
|
388
|
-
.insert(entityCategories)
|
|
389
|
-
.values({ entityId, categoryId, sortOrder })
|
|
390
|
-
.onConflictDoNothing();
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
async removeEntityFromCategory(
|
|
394
|
-
entityId: string,
|
|
395
|
-
categoryId: string,
|
|
396
|
-
ctx?: TxContext,
|
|
397
|
-
): Promise<boolean> {
|
|
398
|
-
const db = this.getDb(ctx);
|
|
399
|
-
const result = await db
|
|
400
|
-
.delete(entityCategories)
|
|
401
|
-
.where(
|
|
402
|
-
and(
|
|
403
|
-
eq(entityCategories.entityId, entityId),
|
|
404
|
-
eq(entityCategories.categoryId, categoryId),
|
|
405
|
-
),
|
|
406
|
-
)
|
|
407
|
-
.returning();
|
|
408
|
-
return result.length > 0;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
async deleteEntityCategoriesByEntityId(
|
|
412
|
-
entityId: string,
|
|
413
|
-
ctx?: TxContext,
|
|
414
|
-
): Promise<void> {
|
|
415
|
-
const db = this.getDb(ctx);
|
|
416
|
-
await db
|
|
417
|
-
.delete(entityCategories)
|
|
418
|
-
.where(eq(entityCategories.entityId, entityId));
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
async deleteEntityCategoriesByCategoryId(
|
|
422
|
-
categoryId: string,
|
|
423
|
-
ctx?: TxContext,
|
|
424
|
-
): Promise<void> {
|
|
425
|
-
const db = this.getDb(ctx);
|
|
426
|
-
await db
|
|
427
|
-
.delete(entityCategories)
|
|
428
|
-
.where(eq(entityCategories.categoryId, categoryId));
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
432
|
-
// Brands
|
|
433
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
434
|
-
|
|
435
|
-
async findBrandById(id: string, ctx?: TxContext): Promise<Brand | undefined> {
|
|
436
|
-
const db = this.getDb(ctx);
|
|
437
|
-
const rows = await db.select().from(brands).where(eq(brands.id, id));
|
|
438
|
-
return rows[0];
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
async findBrandBySlug(
|
|
442
|
-
orgId: string,
|
|
443
|
-
slug: string,
|
|
444
|
-
ctx?: TxContext,
|
|
445
|
-
): Promise<Brand | undefined> {
|
|
446
|
-
const db = this.getDb(ctx);
|
|
447
|
-
const rows = await db
|
|
448
|
-
.select()
|
|
449
|
-
.from(brands)
|
|
450
|
-
.where(
|
|
451
|
-
and(
|
|
452
|
-
eq(brands.organizationId, orgId),
|
|
453
|
-
eq(brands.slug, slug),
|
|
454
|
-
),
|
|
455
|
-
);
|
|
456
|
-
return rows[0];
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
async findAllBrands(orgId: string, ctx?: TxContext): Promise<Brand[]> {
|
|
460
|
-
const db = this.getDb(ctx);
|
|
461
|
-
return db
|
|
462
|
-
.select()
|
|
463
|
-
.from(brands)
|
|
464
|
-
.where(eq(brands.organizationId, orgId));
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
async createBrand(data: BrandInsert, ctx?: TxContext): Promise<Brand> {
|
|
468
|
-
const db = this.getDb(ctx);
|
|
469
|
-
const rows = await db.insert(brands).values(data).returning();
|
|
470
|
-
return rows[0]!;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
async updateBrand(
|
|
474
|
-
id: string,
|
|
475
|
-
data: Partial<Omit<BrandInsert, "id">>,
|
|
476
|
-
ctx?: TxContext,
|
|
477
|
-
): Promise<Brand | undefined> {
|
|
478
|
-
const db = this.getDb(ctx);
|
|
479
|
-
const rows = await db
|
|
480
|
-
.update(brands)
|
|
481
|
-
.set(data)
|
|
482
|
-
.where(eq(brands.id, id))
|
|
483
|
-
.returning();
|
|
484
|
-
return rows[0];
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
async deleteBrand(id: string, ctx?: TxContext): Promise<boolean> {
|
|
488
|
-
const db = this.getDb(ctx);
|
|
489
|
-
const result = await db.delete(brands).where(eq(brands.id, id)).returning();
|
|
490
|
-
return result.length > 0;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
494
|
-
// Entity Brands (Join Table)
|
|
495
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
496
|
-
|
|
497
|
-
async findEntityBrands(
|
|
498
|
-
entityId: string,
|
|
499
|
-
ctx?: TxContext,
|
|
500
|
-
): Promise<EntityBrand[]> {
|
|
501
|
-
const db = this.getDb(ctx);
|
|
502
|
-
return db
|
|
503
|
-
.select()
|
|
504
|
-
.from(entityBrands)
|
|
505
|
-
.where(eq(entityBrands.entityId, entityId));
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
async addEntityToBrand(
|
|
509
|
-
entityId: string,
|
|
510
|
-
brandId: string,
|
|
511
|
-
sortOrder = 0,
|
|
512
|
-
ctx?: TxContext,
|
|
513
|
-
): Promise<void> {
|
|
514
|
-
const db = this.getDb(ctx);
|
|
515
|
-
await db
|
|
516
|
-
.insert(entityBrands)
|
|
517
|
-
.values({ entityId, brandId, sortOrder })
|
|
518
|
-
.onConflictDoNothing();
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
async removeEntityFromBrand(
|
|
522
|
-
entityId: string,
|
|
523
|
-
brandId: string,
|
|
524
|
-
ctx?: TxContext,
|
|
525
|
-
): Promise<boolean> {
|
|
526
|
-
const db = this.getDb(ctx);
|
|
527
|
-
const result = await db
|
|
528
|
-
.delete(entityBrands)
|
|
529
|
-
.where(
|
|
530
|
-
and(
|
|
531
|
-
eq(entityBrands.entityId, entityId),
|
|
532
|
-
eq(entityBrands.brandId, brandId),
|
|
533
|
-
),
|
|
534
|
-
)
|
|
535
|
-
.returning();
|
|
536
|
-
return result.length > 0;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
async deleteEntityBrandsByEntityId(
|
|
540
|
-
entityId: string,
|
|
541
|
-
ctx?: TxContext,
|
|
542
|
-
): Promise<void> {
|
|
543
|
-
const db = this.getDb(ctx);
|
|
544
|
-
await db.delete(entityBrands).where(eq(entityBrands.entityId, entityId));
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
async deleteEntityBrandsByBrandId(
|
|
548
|
-
brandId: string,
|
|
549
|
-
ctx?: TxContext,
|
|
550
|
-
): Promise<void> {
|
|
551
|
-
const db = this.getDb(ctx);
|
|
552
|
-
await db.delete(entityBrands).where(eq(entityBrands.brandId, brandId));
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
556
|
-
// Option Types
|
|
557
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
558
|
-
|
|
559
|
-
async findOptionTypesByEntityId(
|
|
560
|
-
entityId: string,
|
|
561
|
-
ctx?: TxContext,
|
|
562
|
-
): Promise<OptionType[]> {
|
|
563
|
-
const db = this.getDb(ctx);
|
|
564
|
-
return db
|
|
565
|
-
.select()
|
|
566
|
-
.from(optionTypes)
|
|
567
|
-
.where(eq(optionTypes.entityId, entityId));
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
async findOptionTypeById(
|
|
571
|
-
id: string,
|
|
572
|
-
ctx?: TxContext,
|
|
573
|
-
): Promise<OptionType | undefined> {
|
|
574
|
-
const db = this.getDb(ctx);
|
|
575
|
-
const rows = await db
|
|
576
|
-
.select()
|
|
577
|
-
.from(optionTypes)
|
|
578
|
-
.where(eq(optionTypes.id, id));
|
|
579
|
-
return rows[0];
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
async createOptionType(
|
|
583
|
-
data: OptionTypeInsert,
|
|
584
|
-
ctx?: TxContext,
|
|
585
|
-
): Promise<OptionType> {
|
|
586
|
-
const db = this.getDb(ctx);
|
|
587
|
-
const rows = await db.insert(optionTypes).values(data).returning();
|
|
588
|
-
return rows[0]!;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
async deleteOptionTypesByEntityId(
|
|
592
|
-
entityId: string,
|
|
593
|
-
ctx?: TxContext,
|
|
594
|
-
): Promise<void> {
|
|
595
|
-
const db = this.getDb(ctx);
|
|
596
|
-
await db.delete(optionTypes).where(eq(optionTypes.entityId, entityId));
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
600
|
-
// Option Values
|
|
601
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
602
|
-
|
|
603
|
-
async findOptionValuesByTypeId(
|
|
604
|
-
optionTypeId: string,
|
|
605
|
-
ctx?: TxContext,
|
|
606
|
-
): Promise<OptionValue[]> {
|
|
607
|
-
const db = this.getDb(ctx);
|
|
608
|
-
return db
|
|
609
|
-
.select()
|
|
610
|
-
.from(optionValues)
|
|
611
|
-
.where(eq(optionValues.optionTypeId, optionTypeId));
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
async findOptionValueById(
|
|
615
|
-
id: string,
|
|
616
|
-
ctx?: TxContext,
|
|
617
|
-
): Promise<OptionValue | undefined> {
|
|
618
|
-
const db = this.getDb(ctx);
|
|
619
|
-
const rows = await db
|
|
620
|
-
.select()
|
|
621
|
-
.from(optionValues)
|
|
622
|
-
.where(eq(optionValues.id, id));
|
|
623
|
-
return rows[0];
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
async findOptionValuesByIds(
|
|
627
|
-
ids: string[],
|
|
628
|
-
ctx?: TxContext,
|
|
629
|
-
): Promise<OptionValue[]> {
|
|
630
|
-
if (ids.length === 0) return [];
|
|
631
|
-
const db = this.getDb(ctx);
|
|
632
|
-
return db.select().from(optionValues).where(inArray(optionValues.id, ids));
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
async createOptionValue(
|
|
636
|
-
data: OptionValueInsert,
|
|
637
|
-
ctx?: TxContext,
|
|
638
|
-
): Promise<OptionValue> {
|
|
639
|
-
const db = this.getDb(ctx);
|
|
640
|
-
const rows = await db.insert(optionValues).values(data).returning();
|
|
641
|
-
return rows[0]!;
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
async deleteOptionValuesByTypeId(
|
|
645
|
-
optionTypeId: string,
|
|
646
|
-
ctx?: TxContext,
|
|
647
|
-
): Promise<void> {
|
|
648
|
-
const db = this.getDb(ctx);
|
|
649
|
-
await db
|
|
650
|
-
.delete(optionValues)
|
|
651
|
-
.where(eq(optionValues.optionTypeId, optionTypeId));
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
655
|
-
// Variants
|
|
656
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
657
|
-
|
|
658
|
-
async findVariantsByEntityId(
|
|
659
|
-
entityId: string,
|
|
660
|
-
ctx?: TxContext,
|
|
661
|
-
): Promise<Variant[]> {
|
|
662
|
-
const db = this.getDb(ctx);
|
|
663
|
-
return db.select().from(variants).where(eq(variants.entityId, entityId));
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
async findVariantById(
|
|
667
|
-
id: string,
|
|
668
|
-
ctx?: TxContext,
|
|
669
|
-
): Promise<Variant | undefined> {
|
|
670
|
-
const db = this.getDb(ctx);
|
|
671
|
-
const rows = await db.select().from(variants).where(eq(variants.id, id));
|
|
672
|
-
return rows[0];
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
async findVariantBySku(
|
|
676
|
-
sku: string,
|
|
677
|
-
ctx?: TxContext,
|
|
678
|
-
): Promise<Variant | undefined> {
|
|
679
|
-
const db = this.getDb(ctx);
|
|
680
|
-
const rows = await db.select().from(variants).where(eq(variants.sku, sku));
|
|
681
|
-
return rows[0];
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
async findVariantByBarcode(
|
|
685
|
-
barcode: string,
|
|
686
|
-
ctx?: TxContext,
|
|
687
|
-
): Promise<Variant | undefined> {
|
|
688
|
-
const db = this.getDb(ctx);
|
|
689
|
-
const rows = await db
|
|
690
|
-
.select()
|
|
691
|
-
.from(variants)
|
|
692
|
-
.where(eq(variants.barcode, barcode));
|
|
693
|
-
return rows[0];
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
async createVariant(data: VariantInsert, ctx?: TxContext): Promise<Variant> {
|
|
697
|
-
const db = this.getDb(ctx);
|
|
698
|
-
const rows = await db.insert(variants).values(data).returning();
|
|
699
|
-
return rows[0]!;
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
async updateVariant(
|
|
703
|
-
id: string,
|
|
704
|
-
data: Partial<Omit<VariantInsert, "id">>,
|
|
705
|
-
ctx?: TxContext,
|
|
706
|
-
): Promise<Variant | undefined> {
|
|
707
|
-
const db = this.getDb(ctx);
|
|
708
|
-
const rows = await db
|
|
709
|
-
.update(variants)
|
|
710
|
-
.set(data)
|
|
711
|
-
.where(eq(variants.id, id))
|
|
712
|
-
.returning();
|
|
713
|
-
return rows[0];
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
async deleteVariantsByEntityId(
|
|
717
|
-
entityId: string,
|
|
718
|
-
ctx?: TxContext,
|
|
719
|
-
): Promise<void> {
|
|
720
|
-
const db = this.getDb(ctx);
|
|
721
|
-
await db.delete(variants).where(eq(variants.entityId, entityId));
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
725
|
-
// Variant Option Values (Join Table)
|
|
726
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
727
|
-
|
|
728
|
-
async findVariantOptionValues(
|
|
729
|
-
variantId: string,
|
|
730
|
-
ctx?: TxContext,
|
|
731
|
-
): Promise<VariantOptionValue[]> {
|
|
732
|
-
const db = this.getDb(ctx);
|
|
733
|
-
return db
|
|
734
|
-
.select()
|
|
735
|
-
.from(variantOptionValues)
|
|
736
|
-
.where(eq(variantOptionValues.variantId, variantId));
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
async createVariantOptionValues(
|
|
740
|
-
data: VariantOptionValueInsert[],
|
|
741
|
-
ctx?: TxContext,
|
|
742
|
-
): Promise<void> {
|
|
743
|
-
if (data.length === 0) return;
|
|
744
|
-
const db = this.getDb(ctx);
|
|
745
|
-
await db.insert(variantOptionValues).values(data).onConflictDoNothing();
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
async deleteVariantOptionValuesByVariantId(
|
|
749
|
-
variantId: string,
|
|
750
|
-
ctx?: TxContext,
|
|
751
|
-
): Promise<void> {
|
|
752
|
-
const db = this.getDb(ctx);
|
|
753
|
-
await db
|
|
754
|
-
.delete(variantOptionValues)
|
|
755
|
-
.where(eq(variantOptionValues.variantId, variantId));
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
async deleteVariantOptionValuesByEntityId(
|
|
759
|
-
entityId: string,
|
|
760
|
-
ctx?: TxContext,
|
|
761
|
-
): Promise<void> {
|
|
762
|
-
const db = this.getDb(ctx);
|
|
763
|
-
// Get all variant IDs for this entity first
|
|
764
|
-
const entityVariants = await this.findVariantsByEntityId(entityId, ctx);
|
|
765
|
-
const variantIds = entityVariants.map((v) => v.id);
|
|
766
|
-
if (variantIds.length > 0) {
|
|
767
|
-
await db
|
|
768
|
-
.delete(variantOptionValues)
|
|
769
|
-
.where(inArray(variantOptionValues.variantId, variantIds));
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
}
|