@voyantjs/extras 0.20.0 → 0.21.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/dist/catalog-policy.d.ts.map +1 -1
- package/dist/catalog-policy.js +15 -1
- package/dist/content-shape.d.ts +118 -0
- package/dist/content-shape.d.ts.map +1 -0
- package/dist/content-shape.js +98 -0
- package/dist/draft-shape.d.ts +34 -0
- package/dist/draft-shape.d.ts.map +1 -0
- package/dist/draft-shape.js +69 -0
- package/dist/routes.d.ts +18 -14
- package/dist/routes.d.ts.map +1 -1
- package/dist/schema-sourced-content.d.ts +254 -0
- package/dist/schema-sourced-content.d.ts.map +1 -0
- package/dist/schema-sourced-content.js +45 -0
- package/dist/schema.d.ts +21 -3
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +6 -0
- package/dist/service-catalog-plane.d.ts.map +1 -1
- package/dist/service-catalog-plane.js +1 -0
- package/dist/service-content-synthesizer.d.ts +41 -0
- package/dist/service-content-synthesizer.d.ts.map +1 -0
- package/dist/service-content-synthesizer.js +138 -0
- package/dist/service-content.d.ts +48 -0
- package/dist/service-content.d.ts.map +1 -0
- package/dist/service-content.js +253 -0
- package/dist/service.d.ts +18 -14
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +2 -0
- package/dist/validation.d.ts +28 -24
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +2 -0
- package/package.json +7 -7
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extras content service — `getExtraContent` with locale-resolved
|
|
3
|
+
* cache reads, SWR refresh, and synthesizer fallback.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors `service-content.ts` in the products / cruises / hospitality
|
|
6
|
+
* / charters packages but extras-shaped. The extras content aggregate
|
|
7
|
+
* (§3.2 / §3.6) is `{ extra, options[], media[], policies[] }` — one
|
|
8
|
+
* payload returned by a single getContent. Pricing stays out (volatile-
|
|
9
|
+
* live, flows through `liveResolve`).
|
|
10
|
+
*
|
|
11
|
+
* Extras don't appear in the search index (per the vertical's catalog-
|
|
12
|
+
* policy.ts), but sourced extras still need rich content for the
|
|
13
|
+
* booking-flow's add-on selection UI. The cache layer covers exactly
|
|
14
|
+
* that surface.
|
|
15
|
+
*/
|
|
16
|
+
import { createInvalidateOnDrift, fetchOverlaysForEntity, isStale, pickBestCachedLocale, readSourcedEntry, withContentRefreshLock, } from "@voyantjs/catalog";
|
|
17
|
+
import { and, eq } from "drizzle-orm";
|
|
18
|
+
import { EXTRAS_CONTENT_SCHEMA_VERSION, extraContentSchema, mergeOverlaysIntoExtraContent, validateExtraContent, } from "./content-shape.js";
|
|
19
|
+
import { EXTRAS_CONTENT_MARKET_ANY, extrasSourcedContentTable, } from "./schema-sourced-content.js";
|
|
20
|
+
import { synthesizeExtraContent, } from "./service-content-synthesizer.js";
|
|
21
|
+
/** Extras cache TTL is 24h — same as products. */
|
|
22
|
+
const EXTRAS_DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
|
|
23
|
+
export async function getExtraContent(db, entityId, scope, options) {
|
|
24
|
+
const sourcedEntry = await readSourcedEntry(db, "extras", entityId);
|
|
25
|
+
if (!sourcedEntry)
|
|
26
|
+
return null;
|
|
27
|
+
const provenance = {
|
|
28
|
+
kind: "sourced",
|
|
29
|
+
provenance: {
|
|
30
|
+
source_kind: sourcedEntry.source_kind,
|
|
31
|
+
source_provider: sourcedEntry.source_provider ?? undefined,
|
|
32
|
+
source_connection_id: sourcedEntry.source_connection_id ?? undefined,
|
|
33
|
+
source_ref: sourcedEntry.source_ref ?? undefined,
|
|
34
|
+
source_freshness: sourcedEntry.source_freshness,
|
|
35
|
+
last_sourced_at: sourcedEntry.last_sourced_at ?? undefined,
|
|
36
|
+
},
|
|
37
|
+
entry_id: sourcedEntry.id,
|
|
38
|
+
status: sourcedEntry.status,
|
|
39
|
+
projection: sourcedEntry.projection,
|
|
40
|
+
projection_etag: sourcedEntry.projection_etag,
|
|
41
|
+
projection_seen_at: sourcedEntry.projection_seen_at,
|
|
42
|
+
first_seen_at: sourcedEntry.first_seen_at,
|
|
43
|
+
last_seen_at: sourcedEntry.last_seen_at,
|
|
44
|
+
};
|
|
45
|
+
const adapter = sourcedEntry.source_connection_id
|
|
46
|
+
? (options.registry.resolveByConnection(sourcedEntry.source_connection_id) ??
|
|
47
|
+
options.registry.byKind(sourcedEntry.source_kind)[0]?.adapter)
|
|
48
|
+
: options.registry.byKind(sourcedEntry.source_kind)[0]?.adapter;
|
|
49
|
+
const adapterCtx = options.buildAdapterContext?.(adapter) ?? {
|
|
50
|
+
connection_id: sourcedEntry.source_connection_id ?? sourcedEntry.source_kind,
|
|
51
|
+
};
|
|
52
|
+
const market = scope.market ?? EXTRAS_CONTENT_MARKET_ANY;
|
|
53
|
+
const acceptMT = scope.acceptMachineTranslated ?? true;
|
|
54
|
+
const cachedRows = await fetchCacheCandidates(db, entityId, market);
|
|
55
|
+
const eligibleRows = acceptMT ? cachedRows : cachedRows.filter((r) => !r.machine_translated);
|
|
56
|
+
const best = pickBestCachedLocale(eligibleRows.map((row) => ({ ...row, locale: row.locale })), scope.preferredLocales);
|
|
57
|
+
if (best && !isStale(best.candidate)) {
|
|
58
|
+
return finalizeFromCache(db, entityId, best, false, options);
|
|
59
|
+
}
|
|
60
|
+
if (best && isStale(best.candidate)) {
|
|
61
|
+
if (adapter?.getContent) {
|
|
62
|
+
void scheduleRefresh(db, adapter, adapterCtx, {
|
|
63
|
+
entity_module: "extras",
|
|
64
|
+
entity_id: entityId,
|
|
65
|
+
locale: scope.preferredLocales[0] ?? best.candidate.locale,
|
|
66
|
+
market,
|
|
67
|
+
currency: scope.currency,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return finalizeFromCache(db, entityId, best, true, options);
|
|
71
|
+
}
|
|
72
|
+
if (!adapter?.getContent) {
|
|
73
|
+
const overlays = await fetchOverlaysForEntity(db, "extras", entityId);
|
|
74
|
+
const synthesized = synthesizeExtraContent({ locale: scope.preferredLocales[0] ?? "en-GB" }, {
|
|
75
|
+
provenance,
|
|
76
|
+
overlays: overlays.map((o) => ({ field_path: o.field_path, value: o.value })),
|
|
77
|
+
});
|
|
78
|
+
return wrapSynthesized(synthesized, scope, false);
|
|
79
|
+
}
|
|
80
|
+
const fresh = await fetchFreshContent(db, adapter, adapterCtx, {
|
|
81
|
+
entity_module: "extras",
|
|
82
|
+
entity_id: entityId,
|
|
83
|
+
locale: scope.preferredLocales[0] ?? "en-GB",
|
|
84
|
+
market,
|
|
85
|
+
currency: scope.currency,
|
|
86
|
+
});
|
|
87
|
+
if (!fresh) {
|
|
88
|
+
const overlays = await fetchOverlaysForEntity(db, "extras", entityId);
|
|
89
|
+
const synthesized = synthesizeExtraContent({ locale: scope.preferredLocales[0] ?? "en-GB" }, {
|
|
90
|
+
provenance,
|
|
91
|
+
overlays: overlays.map((o) => ({ field_path: o.field_path, value: o.value })),
|
|
92
|
+
});
|
|
93
|
+
return wrapSynthesized(synthesized, scope, false);
|
|
94
|
+
}
|
|
95
|
+
return finalizeFresh(db, entityId, fresh, scope, options);
|
|
96
|
+
}
|
|
97
|
+
async function fetchCacheCandidates(db, entityId, market) {
|
|
98
|
+
return db
|
|
99
|
+
.select()
|
|
100
|
+
.from(extrasSourcedContentTable)
|
|
101
|
+
.where(and(eq(extrasSourcedContentTable.entity_id, entityId), eq(extrasSourcedContentTable.market, market), eq(extrasSourcedContentTable.content_schema_version, EXTRAS_CONTENT_SCHEMA_VERSION)));
|
|
102
|
+
}
|
|
103
|
+
async function fetchFreshContent(db, adapter, ctx, request) {
|
|
104
|
+
const result = await withContentRefreshLock(db, {
|
|
105
|
+
entityModule: request.entity_module,
|
|
106
|
+
entityId: request.entity_id,
|
|
107
|
+
locale: request.locale,
|
|
108
|
+
market: request.market,
|
|
109
|
+
}, async () => {
|
|
110
|
+
const got = await adapter.getContent(ctx, request);
|
|
111
|
+
const validation = validateExtraContent(got.content);
|
|
112
|
+
if (!validation.valid) {
|
|
113
|
+
throw new Error(`extras getContent for ${request.entity_id} failed validation: ${validation.reason}`);
|
|
114
|
+
}
|
|
115
|
+
await writeCacheRow(db, request, got);
|
|
116
|
+
return got;
|
|
117
|
+
});
|
|
118
|
+
return result ?? null;
|
|
119
|
+
}
|
|
120
|
+
function scheduleRefresh(db, adapter, ctx, request) {
|
|
121
|
+
void withContentRefreshLock(db, {
|
|
122
|
+
entityModule: request.entity_module,
|
|
123
|
+
entityId: request.entity_id,
|
|
124
|
+
locale: request.locale,
|
|
125
|
+
market: request.market,
|
|
126
|
+
}, async () => {
|
|
127
|
+
const got = await adapter.getContent(ctx, request);
|
|
128
|
+
const validation = validateExtraContent(got.content);
|
|
129
|
+
if (!validation.valid)
|
|
130
|
+
return;
|
|
131
|
+
await writeCacheRow(db, request, got);
|
|
132
|
+
}).catch(() => {
|
|
133
|
+
// intentional swallow — see §3.4 SWR refresh contract
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
async function writeCacheRow(db, request, result) {
|
|
137
|
+
const market = request.market ?? EXTRAS_CONTENT_MARKET_ANY;
|
|
138
|
+
const now = new Date();
|
|
139
|
+
// Coerce JSON-string dates to Date — see products writeCacheRow.
|
|
140
|
+
const sourceUpdatedAt = toDateOrNull(result.source_updated_at);
|
|
141
|
+
const freshUntil = toDateOrNull(result.fresh_until) ?? new Date(now.getTime() + EXTRAS_DEFAULT_TTL_MS);
|
|
142
|
+
await db
|
|
143
|
+
.insert(extrasSourcedContentTable)
|
|
144
|
+
.values({
|
|
145
|
+
entity_id: request.entity_id,
|
|
146
|
+
locale: request.locale,
|
|
147
|
+
market,
|
|
148
|
+
payload: result.content,
|
|
149
|
+
content_schema_version: result.content_schema_version,
|
|
150
|
+
returned_locale: result.returned_locale,
|
|
151
|
+
machine_translated: result.machine_translated ?? false,
|
|
152
|
+
source_updated_at: sourceUpdatedAt,
|
|
153
|
+
fetched_at: now,
|
|
154
|
+
fresh_until: freshUntil,
|
|
155
|
+
etag: result.etag ?? null,
|
|
156
|
+
fetch_status: "ok",
|
|
157
|
+
fetch_error: null,
|
|
158
|
+
})
|
|
159
|
+
.onConflictDoUpdate({
|
|
160
|
+
target: [
|
|
161
|
+
extrasSourcedContentTable.entity_id,
|
|
162
|
+
extrasSourcedContentTable.locale,
|
|
163
|
+
extrasSourcedContentTable.market,
|
|
164
|
+
],
|
|
165
|
+
set: {
|
|
166
|
+
payload: result.content,
|
|
167
|
+
content_schema_version: result.content_schema_version,
|
|
168
|
+
returned_locale: result.returned_locale,
|
|
169
|
+
machine_translated: result.machine_translated ?? false,
|
|
170
|
+
source_updated_at: sourceUpdatedAt,
|
|
171
|
+
fetched_at: now,
|
|
172
|
+
fresh_until: freshUntil,
|
|
173
|
+
etag: result.etag ?? null,
|
|
174
|
+
fetch_status: "ok",
|
|
175
|
+
fetch_error: null,
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
async function finalizeFromCache(db, entityId, best, servedStale, options) {
|
|
180
|
+
const validation = validateExtraContent(best.candidate.payload);
|
|
181
|
+
if (!validation.valid) {
|
|
182
|
+
throw new Error(`extras cache row for ${entityId} (${best.candidate.locale}) failed validation: ${validation.reason}`);
|
|
183
|
+
}
|
|
184
|
+
const overlays = await fetchOverlaysForEntity(db, "extras", entityId);
|
|
185
|
+
const merged = mergeOverlaysIntoExtraContent(validation.content, overlays.map((o) => ({ field_path: o.field_path, value: o.value })), {
|
|
186
|
+
onOverlayError: options.onOverlayError
|
|
187
|
+
? (e) => options.onOverlayError({
|
|
188
|
+
field_path: e.overlay.field_path,
|
|
189
|
+
reason: e.reason,
|
|
190
|
+
})
|
|
191
|
+
: undefined,
|
|
192
|
+
});
|
|
193
|
+
return {
|
|
194
|
+
content: merged,
|
|
195
|
+
resolution: {
|
|
196
|
+
candidate: { locale: best.candidate.locale, payload: merged },
|
|
197
|
+
served_locale: best.candidate.returned_locale,
|
|
198
|
+
match_kind: best.match_kind,
|
|
199
|
+
},
|
|
200
|
+
source: "sourced-cache",
|
|
201
|
+
served_stale: servedStale,
|
|
202
|
+
synthesized: false,
|
|
203
|
+
machine_translated: best.candidate.machine_translated,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
async function finalizeFresh(db, entityId, fresh, scope, options) {
|
|
207
|
+
const cachedContent = extraContentSchema.parse(fresh.content);
|
|
208
|
+
const overlays = await fetchOverlaysForEntity(db, "extras", entityId);
|
|
209
|
+
const merged = mergeOverlaysIntoExtraContent(cachedContent, overlays.map((o) => ({ field_path: o.field_path, value: o.value })), {
|
|
210
|
+
onOverlayError: options.onOverlayError
|
|
211
|
+
? (e) => options.onOverlayError({
|
|
212
|
+
field_path: e.overlay.field_path,
|
|
213
|
+
reason: e.reason,
|
|
214
|
+
})
|
|
215
|
+
: undefined,
|
|
216
|
+
});
|
|
217
|
+
return {
|
|
218
|
+
content: merged,
|
|
219
|
+
resolution: {
|
|
220
|
+
candidate: { locale: scope.preferredLocales[0] ?? fresh.returned_locale, payload: merged },
|
|
221
|
+
served_locale: fresh.returned_locale,
|
|
222
|
+
match_kind: scope.preferredLocales[0] === fresh.returned_locale ? "exact" : "language_match",
|
|
223
|
+
},
|
|
224
|
+
source: "sourced-fresh",
|
|
225
|
+
served_stale: false,
|
|
226
|
+
synthesized: false,
|
|
227
|
+
machine_translated: fresh.machine_translated ?? false,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
function wrapSynthesized(synthesized, scope, servedStale) {
|
|
231
|
+
return {
|
|
232
|
+
content: synthesized.content,
|
|
233
|
+
resolution: {
|
|
234
|
+
candidate: { locale: synthesized.served_locale, payload: synthesized.content },
|
|
235
|
+
served_locale: synthesized.served_locale,
|
|
236
|
+
match_kind: scope.preferredLocales[0] === synthesized.served_locale ? "exact" : "any",
|
|
237
|
+
},
|
|
238
|
+
source: "synthesized",
|
|
239
|
+
served_stale: servedStale,
|
|
240
|
+
synthesized: true,
|
|
241
|
+
machine_translated: false,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/** Drift event consumer for the extras content cache. Per §3.4.1. */
|
|
245
|
+
export const invalidateExtraContentOnDrift = createInvalidateOnDrift(extrasSourcedContentTable, { entityModule: "extras" });
|
|
246
|
+
function toDateOrNull(value) {
|
|
247
|
+
if (!value)
|
|
248
|
+
return null;
|
|
249
|
+
if (value instanceof Date)
|
|
250
|
+
return value;
|
|
251
|
+
const parsed = new Date(value);
|
|
252
|
+
return Number.isNaN(parsed.getTime()) ? null : parsed;
|
|
253
|
+
}
|
package/dist/service.d.ts
CHANGED
|
@@ -15,10 +15,11 @@ export declare const extrasService: {
|
|
|
15
15
|
data: {
|
|
16
16
|
id: string;
|
|
17
17
|
productId: string;
|
|
18
|
+
supplierId: string | null;
|
|
18
19
|
code: string | null;
|
|
19
20
|
name: string;
|
|
20
21
|
description: string | null;
|
|
21
|
-
selectionType: "
|
|
22
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required";
|
|
22
23
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
23
24
|
pricedPerPerson: boolean;
|
|
24
25
|
minQuantity: number | null;
|
|
@@ -37,10 +38,11 @@ export declare const extrasService: {
|
|
|
37
38
|
getProductExtraById(db: PostgresJsDatabase, id: string): Promise<{
|
|
38
39
|
id: string;
|
|
39
40
|
productId: string;
|
|
41
|
+
supplierId: string | null;
|
|
40
42
|
code: string | null;
|
|
41
43
|
name: string;
|
|
42
44
|
description: string | null;
|
|
43
|
-
selectionType: "
|
|
45
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required";
|
|
44
46
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
45
47
|
pricedPerPerson: boolean;
|
|
46
48
|
minQuantity: number | null;
|
|
@@ -58,9 +60,10 @@ export declare const extrasService: {
|
|
|
58
60
|
createdAt: Date;
|
|
59
61
|
updatedAt: Date;
|
|
60
62
|
productId: string;
|
|
63
|
+
supplierId: string | null;
|
|
61
64
|
name: string;
|
|
62
65
|
description: string | null;
|
|
63
|
-
selectionType: "
|
|
66
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required";
|
|
64
67
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
65
68
|
pricedPerPerson: boolean;
|
|
66
69
|
minQuantity: number | null;
|
|
@@ -73,10 +76,11 @@ export declare const extrasService: {
|
|
|
73
76
|
updateProductExtra(db: PostgresJsDatabase, id: string, data: UpdateProductExtraInput): Promise<{
|
|
74
77
|
id: string;
|
|
75
78
|
productId: string;
|
|
79
|
+
supplierId: string | null;
|
|
76
80
|
code: string | null;
|
|
77
81
|
name: string;
|
|
78
82
|
description: string | null;
|
|
79
|
-
selectionType: "
|
|
83
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required";
|
|
80
84
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
81
85
|
pricedPerPerson: boolean;
|
|
82
86
|
minQuantity: number | null;
|
|
@@ -96,7 +100,7 @@ export declare const extrasService: {
|
|
|
96
100
|
id: string;
|
|
97
101
|
optionId: string;
|
|
98
102
|
productExtraId: string;
|
|
99
|
-
selectionType: "
|
|
103
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required" | null;
|
|
100
104
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free" | null;
|
|
101
105
|
pricedPerPerson: boolean | null;
|
|
102
106
|
minQuantity: number | null;
|
|
@@ -118,7 +122,7 @@ export declare const extrasService: {
|
|
|
118
122
|
id: string;
|
|
119
123
|
optionId: string;
|
|
120
124
|
productExtraId: string;
|
|
121
|
-
selectionType: "
|
|
125
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required" | null;
|
|
122
126
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free" | null;
|
|
123
127
|
pricedPerPerson: boolean | null;
|
|
124
128
|
minQuantity: number | null;
|
|
@@ -136,7 +140,7 @@ export declare const extrasService: {
|
|
|
136
140
|
id: string;
|
|
137
141
|
createdAt: Date;
|
|
138
142
|
updatedAt: Date;
|
|
139
|
-
selectionType: "
|
|
143
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required" | null;
|
|
140
144
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free" | null;
|
|
141
145
|
pricedPerPerson: boolean | null;
|
|
142
146
|
minQuantity: number | null;
|
|
@@ -154,7 +158,7 @@ export declare const extrasService: {
|
|
|
154
158
|
id: string;
|
|
155
159
|
optionId: string;
|
|
156
160
|
productExtraId: string;
|
|
157
|
-
selectionType: "
|
|
161
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required" | null;
|
|
158
162
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free" | null;
|
|
159
163
|
pricedPerPerson: boolean | null;
|
|
160
164
|
minQuantity: number | null;
|
|
@@ -179,7 +183,7 @@ export declare const extrasService: {
|
|
|
179
183
|
optionExtraConfigId: string | null;
|
|
180
184
|
name: string;
|
|
181
185
|
description: string | null;
|
|
182
|
-
status: "
|
|
186
|
+
status: "confirmed" | "cancelled" | "draft" | "selected" | "fulfilled";
|
|
183
187
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
184
188
|
pricedPerPerson: boolean;
|
|
185
189
|
quantity: number;
|
|
@@ -205,7 +209,7 @@ export declare const extrasService: {
|
|
|
205
209
|
optionExtraConfigId: string | null;
|
|
206
210
|
name: string;
|
|
207
211
|
description: string | null;
|
|
208
|
-
status: "
|
|
212
|
+
status: "confirmed" | "cancelled" | "draft" | "selected" | "fulfilled";
|
|
209
213
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
210
214
|
pricedPerPerson: boolean;
|
|
211
215
|
quantity: number;
|
|
@@ -228,13 +232,13 @@ export declare const extrasService: {
|
|
|
228
232
|
description: string | null;
|
|
229
233
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
230
234
|
pricedPerPerson: boolean;
|
|
235
|
+
status: "confirmed" | "cancelled" | "draft" | "selected" | "fulfilled";
|
|
231
236
|
metadata: Record<string, unknown> | null;
|
|
232
|
-
status: "draft" | "selected" | "confirmed" | "cancelled" | "fulfilled";
|
|
233
|
-
notes: string | null;
|
|
234
237
|
bookingId: string;
|
|
238
|
+
quantity: number;
|
|
239
|
+
notes: string | null;
|
|
235
240
|
productExtraId: string | null;
|
|
236
241
|
optionExtraConfigId: string | null;
|
|
237
|
-
quantity: number;
|
|
238
242
|
sellCurrency: string;
|
|
239
243
|
unitSellAmountCents: number | null;
|
|
240
244
|
totalSellAmountCents: number | null;
|
|
@@ -249,7 +253,7 @@ export declare const extrasService: {
|
|
|
249
253
|
optionExtraConfigId: string | null;
|
|
250
254
|
name: string;
|
|
251
255
|
description: string | null;
|
|
252
|
-
status: "
|
|
256
|
+
status: "confirmed" | "cancelled" | "draft" | "selected" | "fulfilled";
|
|
253
257
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
254
258
|
pricedPerPerson: boolean;
|
|
255
259
|
quantity: number;
|
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAG5B,OAAO,KAAK,EACV,2BAA2B,EAC3B,wBAAwB,EACxB,6BAA6B,EAC7B,wBAAwB,EACxB,gCAAgC,EAChC,2BAA2B,EAC3B,wBAAwB,EACxB,6BAA6B,EAC7B,wBAAwB,EACzB,MAAM,iBAAiB,CAAA;AAExB,KAAK,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAA;AACxE,KAAK,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAA;AAClF,KAAK,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAA;AACxE,KAAK,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AACvE,KAAK,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AACvE,KAAK,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAA;AACjF,KAAK,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAA;AACjF,KAAK,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AACvE,KAAK,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAYvE,eAAO,MAAM,aAAa;0BACI,kBAAkB,SAAS,qBAAqB
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAG5B,OAAO,KAAK,EACV,2BAA2B,EAC3B,wBAAwB,EACxB,6BAA6B,EAC7B,wBAAwB,EACxB,gCAAgC,EAChC,2BAA2B,EAC3B,wBAAwB,EACxB,6BAA6B,EAC7B,wBAAwB,EACzB,MAAM,iBAAiB,CAAA;AAExB,KAAK,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAA;AACxE,KAAK,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAA;AAClF,KAAK,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAA;AACxE,KAAK,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AACvE,KAAK,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AACvE,KAAK,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAA;AACjF,KAAK,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAA;AACjF,KAAK,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AACvE,KAAK,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAYvE,eAAO,MAAM,aAAa;0BACI,kBAAkB,SAAS,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;4BAwB9C,kBAAkB,MAAM,MAAM;;;;;;;;;;;;;;;;;;;2BAK/B,kBAAkB,QAAQ,uBAAuB;;;;;;;;;;;;;;;;;;;2BAKjD,kBAAkB,MAAM,MAAM,QAAQ,uBAAuB;;;;;;;;;;;;;;;;;;;2BAS7D,kBAAkB,MAAM,MAAM;;;+BAQ1B,kBAAkB,SAAS,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;iCAqBnD,kBAAkB,MAAM,MAAM;;;;;;;;;;;;;;;;;;gCAS/B,kBAAkB,QAAQ,4BAA4B;;;;;;;;;;;;;;;;;;gCAMlF,kBAAkB,MAClB,MAAM,QACJ,4BAA4B;;;;;;;;;;;;;;;;;;gCAUF,kBAAkB,MAAM,MAAM;;;0BAQpC,kBAAkB,SAAS,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAuB9C,kBAAkB,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;2BAK/B,kBAAkB,QAAQ,uBAAuB;;;;;;;;;;;;;;;;;;;;;;2BAKjD,kBAAkB,MAAM,MAAM,QAAQ,uBAAuB;;;;;;;;;;;;;;;;;;;;;;2BAS7D,kBAAkB,MAAM,MAAM;;;CAO5D,CAAA"}
|
package/dist/service.js
CHANGED
|
@@ -9,6 +9,8 @@ export const extrasService = {
|
|
|
9
9
|
const conditions = [];
|
|
10
10
|
if (query.productId)
|
|
11
11
|
conditions.push(eq(productExtras.productId, query.productId));
|
|
12
|
+
if (query.supplierId)
|
|
13
|
+
conditions.push(eq(productExtras.supplierId, query.supplierId));
|
|
12
14
|
if (query.active !== undefined)
|
|
13
15
|
conditions.push(eq(productExtras.active, query.active));
|
|
14
16
|
if (query.search) {
|
package/dist/validation.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export declare const extraSelectionTypeSchema: z.ZodEnum<{
|
|
3
|
+
unavailable: "unavailable";
|
|
3
4
|
optional: "optional";
|
|
4
|
-
required: "required";
|
|
5
5
|
default_selected: "default_selected";
|
|
6
|
-
|
|
6
|
+
required: "required";
|
|
7
7
|
}>;
|
|
8
8
|
export declare const extraPricingModeSchema: z.ZodEnum<{
|
|
9
9
|
included: "included";
|
|
@@ -14,22 +14,23 @@ export declare const extraPricingModeSchema: z.ZodEnum<{
|
|
|
14
14
|
free: "free";
|
|
15
15
|
}>;
|
|
16
16
|
export declare const bookingExtraStatusSchema: z.ZodEnum<{
|
|
17
|
-
draft: "draft";
|
|
18
|
-
selected: "selected";
|
|
19
17
|
confirmed: "confirmed";
|
|
20
18
|
cancelled: "cancelled";
|
|
19
|
+
draft: "draft";
|
|
20
|
+
selected: "selected";
|
|
21
21
|
fulfilled: "fulfilled";
|
|
22
22
|
}>;
|
|
23
23
|
export declare const productExtraCoreSchema: z.ZodObject<{
|
|
24
24
|
productId: z.ZodString;
|
|
25
|
+
supplierId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
25
26
|
code: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
26
27
|
name: z.ZodString;
|
|
27
28
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
28
29
|
selectionType: z.ZodDefault<z.ZodEnum<{
|
|
30
|
+
unavailable: "unavailable";
|
|
29
31
|
optional: "optional";
|
|
30
|
-
required: "required";
|
|
31
32
|
default_selected: "default_selected";
|
|
32
|
-
|
|
33
|
+
required: "required";
|
|
33
34
|
}>>;
|
|
34
35
|
pricingMode: z.ZodDefault<z.ZodEnum<{
|
|
35
36
|
included: "included";
|
|
@@ -49,14 +50,15 @@ export declare const productExtraCoreSchema: z.ZodObject<{
|
|
|
49
50
|
}, z.core.$strip>;
|
|
50
51
|
export declare const insertProductExtraSchema: z.ZodObject<{
|
|
51
52
|
productId: z.ZodString;
|
|
53
|
+
supplierId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
52
54
|
code: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
53
55
|
name: z.ZodString;
|
|
54
56
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
55
57
|
selectionType: z.ZodDefault<z.ZodEnum<{
|
|
58
|
+
unavailable: "unavailable";
|
|
56
59
|
optional: "optional";
|
|
57
|
-
required: "required";
|
|
58
60
|
default_selected: "default_selected";
|
|
59
|
-
|
|
61
|
+
required: "required";
|
|
60
62
|
}>>;
|
|
61
63
|
pricingMode: z.ZodDefault<z.ZodEnum<{
|
|
62
64
|
included: "included";
|
|
@@ -76,14 +78,15 @@ export declare const insertProductExtraSchema: z.ZodObject<{
|
|
|
76
78
|
}, z.core.$strip>;
|
|
77
79
|
export declare const updateProductExtraSchema: z.ZodObject<{
|
|
78
80
|
productId: z.ZodOptional<z.ZodString>;
|
|
81
|
+
supplierId: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
79
82
|
code: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
80
83
|
name: z.ZodOptional<z.ZodString>;
|
|
81
84
|
description: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
82
85
|
selectionType: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
|
|
86
|
+
unavailable: "unavailable";
|
|
83
87
|
optional: "optional";
|
|
84
|
-
required: "required";
|
|
85
88
|
default_selected: "default_selected";
|
|
86
|
-
|
|
89
|
+
required: "required";
|
|
87
90
|
}>>>;
|
|
88
91
|
pricingMode: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
|
|
89
92
|
included: "included";
|
|
@@ -105,6 +108,7 @@ export declare const productExtraListQuerySchema: z.ZodObject<{
|
|
|
105
108
|
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
106
109
|
offset: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
107
110
|
productId: z.ZodOptional<z.ZodString>;
|
|
111
|
+
supplierId: z.ZodOptional<z.ZodString>;
|
|
108
112
|
active: z.ZodOptional<z.ZodPipe<z.ZodEnum<{
|
|
109
113
|
0: "0";
|
|
110
114
|
1: "1";
|
|
@@ -117,10 +121,10 @@ export declare const optionExtraConfigCoreSchema: z.ZodObject<{
|
|
|
117
121
|
optionId: z.ZodString;
|
|
118
122
|
productExtraId: z.ZodString;
|
|
119
123
|
selectionType: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
124
|
+
unavailable: "unavailable";
|
|
120
125
|
optional: "optional";
|
|
121
|
-
required: "required";
|
|
122
126
|
default_selected: "default_selected";
|
|
123
|
-
|
|
127
|
+
required: "required";
|
|
124
128
|
}>>>;
|
|
125
129
|
pricingMode: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
126
130
|
included: "included";
|
|
@@ -144,10 +148,10 @@ export declare const insertOptionExtraConfigSchema: z.ZodObject<{
|
|
|
144
148
|
optionId: z.ZodString;
|
|
145
149
|
productExtraId: z.ZodString;
|
|
146
150
|
selectionType: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
151
|
+
unavailable: "unavailable";
|
|
147
152
|
optional: "optional";
|
|
148
|
-
required: "required";
|
|
149
153
|
default_selected: "default_selected";
|
|
150
|
-
|
|
154
|
+
required: "required";
|
|
151
155
|
}>>>;
|
|
152
156
|
pricingMode: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
153
157
|
included: "included";
|
|
@@ -171,10 +175,10 @@ export declare const updateOptionExtraConfigSchema: z.ZodObject<{
|
|
|
171
175
|
optionId: z.ZodOptional<z.ZodString>;
|
|
172
176
|
productExtraId: z.ZodOptional<z.ZodString>;
|
|
173
177
|
selectionType: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
178
|
+
unavailable: "unavailable";
|
|
174
179
|
optional: "optional";
|
|
175
|
-
required: "required";
|
|
176
180
|
default_selected: "default_selected";
|
|
177
|
-
|
|
181
|
+
required: "required";
|
|
178
182
|
}>>>>;
|
|
179
183
|
pricingMode: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
180
184
|
included: "included";
|
|
@@ -213,10 +217,10 @@ export declare const bookingExtraCoreSchema: z.ZodObject<{
|
|
|
213
217
|
name: z.ZodString;
|
|
214
218
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
215
219
|
status: z.ZodDefault<z.ZodEnum<{
|
|
216
|
-
draft: "draft";
|
|
217
|
-
selected: "selected";
|
|
218
220
|
confirmed: "confirmed";
|
|
219
221
|
cancelled: "cancelled";
|
|
222
|
+
draft: "draft";
|
|
223
|
+
selected: "selected";
|
|
220
224
|
fulfilled: "fulfilled";
|
|
221
225
|
}>>;
|
|
222
226
|
pricingMode: z.ZodDefault<z.ZodEnum<{
|
|
@@ -245,10 +249,10 @@ export declare const insertBookingExtraSchema: z.ZodObject<{
|
|
|
245
249
|
name: z.ZodString;
|
|
246
250
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
247
251
|
status: z.ZodDefault<z.ZodEnum<{
|
|
248
|
-
draft: "draft";
|
|
249
|
-
selected: "selected";
|
|
250
252
|
confirmed: "confirmed";
|
|
251
253
|
cancelled: "cancelled";
|
|
254
|
+
draft: "draft";
|
|
255
|
+
selected: "selected";
|
|
252
256
|
fulfilled: "fulfilled";
|
|
253
257
|
}>>;
|
|
254
258
|
pricingMode: z.ZodDefault<z.ZodEnum<{
|
|
@@ -277,10 +281,10 @@ export declare const updateBookingExtraSchema: z.ZodObject<{
|
|
|
277
281
|
name: z.ZodOptional<z.ZodString>;
|
|
278
282
|
description: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
279
283
|
status: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
|
|
280
|
-
draft: "draft";
|
|
281
|
-
selected: "selected";
|
|
282
284
|
confirmed: "confirmed";
|
|
283
285
|
cancelled: "cancelled";
|
|
286
|
+
draft: "draft";
|
|
287
|
+
selected: "selected";
|
|
284
288
|
fulfilled: "fulfilled";
|
|
285
289
|
}>>>;
|
|
286
290
|
pricingMode: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
|
|
@@ -309,10 +313,10 @@ export declare const bookingExtraListQuerySchema: z.ZodObject<{
|
|
|
309
313
|
productExtraId: z.ZodOptional<z.ZodString>;
|
|
310
314
|
optionExtraConfigId: z.ZodOptional<z.ZodString>;
|
|
311
315
|
status: z.ZodOptional<z.ZodEnum<{
|
|
312
|
-
draft: "draft";
|
|
313
|
-
selected: "selected";
|
|
314
316
|
confirmed: "confirmed";
|
|
315
317
|
cancelled: "cancelled";
|
|
318
|
+
draft: "draft";
|
|
319
|
+
selected: "selected";
|
|
316
320
|
fulfilled: "fulfilled";
|
|
317
321
|
}>>;
|
|
318
322
|
}, z.core.$strip>;
|
package/dist/validation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AASvB,eAAO,MAAM,wBAAwB;;;;;EAKnC,CAAA;AAEF,eAAO,MAAM,sBAAsB;;;;;;;EAOjC,CAAA;AAEF,eAAO,MAAM,wBAAwB;;;;;;EAMnC,CAAA;AAEF,eAAO,MAAM,sBAAsB
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AASvB,eAAO,MAAM,wBAAwB;;;;;EAKnC,CAAA;AAEF,eAAO,MAAM,sBAAsB;;;;;;;EAOjC,CAAA;AAEF,eAAO,MAAM,wBAAwB;;;;;;EAMnC,CAAA;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAejC,CAAA;AAEF,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAyB,CAAA;AAC9D,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAmC,CAAA;AACxE,eAAO,MAAM,2BAA2B;;;;;;;;;;;;iBAKtC,CAAA;AAEF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;iBActC,CAAA;AAEF,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA8B,CAAA;AACxE,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAwC,CAAA;AAClF,eAAO,MAAM,gCAAgC;;;;;;;;;;;iBAI3C,CAAA;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkBjC,CAAA;AAEF,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAyB,CAAA;AAC9D,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAmC,CAAA;AACxE,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;iBAKtC,CAAA"}
|
package/dist/validation.js
CHANGED
|
@@ -28,6 +28,7 @@ export const bookingExtraStatusSchema = z.enum([
|
|
|
28
28
|
]);
|
|
29
29
|
export const productExtraCoreSchema = z.object({
|
|
30
30
|
productId: z.string(),
|
|
31
|
+
supplierId: z.string().nullable().optional(),
|
|
31
32
|
code: z.string().max(100).nullable().optional(),
|
|
32
33
|
name: z.string().min(1).max(255),
|
|
33
34
|
description: z.string().nullable().optional(),
|
|
@@ -45,6 +46,7 @@ export const insertProductExtraSchema = productExtraCoreSchema;
|
|
|
45
46
|
export const updateProductExtraSchema = productExtraCoreSchema.partial();
|
|
46
47
|
export const productExtraListQuerySchema = paginationSchema.extend({
|
|
47
48
|
productId: z.string().optional(),
|
|
49
|
+
supplierId: z.string().optional(),
|
|
48
50
|
active: booleanQueryParam.optional(),
|
|
49
51
|
search: z.string().optional(),
|
|
50
52
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyantjs/extras",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -29,15 +29,15 @@
|
|
|
29
29
|
"drizzle-orm": "^0.45.2",
|
|
30
30
|
"hono": "^4.12.10",
|
|
31
31
|
"zod": "^4.3.6",
|
|
32
|
-
"@voyantjs/core": "0.
|
|
33
|
-
"@voyantjs/db": "0.
|
|
34
|
-
"@voyantjs/hono": "0.
|
|
35
|
-
"@voyantjs/catalog": "0.
|
|
32
|
+
"@voyantjs/core": "0.21.0",
|
|
33
|
+
"@voyantjs/db": "0.21.0",
|
|
34
|
+
"@voyantjs/hono": "0.21.0",
|
|
35
|
+
"@voyantjs/catalog": "0.21.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"typescript": "^6.0.2",
|
|
39
|
-
"@voyantjs/bookings": "0.
|
|
40
|
-
"@voyantjs/products": "0.
|
|
39
|
+
"@voyantjs/bookings": "0.21.0",
|
|
40
|
+
"@voyantjs/products": "0.21.0",
|
|
41
41
|
"@voyantjs/voyant-typescript-config": "0.1.0"
|
|
42
42
|
},
|
|
43
43
|
"files": [
|