@aglyn/plugins-commerce 1.0.0-beta.221 → 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 +10 -13
- 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/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/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,171 @@
|
|
|
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
|
+
*/ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
17
|
+
import { registerPluginTransferResource } from "@aglyn/aglyn/plugin-manager/plugin-transfer-resources";
|
|
18
|
+
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
19
|
+
import { PRODUCT_ALIAS_DICTIONARIES, PRODUCT_DERIVED_FIELDS, PRODUCT_LOCKED_RULES, PRODUCT_MATCH_KEYS, PRODUCT_STANDARD_FIELDS, PRODUCT_SYSTEM_FIELDS, PRODUCT_TRANSFER_GROUPS, SHOPIFY_PRODUCT_PRESET } from "./product-transfer.js";
|
|
20
|
+
import { CATEGORY_MATCH_KEYS, CATEGORY_TRANSFER_FIELDS, COUPON_MATCH_KEYS, COUPON_TRANSFER_FIELDS, DISCOUNT_MATCH_KEYS, DISCOUNT_TRANSFER_FIELDS, GIFT_CARD_MATCH_KEYS, GIFT_CARD_TRANSFER_FIELDS, ORDER_TRANSFER_FIELDS, ORDER_TRANSFER_GROUPS } from "./records-transfer.js";
|
|
21
|
+
import { COMMERCE_CATEGORIES_TRANSFER, COMMERCE_COUPONS_TRANSFER, COMMERCE_DISCOUNTS_TRANSFER, COMMERCE_GIFT_CARDS_TRANSFER, COMMERCE_ORDERS_TRANSFER, COMMERCE_PRODUCTS_TRANSFER } from "./transfer-keys.js";
|
|
22
|
+
/*
|
|
23
|
+
* THE SERVER HALVES, REGISTERED AT BOOT (AGL-3531), from the console's
|
|
24
|
+
* server declarations — the transfer routes are the console's alone. What a
|
|
25
|
+
* route reads before any record (fields, keys, dictionaries, presets, rules)
|
|
26
|
+
* is data from the pure modules; every hook that touches the store loads its
|
|
27
|
+
* module the first time a job or an export asks.
|
|
28
|
+
*/ const productsServer = ()=>import("./products.server.js");
|
|
29
|
+
const recordsServer = ()=>import("./records.server.js");
|
|
30
|
+
const giftCardsServer = ()=>import("./gift-cards.server.js");
|
|
31
|
+
/** A resource whose store-touching hooks load `pick(module)` on first use. */ function deferred(load, data, hooks = [
|
|
32
|
+
'count'
|
|
33
|
+
]) {
|
|
34
|
+
const call = (name)=>async (...args)=>{
|
|
35
|
+
const impl = await load();
|
|
36
|
+
const hook = impl[name];
|
|
37
|
+
return hook(...args);
|
|
38
|
+
};
|
|
39
|
+
return _extends({}, data, {
|
|
40
|
+
readPage: call('readPage'),
|
|
41
|
+
lookup: call('lookup'),
|
|
42
|
+
apply: call('apply'),
|
|
43
|
+
revert: call('revert')
|
|
44
|
+
}, Object.fromEntries(hooks.map((name)=>[
|
|
45
|
+
name,
|
|
46
|
+
call(name)
|
|
47
|
+
])));
|
|
48
|
+
}
|
|
49
|
+
const catalog = (input)=>()=>input;
|
|
50
|
+
export function registerCommerceTransferResources() {
|
|
51
|
+
registerPluginTransferResource(COMMERCE_PRODUCTS_TRANSFER, {
|
|
52
|
+
fields: catalog({
|
|
53
|
+
standard: PRODUCT_STANDARD_FIELDS,
|
|
54
|
+
derived: PRODUCT_DERIVED_FIELDS,
|
|
55
|
+
system: PRODUCT_SYSTEM_FIELDS,
|
|
56
|
+
groups: PRODUCT_TRANSFER_GROUPS
|
|
57
|
+
}),
|
|
58
|
+
matchKeys: PRODUCT_MATCH_KEYS,
|
|
59
|
+
aliases: PRODUCT_ALIAS_DICTIONARIES,
|
|
60
|
+
presets: [
|
|
61
|
+
SHOPIFY_PRODUCT_PRESET
|
|
62
|
+
],
|
|
63
|
+
lockedRules: ()=>PRODUCT_LOCKED_RULES,
|
|
64
|
+
invariants: [
|
|
65
|
+
{
|
|
66
|
+
id: 'product-storable',
|
|
67
|
+
label: 'A product the store can hold',
|
|
68
|
+
check: (row)=>{
|
|
69
|
+
var _ref;
|
|
70
|
+
var _row_commerce;
|
|
71
|
+
return (_ref = (_row_commerce = row.commerce) == null ? void 0 : _row_commerce.problem) != null ? _ref : null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
],
|
|
75
|
+
count: async (ctx, options)=>(await productsServer()).countProductRows(ctx, options),
|
|
76
|
+
readPage: async (ctx, cursor, fieldIds, options)=>(await productsServer()).readProductsPage(ctx, cursor, fieldIds, options),
|
|
77
|
+
lookup: async (ctx, requests)=>(await productsServer()).lookupProducts(ctx, requests),
|
|
78
|
+
picklists: async (ctx, ids)=>(await productsServer()).productPicklists(ctx, ids),
|
|
79
|
+
addPicklistValues: async (ctx, id, values)=>(await productsServer()).addProductCategories(ctx, id, values),
|
|
80
|
+
plan: async (ctx, input)=>(await productsServer()).planProducts(ctx, input),
|
|
81
|
+
apply: async (ctx, chunk, writer)=>(await productsServer()).applyProducts(ctx, chunk, writer),
|
|
82
|
+
revert: async (ctx, snapshot, decisions)=>(await productsServer()).revertProducts(ctx, snapshot, decisions)
|
|
83
|
+
}, {
|
|
84
|
+
pluginId: BUNDLE_ID
|
|
85
|
+
});
|
|
86
|
+
registerPluginTransferResource(COMMERCE_CATEGORIES_TRANSFER, deferred(async ()=>(await recordsServer()).categoriesTransfer, {
|
|
87
|
+
fields: catalog({
|
|
88
|
+
standard: CATEGORY_TRANSFER_FIELDS
|
|
89
|
+
}),
|
|
90
|
+
matchKeys: CATEGORY_MATCH_KEYS
|
|
91
|
+
}, [
|
|
92
|
+
'count',
|
|
93
|
+
'plan'
|
|
94
|
+
]), {
|
|
95
|
+
pluginId: BUNDLE_ID
|
|
96
|
+
});
|
|
97
|
+
registerPluginTransferResource(COMMERCE_ORDERS_TRANSFER, deferred(async ()=>(await recordsServer()).ordersTransfer, {
|
|
98
|
+
fields: catalog({
|
|
99
|
+
standard: ORDER_TRANSFER_FIELDS,
|
|
100
|
+
groups: ORDER_TRANSFER_GROUPS
|
|
101
|
+
}),
|
|
102
|
+
matchKeys: [
|
|
103
|
+
{
|
|
104
|
+
fieldId: 'id',
|
|
105
|
+
normalizer: 'aglynId'
|
|
106
|
+
}
|
|
107
|
+
],
|
|
108
|
+
invariants: [
|
|
109
|
+
{
|
|
110
|
+
id: 'orders-export-only',
|
|
111
|
+
label: 'Orders are exported only',
|
|
112
|
+
check: ()=>'Orders are exported, never imported: an order is the record of a sale, written by checkout, the register or a paid draft.'
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
}), {
|
|
116
|
+
pluginId: BUNDLE_ID
|
|
117
|
+
});
|
|
118
|
+
registerPluginTransferResource(COMMERCE_DISCOUNTS_TRANSFER, deferred(async ()=>(await recordsServer()).discountsTransfer, {
|
|
119
|
+
fields: catalog({
|
|
120
|
+
standard: DISCOUNT_TRANSFER_FIELDS
|
|
121
|
+
}),
|
|
122
|
+
matchKeys: DISCOUNT_MATCH_KEYS
|
|
123
|
+
}, [
|
|
124
|
+
'count',
|
|
125
|
+
'plan',
|
|
126
|
+
'picklists'
|
|
127
|
+
]), {
|
|
128
|
+
pluginId: BUNDLE_ID
|
|
129
|
+
});
|
|
130
|
+
registerPluginTransferResource(COMMERCE_COUPONS_TRANSFER, deferred(async ()=>(await recordsServer()).couponsTransfer, {
|
|
131
|
+
fields: catalog({
|
|
132
|
+
standard: COUPON_TRANSFER_FIELDS
|
|
133
|
+
}),
|
|
134
|
+
matchKeys: COUPON_MATCH_KEYS
|
|
135
|
+
}, [
|
|
136
|
+
'count',
|
|
137
|
+
'plan'
|
|
138
|
+
]), {
|
|
139
|
+
pluginId: BUNDLE_ID
|
|
140
|
+
});
|
|
141
|
+
// Imported by ISSUING each card (AGL-3551): the plan decides each card and
|
|
142
|
+
// the total, and a row it refuses is failed here with the reason. Only on
|
|
143
|
+
// a plan with gift cards (`featureFlag: "giftCards"`, imports only,
|
|
144
|
+
// AGL-3548), refused in the issue route's words.
|
|
145
|
+
registerPluginTransferResource(COMMERCE_GIFT_CARDS_TRANSFER, _extends({}, deferred(async ()=>(await giftCardsServer()).giftCardsTransfer, {
|
|
146
|
+
fields: catalog({
|
|
147
|
+
standard: GIFT_CARD_TRANSFER_FIELDS
|
|
148
|
+
}),
|
|
149
|
+
matchKeys: GIFT_CARD_MATCH_KEYS,
|
|
150
|
+
invariants: [
|
|
151
|
+
{
|
|
152
|
+
id: 'gift-card-issuable',
|
|
153
|
+
label: 'A gift card the store can issue',
|
|
154
|
+
check: (row)=>{
|
|
155
|
+
var _ref;
|
|
156
|
+
var _row_giftCard;
|
|
157
|
+
return (_ref = (_row_giftCard = row.giftCard) == null ? void 0 : _row_giftCard.problem) != null ? _ref : null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
]
|
|
161
|
+
}, [
|
|
162
|
+
'count',
|
|
163
|
+
'plan'
|
|
164
|
+
]), {
|
|
165
|
+
planGate: async (subject)=>(await import("./gift-cards-plan.js")).giftCardsPlanRefusal(subject.org)
|
|
166
|
+
}), {
|
|
167
|
+
pluginId: BUNDLE_ID
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
//# sourceMappingURL=register-transfer-resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/transfer/register-transfer-resources.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 type { TransferCatalogInput } from '@aglyn/aglyn/data-transfer'\nimport {\n registerPluginTransferResource,\n type PluginTransferResource,\n} from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport {\n PRODUCT_ALIAS_DICTIONARIES,\n PRODUCT_DERIVED_FIELDS,\n PRODUCT_LOCKED_RULES,\n PRODUCT_MATCH_KEYS,\n PRODUCT_STANDARD_FIELDS,\n PRODUCT_SYSTEM_FIELDS,\n PRODUCT_TRANSFER_GROUPS,\n SHOPIFY_PRODUCT_PRESET,\n type ProductPlannedRow,\n} from './product-transfer'\nimport {\n CATEGORY_MATCH_KEYS,\n CATEGORY_TRANSFER_FIELDS,\n COUPON_MATCH_KEYS,\n COUPON_TRANSFER_FIELDS,\n DISCOUNT_MATCH_KEYS,\n DISCOUNT_TRANSFER_FIELDS,\n GIFT_CARD_MATCH_KEYS,\n GIFT_CARD_TRANSFER_FIELDS,\n ORDER_TRANSFER_FIELDS,\n ORDER_TRANSFER_GROUPS,\n type GiftCardPlannedRow,\n} from './records-transfer'\nimport {\n COMMERCE_CATEGORIES_TRANSFER,\n COMMERCE_COUPONS_TRANSFER,\n COMMERCE_DISCOUNTS_TRANSFER,\n COMMERCE_GIFT_CARDS_TRANSFER,\n COMMERCE_ORDERS_TRANSFER,\n COMMERCE_PRODUCTS_TRANSFER,\n} from './transfer-keys'\n\n/*\n * THE SERVER HALVES, REGISTERED AT BOOT (AGL-3531), from the console's\n * server declarations — the transfer routes are the console's alone. What a\n * route reads before any record (fields, keys, dictionaries, presets, rules)\n * is data from the pure modules; every hook that touches the store loads its\n * module the first time a job or an export asks.\n */\n\nconst productsServer = () => import('./products.server')\nconst recordsServer = () => import('./records.server')\nconst giftCardsServer = () => import('./gift-cards.server')\n\n/** A resource whose store-touching hooks load `pick(module)` on first use. */\nfunction deferred(\n load: () => Promise<PluginTransferResource>,\n data: Pick<PluginTransferResource, 'fields' | 'matchKeys' | 'aliases' | 'presets' | 'lockedRules' | 'invariants'>,\n hooks: ReadonlyArray<'count' | 'picklists' | 'addPicklistValues' | 'plan'> = ['count'],\n): PluginTransferResource {\n const call =\n <K extends keyof PluginTransferResource>(name: K) =>\n async (...args: unknown[]) => {\n const impl = await load()\n const hook = impl[name] as unknown as (...rest: unknown[]) => unknown\n return hook(...args)\n }\n return {\n ...data,\n readPage: call('readPage') as PluginTransferResource['readPage'],\n lookup: call('lookup') as PluginTransferResource['lookup'],\n apply: call('apply') as PluginTransferResource['apply'],\n revert: call('revert') as PluginTransferResource['revert'],\n ...Object.fromEntries(hooks.map((name) => [name, call(name)])),\n }\n}\n\nconst catalog = (input: TransferCatalogInput) => () => input\n\nexport function registerCommerceTransferResources(): void {\n registerPluginTransferResource(\n COMMERCE_PRODUCTS_TRANSFER,\n {\n fields: catalog({\n standard: PRODUCT_STANDARD_FIELDS,\n derived: PRODUCT_DERIVED_FIELDS,\n system: PRODUCT_SYSTEM_FIELDS,\n groups: PRODUCT_TRANSFER_GROUPS,\n }),\n matchKeys: PRODUCT_MATCH_KEYS,\n aliases: PRODUCT_ALIAS_DICTIONARIES,\n presets: [SHOPIFY_PRODUCT_PRESET],\n lockedRules: () => PRODUCT_LOCKED_RULES,\n invariants: [\n {\n id: 'product-storable',\n label: 'A product the store can hold',\n check: (row) => (row as ProductPlannedRow).commerce?.problem ?? null,\n },\n ],\n count: async (ctx, options) => (await productsServer()).countProductRows(ctx, options),\n readPage: async (ctx, cursor, fieldIds, options) =>\n (await productsServer()).readProductsPage(ctx, cursor, fieldIds, options),\n lookup: async (ctx, requests) => (await productsServer()).lookupProducts(ctx, requests),\n picklists: async (ctx, ids) => (await productsServer()).productPicklists(ctx, ids),\n addPicklistValues: async (ctx, id, values) => (await productsServer()).addProductCategories(ctx, id, values),\n plan: async (ctx, input) => (await productsServer()).planProducts(ctx, input),\n apply: async (ctx, chunk, writer) =>\n (await productsServer()).applyProducts(ctx, chunk as Parameters<typeof import('./products.server').applyProducts>[1], writer),\n revert: async (ctx, snapshot, decisions) => (await productsServer()).revertProducts(ctx, snapshot, decisions),\n },\n { pluginId: BUNDLE_ID },\n )\n\n registerPluginTransferResource(\n COMMERCE_CATEGORIES_TRANSFER,\n deferred(async () => (await recordsServer()).categoriesTransfer, {\n fields: catalog({ standard: CATEGORY_TRANSFER_FIELDS }),\n matchKeys: CATEGORY_MATCH_KEYS,\n }, ['count', 'plan']),\n { pluginId: BUNDLE_ID },\n )\n\n registerPluginTransferResource(\n COMMERCE_ORDERS_TRANSFER,\n deferred(async () => (await recordsServer()).ordersTransfer, {\n fields: catalog({ standard: ORDER_TRANSFER_FIELDS, groups: ORDER_TRANSFER_GROUPS }),\n matchKeys: [{ fieldId: 'id', normalizer: 'aglynId' }],\n invariants: [\n {\n id: 'orders-export-only',\n label: 'Orders are exported only',\n check: () =>\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 { pluginId: BUNDLE_ID },\n )\n\n registerPluginTransferResource(\n COMMERCE_DISCOUNTS_TRANSFER,\n deferred(\n async () => (await recordsServer()).discountsTransfer,\n { fields: catalog({ standard: DISCOUNT_TRANSFER_FIELDS }), matchKeys: DISCOUNT_MATCH_KEYS },\n ['count', 'plan', 'picklists'],\n ),\n { pluginId: BUNDLE_ID },\n )\n\n registerPluginTransferResource(\n COMMERCE_COUPONS_TRANSFER,\n deferred(\n async () => (await recordsServer()).couponsTransfer,\n { fields: catalog({ standard: COUPON_TRANSFER_FIELDS }), matchKeys: COUPON_MATCH_KEYS },\n ['count', 'plan'],\n ),\n { pluginId: BUNDLE_ID },\n )\n\n // Imported by ISSUING each card (AGL-3551): the plan decides each card and\n // the total, and a row it refuses is failed here with the reason. Only on\n // a plan with gift cards (`featureFlag: \"giftCards\"`, imports only,\n // AGL-3548), refused in the issue route's words.\n registerPluginTransferResource(\n COMMERCE_GIFT_CARDS_TRANSFER,\n {\n ...deferred(\n async () => (await giftCardsServer()).giftCardsTransfer,\n {\n fields: catalog({ standard: GIFT_CARD_TRANSFER_FIELDS }),\n matchKeys: GIFT_CARD_MATCH_KEYS,\n invariants: [\n {\n id: 'gift-card-issuable',\n label: 'A gift card the store can issue',\n check: (row) => (row as GiftCardPlannedRow).giftCard?.problem ?? null,\n },\n ],\n },\n ['count', 'plan'],\n ),\n planGate: async (subject) => (await import('./gift-cards-plan')).giftCardsPlanRefusal(subject.org),\n },\n { pluginId: BUNDLE_ID },\n )\n}\n"],"names":["registerPluginTransferResource","BUNDLE_ID","PRODUCT_ALIAS_DICTIONARIES","PRODUCT_DERIVED_FIELDS","PRODUCT_LOCKED_RULES","PRODUCT_MATCH_KEYS","PRODUCT_STANDARD_FIELDS","PRODUCT_SYSTEM_FIELDS","PRODUCT_TRANSFER_GROUPS","SHOPIFY_PRODUCT_PRESET","CATEGORY_MATCH_KEYS","CATEGORY_TRANSFER_FIELDS","COUPON_MATCH_KEYS","COUPON_TRANSFER_FIELDS","DISCOUNT_MATCH_KEYS","DISCOUNT_TRANSFER_FIELDS","GIFT_CARD_MATCH_KEYS","GIFT_CARD_TRANSFER_FIELDS","ORDER_TRANSFER_FIELDS","ORDER_TRANSFER_GROUPS","COMMERCE_CATEGORIES_TRANSFER","COMMERCE_COUPONS_TRANSFER","COMMERCE_DISCOUNTS_TRANSFER","COMMERCE_GIFT_CARDS_TRANSFER","COMMERCE_ORDERS_TRANSFER","COMMERCE_PRODUCTS_TRANSFER","productsServer","recordsServer","giftCardsServer","deferred","load","data","hooks","call","name","args","impl","hook","readPage","lookup","apply","revert","Object","fromEntries","map","catalog","input","registerCommerceTransferResources","fields","standard","derived","system","groups","matchKeys","aliases","presets","lockedRules","invariants","id","label","check","row","commerce","problem","count","ctx","options","countProductRows","cursor","fieldIds","readProductsPage","requests","lookupProducts","picklists","ids","productPicklists","addPicklistValues","values","addProductCategories","plan","planProducts","chunk","writer","applyProducts","snapshot","decisions","revertProducts","pluginId","categoriesTransfer","ordersTransfer","fieldId","normalizer","discountsTransfer","couponsTransfer","giftCardsTransfer","giftCard","planGate","subject","giftCardsPlanRefusal","org"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAGD,SACEA,8BAA8B,QAEzB,wDAAuD;AAC9D,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SACEC,0BAA0B,EAC1BC,sBAAsB,EACtBC,oBAAoB,EACpBC,kBAAkB,EAClBC,uBAAuB,EACvBC,qBAAqB,EACrBC,uBAAuB,EACvBC,sBAAsB,QAEjB,wBAAoB;AAC3B,SACEC,mBAAmB,EACnBC,wBAAwB,EACxBC,iBAAiB,EACjBC,sBAAsB,EACtBC,mBAAmB,EACnBC,wBAAwB,EACxBC,oBAAoB,EACpBC,yBAAyB,EACzBC,qBAAqB,EACrBC,qBAAqB,QAEhB,wBAAoB;AAC3B,SACEC,4BAA4B,EAC5BC,yBAAyB,EACzBC,2BAA2B,EAC3BC,4BAA4B,EAC5BC,wBAAwB,EACxBC,0BAA0B,QACrB,qBAAiB;AAExB;;;;;;CAMC,GAED,MAAMC,iBAAiB,IAAM,MAAM,CAAC;AACpC,MAAMC,gBAAgB,IAAM,MAAM,CAAC;AACnC,MAAMC,kBAAkB,IAAM,MAAM,CAAC;AAErC,4EAA4E,GAC5E,SAASC,SACPC,IAA2C,EAC3CC,IAAiH,EACjHC,QAA6E;IAAC;CAAQ;IAEtF,MAAMC,OACJ,CAAyCC,OACzC,OAAO,GAAGC;YACR,MAAMC,OAAO,MAAMN;YACnB,MAAMO,OAAOD,IAAI,CAACF,KAAK;YACvB,OAAOG,QAAQF;QACjB;IACF,OAAO,aACFJ;QACHO,UAAUL,KAAK;QACfM,QAAQN,KAAK;QACbO,OAAOP,KAAK;QACZQ,QAAQR,KAAK;OACVS,OAAOC,WAAW,CAACX,MAAMY,GAAG,CAAC,CAACV,OAAS;YAACA;YAAMD,KAAKC;SAAM;AAEhE;AAEA,MAAMW,UAAU,CAACC,QAAgC,IAAMA;AAEvD,OAAO,SAASC;IACd/C,+BACEyB,4BACA;QACEuB,QAAQH,QAAQ;YACdI,UAAU3C;YACV4C,SAAS/C;YACTgD,QAAQ5C;YACR6C,QAAQ5C;QACV;QACA6C,WAAWhD;QACXiD,SAASpD;QACTqD,SAAS;YAAC9C;SAAuB;QACjC+C,aAAa,IAAMpD;QACnBqD,YAAY;YACV;gBACEC,IAAI;gBACJC,OAAO;gBACPC,OAAO,CAACC;;wBAAQ;oCAAA,gBAAA,AAACA,IAA0BC,QAAQ,qBAAnC,cAAqCC,OAAO,mBAAI;;YAClE;SACD;QACDC,OAAO,OAAOC,KAAKC,UAAY,AAAC,CAAA,MAAMxC,gBAAe,EAAGyC,gBAAgB,CAACF,KAAKC;QAC9E5B,UAAU,OAAO2B,KAAKG,QAAQC,UAAUH,UACtC,AAAC,CAAA,MAAMxC,gBAAe,EAAG4C,gBAAgB,CAACL,KAAKG,QAAQC,UAAUH;QACnE3B,QAAQ,OAAO0B,KAAKM,WAAa,AAAC,CAAA,MAAM7C,gBAAe,EAAG8C,cAAc,CAACP,KAAKM;QAC9EE,WAAW,OAAOR,KAAKS,MAAQ,AAAC,CAAA,MAAMhD,gBAAe,EAAGiD,gBAAgB,CAACV,KAAKS;QAC9EE,mBAAmB,OAAOX,KAAKP,IAAImB,SAAW,AAAC,CAAA,MAAMnD,gBAAe,EAAGoD,oBAAoB,CAACb,KAAKP,IAAImB;QACrGE,MAAM,OAAOd,KAAKnB,QAAU,AAAC,CAAA,MAAMpB,gBAAe,EAAGsD,YAAY,CAACf,KAAKnB;QACvEN,OAAO,OAAOyB,KAAKgB,OAAOC,SACxB,AAAC,CAAA,MAAMxD,gBAAe,EAAGyD,aAAa,CAAClB,KAAKgB,OAA0EC;QACxHzC,QAAQ,OAAOwB,KAAKmB,UAAUC,YAAc,AAAC,CAAA,MAAM3D,gBAAe,EAAG4D,cAAc,CAACrB,KAAKmB,UAAUC;IACrG,GACA;QAAEE,UAAUtF;IAAU;IAGxBD,+BACEoB,8BACAS,SAAS,UAAY,AAAC,CAAA,MAAMF,eAAc,EAAG6D,kBAAkB,EAAE;QAC/DxC,QAAQH,QAAQ;YAAEI,UAAUtC;QAAyB;QACrD0C,WAAW3C;IACb,GAAG;QAAC;QAAS;KAAO,GACpB;QAAE6E,UAAUtF;IAAU;IAGxBD,+BACEwB,0BACAK,SAAS,UAAY,AAAC,CAAA,MAAMF,eAAc,EAAG8D,cAAc,EAAE;QAC3DzC,QAAQH,QAAQ;YAAEI,UAAU/B;YAAuBkC,QAAQjC;QAAsB;QACjFkC,WAAW;YAAC;gBAAEqC,SAAS;gBAAMC,YAAY;YAAU;SAAE;QACrDlC,YAAY;YACV;gBACEC,IAAI;gBACJC,OAAO;gBACPC,OAAO,IACL;YACJ;SACD;IACH,IACA;QAAE2B,UAAUtF;IAAU;IAGxBD,+BACEsB,6BACAO,SACE,UAAY,AAAC,CAAA,MAAMF,eAAc,EAAGiE,iBAAiB,EACrD;QAAE5C,QAAQH,QAAQ;YAAEI,UAAUlC;QAAyB;QAAIsC,WAAWvC;IAAoB,GAC1F;QAAC;QAAS;QAAQ;KAAY,GAEhC;QAAEyE,UAAUtF;IAAU;IAGxBD,+BACEqB,2BACAQ,SACE,UAAY,AAAC,CAAA,MAAMF,eAAc,EAAGkE,eAAe,EACnD;QAAE7C,QAAQH,QAAQ;YAAEI,UAAUpC;QAAuB;QAAIwC,WAAWzC;IAAkB,GACtF;QAAC;QAAS;KAAO,GAEnB;QAAE2E,UAAUtF;IAAU;IAGxB,2EAA2E;IAC3E,0EAA0E;IAC1E,oEAAoE;IACpE,iDAAiD;IACjDD,+BACEuB,8BACA,aACKM,SACD,UAAY,AAAC,CAAA,MAAMD,iBAAgB,EAAGkE,iBAAiB,EACvD;QACE9C,QAAQH,QAAQ;YAAEI,UAAUhC;QAA0B;QACtDoC,WAAWrC;QACXyC,YAAY;YACV;gBACEC,IAAI;gBACJC,OAAO;gBACPC,OAAO,CAACC;;wBAAQ;oCAAA,gBAAA,AAACA,IAA2BkC,QAAQ,qBAApC,cAAsChC,OAAO,mBAAI;;YACnE;SACD;IACH,GACA;QAAC;QAAS;KAAO;QAEnBiC,UAAU,OAAOC,UAAY,AAAC,CAAA,MAAM,MAAM,CAAC,uBAAmB,EAAGC,oBAAoB,CAACD,QAAQE,GAAG;QAEnG;QAAEZ,UAAUtF;IAAU;AAE1B"}
|
|
@@ -0,0 +1,23 @@
|
|
|
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
|
+
/**
|
|
18
|
+
* The client halves of the commerce transfer resources (AGL-3531): how the
|
|
19
|
+
* wizard and the dialog name each, the products wizard's own After import
|
|
20
|
+
* step, where the `productImport` zone sets what happens to new products,
|
|
21
|
+
* and the gift card import's Confirm step (AGL-3551).
|
|
22
|
+
*/
|
|
23
|
+
export declare function registerCommerceTransferUi(): void;
|
|
@@ -0,0 +1,78 @@
|
|
|
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
|
+
*/ import { registerPluginTransferResourceUi } from "@aglyn/aglyn/plugin-manager/plugin-transfer-resources";
|
|
17
|
+
import { createElement, lazy, Suspense } from "react";
|
|
18
|
+
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
19
|
+
import { COMMERCE_CATEGORIES_TRANSFER, COMMERCE_COUPONS_TRANSFER, COMMERCE_DISCOUNTS_TRANSFER, COMMERCE_GIFT_CARDS_TRANSFER, COMMERCE_ORDERS_TRANSFER, COMMERCE_PRODUCTS_TRANSFER, GIFT_CARD_CONFIRM_STEP_ID } from "./transfer-keys.js";
|
|
20
|
+
/** The After import step loads with the wizard, not with the products page. */ const ProductImportOptionsStep = lazy(()=>import("./product-import-step.component.js"));
|
|
21
|
+
function AfterImportStep(props) {
|
|
22
|
+
return createElement(Suspense, {
|
|
23
|
+
fallback: null
|
|
24
|
+
}, createElement(ProductImportOptionsStep, props));
|
|
25
|
+
}
|
|
26
|
+
/** The gift card import's Confirm step loads with the wizard, not with the Gift cards card. */ const GiftCardConfirmStepBody = lazy(()=>import("./gift-card-confirm-step.component.js"));
|
|
27
|
+
function GiftCardConfirmStep(props) {
|
|
28
|
+
return createElement(Suspense, {
|
|
29
|
+
fallback: null
|
|
30
|
+
}, createElement(GiftCardConfirmStepBody, props));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The client halves of the commerce transfer resources (AGL-3531): how the
|
|
34
|
+
* wizard and the dialog name each, the products wizard's own After import
|
|
35
|
+
* step, where the `productImport` zone sets what happens to new products,
|
|
36
|
+
* and the gift card import's Confirm step (AGL-3551).
|
|
37
|
+
*/ export function registerCommerceTransferUi() {
|
|
38
|
+
const owner = {
|
|
39
|
+
pluginId: BUNDLE_ID
|
|
40
|
+
};
|
|
41
|
+
registerPluginTransferResourceUi(COMMERCE_PRODUCTS_TRANSFER, {
|
|
42
|
+
label: 'Products',
|
|
43
|
+
extraSteps: [
|
|
44
|
+
{
|
|
45
|
+
id: 'afterImport',
|
|
46
|
+
label: 'After import',
|
|
47
|
+
after: 'conflicts',
|
|
48
|
+
component: AfterImportStep
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}, owner);
|
|
52
|
+
registerPluginTransferResourceUi(COMMERCE_CATEGORIES_TRANSFER, {
|
|
53
|
+
label: 'Product categories'
|
|
54
|
+
}, owner);
|
|
55
|
+
registerPluginTransferResourceUi(COMMERCE_ORDERS_TRANSFER, {
|
|
56
|
+
label: 'Orders'
|
|
57
|
+
}, owner);
|
|
58
|
+
registerPluginTransferResourceUi(COMMERCE_DISCOUNTS_TRANSFER, {
|
|
59
|
+
label: 'Discounts'
|
|
60
|
+
}, owner);
|
|
61
|
+
registerPluginTransferResourceUi(COMMERCE_COUPONS_TRANSFER, {
|
|
62
|
+
label: 'Coupons'
|
|
63
|
+
}, owner);
|
|
64
|
+
registerPluginTransferResourceUi(COMMERCE_GIFT_CARDS_TRANSFER, {
|
|
65
|
+
label: 'Gift cards',
|
|
66
|
+
// Every card and its value, and the total typed back (AGL-3551).
|
|
67
|
+
extraSteps: [
|
|
68
|
+
{
|
|
69
|
+
id: GIFT_CARD_CONFIRM_STEP_ID,
|
|
70
|
+
label: 'Confirm the cards',
|
|
71
|
+
after: 'conflicts',
|
|
72
|
+
component: GiftCardConfirmStep
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}, owner);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=register-transfer-ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/transfer/register-transfer-ui.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 {\n registerPluginTransferResourceUi,\n type TransferWizardStepProps,\n} from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources'\nimport { createElement, lazy, Suspense } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport {\n COMMERCE_CATEGORIES_TRANSFER,\n COMMERCE_COUPONS_TRANSFER,\n COMMERCE_DISCOUNTS_TRANSFER,\n COMMERCE_GIFT_CARDS_TRANSFER,\n COMMERCE_ORDERS_TRANSFER,\n COMMERCE_PRODUCTS_TRANSFER,\n GIFT_CARD_CONFIRM_STEP_ID,\n} from './transfer-keys'\n\n/** The After import step loads with the wizard, not with the products page. */\nconst ProductImportOptionsStep = lazy(() => import('./product-import-step.component'))\n\nfunction AfterImportStep(props: TransferWizardStepProps) {\n return createElement(Suspense, { fallback: null }, createElement(ProductImportOptionsStep, props))\n}\n\n/** The gift card import's Confirm step loads with the wizard, not with the Gift cards card. */\nconst GiftCardConfirmStepBody = lazy(() => import('./gift-card-confirm-step.component'))\n\nfunction GiftCardConfirmStep(props: TransferWizardStepProps) {\n return createElement(Suspense, { fallback: null }, createElement(GiftCardConfirmStepBody, props))\n}\n\n/**\n * The client halves of the commerce transfer resources (AGL-3531): how the\n * wizard and the dialog name each, the products wizard's own After import\n * step, where the `productImport` zone sets what happens to new products,\n * and the gift card import's Confirm step (AGL-3551).\n */\nexport function registerCommerceTransferUi(): void {\n const owner = { pluginId: BUNDLE_ID }\n registerPluginTransferResourceUi(\n COMMERCE_PRODUCTS_TRANSFER,\n {\n label: 'Products',\n extraSteps: [\n { id: 'afterImport', label: 'After import', after: 'conflicts', component: AfterImportStep },\n ],\n },\n owner,\n )\n registerPluginTransferResourceUi(COMMERCE_CATEGORIES_TRANSFER, { label: 'Product categories' }, owner)\n registerPluginTransferResourceUi(COMMERCE_ORDERS_TRANSFER, { label: 'Orders' }, owner)\n registerPluginTransferResourceUi(COMMERCE_DISCOUNTS_TRANSFER, { label: 'Discounts' }, owner)\n registerPluginTransferResourceUi(COMMERCE_COUPONS_TRANSFER, { label: 'Coupons' }, owner)\n registerPluginTransferResourceUi(\n COMMERCE_GIFT_CARDS_TRANSFER,\n {\n label: 'Gift cards',\n // Every card and its value, and the total typed back (AGL-3551).\n extraSteps: [\n { id: GIFT_CARD_CONFIRM_STEP_ID, label: 'Confirm the cards', after: 'conflicts', component: GiftCardConfirmStep },\n ],\n },\n owner,\n )\n}\n"],"names":["registerPluginTransferResourceUi","createElement","lazy","Suspense","BUNDLE_ID","COMMERCE_CATEGORIES_TRANSFER","COMMERCE_COUPONS_TRANSFER","COMMERCE_DISCOUNTS_TRANSFER","COMMERCE_GIFT_CARDS_TRANSFER","COMMERCE_ORDERS_TRANSFER","COMMERCE_PRODUCTS_TRANSFER","GIFT_CARD_CONFIRM_STEP_ID","ProductImportOptionsStep","AfterImportStep","props","fallback","GiftCardConfirmStepBody","GiftCardConfirmStep","registerCommerceTransferUi","owner","pluginId","label","extraSteps","id","after","component"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,gCAAgC,QAE3B,wDAAuD;AAC9D,SAASC,aAAa,EAAEC,IAAI,EAAEC,QAAQ,QAAQ,QAAO;AACrD,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SACEC,4BAA4B,EAC5BC,yBAAyB,EACzBC,2BAA2B,EAC3BC,4BAA4B,EAC5BC,wBAAwB,EACxBC,0BAA0B,EAC1BC,yBAAyB,QACpB,qBAAiB;AAExB,6EAA6E,GAC7E,MAAMC,2BAA2BV,KAAK,IAAM,MAAM,CAAC;AAEnD,SAASW,gBAAgBC,KAA8B;IACrD,OAAOb,cAAcE,UAAU;QAAEY,UAAU;IAAK,GAAGd,cAAcW,0BAA0BE;AAC7F;AAEA,6FAA6F,GAC7F,MAAME,0BAA0Bd,KAAK,IAAM,MAAM,CAAC;AAElD,SAASe,oBAAoBH,KAA8B;IACzD,OAAOb,cAAcE,UAAU;QAAEY,UAAU;IAAK,GAAGd,cAAce,yBAAyBF;AAC5F;AAEA;;;;;CAKC,GACD,OAAO,SAASI;IACd,MAAMC,QAAQ;QAAEC,UAAUhB;IAAU;IACpCJ,iCACEU,4BACA;QACEW,OAAO;QACPC,YAAY;YACV;gBAAEC,IAAI;gBAAeF,OAAO;gBAAgBG,OAAO;gBAAaC,WAAWZ;YAAgB;SAC5F;IACH,GACAM;IAEFnB,iCAAiCK,8BAA8B;QAAEgB,OAAO;IAAqB,GAAGF;IAChGnB,iCAAiCS,0BAA0B;QAAEY,OAAO;IAAS,GAAGF;IAChFnB,iCAAiCO,6BAA6B;QAAEc,OAAO;IAAY,GAAGF;IACtFnB,iCAAiCM,2BAA2B;QAAEe,OAAO;IAAU,GAAGF;IAClFnB,iCACEQ,8BACA;QACEa,OAAO;QACP,iEAAiE;QACjEC,YAAY;YACV;gBAAEC,IAAIZ;gBAA2BU,OAAO;gBAAqBG,OAAO;gBAAaC,WAAWR;YAAoB;SACjH;IACH,GACAE;AAEJ"}
|
|
@@ -0,0 +1,76 @@
|
|
|
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
|
+
import { type TransferUndoEntry, type TransferUndoSnapshot } from '@aglyn/aglyn/data-transfer';
|
|
18
|
+
import type { TransferReadOptions, TransferReadPage, TransferResourceContext, TransferRevertDecisions, TransferRevertResult } from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources';
|
|
19
|
+
import type { ListQueryDeclaration } from '@aglyn/shared-ui-jsx/const/list-query-plan';
|
|
20
|
+
export type Firestore = FirebaseFirestore.Firestore;
|
|
21
|
+
type Snapshot = FirebaseFirestore.QueryDocumentSnapshot | FirebaseFirestore.DocumentSnapshot;
|
|
22
|
+
export declare const firestoreOf: () => Firestore;
|
|
23
|
+
/** The site a host resource's job names; every commerce resource is a site's. */
|
|
24
|
+
export declare function hostRefOf(firestore: Firestore, ctx: TransferResourceContext): FirebaseFirestore.DocumentReference;
|
|
25
|
+
/**
|
|
26
|
+
* Whether the reader reaches the site. A collaborator scoped to some sites
|
|
27
|
+
* reads only through their tokens (`scopeTokens`): a site's commerce records
|
|
28
|
+
* carry no `visibleTo` of their own, so the site's token is the whole test.
|
|
29
|
+
*/
|
|
30
|
+
export declare function readerSeesHost(ctx: TransferResourceContext, options: TransferReadOptions | undefined): boolean;
|
|
31
|
+
/** Plain data for Firestore: `undefined` dropped at every depth. */
|
|
32
|
+
export declare function withoutUndefined<T>(value: T): T;
|
|
33
|
+
/** A list's query, as one read of a page. */
|
|
34
|
+
export interface CommerceListSource {
|
|
35
|
+
collection: FirebaseFirestore.CollectionReference;
|
|
36
|
+
declaration: ListQueryDeclaration;
|
|
37
|
+
/** Predicates every read applies — the list's scope (a product never deleted). */
|
|
38
|
+
base?: Array<{
|
|
39
|
+
path: string;
|
|
40
|
+
op: FirebaseFirestore.WhereFilterOp;
|
|
41
|
+
value: unknown;
|
|
42
|
+
}>;
|
|
43
|
+
/** The order an export of everything reads in; the document id when absent. */
|
|
44
|
+
order?: {
|
|
45
|
+
path: string;
|
|
46
|
+
direction: 'asc' | 'desc';
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* One page of a list's documents for an export: the selection by id, the
|
|
51
|
+
* list's filter, or everything, from `cursor`. The cursor is the last row's
|
|
52
|
+
* order value and id, so the next page starts after it whatever the order.
|
|
53
|
+
*/
|
|
54
|
+
export declare function readSourcePage(firestore: Firestore, source: CommerceListSource, cursor: string | null, options: TransferReadOptions | undefined, pageSize: number): Promise<{
|
|
55
|
+
docs: Snapshot[];
|
|
56
|
+
next: string | null;
|
|
57
|
+
}>;
|
|
58
|
+
/** Every document an export's options read, page by page, handed to `each` — for a count. */
|
|
59
|
+
export declare function eachSourceDoc(firestore: Firestore, source: CommerceListSource, options: TransferReadOptions | undefined, each: (doc: Snapshot) => void): Promise<void>;
|
|
60
|
+
/** How many documents an export's options read, by the store's own count where it can. */
|
|
61
|
+
export declare function countSource(firestore: Firestore, source: CommerceListSource, options: TransferReadOptions | undefined, live?: (doc: Snapshot) => boolean): Promise<number>;
|
|
62
|
+
/** An empty page, for a reader who does not reach the site. */
|
|
63
|
+
export declare const NOTHING: TransferReadPage;
|
|
64
|
+
/**
|
|
65
|
+
* Reverses one chunk's writes, newest first: each entry planned against the
|
|
66
|
+
* record as it is now (`planTransferUndo`); a record edited since is a
|
|
67
|
+
* conflict, carried out only when the person's decision says `revert`.
|
|
68
|
+
*/
|
|
69
|
+
export declare function revertEntries(snapshot: TransferUndoSnapshot, decisions: TransferRevertDecisions | undefined, hooks: {
|
|
70
|
+
current(entry: TransferUndoEntry): Promise<Readonly<Record<string, unknown>> | null>;
|
|
71
|
+
restore(entry: TransferUndoEntry, values: Record<string, unknown>): Promise<void>;
|
|
72
|
+
remove(entry: TransferUndoEntry): Promise<void>;
|
|
73
|
+
}): Promise<TransferRevertResult>;
|
|
74
|
+
/** Milliseconds a row's write is given; past this the chunk stops at a row boundary. */
|
|
75
|
+
export declare const ROW_BUDGET_MS = 1500;
|
|
76
|
+
export {};
|
|
@@ -0,0 +1,165 @@
|
|
|
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
|
+
*/ import { hostScopeToken } from "@aglyn/aglyn/app-utils/scope-tokens";
|
|
17
|
+
import { planTransferUndo } from "@aglyn/aglyn/data-transfer";
|
|
18
|
+
import { firebaseAdmin } from "@aglyn/tenant-data-admin";
|
|
19
|
+
import { readCommerceListFilter } from "./list-filter.js";
|
|
20
|
+
export const firestoreOf = ()=>firebaseAdmin.app().firestore();
|
|
21
|
+
/** The site a host resource's job names; every commerce resource is a site's. */ export function hostRefOf(firestore, ctx) {
|
|
22
|
+
if (!ctx.hostId) throw new Error(`${ctx.resource} is a site's records; name the site.`);
|
|
23
|
+
return firestore.collection('hosts').doc(ctx.hostId);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Whether the reader reaches the site. A collaborator scoped to some sites
|
|
27
|
+
* reads only through their tokens (`scopeTokens`): a site's commerce records
|
|
28
|
+
* carry no `visibleTo` of their own, so the site's token is the whole test.
|
|
29
|
+
*/ export function readerSeesHost(ctx, options) {
|
|
30
|
+
if (!(options == null ? void 0 : options.scopeTokens)) return true;
|
|
31
|
+
return Boolean(ctx.hostId) && options.scopeTokens.includes(hostScopeToken(ctx.hostId));
|
|
32
|
+
}
|
|
33
|
+
/** Plain data for Firestore: `undefined` dropped at every depth. */ export function withoutUndefined(value) {
|
|
34
|
+
if (Array.isArray(value)) return value.map((item)=>withoutUndefined(item));
|
|
35
|
+
if (value && typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype) {
|
|
36
|
+
const out = {};
|
|
37
|
+
for (const [key, item] of Object.entries(value)){
|
|
38
|
+
if (item !== undefined) out[key] = withoutUndefined(item);
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
const idPath = ()=>firebaseAdmin.firestore.FieldPath.documentId();
|
|
45
|
+
const fieldOf = (path)=>path === '__name__' ? idPath() : path;
|
|
46
|
+
/** The query an export's options read: the list's filter, or everything in the list's scope. */ function sourceQuery(source, options) {
|
|
47
|
+
var _source_base, _source_order;
|
|
48
|
+
let query = source.collection;
|
|
49
|
+
const basePaths = ((_source_base = source.base) != null ? _source_base : []).map((entry)=>entry.path);
|
|
50
|
+
let order = (_source_order = source.order) != null ? _source_order : {
|
|
51
|
+
path: '__name__',
|
|
52
|
+
direction: 'asc'
|
|
53
|
+
};
|
|
54
|
+
if (options == null ? void 0 : options.filter) {
|
|
55
|
+
var _source_base1;
|
|
56
|
+
const filter = readCommerceListFilter(options.filter, source.declaration, basePaths);
|
|
57
|
+
const filtered = new Set(filter.filters.map((entry)=>entry.path));
|
|
58
|
+
for (const entry of (_source_base1 = source.base) != null ? _source_base1 : []){
|
|
59
|
+
if (!filtered.has(entry.path)) query = query.where(entry.path, entry.op, entry.value);
|
|
60
|
+
}
|
|
61
|
+
for (const entry of filter.filters)query = query.where(fieldOf(entry.path), entry.op, entry.value);
|
|
62
|
+
order = filter.orderBy;
|
|
63
|
+
} else {
|
|
64
|
+
var _source_base2;
|
|
65
|
+
for (const entry of (_source_base2 = source.base) != null ? _source_base2 : [])query = query.where(entry.path, entry.op, entry.value);
|
|
66
|
+
}
|
|
67
|
+
query = order.path === '__name__' ? query.orderBy(idPath(), order.direction) : query.orderBy(order.path, order.direction).orderBy(idPath(), order.direction);
|
|
68
|
+
return {
|
|
69
|
+
query,
|
|
70
|
+
order
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* One page of a list's documents for an export: the selection by id, the
|
|
75
|
+
* list's filter, or everything, from `cursor`. The cursor is the last row's
|
|
76
|
+
* order value and id, so the next page starts after it whatever the order.
|
|
77
|
+
*/ export async function readSourcePage(firestore, source, cursor, options, pageSize) {
|
|
78
|
+
var _last_get;
|
|
79
|
+
if (options == null ? void 0 : options.ids) {
|
|
80
|
+
const offset = cursor ? Number(cursor) : 0;
|
|
81
|
+
const ids = options.ids.slice(offset, offset + pageSize);
|
|
82
|
+
if (!ids.length) return {
|
|
83
|
+
docs: [],
|
|
84
|
+
next: null
|
|
85
|
+
};
|
|
86
|
+
const refs = ids.map((id)=>source.collection.doc(id));
|
|
87
|
+
const snapshots = await firestore.getAll(...refs);
|
|
88
|
+
const end = offset + ids.length;
|
|
89
|
+
return {
|
|
90
|
+
docs: snapshots.filter((entry)=>entry.exists),
|
|
91
|
+
next: end < options.ids.length ? String(end) : null
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const { query, order } = sourceQuery(source, options);
|
|
95
|
+
const after = cursor ? JSON.parse(cursor) : null;
|
|
96
|
+
const page = await (after ? query.startAfter(...after) : query).limit(pageSize).get();
|
|
97
|
+
const last = page.docs[page.docs.length - 1];
|
|
98
|
+
const next = last && page.docs.length === pageSize ? JSON.stringify(order.path === '__name__' ? [
|
|
99
|
+
last.id
|
|
100
|
+
] : [
|
|
101
|
+
(_last_get = last.get(order.path)) != null ? _last_get : null,
|
|
102
|
+
last.id
|
|
103
|
+
]) : null;
|
|
104
|
+
return {
|
|
105
|
+
docs: page.docs,
|
|
106
|
+
next
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/** Every document an export's options read, page by page, handed to `each` — for a count. */ export async function eachSourceDoc(firestore, source, options, each) {
|
|
110
|
+
let cursor = null;
|
|
111
|
+
do {
|
|
112
|
+
const page = await readSourcePage(firestore, source, cursor, options, 500);
|
|
113
|
+
for (const doc of page.docs)each(doc);
|
|
114
|
+
cursor = page.next;
|
|
115
|
+
}while (cursor)
|
|
116
|
+
}
|
|
117
|
+
/** How many documents an export's options read, by the store's own count where it can. */ export async function countSource(firestore, source, options, live = ()=>true) {
|
|
118
|
+
if (options == null ? void 0 : options.ids) {
|
|
119
|
+
let total = 0;
|
|
120
|
+
for(let offset = 0; offset < options.ids.length; offset += 500){
|
|
121
|
+
const refs = options.ids.slice(offset, offset + 500).map((id)=>source.collection.doc(id));
|
|
122
|
+
total += (await firestore.getAll(...refs)).filter((entry)=>entry.exists && live(entry)).length;
|
|
123
|
+
}
|
|
124
|
+
return total;
|
|
125
|
+
}
|
|
126
|
+
const { query } = sourceQuery(source, options);
|
|
127
|
+
return Number((await query.count().get()).data().count) || 0;
|
|
128
|
+
}
|
|
129
|
+
/** An empty page, for a reader who does not reach the site. */ export const NOTHING = {
|
|
130
|
+
rows: [],
|
|
131
|
+
next: null
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Reverses one chunk's writes, newest first: each entry planned against the
|
|
135
|
+
* record as it is now (`planTransferUndo`); a record edited since is a
|
|
136
|
+
* conflict, carried out only when the person's decision says `revert`.
|
|
137
|
+
*/ export async function revertEntries(snapshot, decisions, hooks) {
|
|
138
|
+
const done = [];
|
|
139
|
+
const conflicts = [];
|
|
140
|
+
for (const entry of [
|
|
141
|
+
...snapshot.entries
|
|
142
|
+
].reverse()){
|
|
143
|
+
const step = planTransferUndo(entry, await hooks.current(entry));
|
|
144
|
+
if (step.action === 'conflict') {
|
|
145
|
+
if ((decisions == null ? void 0 : decisions[entry.recordId]) !== 'revert') {
|
|
146
|
+
conflicts.push(step);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (entry.action === 'created') await hooks.remove(entry);
|
|
150
|
+
else await hooks.restore(entry, step.values);
|
|
151
|
+
done.push(step);
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (step.action === 'delete') await hooks.remove(entry);
|
|
155
|
+
if (step.action === 'restore') await hooks.restore(entry, step.values);
|
|
156
|
+
done.push(step);
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
done,
|
|
160
|
+
conflicts
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/** Milliseconds a row's write is given; past this the chunk stops at a row boundary. */ export const ROW_BUDGET_MS = 1500;
|
|
164
|
+
|
|
165
|
+
//# sourceMappingURL=server-common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/transfer/server-common.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 { hostScopeToken } from '@aglyn/aglyn/app-utils/scope-tokens'\nimport {\n planTransferUndo,\n type TransferUndoEntry,\n type TransferUndoSnapshot,\n type TransferUndoStep,\n} from '@aglyn/aglyn/data-transfer'\nimport type {\n TransferReadOptions,\n TransferReadPage,\n TransferResourceContext,\n TransferRevertDecisions,\n TransferRevertResult,\n} from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources'\nimport type { ListQueryDeclaration } from '@aglyn/shared-ui-jsx/const/list-query-plan'\nimport { firebaseAdmin } from '@aglyn/tenant-data-admin'\nimport { readCommerceListFilter } from './list-filter'\n\n/*\n * WHAT EVERY COMMERCE RESOURCE'S SERVER HALF SHARES (AGL-3531): the site a\n * job names, whether the reader reaches it, a list's query read page by page\n * from a cursor, and the undo loop.\n */\n\nexport type Firestore = FirebaseFirestore.Firestore\ntype Query = FirebaseFirestore.Query\ntype Snapshot = FirebaseFirestore.QueryDocumentSnapshot | FirebaseFirestore.DocumentSnapshot\n\nexport const firestoreOf = (): Firestore => firebaseAdmin.app().firestore()\n\n/** The site a host resource's job names; every commerce resource is a site's. */\nexport function hostRefOf(firestore: Firestore, ctx: TransferResourceContext): FirebaseFirestore.DocumentReference {\n if (!ctx.hostId) throw new Error(`${ctx.resource} is a site's records; name the site.`)\n return firestore.collection('hosts').doc(ctx.hostId)\n}\n\n/**\n * Whether the reader reaches the site. A collaborator scoped to some sites\n * reads only through their tokens (`scopeTokens`): a site's commerce records\n * carry no `visibleTo` of their own, so the site's token is the whole test.\n */\nexport function readerSeesHost(ctx: TransferResourceContext, options: TransferReadOptions | undefined): boolean {\n if (!options?.scopeTokens) return true\n return Boolean(ctx.hostId) && options.scopeTokens.includes(hostScopeToken(ctx.hostId as string))\n}\n\n/** Plain data for Firestore: `undefined` dropped at every depth. */\nexport function withoutUndefined<T>(value: T): T {\n if (Array.isArray(value)) return value.map((item) => withoutUndefined(item)) as T\n if (value && typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype) {\n const out: Record<string, unknown> = {}\n for (const [key, item] of Object.entries(value as Record<string, unknown>)) {\n if (item !== undefined) out[key] = withoutUndefined(item)\n }\n return out as T\n }\n return value\n}\n\n/** A list's query, as one read of a page. */\nexport interface CommerceListSource {\n collection: FirebaseFirestore.CollectionReference\n declaration: ListQueryDeclaration\n /** Predicates every read applies — the list's scope (a product never deleted). */\n base?: Array<{ path: string; op: FirebaseFirestore.WhereFilterOp; value: unknown }>\n /** The order an export of everything reads in; the document id when absent. */\n order?: { path: string; direction: 'asc' | 'desc' }\n}\n\nconst idPath = () => firebaseAdmin.firestore.FieldPath.documentId()\n\nconst fieldOf = (path: string) => (path === '__name__' ? idPath() : path)\n\n/** The query an export's options read: the list's filter, or everything in the list's scope. */\nfunction sourceQuery(\n source: CommerceListSource,\n options: TransferReadOptions | undefined,\n): { query: Query; order: { path: string; direction: 'asc' | 'desc' } } {\n let query: Query = source.collection\n const basePaths = (source.base ?? []).map((entry) => entry.path)\n let order = source.order ?? { path: '__name__', direction: 'asc' as const }\n if (options?.filter) {\n const filter = readCommerceListFilter(options.filter, source.declaration, basePaths)\n const filtered = new Set(filter.filters.map((entry) => entry.path))\n for (const entry of source.base ?? []) {\n if (!filtered.has(entry.path)) query = query.where(entry.path, entry.op, entry.value)\n }\n for (const entry of filter.filters) query = query.where(fieldOf(entry.path), entry.op, entry.value)\n order = filter.orderBy\n } else {\n for (const entry of source.base ?? []) query = query.where(entry.path, entry.op, entry.value)\n }\n query =\n order.path === '__name__'\n ? query.orderBy(idPath(), order.direction)\n : query.orderBy(order.path, order.direction).orderBy(idPath(), order.direction)\n return { query, order }\n}\n\n/**\n * One page of a list's documents for an export: the selection by id, the\n * list's filter, or everything, from `cursor`. The cursor is the last row's\n * order value and id, so the next page starts after it whatever the order.\n */\nexport async function readSourcePage(\n firestore: Firestore,\n source: CommerceListSource,\n cursor: string | null,\n options: TransferReadOptions | undefined,\n pageSize: number,\n): Promise<{ docs: Snapshot[]; next: string | null }> {\n if (options?.ids) {\n const offset = cursor ? Number(cursor) : 0\n const ids = options.ids.slice(offset, offset + pageSize)\n if (!ids.length) return { docs: [], next: null }\n const refs = ids.map((id) => source.collection.doc(id))\n const snapshots = await firestore.getAll(...refs)\n const end = offset + ids.length\n return { docs: snapshots.filter((entry) => entry.exists), next: end < options.ids.length ? String(end) : null }\n }\n const { query, order } = sourceQuery(source, options)\n const after = cursor ? (JSON.parse(cursor) as unknown[]) : null\n const page = await (after ? query.startAfter(...after) : query).limit(pageSize).get()\n const last = page.docs[page.docs.length - 1]\n const next =\n last && page.docs.length === pageSize\n ? JSON.stringify(order.path === '__name__' ? [last.id] : [last.get(order.path) ?? null, last.id])\n : null\n return { docs: page.docs, next }\n}\n\n/** Every document an export's options read, page by page, handed to `each` — for a count. */\nexport async function eachSourceDoc(\n firestore: Firestore,\n source: CommerceListSource,\n options: TransferReadOptions | undefined,\n each: (doc: Snapshot) => void,\n): Promise<void> {\n let cursor: string | null = null\n do {\n const page = await readSourcePage(firestore, source, cursor, options, 500)\n for (const doc of page.docs) each(doc)\n cursor = page.next\n } while (cursor)\n}\n\n/** How many documents an export's options read, by the store's own count where it can. */\nexport async function countSource(\n firestore: Firestore,\n source: CommerceListSource,\n options: TransferReadOptions | undefined,\n live: (doc: Snapshot) => boolean = () => true,\n): Promise<number> {\n if (options?.ids) {\n let total = 0\n for (let offset = 0; offset < options.ids.length; offset += 500) {\n const refs = options.ids.slice(offset, offset + 500).map((id) => source.collection.doc(id))\n total += (await firestore.getAll(...refs)).filter((entry) => entry.exists && live(entry)).length\n }\n return total\n }\n const { query } = sourceQuery(source, options)\n return Number((await query.count().get()).data().count) || 0\n}\n\n/** An empty page, for a reader who does not reach the site. */\nexport const NOTHING: TransferReadPage = { rows: [], next: null }\n\n/**\n * Reverses one chunk's writes, newest first: each entry planned against the\n * record as it is now (`planTransferUndo`); a record edited since is a\n * conflict, carried out only when the person's decision says `revert`.\n */\nexport async function revertEntries(\n snapshot: TransferUndoSnapshot,\n decisions: TransferRevertDecisions | undefined,\n hooks: {\n current(entry: TransferUndoEntry): Promise<Readonly<Record<string, unknown>> | null>\n restore(entry: TransferUndoEntry, values: Record<string, unknown>): Promise<void>\n remove(entry: TransferUndoEntry): Promise<void>\n },\n): Promise<TransferRevertResult> {\n const done: TransferUndoStep[] = []\n const conflicts: TransferUndoStep[] = []\n for (const entry of [...snapshot.entries].reverse()) {\n const step = planTransferUndo(entry, await hooks.current(entry))\n if (step.action === 'conflict') {\n if (decisions?.[entry.recordId] !== 'revert') {\n conflicts.push(step)\n continue\n }\n if (entry.action === 'created') await hooks.remove(entry)\n else await hooks.restore(entry, step.values)\n done.push(step)\n continue\n }\n if (step.action === 'delete') await hooks.remove(entry)\n if (step.action === 'restore') await hooks.restore(entry, step.values)\n done.push(step)\n }\n return { done, conflicts }\n}\n\n/** Milliseconds a row's write is given; past this the chunk stops at a row boundary. */\nexport const ROW_BUDGET_MS = 1_500\n"],"names":["hostScopeToken","planTransferUndo","firebaseAdmin","readCommerceListFilter","firestoreOf","app","firestore","hostRefOf","ctx","hostId","Error","resource","collection","doc","readerSeesHost","options","scopeTokens","Boolean","includes","withoutUndefined","value","Array","isArray","map","item","Object","getPrototypeOf","prototype","out","key","entries","undefined","idPath","FieldPath","documentId","fieldOf","path","sourceQuery","source","query","basePaths","base","entry","order","direction","filter","declaration","filtered","Set","filters","has","where","op","orderBy","readSourcePage","cursor","pageSize","last","ids","offset","Number","slice","length","docs","next","refs","id","snapshots","getAll","end","exists","String","after","JSON","parse","page","startAfter","limit","get","stringify","eachSourceDoc","each","countSource","live","total","count","data","NOTHING","rows","revertEntries","snapshot","decisions","hooks","done","conflicts","reverse","step","current","action","recordId","push","remove","restore","values","ROW_BUDGET_MS"],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
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 interface TransferHeaderActionsProps {
|
|
18
|
+
/** The commerce resource key (`transfer-keys.ts`). */
|
|
19
|
+
resource: string;
|
|
20
|
+
hostId: string;
|
|
21
|
+
/** What the buttons name, when the card holds more than this resource ("categories"). */
|
|
22
|
+
noun?: string;
|
|
23
|
+
/** Called when the person leaves the import wizard from its results. */
|
|
24
|
+
onImported?(): void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A commerce card's Import and Export, for its card header (AGL-3531): the
|
|
28
|
+
* console's import wizard and export dialog on the card's resource, through
|
|
29
|
+
* the core launcher. Each shows only when the launcher's `can` says the
|
|
30
|
+
* person may (AGL-3554) — their access on the site, the resource's
|
|
31
|
+
* `importRoles` (gift cards: a site's admins) and the workspace's plan —
|
|
32
|
+
* and Import only for a resource a file may write. Off the console shell
|
|
33
|
+
* there is no launcher, and nothing renders.
|
|
34
|
+
*/
|
|
35
|
+
export declare function TransferHeaderActions(props: TransferHeaderActionsProps): import("react").JSX.Element;
|
|
36
|
+
export declare namespace TransferHeaderActions {
|
|
37
|
+
var displayName: string;
|
|
38
|
+
}
|
|
39
|
+
export default TransferHeaderActions;
|