@aglyn/plugins-commerce 1.0.0-beta.220 → 1.0.0-beta.222
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/README.md +4 -2
- package/package.json +14 -13
- package/src/lib/components/console/catalog-organization-card.component.js +9 -0
- package/src/lib/components/console/catalog-organization-card.component.js.map +1 -1
- package/src/lib/components/console/discounts-card.component.js +8 -0
- package/src/lib/components/console/discounts-card.component.js.map +1 -1
- package/src/lib/components/console/gift-cards-card.component.js +8 -0
- package/src/lib/components/console/gift-cards-card.component.js.map +1 -1
- package/src/lib/components/console/host-coupons-card.component.js +8 -0
- package/src/lib/components/console/host-coupons-card.component.js.map +1 -1
- package/src/lib/components/console/host-orders-card.component.js +34 -70
- package/src/lib/components/console/host-orders-card.component.js.map +1 -1
- package/src/lib/components/console/product-zones.d.ts +7 -6
- package/src/lib/components/console/product-zones.js +5 -4
- package/src/lib/components/console/product-zones.js.map +1 -1
- package/src/lib/components/console/products-hub-card.component.js +86 -284
- package/src/lib/components/console/products-hub-card.component.js.map +1 -1
- package/src/lib/declarations.console-server.d.ts +38 -0
- package/src/lib/declarations.console-server.js +67 -0
- package/src/lib/declarations.console-server.js.map +1 -0
- package/src/lib/model/commerce-gift-cards.d.ts +26 -0
- package/src/lib/model/commerce-gift-cards.js +42 -0
- package/src/lib/model/commerce-gift-cards.js.map +1 -1
- package/src/lib/model/commerce-orders.d.ts +0 -57
- package/src/lib/model/commerce-orders.js +0 -80
- package/src/lib/model/commerce-orders.js.map +1 -1
- package/src/lib/model/index.d.ts +0 -1
- package/src/lib/model/index.js +0 -1
- package/src/lib/model/index.js.map +1 -1
- package/src/lib/plugin.js +5 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/server/api-v1/openapi.d.ts +27 -0
- package/src/lib/server/api-v1/openapi.js +219 -0
- package/src/lib/server/api-v1/openapi.js.map +1 -0
- package/src/lib/server/api-v1/orders-and-products.d.ts +19 -0
- package/src/lib/server/api-v1/orders-and-products.js +419 -0
- package/src/lib/server/api-v1/orders-and-products.js.map +1 -0
- package/src/lib/server/billing-webhook.js +83 -56
- package/src/lib/server/billing-webhook.js.map +1 -1
- package/src/lib/server/download.js +4 -1
- package/src/lib/server/download.js.map +1 -1
- package/src/lib/server/fulfill-order.d.ts +52 -11
- package/src/lib/server/fulfill-order.js +6 -9
- package/src/lib/server/fulfill-order.js.map +1 -1
- package/src/lib/server/gift-card-issue.d.ts +57 -0
- package/src/lib/server/gift-card-issue.js +155 -0
- package/src/lib/server/gift-card-issue.js.map +1 -0
- package/src/lib/server/gift-cards.js +25 -84
- package/src/lib/server/gift-cards.js.map +1 -1
- package/src/lib/server/membership-register.js +9 -8
- package/src/lib/server/membership-register.js.map +1 -1
- package/src/lib/server/newsletter.js +7 -5
- package/src/lib/server/newsletter.js.map +1 -1
- package/src/lib/server/paid-media-delivery.d.ts +21 -0
- package/src/lib/server/paid-media-delivery.js +23 -5
- package/src/lib/server/paid-media-delivery.js.map +1 -1
- package/src/lib/server/paid-media-serve-count.d.ts +28 -0
- package/src/lib/server/paid-media-serve-count.js +46 -0
- package/src/lib/server/paid-media-serve-count.js.map +1 -0
- package/src/lib/server/person-eraser.d.ts +45 -0
- package/src/lib/server/person-eraser.js +57 -0
- package/src/lib/server/person-eraser.js.map +1 -0
- package/src/lib/server/pos-order.js +17 -9
- package/src/lib/server/pos-order.js.map +1 -1
- package/src/lib/server/refund.js +15 -15
- package/src/lib/server/refund.js.map +1 -1
- package/src/lib/server/restock-flag.d.ts +2 -2
- package/src/lib/server/restock-flag.js +1 -1
- package/src/lib/server/restock-flag.js.map +1 -1
- package/src/lib/server/stream.js +4 -1
- package/src/lib/server/stream.js.map +1 -1
- package/src/lib/server.js +5 -21
- package/src/lib/server.js.map +1 -1
- package/src/lib/testing/stand-in-person-records.d.ts +43 -0
- package/src/lib/testing/stand-in-person-records.js +63 -0
- package/src/lib/testing/stand-in-person-records.js.map +1 -0
- package/src/lib/testing/stand-in-record-system.d.ts +11 -2
- package/src/lib/testing/stand-in-record-system.js +5 -3
- package/src/lib/testing/stand-in-record-system.js.map +1 -1
- package/src/lib/transfer/gift-card-confirm-step.component.d.ts +22 -0
- package/src/lib/transfer/gift-card-confirm-step.component.js +259 -0
- package/src/lib/transfer/gift-card-confirm-step.component.js.map +1 -0
- package/src/lib/transfer/gift-cards-plan.d.ts +29 -0
- package/src/lib/transfer/gift-cards-plan.js +40 -0
- package/src/lib/transfer/gift-cards-plan.js.map +1 -0
- package/src/lib/transfer/gift-cards.server.d.ts +34 -0
- package/src/lib/transfer/gift-cards.server.js +296 -0
- package/src/lib/transfer/gift-cards.server.js.map +1 -0
- package/src/lib/transfer/list-filter.d.ts +29 -0
- package/src/lib/transfer/list-filter.js +112 -0
- package/src/lib/transfer/list-filter.js.map +1 -0
- package/src/lib/transfer/product-import-results.d.ts +29 -0
- package/src/lib/transfer/product-import-results.js +49 -0
- package/src/lib/transfer/product-import-results.js.map +1 -0
- package/src/lib/transfer/product-import-step.component.d.ts +30 -0
- package/src/lib/transfer/product-import-step.component.js +99 -0
- package/src/lib/transfer/product-import-step.component.js.map +1 -0
- package/src/lib/transfer/product-transfer.d.ts +211 -0
- package/src/lib/transfer/product-transfer.js +1594 -0
- package/src/lib/transfer/product-transfer.js.map +1 -0
- package/src/lib/transfer/products.server.d.ts +44 -0
- package/src/lib/transfer/products.server.js +550 -0
- package/src/lib/transfer/products.server.js.map +1 -0
- package/src/lib/transfer/records-transfer.d.ts +182 -0
- package/src/lib/transfer/records-transfer.js +1153 -0
- package/src/lib/transfer/records-transfer.js.map +1 -0
- package/src/lib/transfer/records.server.d.ts +68 -0
- package/src/lib/transfer/records.server.js +455 -0
- package/src/lib/transfer/records.server.js.map +1 -0
- package/src/lib/transfer/register-transfer-resources.d.ts +17 -0
- package/src/lib/transfer/register-transfer-resources.js +171 -0
- package/src/lib/transfer/register-transfer-resources.js.map +1 -0
- package/src/lib/transfer/register-transfer-ui.d.ts +23 -0
- package/src/lib/transfer/register-transfer-ui.js +78 -0
- package/src/lib/transfer/register-transfer-ui.js.map +1 -0
- package/src/lib/transfer/server-common.d.ts +76 -0
- package/src/lib/transfer/server-common.js +165 -0
- package/src/lib/transfer/server-common.js.map +1 -0
- package/src/lib/transfer/transfer-header-actions.component.d.ts +39 -0
- package/src/lib/transfer/transfer-header-actions.component.js +79 -0
- package/src/lib/transfer/transfer-header-actions.component.js.map +1 -0
- package/src/lib/transfer/transfer-keys.d.ts +31 -0
- package/src/lib/transfer/transfer-keys.js +56 -0
- package/src/lib/transfer/transfer-keys.js.map +1 -0
- package/src/lib/model/commerce-io.d.ts +0 -36
- package/src/lib/model/commerce-io.js +0 -245
- package/src/lib/model/commerce-io.js.map +0 -1
- package/src/lib/server/contact-refund.d.ts +0 -117
- package/src/lib/server/contact-refund.js +0 -196
- package/src/lib/server/contact-refund.js.map +0 -1
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2026 Aglyn LLC
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/ import * as Aglyn from "@aglyn/aglyn/server";
|
|
18
|
+
import { buildMatchLookup } from "@aglyn/aglyn/data-transfer";
|
|
19
|
+
import { firebaseAdmin } from "@aglyn/tenant-data-admin";
|
|
20
|
+
import { ORDER_LIST_QUERY } from "../constants/orders-list-query.js";
|
|
21
|
+
import { CATEGORY_MATCH_KEYS, COUPON_MATCH_KEYS, DISCOUNT_KIND_PICKLIST, DISCOUNT_KIND_SPEC, DISCOUNT_MATCH_KEYS, categoryRecord, categoryWrite, couponRecord, couponWrite, discountRecord, discountWrite, orderRecord, planWithCreateRequired, promotionCode, rowChanges } from "./records-transfer.js";
|
|
22
|
+
import { NOTHING, ROW_BUDGET_MS, countSource, firestoreOf, hostRefOf, readSourcePage, readerSeesHost, revertEntries, withoutUndefined } from "./server-common.js";
|
|
23
|
+
const IN_MAX = 30;
|
|
24
|
+
const noExtra = async ()=>({});
|
|
25
|
+
function sourceFor(spec, firestore, ctx) {
|
|
26
|
+
var _ref;
|
|
27
|
+
var _spec_source, _spec_source1;
|
|
28
|
+
return _extends({
|
|
29
|
+
collection: spec.collection(firestore, ctx),
|
|
30
|
+
declaration: (_ref = (_spec_source = spec.source) == null ? void 0 : _spec_source.declaration) != null ? _ref : {
|
|
31
|
+
fields: [],
|
|
32
|
+
sorts: []
|
|
33
|
+
}
|
|
34
|
+
}, ((_spec_source1 = spec.source) == null ? void 0 : _spec_source1.order) ? {
|
|
35
|
+
order: spec.source.order
|
|
36
|
+
} : {});
|
|
37
|
+
}
|
|
38
|
+
function refuseFilterWithout(spec, options) {
|
|
39
|
+
if ((options == null ? void 0 : options.filter) && !spec.source) throw new Error('This list exports everything, or the records you select.');
|
|
40
|
+
}
|
|
41
|
+
async function readPage(spec, ctx, cursor, fieldIds, options, firestore) {
|
|
42
|
+
var _ref, _spec_extra;
|
|
43
|
+
if (!readerSeesHost(ctx, options)) return NOTHING;
|
|
44
|
+
refuseFilterWithout(spec, options);
|
|
45
|
+
const pageSize = Math.max(1, Math.min(500, (_ref = options == null ? void 0 : options.pageSize) != null ? _ref : 500));
|
|
46
|
+
const page = await readSourcePage(firestore, sourceFor(spec, firestore, ctx), cursor, options, pageSize);
|
|
47
|
+
const extra = await ((_spec_extra = spec.extra) != null ? _spec_extra : noExtra)(firestore, ctx, page.docs);
|
|
48
|
+
const rows = page.docs.map((doc)=>{
|
|
49
|
+
var _doc_data;
|
|
50
|
+
const record = spec.record(doc.id, (_doc_data = doc.data()) != null ? _doc_data : {}, extra);
|
|
51
|
+
return Object.fromEntries(fieldIds.map((fieldId)=>{
|
|
52
|
+
var _record_fieldId;
|
|
53
|
+
return [
|
|
54
|
+
fieldId,
|
|
55
|
+
(_record_fieldId = record[fieldId]) != null ? _record_fieldId : null
|
|
56
|
+
];
|
|
57
|
+
}));
|
|
58
|
+
});
|
|
59
|
+
return {
|
|
60
|
+
rows,
|
|
61
|
+
next: page.next
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
async function count(spec, ctx, options, firestore) {
|
|
65
|
+
if (!readerSeesHost(ctx, options)) return 0;
|
|
66
|
+
refuseFilterWithout(spec, options);
|
|
67
|
+
return countSource(firestore, sourceFor(spec, firestore, ctx), options);
|
|
68
|
+
}
|
|
69
|
+
async function lookup(spec, ctx, requests, firestore) {
|
|
70
|
+
var _spec_extra, _doc_data;
|
|
71
|
+
const collection = spec.collection(firestore, ctx);
|
|
72
|
+
const found = new Map();
|
|
73
|
+
const keys = [];
|
|
74
|
+
for (const request of requests){
|
|
75
|
+
keys.push({
|
|
76
|
+
fieldId: request.fieldId,
|
|
77
|
+
normalizer: request.normalizer
|
|
78
|
+
});
|
|
79
|
+
for(let at = 0; at < request.values.length; at += IN_MAX){
|
|
80
|
+
var _spec_find;
|
|
81
|
+
const slice = request.values.slice(at, at + IN_MAX);
|
|
82
|
+
if (request.fieldId === 'id') {
|
|
83
|
+
for (const doc of (await firestore.getAll(...slice.map((id)=>collection.doc(id))))){
|
|
84
|
+
if (doc.exists) found.set(doc.id, doc);
|
|
85
|
+
}
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const query = (_spec_find = spec.find) == null ? void 0 : _spec_find[request.fieldId];
|
|
89
|
+
if (!query) continue;
|
|
90
|
+
for (const doc of (await query(collection, slice).get()).docs)found.set(doc.id, doc);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const docs = [
|
|
94
|
+
...found.values()
|
|
95
|
+
];
|
|
96
|
+
const extra = docs.length ? await ((_spec_extra = spec.extra) != null ? _spec_extra : noExtra)(firestore, ctx, docs) : {};
|
|
97
|
+
const records = new Map();
|
|
98
|
+
for (const doc of docs)records.set(doc.id, spec.record(doc.id, (_doc_data = doc.data()) != null ? _doc_data : {}, extra));
|
|
99
|
+
const lookupMap = buildMatchLookup(docs.map((doc)=>{
|
|
100
|
+
var _doc_data;
|
|
101
|
+
return {
|
|
102
|
+
id: doc.id,
|
|
103
|
+
values: spec.matchValues(doc.id, (_doc_data = doc.data()) != null ? _doc_data : {})
|
|
104
|
+
};
|
|
105
|
+
}), keys);
|
|
106
|
+
return {
|
|
107
|
+
lookup: lookupMap,
|
|
108
|
+
records
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/** The reading hooks every records resource shares: count, a page of an export, and the lookup. */ export function readableRecords(spec) {
|
|
112
|
+
return {
|
|
113
|
+
count: (ctx, options)=>count(spec, ctx, options, firestoreOf()),
|
|
114
|
+
readPage: (ctx, cursor, fieldIds, options)=>readPage(spec, ctx, cursor, fieldIds, options, firestoreOf()),
|
|
115
|
+
lookup: (ctx, requests)=>lookup(spec, ctx, requests, firestoreOf())
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** The hooks an export-only resource answers with: read, find by id, and refuse every write. */ function exportOnly(spec, noun, why) {
|
|
119
|
+
return _extends({
|
|
120
|
+
matchKeys: [
|
|
121
|
+
{
|
|
122
|
+
fieldId: 'id',
|
|
123
|
+
normalizer: 'aglynId'
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
}, readableRecords(spec), {
|
|
127
|
+
invariants: [
|
|
128
|
+
{
|
|
129
|
+
id: `${noun}-export-only`,
|
|
130
|
+
label: why,
|
|
131
|
+
check: ()=>why
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
async apply (_ctx, chunk) {
|
|
135
|
+
const results = chunk.rows.map((row)=>({
|
|
136
|
+
row: row.index,
|
|
137
|
+
outcome: 'failed',
|
|
138
|
+
reason: 'refusedValue',
|
|
139
|
+
message: why
|
|
140
|
+
}));
|
|
141
|
+
return {
|
|
142
|
+
results,
|
|
143
|
+
undo: []
|
|
144
|
+
};
|
|
145
|
+
},
|
|
146
|
+
async revert () {
|
|
147
|
+
return {
|
|
148
|
+
done: [],
|
|
149
|
+
conflicts: []
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/*==========================================
|
|
155
|
+
* ORDERS — exported only
|
|
156
|
+
*=========================================*/ const ORDERS = {
|
|
157
|
+
collection: (firestore, ctx)=>hostRefOf(firestore, ctx).collection('orders'),
|
|
158
|
+
source: {
|
|
159
|
+
declaration: ORDER_LIST_QUERY,
|
|
160
|
+
order: {
|
|
161
|
+
path: 'createdAtMs',
|
|
162
|
+
direction: 'desc'
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
record: (id, data, extra)=>orderRecord(id, data, extra.productNames),
|
|
166
|
+
matchValues: (id)=>({
|
|
167
|
+
id
|
|
168
|
+
}),
|
|
169
|
+
/** A legacy flat row is named by its product, read for that page alone. */ async extra (firestore, ctx, docs) {
|
|
170
|
+
const ids = [
|
|
171
|
+
...new Set(docs.filter((doc)=>{
|
|
172
|
+
var _doc_get;
|
|
173
|
+
return !((_doc_get = doc.get('lineItems')) == null ? void 0 : _doc_get.length) && doc.get('productId');
|
|
174
|
+
}).map((doc)=>String(doc.get('productId'))))
|
|
175
|
+
];
|
|
176
|
+
const productNames = {};
|
|
177
|
+
const products = hostRefOf(firestore, ctx).collection('products');
|
|
178
|
+
for(let at = 0; at < ids.length; at += 100){
|
|
179
|
+
for (const doc of (await firestore.getAll(...ids.slice(at, at + 100).map((id)=>products.doc(id))))){
|
|
180
|
+
if (doc.exists && doc.get('name')) productNames[doc.id] = String(doc.get('name'));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
productNames
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
export const ordersTransfer = exportOnly(ORDERS, 'orders', 'Orders are exported, never imported: an order is the record of a sale, written by checkout, the register or a paid draft.');
|
|
189
|
+
/*==========================================
|
|
190
|
+
* IMPORTABLE RECORDS
|
|
191
|
+
*=========================================*/ /** A row the apply refuses, with the sentence the results show. */ let RowRefusal = class RowRefusal extends Error {
|
|
192
|
+
};
|
|
193
|
+
function writable(spec, matchKeys) {
|
|
194
|
+
return {
|
|
195
|
+
matchKeys,
|
|
196
|
+
count: (ctx, options)=>count(spec, ctx, options, firestoreOf()),
|
|
197
|
+
readPage: (ctx, cursor, fieldIds, options)=>readPage(spec, ctx, cursor, fieldIds, options, firestoreOf()),
|
|
198
|
+
lookup: (ctx, requests)=>lookup(spec, ctx, requests, firestoreOf()),
|
|
199
|
+
plan (_ctx, input) {
|
|
200
|
+
const rows = spec.normalize ? input.rows.map((row)=>{
|
|
201
|
+
var _ref;
|
|
202
|
+
return _extends({}, row, {
|
|
203
|
+
values: (_ref = spec.normalize == null ? void 0 : spec.normalize.call(spec, _extends({}, row.values))) != null ? _ref : row.values
|
|
204
|
+
});
|
|
205
|
+
}) : input.rows;
|
|
206
|
+
return planWithCreateRequired(_extends({}, input, {
|
|
207
|
+
rows
|
|
208
|
+
}), spec.requiredToCreate);
|
|
209
|
+
},
|
|
210
|
+
apply: (ctx, chunk, writer)=>applyRecords(spec, ctx, chunk, writer, firestoreOf()),
|
|
211
|
+
revert: (ctx, snapshot, decisions)=>revertRecords(spec, ctx, snapshot, decisions, firestoreOf())
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
/** Writes one chunk of planned rows: each a create or an update of one document. */ export async function applyRecords(spec, ctx, chunk, writer, firestore) {
|
|
215
|
+
var _spec_extra;
|
|
216
|
+
const collection = spec.collection(firestore, ctx);
|
|
217
|
+
const results = [];
|
|
218
|
+
const undo = [];
|
|
219
|
+
const extra = await ((_spec_extra = spec.extra) != null ? _spec_extra : noExtra)(firestore, ctx, []);
|
|
220
|
+
for (const row of chunk.rows){
|
|
221
|
+
const earlier = await writer.alreadyApplied(row.index);
|
|
222
|
+
if (earlier) {
|
|
223
|
+
results.push(earlier);
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (writer.timeLeftMs() < ROW_BUDGET_MS) break;
|
|
227
|
+
const changes = rowChanges(row);
|
|
228
|
+
const creating = row.verdict === 'create';
|
|
229
|
+
const id = creating ? spec.newId(row, changes) : row.recordId;
|
|
230
|
+
const ref = collection.doc(id);
|
|
231
|
+
try {
|
|
232
|
+
const outcome = await firestore.runTransaction(async (tx)=>{
|
|
233
|
+
var _snapshot_data, _ref;
|
|
234
|
+
const snapshot = await tx.get(ref);
|
|
235
|
+
if (creating && snapshot.exists) throw new RowRefusal(`"${id}" already exists; match it to update it instead.`);
|
|
236
|
+
if (!creating && !snapshot.exists) throw new RowRefusal('The record was deleted after the dry run.');
|
|
237
|
+
const current = snapshot.exists ? (_snapshot_data = snapshot.data()) != null ? _snapshot_data : {} : null;
|
|
238
|
+
const made = spec.write(id, current, changes, extra);
|
|
239
|
+
if ('problem' in made) throw new RowRefusal(made.problem);
|
|
240
|
+
const doc = withoutUndefined(_extends({}, made.doc, creating ? (_ref = spec.createStamps == null ? void 0 : spec.createStamps.call(spec)) != null ? _ref : {} : {}));
|
|
241
|
+
if (creating) tx.create(ref, doc);
|
|
242
|
+
else tx.set(ref, doc);
|
|
243
|
+
return {
|
|
244
|
+
current,
|
|
245
|
+
doc
|
|
246
|
+
};
|
|
247
|
+
});
|
|
248
|
+
spec.afterWrite == null ? void 0 : spec.afterWrite.call(spec, id, outcome.doc, extra);
|
|
249
|
+
const after = spec.record(id, outcome.doc, extra);
|
|
250
|
+
const before = outcome.current ? spec.record(id, outcome.current, extra) : null;
|
|
251
|
+
const touched = Object.keys(changes);
|
|
252
|
+
const result = {
|
|
253
|
+
row: row.index,
|
|
254
|
+
outcome: creating ? 'created' : 'updated',
|
|
255
|
+
recordId: id
|
|
256
|
+
};
|
|
257
|
+
const entry = creating ? {
|
|
258
|
+
row: row.index,
|
|
259
|
+
recordId: id,
|
|
260
|
+
action: 'created',
|
|
261
|
+
written: pickKeys(after, touched)
|
|
262
|
+
} : {
|
|
263
|
+
row: row.index,
|
|
264
|
+
recordId: id,
|
|
265
|
+
action: 'updated',
|
|
266
|
+
previous: pickKeys(before != null ? before : {}, touched),
|
|
267
|
+
written: pickKeys(after, touched)
|
|
268
|
+
};
|
|
269
|
+
results.push(result);
|
|
270
|
+
undo.push(entry);
|
|
271
|
+
await writer.markApplied(result, entry);
|
|
272
|
+
} catch (error) {
|
|
273
|
+
if (!(error instanceof RowRefusal)) throw error;
|
|
274
|
+
const result = {
|
|
275
|
+
row: row.index,
|
|
276
|
+
outcome: 'failed',
|
|
277
|
+
reason: 'refusedValue',
|
|
278
|
+
message: error.message
|
|
279
|
+
};
|
|
280
|
+
results.push(result);
|
|
281
|
+
await writer.markApplied(result);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
results,
|
|
286
|
+
undo
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
const pickKeys = (record, keys)=>Object.fromEntries(keys.map((key)=>{
|
|
290
|
+
var _record_key;
|
|
291
|
+
return [
|
|
292
|
+
key,
|
|
293
|
+
(_record_key = record[key]) != null ? _record_key : null
|
|
294
|
+
];
|
|
295
|
+
}));
|
|
296
|
+
/** Reverses one chunk: a created record deleted, an updated one's fields put back. */ export async function revertRecords(spec, ctx, snapshot, decisions, firestore) {
|
|
297
|
+
var _spec_extra;
|
|
298
|
+
const collection = spec.collection(firestore, ctx);
|
|
299
|
+
const extra = await ((_spec_extra = spec.extra) != null ? _spec_extra : noExtra)(firestore, ctx, []);
|
|
300
|
+
return revertEntries(snapshot, decisions, {
|
|
301
|
+
async current (entry) {
|
|
302
|
+
var _doc_data;
|
|
303
|
+
const doc = await collection.doc(entry.recordId).get();
|
|
304
|
+
return doc.exists ? spec.record(doc.id, (_doc_data = doc.data()) != null ? _doc_data : {}, extra) : null;
|
|
305
|
+
},
|
|
306
|
+
async remove (entry) {
|
|
307
|
+
await collection.doc(entry.recordId).delete();
|
|
308
|
+
},
|
|
309
|
+
async restore (entry, values) {
|
|
310
|
+
var _doc_data;
|
|
311
|
+
const ref = collection.doc(entry.recordId);
|
|
312
|
+
const doc = await ref.get();
|
|
313
|
+
if (!doc.exists) return;
|
|
314
|
+
const made = spec.write(entry.recordId, (_doc_data = doc.data()) != null ? _doc_data : {}, values, extra);
|
|
315
|
+
// A value the record held before the import is put back as it was, even one a file could not set.
|
|
316
|
+
if ('problem' in made) throw new Error(`Undo could not restore ${entry.recordId}: ${made.problem}`);
|
|
317
|
+
await ref.set(withoutUndefined(made.doc));
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
/*------------------------------------------
|
|
322
|
+
* Discounts
|
|
323
|
+
*-----------------------------------------*/ const DISCOUNTS = {
|
|
324
|
+
collection: (firestore, ctx)=>hostRefOf(firestore, ctx).collection('discounts'),
|
|
325
|
+
record: (id, data)=>discountRecord(id, data),
|
|
326
|
+
matchValues: (id, data)=>{
|
|
327
|
+
var _data_code, _data_name;
|
|
328
|
+
return {
|
|
329
|
+
id,
|
|
330
|
+
code: (_data_code = data['code']) != null ? _data_code : null,
|
|
331
|
+
name: (_data_name = data['name']) != null ? _data_name : null
|
|
332
|
+
};
|
|
333
|
+
},
|
|
334
|
+
find: {
|
|
335
|
+
code: (collection, values)=>collection.where('code', 'in', values.map((value)=>promotionCode(value))),
|
|
336
|
+
name: (collection, values)=>collection.where('name', 'in', values)
|
|
337
|
+
},
|
|
338
|
+
requiredToCreate: [
|
|
339
|
+
'kind'
|
|
340
|
+
],
|
|
341
|
+
newId: ()=>Aglyn.createResourceUid(),
|
|
342
|
+
write: (_id, current, changes)=>discountWrite(current, changes),
|
|
343
|
+
normalize (values) {
|
|
344
|
+
if ('code' in values) values['code'] = promotionCode(values['code']) || null;
|
|
345
|
+
return values;
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
export const discountsTransfer = _extends({}, writable(DISCOUNTS, DISCOUNT_MATCH_KEYS), {
|
|
349
|
+
async picklists (_ctx, picklistIds) {
|
|
350
|
+
return picklistIds.includes(DISCOUNT_KIND_PICKLIST) ? {
|
|
351
|
+
[DISCOUNT_KIND_PICKLIST]: {
|
|
352
|
+
spec: DISCOUNT_KIND_SPEC,
|
|
353
|
+
set: {
|
|
354
|
+
values: DISCOUNT_KIND_SPEC.standardValues.map((value)=>({
|
|
355
|
+
id: value.id,
|
|
356
|
+
label: value.label,
|
|
357
|
+
active: true
|
|
358
|
+
})),
|
|
359
|
+
defaultValueId: 'percent'
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
} : {};
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
/*------------------------------------------
|
|
366
|
+
* Coupons
|
|
367
|
+
*-----------------------------------------*/ const COUPONS = {
|
|
368
|
+
collection: (firestore, ctx)=>hostRefOf(firestore, ctx).collection('coupons'),
|
|
369
|
+
record: (id, data)=>couponRecord(id, data),
|
|
370
|
+
matchValues: (id)=>({
|
|
371
|
+
id,
|
|
372
|
+
code: id
|
|
373
|
+
}),
|
|
374
|
+
// A coupon's code is its document id: a code is looked up by id.
|
|
375
|
+
find: {
|
|
376
|
+
code: (collection, values)=>collection.where(firebaseAdmin.firestore.FieldPath.documentId(), 'in', values.map((value)=>promotionCode(value)).filter(Boolean))
|
|
377
|
+
},
|
|
378
|
+
requiredToCreate: [
|
|
379
|
+
'code',
|
|
380
|
+
'percentOff'
|
|
381
|
+
],
|
|
382
|
+
newId: (_row, changes)=>{
|
|
383
|
+
const code = promotionCode(changes['code']);
|
|
384
|
+
if (!code) throw new RowRefusal('A coupon needs a code.');
|
|
385
|
+
return code;
|
|
386
|
+
},
|
|
387
|
+
write: (_id, current, changes)=>couponWrite(current, changes),
|
|
388
|
+
createStamps: ()=>({
|
|
389
|
+
createdAt: firebaseAdmin.firestore.Timestamp.now()
|
|
390
|
+
}),
|
|
391
|
+
normalize (values) {
|
|
392
|
+
if ('code' in values) values['code'] = promotionCode(values['code']) || null;
|
|
393
|
+
return values;
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
export const couponsTransfer = writable(COUPONS, COUPON_MATCH_KEYS);
|
|
397
|
+
/*------------------------------------------
|
|
398
|
+
* Categories
|
|
399
|
+
*-----------------------------------------*/ /** Every category of the site, for parents and for naming them. */ async function readCategories(firestore, ctx) {
|
|
400
|
+
const snapshot = await hostRefOf(firestore, ctx).collection('productCategories').limit(2000).get();
|
|
401
|
+
return new Map(snapshot.docs.map((doc)=>{
|
|
402
|
+
var _doc_data;
|
|
403
|
+
return [
|
|
404
|
+
doc.id,
|
|
405
|
+
(_doc_data = doc.data()) != null ? _doc_data : {}
|
|
406
|
+
];
|
|
407
|
+
}));
|
|
408
|
+
}
|
|
409
|
+
const CATEGORIES = {
|
|
410
|
+
collection: (firestore, ctx)=>hostRefOf(firestore, ctx).collection('productCategories'),
|
|
411
|
+
record (id, data, extra) {
|
|
412
|
+
var _extra_categories;
|
|
413
|
+
const slugs = new Map([
|
|
414
|
+
...(_extra_categories = extra.categories) != null ? _extra_categories : new Map()
|
|
415
|
+
].map(([key, category])=>{
|
|
416
|
+
var _category_slug;
|
|
417
|
+
return [
|
|
418
|
+
key,
|
|
419
|
+
String((_category_slug = category.slug) != null ? _category_slug : key)
|
|
420
|
+
];
|
|
421
|
+
}));
|
|
422
|
+
return categoryRecord(id, data, slugs);
|
|
423
|
+
},
|
|
424
|
+
matchValues: (id, data)=>{
|
|
425
|
+
var _data_slug, _data_name;
|
|
426
|
+
return {
|
|
427
|
+
id,
|
|
428
|
+
slug: (_data_slug = data['slug']) != null ? _data_slug : null,
|
|
429
|
+
name: (_data_name = data['name']) != null ? _data_name : null
|
|
430
|
+
};
|
|
431
|
+
},
|
|
432
|
+
find: {
|
|
433
|
+
slug: (collection, values)=>collection.where('slug', 'in', values),
|
|
434
|
+
name: (collection, values)=>collection.where('name', 'in', values)
|
|
435
|
+
},
|
|
436
|
+
extra: async (firestore, ctx)=>({
|
|
437
|
+
categories: await readCategories(firestore, ctx)
|
|
438
|
+
}),
|
|
439
|
+
requiredToCreate: [
|
|
440
|
+
'name'
|
|
441
|
+
],
|
|
442
|
+
newId: ()=>Aglyn.createResourceUid(),
|
|
443
|
+
write: (id, current, changes, extra)=>{
|
|
444
|
+
var _extra_categories;
|
|
445
|
+
return categoryWrite(id, current, changes, (_extra_categories = extra.categories) != null ? _extra_categories : new Map());
|
|
446
|
+
},
|
|
447
|
+
// A category written earlier in the file is a parent a later row can name.
|
|
448
|
+
afterWrite (id, doc, extra) {
|
|
449
|
+
var _extra_categories;
|
|
450
|
+
(_extra_categories = extra.categories) == null ? void 0 : _extra_categories.set(id, doc);
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
export const categoriesTransfer = writable(CATEGORIES, CATEGORY_MATCH_KEYS);
|
|
454
|
+
|
|
455
|
+
//# sourceMappingURL=records.server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/transfer/records.server.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn/server'\nimport {\n buildMatchLookup,\n type BuildTransferPlanInput,\n type MatchKeySpec,\n type MatchLookupRequest,\n type PlannedTransferRow,\n type TransferChunk,\n type TransferPlan,\n type TransferRowResult,\n type TransferUndoEntry,\n type TransferUndoSnapshot,\n} from '@aglyn/aglyn/data-transfer'\nimport type {\n PluginTransferResource,\n TransferApplyResult,\n TransferApplyWriter,\n TransferLookupResult,\n TransferReadOptions,\n TransferReadPage,\n TransferResourceContext,\n TransferRevertDecisions,\n TransferRevertResult,\n} from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources'\nimport { firebaseAdmin } from '@aglyn/tenant-data-admin'\nimport { ORDER_LIST_QUERY } from '../constants/orders-list-query'\nimport {\n CATEGORY_MATCH_KEYS,\n COUPON_MATCH_KEYS,\n DISCOUNT_KIND_PICKLIST,\n DISCOUNT_KIND_SPEC,\n DISCOUNT_MATCH_KEYS,\n categoryRecord,\n categoryWrite,\n couponRecord,\n couponWrite,\n discountRecord,\n discountWrite,\n orderRecord,\n planWithCreateRequired,\n promotionCode,\n rowChanges,\n type CategoryIndex,\n type StoredCategory,\n type StoredCoupon,\n type StoredOrder,\n} from './records-transfer'\nimport {\n NOTHING,\n ROW_BUDGET_MS,\n countSource,\n firestoreOf,\n hostRefOf,\n readSourcePage,\n readerSeesHost,\n revertEntries,\n withoutUndefined,\n type CommerceListSource,\n type Firestore,\n} from './server-common'\n\n/*\n * THE SERVER HALVES OF ORDERS, DISCOUNTS, COUPONS AND CATEGORIES\n * (AGL-3531), and the reads gift cards share (`gift-cards.server.ts`,\n * AGL-3551). Their records are plain documents under the site,\n * so one shape serves each: an export reads the list's query (orders) or the\n * whole collection page by page; a lookup finds documents by the resource's\n * keys; an import writes the same document the console's card writes, and\n * undo puts back what it held or deletes what the import made.\n *\n * Orders declare `records` too — the kind a file of rows is — but refuse\n * every row they are handed: their fields are all read-only\n * and the invariant below fails a row that would write, so a dry run says\n * why rather than an apply discovering it.\n */\n\nexport type Doc = Record<string, unknown>\ntype Collection = FirebaseFirestore.CollectionReference\n\nconst IN_MAX = 30\n\nexport interface RecordsSpec {\n collection(firestore: Firestore, ctx: TransferResourceContext): Collection\n /** The list's query an export may carry a filter of. */\n source?: Omit<CommerceListSource, 'collection'>\n /** A document as a file names it. */\n record(id: string, data: Doc, extra: RecordsExtra): Record<string, unknown>\n /** The values a document is found by, per match key. */\n matchValues(id: string, data: Doc): Record<string, unknown>\n /** What a lookup or export reads once per call, besides the documents. */\n extra?(firestore: Firestore, ctx: TransferResourceContext, docs: readonly FirebaseFirestore.DocumentSnapshot[]): Promise<RecordsExtra>\n /** Finds documents by a key's values (at most 30); the id key is read directly. */\n find?: Record<string, (collection: Collection, values: string[]) => FirebaseFirestore.Query>\n}\n\nexport type RecordsExtra = {\n productNames?: Record<string, string>\n categories?: CategoryIndex\n}\n\nconst noExtra = async (): Promise<RecordsExtra> => ({})\n\nfunction sourceFor(spec: RecordsSpec, firestore: Firestore, ctx: TransferResourceContext): CommerceListSource {\n return {\n collection: spec.collection(firestore, ctx),\n declaration: spec.source?.declaration ?? { fields: [], sorts: [] },\n ...(spec.source?.order ? { order: spec.source.order } : {}),\n }\n}\n\nfunction refuseFilterWithout(spec: RecordsSpec, options?: TransferReadOptions): void {\n if (options?.filter && !spec.source) throw new Error('This list exports everything, or the records you select.')\n}\n\nasync function readPage(\n spec: RecordsSpec,\n ctx: TransferResourceContext,\n cursor: string | null,\n fieldIds: readonly string[],\n options: TransferReadOptions | undefined,\n firestore: Firestore,\n): Promise<TransferReadPage> {\n if (!readerSeesHost(ctx, options)) return NOTHING\n refuseFilterWithout(spec, options)\n const pageSize = Math.max(1, Math.min(500, options?.pageSize ?? 500))\n const page = await readSourcePage(firestore, sourceFor(spec, firestore, ctx), cursor, options, pageSize)\n const extra = await (spec.extra ?? noExtra)(firestore, ctx, page.docs)\n const rows = page.docs.map((doc) => {\n const record = spec.record(doc.id, (doc.data() ?? {}) as Doc, extra)\n return Object.fromEntries(fieldIds.map((fieldId) => [fieldId, record[fieldId] ?? null]))\n })\n return { rows, next: page.next }\n}\n\nasync function count(\n spec: RecordsSpec,\n ctx: TransferResourceContext,\n options: TransferReadOptions,\n firestore: Firestore,\n): Promise<number> {\n if (!readerSeesHost(ctx, options)) return 0\n refuseFilterWithout(spec, options)\n return countSource(firestore, sourceFor(spec, firestore, ctx), options)\n}\n\nasync function lookup(\n spec: RecordsSpec,\n ctx: TransferResourceContext,\n requests: readonly MatchLookupRequest[],\n firestore: Firestore,\n): Promise<TransferLookupResult> {\n const collection = spec.collection(firestore, ctx)\n const found = new Map<string, FirebaseFirestore.DocumentSnapshot>()\n const keys: MatchKeySpec[] = []\n for (const request of requests) {\n keys.push({ fieldId: request.fieldId, normalizer: request.normalizer })\n for (let at = 0; at < request.values.length; at += IN_MAX) {\n const slice = request.values.slice(at, at + IN_MAX)\n if (request.fieldId === 'id') {\n for (const doc of await firestore.getAll(...slice.map((id) => collection.doc(id)))) {\n if (doc.exists) found.set(doc.id, doc)\n }\n continue\n }\n const query = spec.find?.[request.fieldId]\n if (!query) continue\n for (const doc of (await query(collection, slice).get()).docs) found.set(doc.id, doc)\n }\n }\n const docs = [...found.values()]\n const extra = docs.length ? await (spec.extra ?? noExtra)(firestore, ctx, docs) : {}\n const records = new Map<string, Readonly<Record<string, unknown>>>()\n for (const doc of docs) records.set(doc.id, spec.record(doc.id, (doc.data() ?? {}) as Doc, extra))\n const lookupMap = buildMatchLookup(\n docs.map((doc) => ({ id: doc.id, values: spec.matchValues(doc.id, (doc.data() ?? {}) as Doc) })),\n keys,\n )\n return { lookup: lookupMap, records }\n}\n\n/** The reading hooks every records resource shares: count, a page of an export, and the lookup. */\nexport function readableRecords(spec: RecordsSpec): Pick<PluginTransferResource, 'count' | 'readPage' | 'lookup'> {\n return {\n count: (ctx, options) => count(spec, ctx, options, firestoreOf()),\n readPage: (ctx, cursor, fieldIds, options) => readPage(spec, ctx, cursor, fieldIds, options, firestoreOf()),\n lookup: (ctx, requests) => lookup(spec, ctx, requests, firestoreOf()),\n }\n}\n\n/** The hooks an export-only resource answers with: read, find by id, and refuse every write. */\nfunction exportOnly(spec: RecordsSpec, noun: string, why: string): PluginTransferResource {\n return {\n matchKeys: [{ fieldId: 'id', normalizer: 'aglynId' }],\n ...readableRecords(spec),\n invariants: [{ id: `${noun}-export-only`, label: why, check: () => why }],\n async apply(_ctx, chunk) {\n const results: TransferRowResult[] = chunk.rows.map((row) => ({\n row: row.index,\n outcome: 'failed',\n reason: 'refusedValue',\n message: why,\n }))\n return { results, undo: [] }\n },\n async revert() {\n return { done: [], conflicts: [] }\n },\n }\n}\n\n/*==========================================\n * ORDERS — exported only\n *=========================================*/\n\nconst ORDERS: RecordsSpec = {\n collection: (firestore, ctx) => hostRefOf(firestore, ctx).collection('orders'),\n source: { declaration: ORDER_LIST_QUERY, order: { path: 'createdAtMs', direction: 'desc' } },\n record: (id, data, extra) => orderRecord(id, data as StoredOrder, extra.productNames),\n matchValues: (id) => ({ id }),\n /** A legacy flat row is named by its product, read for that page alone. */\n async extra(firestore, ctx, docs) {\n const ids = [\n ...new Set(\n docs\n .filter((doc) => !(doc.get('lineItems') as unknown[] | undefined)?.length && doc.get('productId'))\n .map((doc) => String(doc.get('productId'))),\n ),\n ]\n const productNames: Record<string, string> = {}\n const products = hostRefOf(firestore, ctx).collection('products')\n for (let at = 0; at < ids.length; at += 100) {\n for (const doc of await firestore.getAll(...ids.slice(at, at + 100).map((id) => products.doc(id)))) {\n if (doc.exists && doc.get('name')) productNames[doc.id] = String(doc.get('name'))\n }\n }\n return { productNames }\n },\n}\n\nexport const ordersTransfer: PluginTransferResource = exportOnly(\n ORDERS,\n 'orders',\n 'Orders are exported, never imported: an order is the record of a sale, written by checkout, the register or a paid draft.',\n)\n\n\n/*==========================================\n * IMPORTABLE RECORDS\n *=========================================*/\n\n/** A row the apply refuses, with the sentence the results show. */\nclass RowRefusal extends Error {}\n\ninterface WritableSpec extends RecordsSpec {\n /** The fields a new record cannot be made without. */\n requiredToCreate: readonly string[]\n /** A new record's id: a fresh one, or what the row names (a coupon's code). */\n newId(row: PlannedTransferRow, changes: Readonly<Record<string, unknown>>): string\n /** The document a row's changes make, or the refusal. */\n write(\n id: string,\n current: Doc | null,\n changes: Readonly<Record<string, unknown>>,\n extra: RecordsExtra,\n ): { doc: Record<string, unknown> } | { problem: string }\n /** Stamps a create carries beyond its fields. */\n createStamps?(): Record<string, unknown>\n /** Values normalized before matching and planning (a code's case). */\n normalize?(values: Record<string, unknown>): Record<string, unknown>\n /** Called after a record is written, with what the next rows resolve against. */\n afterWrite?(id: string, doc: Doc, extra: RecordsExtra): void\n}\n\nfunction writable(spec: WritableSpec, matchKeys: readonly MatchKeySpec[]): PluginTransferResource {\n return {\n matchKeys,\n count: (ctx, options) => count(spec, ctx, options, firestoreOf()),\n readPage: (ctx, cursor, fieldIds, options) => readPage(spec, ctx, cursor, fieldIds, options, firestoreOf()),\n lookup: (ctx, requests) => lookup(spec, ctx, requests, firestoreOf()),\n plan(_ctx, input: BuildTransferPlanInput): TransferPlan {\n const rows = spec.normalize\n ? input.rows.map((row) => ({ ...row, values: spec.normalize?.({ ...row.values }) ?? row.values }))\n : input.rows\n return planWithCreateRequired({ ...input, rows }, spec.requiredToCreate)\n },\n apply: (ctx, chunk, writer) => applyRecords(spec, ctx, chunk, writer, firestoreOf()),\n revert: (ctx, snapshot, decisions) => revertRecords(spec, ctx, snapshot, decisions, firestoreOf()),\n }\n}\n\n/** Writes one chunk of planned rows: each a create or an update of one document. */\nexport async function applyRecords(\n spec: WritableSpec,\n ctx: TransferResourceContext,\n chunk: TransferChunk<PlannedTransferRow>,\n writer: TransferApplyWriter,\n firestore: Firestore,\n): Promise<TransferApplyResult> {\n const collection = spec.collection(firestore, ctx)\n const results: TransferRowResult[] = []\n const undo: TransferUndoEntry[] = []\n const extra = await (spec.extra ?? noExtra)(firestore, ctx, [])\n for (const row of chunk.rows) {\n const earlier = await writer.alreadyApplied(row.index)\n if (earlier) {\n results.push(earlier)\n continue\n }\n if (writer.timeLeftMs() < ROW_BUDGET_MS) break\n const changes = rowChanges(row)\n const creating = row.verdict === 'create'\n const id = creating ? spec.newId(row, changes) : (row.recordId as string)\n const ref = collection.doc(id)\n try {\n const outcome = await firestore.runTransaction(async (tx) => {\n const snapshot = await tx.get(ref)\n if (creating && snapshot.exists) throw new RowRefusal(`\"${id}\" already exists; match it to update it instead.`)\n if (!creating && !snapshot.exists) throw new RowRefusal('The record was deleted after the dry run.')\n const current = snapshot.exists ? ((snapshot.data() ?? {}) as Doc) : null\n const made = spec.write(id, current, changes, extra)\n if ('problem' in made) throw new RowRefusal(made.problem)\n const doc = withoutUndefined({ ...made.doc, ...(creating ? (spec.createStamps?.() ?? {}) : {}) })\n if (creating) tx.create(ref, doc)\n else tx.set(ref, doc)\n return { current, doc }\n })\n spec.afterWrite?.(id, outcome.doc, extra)\n const after = spec.record(id, outcome.doc, extra)\n const before = outcome.current ? spec.record(id, outcome.current, extra) : null\n const touched = Object.keys(changes)\n const result: TransferRowResult = { row: row.index, outcome: creating ? 'created' : 'updated', recordId: id }\n const entry: TransferUndoEntry = creating\n ? { row: row.index, recordId: id, action: 'created', written: pickKeys(after, touched) }\n : {\n row: row.index,\n recordId: id,\n action: 'updated',\n previous: pickKeys(before ?? {}, touched),\n written: pickKeys(after, touched),\n }\n results.push(result)\n undo.push(entry)\n await writer.markApplied(result, entry)\n } catch (error) {\n if (!(error instanceof RowRefusal)) throw error\n const result: TransferRowResult = { row: row.index, outcome: 'failed', reason: 'refusedValue', message: error.message }\n results.push(result)\n await writer.markApplied(result)\n }\n }\n return { results, undo }\n}\n\nconst pickKeys = (record: Readonly<Record<string, unknown>>, keys: readonly string[]) =>\n Object.fromEntries(keys.map((key) => [key, record[key] ?? null]))\n\n/** Reverses one chunk: a created record deleted, an updated one's fields put back. */\nexport async function revertRecords(\n spec: WritableSpec,\n ctx: TransferResourceContext,\n snapshot: TransferUndoSnapshot,\n decisions: TransferRevertDecisions | undefined,\n firestore: Firestore,\n): Promise<TransferRevertResult> {\n const collection = spec.collection(firestore, ctx)\n const extra = await (spec.extra ?? noExtra)(firestore, ctx, [])\n return revertEntries(snapshot, decisions, {\n async current(entry) {\n const doc = await collection.doc(entry.recordId).get()\n return doc.exists ? spec.record(doc.id, (doc.data() ?? {}) as Doc, extra) : null\n },\n async remove(entry) {\n await collection.doc(entry.recordId).delete()\n },\n async restore(entry, values) {\n const ref = collection.doc(entry.recordId)\n const doc = await ref.get()\n if (!doc.exists) return\n const made = spec.write(entry.recordId, (doc.data() ?? {}) as Doc, values, extra)\n // A value the record held before the import is put back as it was, even one a file could not set.\n if ('problem' in made) throw new Error(`Undo could not restore ${entry.recordId}: ${made.problem}`)\n await ref.set(withoutUndefined(made.doc))\n },\n })\n}\n\n/*------------------------------------------\n * Discounts\n *-----------------------------------------*/\n\nconst DISCOUNTS: WritableSpec = {\n collection: (firestore, ctx) => hostRefOf(firestore, ctx).collection('discounts'),\n record: (id, data) => discountRecord(id, data),\n matchValues: (id, data) => ({ id, code: data['code'] ?? null, name: data['name'] ?? null }),\n find: {\n code: (collection, values) => collection.where('code', 'in', values.map((value) => promotionCode(value))),\n name: (collection, values) => collection.where('name', 'in', values),\n },\n requiredToCreate: ['kind'],\n newId: () => Aglyn.createResourceUid(),\n write: (_id, current, changes) => discountWrite(current, changes),\n normalize(values) {\n if ('code' in values) values['code'] = promotionCode(values['code']) || null\n return values\n },\n}\n\nexport const discountsTransfer: PluginTransferResource = {\n ...writable(DISCOUNTS, DISCOUNT_MATCH_KEYS),\n async picklists(_ctx, picklistIds) {\n return picklistIds.includes(DISCOUNT_KIND_PICKLIST)\n ? {\n [DISCOUNT_KIND_PICKLIST]: {\n spec: DISCOUNT_KIND_SPEC,\n set: {\n values: DISCOUNT_KIND_SPEC.standardValues.map((value) => ({ id: value.id, label: value.label, active: true })),\n defaultValueId: 'percent',\n },\n },\n }\n : {}\n },\n}\n\n/*------------------------------------------\n * Coupons\n *-----------------------------------------*/\n\nconst COUPONS: WritableSpec = {\n collection: (firestore, ctx) => hostRefOf(firestore, ctx).collection('coupons'),\n record: (id, data) => couponRecord(id, data as StoredCoupon),\n matchValues: (id) => ({ id, code: id }),\n // A coupon's code is its document id: a code is looked up by id.\n find: {\n code: (collection, values) =>\n collection.where(\n firebaseAdmin.firestore.FieldPath.documentId(),\n 'in',\n values.map((value) => promotionCode(value)).filter(Boolean),\n ),\n },\n requiredToCreate: ['code', 'percentOff'],\n newId: (_row, changes) => {\n const code = promotionCode(changes['code'])\n if (!code) throw new RowRefusal('A coupon needs a code.')\n return code\n },\n write: (_id, current, changes) => couponWrite(current as StoredCoupon | null, changes),\n createStamps: () => ({ createdAt: firebaseAdmin.firestore.Timestamp.now() }),\n normalize(values) {\n if ('code' in values) values['code'] = promotionCode(values['code']) || null\n return values\n },\n}\n\nexport const couponsTransfer: PluginTransferResource = writable(COUPONS, COUPON_MATCH_KEYS)\n\n/*------------------------------------------\n * Categories\n *-----------------------------------------*/\n\n/** Every category of the site, for parents and for naming them. */\nasync function readCategories(firestore: Firestore, ctx: TransferResourceContext): Promise<CategoryIndex> {\n const snapshot = await hostRefOf(firestore, ctx).collection('productCategories').limit(2000).get()\n return new Map(snapshot.docs.map((doc) => [doc.id, (doc.data() ?? {}) as StoredCategory]))\n}\n\nconst CATEGORIES: WritableSpec = {\n collection: (firestore, ctx) => hostRefOf(firestore, ctx).collection('productCategories'),\n record(id, data, extra) {\n const slugs = new Map([...(extra.categories ?? new Map())].map(([key, category]) => [key, String(category.slug ?? key)]))\n return categoryRecord(id, data as StoredCategory, slugs)\n },\n matchValues: (id, data) => ({ id, slug: data['slug'] ?? null, name: data['name'] ?? null }),\n find: {\n slug: (collection, values) => collection.where('slug', 'in', values),\n name: (collection, values) => collection.where('name', 'in', values),\n },\n extra: async (firestore, ctx) => ({ categories: await readCategories(firestore, ctx) }),\n requiredToCreate: ['name'],\n newId: () => Aglyn.createResourceUid(),\n write: (id, current, changes, extra) =>\n categoryWrite(id, current as StoredCategory | null, changes, extra.categories ?? new Map()),\n // A category written earlier in the file is a parent a later row can name.\n afterWrite(id, doc, extra) {\n extra.categories?.set(id, doc as StoredCategory)\n },\n}\n\nexport const categoriesTransfer: PluginTransferResource = writable(CATEGORIES, CATEGORY_MATCH_KEYS)\n"],"names":["Aglyn","buildMatchLookup","firebaseAdmin","ORDER_LIST_QUERY","CATEGORY_MATCH_KEYS","COUPON_MATCH_KEYS","DISCOUNT_KIND_PICKLIST","DISCOUNT_KIND_SPEC","DISCOUNT_MATCH_KEYS","categoryRecord","categoryWrite","couponRecord","couponWrite","discountRecord","discountWrite","orderRecord","planWithCreateRequired","promotionCode","rowChanges","NOTHING","ROW_BUDGET_MS","countSource","firestoreOf","hostRefOf","readSourcePage","readerSeesHost","revertEntries","withoutUndefined","IN_MAX","noExtra","sourceFor","spec","firestore","ctx","collection","declaration","source","fields","sorts","order","refuseFilterWithout","options","filter","Error","readPage","cursor","fieldIds","pageSize","Math","max","min","page","extra","docs","rows","map","doc","record","id","data","Object","fromEntries","fieldId","next","count","lookup","requests","found","Map","keys","request","push","normalizer","at","values","length","slice","getAll","exists","set","query","find","get","records","lookupMap","matchValues","readableRecords","exportOnly","noun","why","matchKeys","invariants","label","check","apply","_ctx","chunk","results","row","index","outcome","reason","message","undo","revert","done","conflicts","ORDERS","path","direction","productNames","ids","Set","String","products","ordersTransfer","RowRefusal","writable","plan","input","normalize","requiredToCreate","writer","applyRecords","snapshot","decisions","revertRecords","earlier","alreadyApplied","timeLeftMs","changes","creating","verdict","newId","recordId","ref","runTransaction","tx","current","made","write","problem","createStamps","create","afterWrite","after","before","touched","result","entry","action","written","pickKeys","previous","markApplied","error","key","remove","delete","restore","DISCOUNTS","code","name","where","value","createResourceUid","_id","discountsTransfer","picklists","picklistIds","includes","standardValues","active","defaultValueId","COUPONS","FieldPath","documentId","Boolean","_row","createdAt","Timestamp","now","couponsTransfer","readCategories","limit","CATEGORIES","slugs","categories","category","slug","categoriesTransfer"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
export declare function registerCommerceTransferResources(): void;
|