@unchainedshop/plugins 4.6.1 → 4.6.2
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/lib/delivery/post/adapter.d.ts +2 -0
- package/lib/delivery/post/adapter.js +22 -0
- package/lib/delivery/post/index.d.ts +4 -0
- package/lib/delivery/post/index.js +10 -0
- package/lib/delivery/send-message/adapter.d.ts +2 -0
- package/lib/delivery/send-message/adapter.js +39 -0
- package/lib/delivery/send-message/index.d.ts +4 -0
- package/lib/delivery/send-message/index.js +10 -0
- package/lib/delivery/stores/adapter.d.ts +2 -0
- package/lib/delivery/stores/adapter.js +42 -0
- package/lib/delivery/stores/index.d.ts +4 -0
- package/lib/delivery/stores/index.js +10 -0
- package/lib/enrollments/licensed/adapter.d.ts +6 -0
- package/lib/enrollments/licensed/adapter.js +51 -0
- package/lib/enrollments/licensed/index.d.ts +4 -0
- package/lib/enrollments/licensed/index.js +10 -0
- package/lib/files/gridfs/api.d.ts +7 -0
- package/lib/files/gridfs/api.js +163 -0
- package/lib/files/minio/adapter.d.ts +4 -0
- package/lib/files/minio/adapter.js +160 -0
- package/lib/files/minio/api.d.ts +2 -0
- package/lib/files/minio/api.js +41 -0
- package/lib/files/temp-upload/api.d.ts +6 -0
- package/lib/files/temp-upload/api.js +49 -0
- package/lib/files/temp-upload/index.d.ts +3 -0
- package/lib/files/temp-upload/index.js +15 -0
- package/lib/filters/local-search/adapter.d.ts +2 -0
- package/lib/filters/local-search/adapter.js +56 -0
- package/lib/filters/local-search/index.d.ts +4 -0
- package/lib/filters/local-search/index.js +16 -0
- package/lib/filters/strict-equal/adapter.d.ts +2 -0
- package/lib/filters/strict-equal/adapter.js +23 -0
- package/lib/filters/strict-equal/index.d.ts +4 -0
- package/lib/filters/strict-equal/index.js +10 -0
- package/lib/payment/apple-iap/api.d.ts +2 -0
- package/lib/payment/apple-iap/api.js +119 -0
- package/lib/payment/cryptopay/adapter.d.ts +2 -0
- package/lib/payment/cryptopay/adapter.js +157 -0
- package/lib/payment/cryptopay/api.d.ts +2 -0
- package/lib/payment/cryptopay/api.js +23 -0
- package/lib/payment/datatrans-v2/adapter.d.ts +2 -0
- package/lib/payment/datatrans-v2/adapter.js +406 -0
- package/lib/payment/datatrans-v2/api.d.ts +2 -0
- package/lib/payment/datatrans-v2/api.js +108 -0
- package/lib/payment/invoice/adapter.d.ts +2 -0
- package/lib/payment/invoice/adapter.js +26 -0
- package/lib/payment/invoice/index.d.ts +4 -0
- package/lib/payment/invoice/index.js +10 -0
- package/lib/payment/invoice-prepaid/adapter.d.ts +2 -0
- package/lib/payment/invoice-prepaid/adapter.js +29 -0
- package/lib/payment/invoice-prepaid/index.d.ts +4 -0
- package/lib/payment/invoice-prepaid/index.js +10 -0
- package/lib/payment/payrexx/adapter.d.ts +2 -0
- package/lib/payment/payrexx/adapter.js +161 -0
- package/lib/payment/payrexx/api.d.ts +2 -0
- package/lib/payment/payrexx/api.js +97 -0
- package/lib/payment/postfinance-checkout/adapter.d.ts +2 -0
- package/lib/payment/postfinance-checkout/adapter.js +189 -0
- package/lib/payment/postfinance-checkout/webhook.d.ts +2 -0
- package/lib/payment/postfinance-checkout/webhook.js +48 -0
- package/lib/payment/saferpay/webhook.d.ts +2 -0
- package/lib/payment/saferpay/webhook.js +64 -0
- package/lib/payment/stripe/adapter.d.ts +2 -0
- package/lib/payment/stripe/adapter.js +121 -0
- package/lib/payment/stripe/api.d.ts +6 -0
- package/lib/payment/stripe/api.js +165 -0
- package/lib/pricing/delivery-swiss-tax/adapter.d.ts +3 -0
- package/lib/pricing/delivery-swiss-tax/adapter.js +62 -0
- package/lib/pricing/delivery-swiss-tax/index.d.ts +4 -0
- package/lib/pricing/delivery-swiss-tax/index.js +10 -0
- package/lib/pricing/discount-100-off/adapter.d.ts +3 -0
- package/lib/pricing/discount-100-off/adapter.js +30 -0
- package/lib/pricing/discount-100-off/index.d.ts +4 -0
- package/lib/pricing/discount-100-off/index.js +10 -0
- package/lib/pricing/discount-half-price-manual/adapter.d.ts +3 -0
- package/lib/pricing/discount-half-price-manual/adapter.js +30 -0
- package/lib/pricing/discount-half-price-manual/index.d.ts +4 -0
- package/lib/pricing/discount-half-price-manual/index.js +10 -0
- package/lib/pricing/free-delivery/adapter.d.ts +3 -0
- package/lib/pricing/free-delivery/adapter.js +27 -0
- package/lib/pricing/free-delivery/index.d.ts +4 -0
- package/lib/pricing/free-delivery/index.js +10 -0
- package/lib/pricing/free-payment/adapter.d.ts +3 -0
- package/lib/pricing/free-payment/adapter.js +27 -0
- package/lib/pricing/free-payment/index.d.ts +4 -0
- package/lib/pricing/free-payment/index.js +10 -0
- package/lib/pricing/order-delivery/adapter.d.ts +3 -0
- package/lib/pricing/order-delivery/adapter.js +33 -0
- package/lib/pricing/order-delivery/index.d.ts +4 -0
- package/lib/pricing/order-delivery/index.js +10 -0
- package/lib/pricing/order-discount/adapter.d.ts +3 -0
- package/lib/pricing/order-discount/adapter.js +74 -0
- package/lib/pricing/order-discount/index.d.ts +4 -0
- package/lib/pricing/order-discount/index.js +10 -0
- package/lib/pricing/order-items/adapter.d.ts +3 -0
- package/lib/pricing/order-items/adapter.js +43 -0
- package/lib/pricing/order-items/index.d.ts +4 -0
- package/lib/pricing/order-items/index.js +10 -0
- package/lib/pricing/order-payment/adapter.d.ts +3 -0
- package/lib/pricing/order-payment/adapter.js +33 -0
- package/lib/pricing/order-payment/index.d.ts +4 -0
- package/lib/pricing/order-payment/index.js +10 -0
- package/lib/pricing/product-catalog-price/adapter.d.ts +3 -0
- package/lib/pricing/product-catalog-price/adapter.js +60 -0
- package/lib/pricing/product-catalog-price/index.d.ts +4 -0
- package/lib/pricing/product-catalog-price/index.js +10 -0
- package/lib/pricing/product-discount/adapter.d.ts +3 -0
- package/lib/pricing/product-discount/adapter.js +69 -0
- package/lib/pricing/product-discount/index.d.ts +4 -0
- package/lib/pricing/product-discount/index.js +10 -0
- package/lib/pricing/product-price-rateconversion/adapter.d.ts +3 -0
- package/lib/pricing/product-price-rateconversion/adapter.js +53 -0
- package/lib/pricing/product-price-rateconversion/index.d.ts +4 -0
- package/lib/pricing/product-price-rateconversion/index.js +10 -0
- package/lib/pricing/product-swiss-tax/adapter.d.ts +3 -0
- package/lib/pricing/product-swiss-tax/adapter.js +76 -0
- package/lib/pricing/product-swiss-tax/index.d.ts +4 -0
- package/lib/pricing/product-swiss-tax/index.js +10 -0
- package/lib/quotations/manual/adapter.d.ts +2 -0
- package/lib/quotations/manual/adapter.js +19 -0
- package/lib/quotations/manual/index.d.ts +4 -0
- package/lib/quotations/manual/index.js +10 -0
- package/lib/warehousing/erc-metadata/api.d.ts +12 -0
- package/lib/warehousing/erc-metadata/api.js +43 -0
- package/lib/warehousing/erc-metadata/index.d.ts +3 -0
- package/lib/warehousing/erc-metadata/index.js +15 -0
- package/lib/warehousing/eth-minter/adapter.d.ts +2 -0
- package/lib/warehousing/eth-minter/adapter.js +119 -0
- package/lib/warehousing/eth-minter/index.d.ts +4 -0
- package/lib/warehousing/eth-minter/index.js +10 -0
- package/lib/warehousing/store/adapter.d.ts +2 -0
- package/lib/warehousing/store/adapter.js +33 -0
- package/lib/warehousing/store/index.d.ts +4 -0
- package/lib/warehousing/store/index.js +10 -0
- package/lib/worker/budgetsms/adapter.d.ts +22 -0
- package/lib/worker/budgetsms/adapter.js +169 -0
- package/lib/worker/budgetsms/index.d.ts +4 -0
- package/lib/worker/budgetsms/index.js +10 -0
- package/lib/worker/bulk-export/adapter.d.ts +3 -0
- package/lib/worker/bulk-export/adapter.js +64 -0
- package/lib/worker/bulk-export/index.d.ts +4 -0
- package/lib/worker/bulk-export/index.js +10 -0
- package/lib/worker/bulk-import/adapter.d.ts +3 -0
- package/lib/worker/bulk-import/adapter.js +65 -0
- package/lib/worker/bulk-import/api.d.ts +7 -0
- package/lib/worker/bulk-import/api.js +53 -0
- package/lib/worker/bulk-import/index.d.ts +4 -0
- package/lib/worker/bulk-import/index.js +18 -0
- package/lib/worker/bulkgate/adapter.d.ts +12 -0
- package/lib/worker/bulkgate/adapter.js +91 -0
- package/lib/worker/bulkgate/index.d.ts +4 -0
- package/lib/worker/bulkgate/index.js +10 -0
- package/lib/worker/email/adapter.d.ts +9 -0
- package/lib/worker/email/adapter.js +150 -0
- package/lib/worker/email/index.d.ts +4 -0
- package/lib/worker/email/index.js +10 -0
- package/lib/worker/enrollment-order-generator/adapter.d.ts +4 -0
- package/lib/worker/enrollment-order-generator/adapter.js +77 -0
- package/lib/worker/enrollment-order-generator/index.d.ts +4 -0
- package/lib/worker/enrollment-order-generator/index.js +13 -0
- package/lib/worker/error-notifications/adapter.d.ts +10 -0
- package/lib/worker/error-notifications/adapter.js +62 -0
- package/lib/worker/error-notifications/index.d.ts +4 -0
- package/lib/worker/error-notifications/index.js +13 -0
- package/lib/worker/export-token/adapter.d.ts +4 -0
- package/lib/worker/export-token/adapter.js +25 -0
- package/lib/worker/export-token/index.d.ts +4 -0
- package/lib/worker/export-token/index.js +13 -0
- package/lib/worker/external/adapter.d.ts +3 -0
- package/lib/worker/external/adapter.js +13 -0
- package/lib/worker/external/index.d.ts +4 -0
- package/lib/worker/external/index.js +10 -0
- package/lib/worker/heartbeat/adapter.d.ts +8 -0
- package/lib/worker/heartbeat/adapter.js +26 -0
- package/lib/worker/heartbeat/index.d.ts +4 -0
- package/lib/worker/heartbeat/index.js +10 -0
- package/lib/worker/http-request/adapter.d.ts +8 -0
- package/lib/worker/http-request/adapter.js +55 -0
- package/lib/worker/http-request/index.d.ts +4 -0
- package/lib/worker/http-request/index.js +10 -0
- package/lib/worker/message/adapter.d.ts +11 -0
- package/lib/worker/message/adapter.js +42 -0
- package/lib/worker/message/index.d.ts +4 -0
- package/lib/worker/message/index.js +10 -0
- package/lib/worker/push-notification/adapter.d.ts +9 -0
- package/lib/worker/push-notification/adapter.js +87 -0
- package/lib/worker/push-notification/index.d.ts +4 -0
- package/lib/worker/push-notification/index.js +10 -0
- package/lib/worker/twilio/adapter.d.ts +8 -0
- package/lib/worker/twilio/adapter.js +59 -0
- package/lib/worker/twilio/index.d.ts +4 -0
- package/lib/worker/twilio/index.js +10 -0
- package/lib/worker/update-coinbase-rates/adapter.d.ts +4 -0
- package/lib/worker/update-coinbase-rates/adapter.js +61 -0
- package/lib/worker/update-coinbase-rates/index.d.ts +4 -0
- package/lib/worker/update-coinbase-rates/index.js +13 -0
- package/lib/worker/update-ecb-rates/adapter.d.ts +4 -0
- package/lib/worker/update-ecb-rates/adapter.js +94 -0
- package/lib/worker/update-ecb-rates/index.d.ts +4 -0
- package/lib/worker/update-ecb-rates/index.js +13 -0
- package/lib/worker/update-token-ownership/adapter.d.ts +5 -0
- package/lib/worker/update-token-ownership/adapter.js +58 -0
- package/lib/worker/update-token-ownership/index.d.ts +4 -0
- package/lib/worker/update-token-ownership/index.js +13 -0
- package/lib/worker/zombie-killer/adapter.d.ts +13 -0
- package/lib/worker/zombie-killer/adapter.js +90 -0
- package/lib/worker/zombie-killer/index.d.ts +4 -0
- package/lib/worker/zombie-killer/index.js +10 -0
- package/package.json +1 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createLogger } from '@unchainedshop/logger';
|
|
2
|
+
import { ProductContractStandard } from '@unchainedshop/core-products';
|
|
3
|
+
import { systemLocale } from '@unchainedshop/utils';
|
|
4
|
+
const logger = createLogger('unchained:erc-metadata');
|
|
5
|
+
export async function ercMetadataHandler(request, context) {
|
|
6
|
+
try {
|
|
7
|
+
const { ROOT_URL = 'http://localhost:4010' } = process.env;
|
|
8
|
+
const { services, modules, locale, loaders, params } = context;
|
|
9
|
+
const url = new URL(request.url, ROOT_URL);
|
|
10
|
+
if (!url.pathname.toLowerCase().endsWith('.json')) {
|
|
11
|
+
throw new Error('Invalid ERC Metadata URI');
|
|
12
|
+
}
|
|
13
|
+
const { productId, localeOrTokenFilename, tokenFileName } = params;
|
|
14
|
+
const product = loaders
|
|
15
|
+
? await loaders.productLoader.load({ productId })
|
|
16
|
+
: await modules.products.findProduct({ productId });
|
|
17
|
+
const tokenSelector = {
|
|
18
|
+
contractAddress: product?.tokenization?.contractAddress,
|
|
19
|
+
};
|
|
20
|
+
if (product?.tokenization?.contractStandard !== ProductContractStandard.ERC721) {
|
|
21
|
+
tokenSelector.tokenSerialNumber = (tokenFileName || localeOrTokenFilename)
|
|
22
|
+
.toLowerCase()
|
|
23
|
+
.replace('.json', '');
|
|
24
|
+
}
|
|
25
|
+
const [token] = await modules.warehousing.findTokens(tokenSelector);
|
|
26
|
+
const resolvedLocale = tokenFileName
|
|
27
|
+
? new Intl.Locale(localeOrTokenFilename)
|
|
28
|
+
: locale || systemLocale;
|
|
29
|
+
const ercMetadata = await services.warehousing.ercMetadata({
|
|
30
|
+
product,
|
|
31
|
+
token,
|
|
32
|
+
locale: resolvedLocale,
|
|
33
|
+
});
|
|
34
|
+
if (!ercMetadata) {
|
|
35
|
+
return new Response(null, { status: 404 });
|
|
36
|
+
}
|
|
37
|
+
return Response.json(ercMetadata, { status: 200 });
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
logger.error(e);
|
|
41
|
+
return Response.json({ name: e.name, code: e.code, message: e.message }, { status: 503 });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ercMetadataHandler } from "./api.js";
|
|
2
|
+
const { ERC_METADATA_API_PATH = '/erc-metadata' } = process.env;
|
|
3
|
+
export const ERCMetadataPlugin = {
|
|
4
|
+
key: 'shop.unchained.warehousing.erc-metadata',
|
|
5
|
+
label: 'ERC Metadata Plugin',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
routes: [
|
|
8
|
+
{
|
|
9
|
+
path: `${ERC_METADATA_API_PATH}/:productId/:localeOrTokenFilename{/:tokenFileName}`,
|
|
10
|
+
method: 'GET',
|
|
11
|
+
handler: ercMetadataHandler,
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
};
|
|
15
|
+
export default ERCMetadataPlugin;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { WarehousingError, WarehousingAdapter, } from '@unchainedshop/core';
|
|
2
|
+
import { WarehousingProviderType } from '@unchainedshop/core-warehousing';
|
|
3
|
+
import { ProductContractStandard, ProductType } from '@unchainedshop/core-products';
|
|
4
|
+
import { systemLocale } from '@unchainedshop/utils';
|
|
5
|
+
import { generateDbObjectId } from '@unchainedshop/mongodb';
|
|
6
|
+
import { getFileAdapter } from '@unchainedshop/core';
|
|
7
|
+
import { createLogger } from '@unchainedshop/logger';
|
|
8
|
+
const logger = createLogger('unchained:eth-minter');
|
|
9
|
+
export const ETHMinter = {
|
|
10
|
+
...WarehousingAdapter,
|
|
11
|
+
key: 'shop.unchained.warehousing.infinite-minter',
|
|
12
|
+
version: '1.0',
|
|
13
|
+
label: 'Infinite Minter',
|
|
14
|
+
orderIndex: 0,
|
|
15
|
+
initialConfiguration: [{ key: 'chainId', value: '0' }],
|
|
16
|
+
typeSupported: (type) => {
|
|
17
|
+
return type === WarehousingProviderType.VIRTUAL;
|
|
18
|
+
},
|
|
19
|
+
actions: (configuration, context) => {
|
|
20
|
+
const { MINTER_TOKEN_OFFSET = '0', ROOT_URL = 'http://localhost:4010' } = process.env;
|
|
21
|
+
const { product, orderPosition, token, modules, locale } = context;
|
|
22
|
+
const { contractAddress, contractStandard, tokenId, supply, ercMetadataProperties } = product?.tokenization || {};
|
|
23
|
+
const getTokensCreated = async () => {
|
|
24
|
+
const existingTokens = await modules.warehousing.findTokens(contractStandard === ProductContractStandard.ERC721
|
|
25
|
+
? { contractAddress: contractStandard }
|
|
26
|
+
: {
|
|
27
|
+
contractAddress: contractStandard,
|
|
28
|
+
tokenSerialNumber: tokenId,
|
|
29
|
+
});
|
|
30
|
+
const tokensCreated = existingTokens.reduce((acc, curToken) => {
|
|
31
|
+
return acc + curToken.quantity;
|
|
32
|
+
}, 0);
|
|
33
|
+
return tokensCreated;
|
|
34
|
+
};
|
|
35
|
+
return {
|
|
36
|
+
...WarehousingAdapter.actions(configuration, context),
|
|
37
|
+
isActive() {
|
|
38
|
+
return product?.type === ProductType.TOKENIZED_PRODUCT;
|
|
39
|
+
},
|
|
40
|
+
configurationError() {
|
|
41
|
+
if (contractStandard === 'ERC1155' && !tokenId) {
|
|
42
|
+
logger.error(`Token ID is required for ERC1155 contract standard (productId: ${product._id})`);
|
|
43
|
+
return WarehousingError.INCOMPLETE_CONFIGURATION;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
},
|
|
47
|
+
stock: async () => {
|
|
48
|
+
const tokensCreated = await getTokensCreated();
|
|
49
|
+
return supply ? supply - tokensCreated : 0;
|
|
50
|
+
},
|
|
51
|
+
tokenize: async () => {
|
|
52
|
+
const chainId = configuration.find(({ key }) => key === 'chainId')?.value || undefined;
|
|
53
|
+
const meta = { contractStandard };
|
|
54
|
+
const tokensCreated = await getTokensCreated();
|
|
55
|
+
if (!orderPosition) {
|
|
56
|
+
throw new Error('Order position not found in context');
|
|
57
|
+
}
|
|
58
|
+
if (contractStandard === 'ERC721') {
|
|
59
|
+
const items = new Array(orderPosition.quantity).fill(null).map((_, i) => ({
|
|
60
|
+
_id: generateDbObjectId(),
|
|
61
|
+
tokenSerialNumber: Number(parseInt(MINTER_TOKEN_OFFSET, 10) + tokensCreated + (i + 1)).toString(),
|
|
62
|
+
contractAddress,
|
|
63
|
+
quantity: 1,
|
|
64
|
+
chainId,
|
|
65
|
+
meta,
|
|
66
|
+
}));
|
|
67
|
+
return items;
|
|
68
|
+
}
|
|
69
|
+
return [
|
|
70
|
+
{
|
|
71
|
+
_id: generateDbObjectId(),
|
|
72
|
+
tokenSerialNumber: tokenId,
|
|
73
|
+
contractAddress,
|
|
74
|
+
quantity: orderPosition.quantity,
|
|
75
|
+
chainId,
|
|
76
|
+
meta,
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
},
|
|
80
|
+
tokenMetadata: async (tokenSerialNumber) => {
|
|
81
|
+
if (!product) {
|
|
82
|
+
throw new Error('Product not found in context');
|
|
83
|
+
}
|
|
84
|
+
const allLanguages = await modules.languages.findLanguages({
|
|
85
|
+
includeInactive: false,
|
|
86
|
+
});
|
|
87
|
+
const [firstMedia] = await modules.products.media.findProductMedias({
|
|
88
|
+
productId: product._id,
|
|
89
|
+
limit: 1,
|
|
90
|
+
});
|
|
91
|
+
const file = firstMedia && (await modules.files.findFile({ fileId: firstMedia.mediaId }));
|
|
92
|
+
const fileAdapter = file && getFileAdapter();
|
|
93
|
+
const signedUrl = await fileAdapter?.createDownloadURL(file);
|
|
94
|
+
const url = signedUrl && (await modules.files.normalizeUrl(signedUrl, {}));
|
|
95
|
+
const text = await modules.products.texts.findLocalizedText({
|
|
96
|
+
productId: product._id,
|
|
97
|
+
locale: locale || systemLocale,
|
|
98
|
+
});
|
|
99
|
+
const name = `${text.title} #${tokenSerialNumber}`;
|
|
100
|
+
const isDefaultLanguageActive = locale ? locale.language === systemLocale.language : true;
|
|
101
|
+
const localization = isDefaultLanguageActive
|
|
102
|
+
? {
|
|
103
|
+
uri: `${ROOT_URL}/erc-metadata/${product._id}/${locale}/${tokenId}.json`,
|
|
104
|
+
default: systemLocale.language,
|
|
105
|
+
locales: allLanguages.map((lang) => lang.isoCode),
|
|
106
|
+
}
|
|
107
|
+
: undefined;
|
|
108
|
+
return {
|
|
109
|
+
name,
|
|
110
|
+
description: text.description,
|
|
111
|
+
image: url,
|
|
112
|
+
properties: ercMetadataProperties,
|
|
113
|
+
localization,
|
|
114
|
+
...(token?.meta || {}),
|
|
115
|
+
};
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
},
|
|
119
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {} from '@unchainedshop/core';
|
|
2
|
+
import { ETHMinter } from "./adapter.js";
|
|
3
|
+
export const ETHMinterPlugin = {
|
|
4
|
+
key: 'shop.unchained.warehousing.infinite-minter',
|
|
5
|
+
label: 'ETH Infinite Minter Warehousing Plugin',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
adapters: [ETHMinter],
|
|
8
|
+
};
|
|
9
|
+
export default ETHMinterPlugin;
|
|
10
|
+
export { ETHMinter } from "./adapter.js";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { WarehousingAdapter } from '@unchainedshop/core';
|
|
2
|
+
import { WarehousingProviderType } from '@unchainedshop/core-warehousing';
|
|
3
|
+
export const Store = {
|
|
4
|
+
...WarehousingAdapter,
|
|
5
|
+
key: 'shop.unchained.warehousing.store',
|
|
6
|
+
label: 'Store',
|
|
7
|
+
version: '1.0.0',
|
|
8
|
+
orderIndex: 0,
|
|
9
|
+
initialConfiguration: [{ key: 'name', value: 'Flagship Store' }],
|
|
10
|
+
typeSupported: (type) => {
|
|
11
|
+
return type === WarehousingProviderType.PHYSICAL;
|
|
12
|
+
},
|
|
13
|
+
actions: (configuration, context) => {
|
|
14
|
+
return {
|
|
15
|
+
...WarehousingAdapter.actions(configuration, context),
|
|
16
|
+
isActive() {
|
|
17
|
+
return true;
|
|
18
|
+
},
|
|
19
|
+
configurationError() {
|
|
20
|
+
return null;
|
|
21
|
+
},
|
|
22
|
+
stock: async () => {
|
|
23
|
+
return 99999;
|
|
24
|
+
},
|
|
25
|
+
productionTime: async () => {
|
|
26
|
+
return 0;
|
|
27
|
+
},
|
|
28
|
+
commissioningTime: async () => {
|
|
29
|
+
return 0;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {} from '@unchainedshop/core';
|
|
2
|
+
import { Store } from "./adapter.js";
|
|
3
|
+
export const StorePlugin = {
|
|
4
|
+
key: 'shop.unchained.warehousing.store',
|
|
5
|
+
label: 'Store Warehousing Plugin',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
adapters: [Store],
|
|
8
|
+
};
|
|
9
|
+
export default StorePlugin;
|
|
10
|
+
export { Store } from "./adapter.js";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type IWorkerAdapter } from '@unchainedshop/core';
|
|
2
|
+
export declare const BudgetSMSWorker: IWorkerAdapter<{
|
|
3
|
+
from?: string;
|
|
4
|
+
to: string;
|
|
5
|
+
text?: string;
|
|
6
|
+
test?: boolean;
|
|
7
|
+
customid?: string;
|
|
8
|
+
price?: boolean;
|
|
9
|
+
mccmnc?: boolean;
|
|
10
|
+
credit?: boolean;
|
|
11
|
+
[key: string]: any;
|
|
12
|
+
}, any>;
|
|
13
|
+
export declare function checkBudgetSmsCredentials(): Promise<{
|
|
14
|
+
success: boolean;
|
|
15
|
+
credit: number;
|
|
16
|
+
error?: undefined;
|
|
17
|
+
} | {
|
|
18
|
+
error: any;
|
|
19
|
+
success?: undefined;
|
|
20
|
+
credit?: undefined;
|
|
21
|
+
}>;
|
|
22
|
+
export default BudgetSMSWorker;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { WorkerAdapter } from '@unchainedshop/core';
|
|
2
|
+
const { BUDGETSMS_USERNAME, BUDGETSMS_USERID, BUDGETSMS_HANDLE } = process.env;
|
|
3
|
+
export const BudgetSMSWorker = {
|
|
4
|
+
...WorkerAdapter,
|
|
5
|
+
key: 'shop.unchained.worker-plugin.budgetsms',
|
|
6
|
+
label: 'Send Messages through BudgetSMS',
|
|
7
|
+
version: '1.0.0',
|
|
8
|
+
type: 'BUDGETSMS',
|
|
9
|
+
doWork: async ({ from, to, text, test = false, customid, price = false, mccmnc = false, credit = false, ...params }) => {
|
|
10
|
+
try {
|
|
11
|
+
if (!BUDGETSMS_USERNAME || !BUDGETSMS_USERID || !BUDGETSMS_HANDLE) {
|
|
12
|
+
throw new Error('Missing BudgetSMS credentials. Please set BUDGETSMS_USERNAME, BUDGETSMS_USERID, and BUDGETSMS_HANDLE');
|
|
13
|
+
}
|
|
14
|
+
const username = BUDGETSMS_USERNAME.trim();
|
|
15
|
+
const userid = BUDGETSMS_USERID.trim();
|
|
16
|
+
const handle = BUDGETSMS_HANDLE.trim();
|
|
17
|
+
if (!/^\d+$/.test(userid)) {
|
|
18
|
+
throw new Error('BUDGETSMS_USERID must be numeric only. Found: ' + userid);
|
|
19
|
+
}
|
|
20
|
+
const url = test ? 'https://api.budgetsms.net/testsms/' : 'https://api.budgetsms.net/sendsms/';
|
|
21
|
+
const formattedTo = to.replace(/^\+|^00/, '').replace(/[\s-]/g, '');
|
|
22
|
+
const queryParams = new URLSearchParams({
|
|
23
|
+
username: username,
|
|
24
|
+
userid: userid,
|
|
25
|
+
handle: handle,
|
|
26
|
+
msg: text || '',
|
|
27
|
+
from: from || '',
|
|
28
|
+
to: formattedTo,
|
|
29
|
+
...(customid && { customid }),
|
|
30
|
+
...(!test && price && { price: '1' }),
|
|
31
|
+
...(!test && mccmnc && { mccmnc: '1' }),
|
|
32
|
+
...(!test && credit && { credit: '1' }),
|
|
33
|
+
...params,
|
|
34
|
+
});
|
|
35
|
+
const fullUrl = `${url}?${queryParams.toString()}`;
|
|
36
|
+
const response = await fetch(fullUrl, {
|
|
37
|
+
method: 'GET',
|
|
38
|
+
headers: {
|
|
39
|
+
Accept: 'text/plain',
|
|
40
|
+
'User-Agent': 'Unchained/BudgetSMS-Plugin',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
const responseText = await response.text().then((text) => text.trim());
|
|
44
|
+
if (responseText.startsWith('OK')) {
|
|
45
|
+
const parts = responseText.split(' ');
|
|
46
|
+
const result = {
|
|
47
|
+
sms_id: parts[1] || null,
|
|
48
|
+
status: test ? 'test_successful' : 'sent',
|
|
49
|
+
test_mode: test,
|
|
50
|
+
};
|
|
51
|
+
if (test) {
|
|
52
|
+
result.message = 'Test SMS validated successfully (no credit deducted)';
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
let index = 2;
|
|
56
|
+
if (price && parts[index] && parts[index + 1]) {
|
|
57
|
+
result.price = parseFloat(parts[index]);
|
|
58
|
+
result.parts = parseInt(parts[index + 1]);
|
|
59
|
+
index += 2;
|
|
60
|
+
}
|
|
61
|
+
if (mccmnc && parts[index]) {
|
|
62
|
+
result.mccmnc = parts[index];
|
|
63
|
+
index += 1;
|
|
64
|
+
}
|
|
65
|
+
if (credit && parts[index]) {
|
|
66
|
+
result.remaining_credit = parseFloat(parts[index]);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
success: true,
|
|
71
|
+
result,
|
|
72
|
+
error: null,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (responseText.startsWith('ERR')) {
|
|
76
|
+
const parts = responseText.split(' ');
|
|
77
|
+
const errorCode = parts[1] || 'UNKNOWN';
|
|
78
|
+
const errorMessages = {
|
|
79
|
+
'1001': 'Authentication failed OR insufficient credit (BudgetSMS returns 1001 for both)',
|
|
80
|
+
'1002': 'Account not active',
|
|
81
|
+
'1003': 'Insufficient credit',
|
|
82
|
+
'1004': 'No access to this API',
|
|
83
|
+
'1005': 'No handle provided',
|
|
84
|
+
'1006': 'No UserID provided',
|
|
85
|
+
'1007': 'No Username provided',
|
|
86
|
+
'2001': 'SMS message text is empty',
|
|
87
|
+
'2002': 'SMS numeric senderid can be max. 16 numbers',
|
|
88
|
+
'2003': 'SMS alphanumeric sender can be max. 11 characters',
|
|
89
|
+
'2004': 'SMS senderid is empty or invalid',
|
|
90
|
+
'2005': 'Destination number is too short',
|
|
91
|
+
'2006': 'Destination is not numeric',
|
|
92
|
+
'2007': 'Destination is empty',
|
|
93
|
+
'2008': 'SMS text is not OK (check encoding?)',
|
|
94
|
+
'2009': 'Parameter issue',
|
|
95
|
+
'2010': 'Destination number is invalidly formatted',
|
|
96
|
+
'2011': 'Destination is invalid',
|
|
97
|
+
'2012': 'SMS message text is too long',
|
|
98
|
+
'2013': 'SMS message is invalid',
|
|
99
|
+
'2014': 'SMS CustomID is used before',
|
|
100
|
+
'2015': 'Charset problem',
|
|
101
|
+
'2016': 'Invalid UTF-8 encoding',
|
|
102
|
+
'3001': 'No route to destination',
|
|
103
|
+
'3002': 'No routes are setup',
|
|
104
|
+
'3003': 'Invalid destination',
|
|
105
|
+
'4001': 'System error, related to customid',
|
|
106
|
+
'4002': 'System error, temporary issue',
|
|
107
|
+
};
|
|
108
|
+
let message = errorMessages[errorCode] || `Unknown error code: ${errorCode}`;
|
|
109
|
+
if (errorCode === '1001') {
|
|
110
|
+
message += '. Note: Check your account balance - BudgetSMS may return 1001 when credit is 0.';
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
success: false,
|
|
114
|
+
error: {
|
|
115
|
+
name: 'BUDGETSMS_ERROR',
|
|
116
|
+
code: errorCode,
|
|
117
|
+
message,
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
success: false,
|
|
123
|
+
error: {
|
|
124
|
+
name: 'BUDGETSMS_ERROR',
|
|
125
|
+
message: 'Unexpected response format from BudgetSMS API',
|
|
126
|
+
response: responseText,
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
return {
|
|
132
|
+
success: false,
|
|
133
|
+
error: {
|
|
134
|
+
name: err.name,
|
|
135
|
+
message: err.message,
|
|
136
|
+
stack: err.stack,
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
export async function checkBudgetSmsCredentials() {
|
|
143
|
+
const url = 'https://api.budgetsms.net/checkcredit/';
|
|
144
|
+
const username = process.env.BUDGETSMS_USERNAME?.trim();
|
|
145
|
+
const userid = process.env.BUDGETSMS_USERID?.trim();
|
|
146
|
+
const handle = process.env.BUDGETSMS_HANDLE?.trim();
|
|
147
|
+
if (!username || !userid || !handle) {
|
|
148
|
+
return { error: 'Missing credentials' };
|
|
149
|
+
}
|
|
150
|
+
if (!/^\d+$/.test(userid)) {
|
|
151
|
+
return { error: 'UserID must be numeric only' };
|
|
152
|
+
}
|
|
153
|
+
const queryParams = new URLSearchParams({ username, userid, handle });
|
|
154
|
+
try {
|
|
155
|
+
const response = await fetch(`${url}?${queryParams.toString()}`, { method: 'GET' });
|
|
156
|
+
const text = await response.text();
|
|
157
|
+
if (text.startsWith('OK')) {
|
|
158
|
+
const credit = parseFloat(text.split(' ')[1]) || 0;
|
|
159
|
+
return { success: true, credit };
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
return { error: text };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
return { error: err.message };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
export default BudgetSMSWorker;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {} from '@unchainedshop/core';
|
|
2
|
+
import { BudgetSMSWorker } from "./adapter.js";
|
|
3
|
+
export const BudgetSMSPlugin = {
|
|
4
|
+
key: 'shop.unchained.worker-plugin.budgetsms',
|
|
5
|
+
label: 'Budget SMS Worker Plugin',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
adapters: [BudgetSMSWorker],
|
|
8
|
+
};
|
|
9
|
+
export default BudgetSMSPlugin;
|
|
10
|
+
export { BudgetSMSWorker, checkBudgetSmsCredentials } from "./adapter.js";
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { WorkerAdapter } from '@unchainedshop/core';
|
|
2
|
+
import { createLogger } from '@unchainedshop/logger';
|
|
3
|
+
const isSupportedLocale = (locale) => {
|
|
4
|
+
try {
|
|
5
|
+
const dtf = new Intl.DateTimeFormat(locale);
|
|
6
|
+
const resolved = dtf.resolvedOptions().locale;
|
|
7
|
+
return resolved.toLowerCase() === locale.toLowerCase();
|
|
8
|
+
}
|
|
9
|
+
catch (e) {
|
|
10
|
+
console.error(e);
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const createLanguageDialectList = (languages, countries) => {
|
|
15
|
+
const result = new Set();
|
|
16
|
+
(languages || []).forEach(({ isoCode: baseIsoCode }) => {
|
|
17
|
+
result.add(baseIsoCode);
|
|
18
|
+
(countries || []).forEach(({ isoCode: countryIsoCode }) => {
|
|
19
|
+
const dialectIsoCode = [baseIsoCode, countryIsoCode.toUpperCase()].join('-');
|
|
20
|
+
if (isSupportedLocale(dialectIsoCode))
|
|
21
|
+
result.add(dialectIsoCode);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
return Array.from(result);
|
|
25
|
+
};
|
|
26
|
+
const logger = createLogger('unchained:bulk-export');
|
|
27
|
+
export const BulkExport = {
|
|
28
|
+
...WorkerAdapter,
|
|
29
|
+
key: 'shop.unchained.worker-plugin.bulk-export',
|
|
30
|
+
label: 'Bulk Export',
|
|
31
|
+
version: '2.1.0',
|
|
32
|
+
type: 'BULK_EXPORT',
|
|
33
|
+
maxParallelAllocations: 1,
|
|
34
|
+
doWork: async (payload, unchainedAPI) => {
|
|
35
|
+
try {
|
|
36
|
+
const { modules } = unchainedAPI;
|
|
37
|
+
const languages = await modules.languages.findLanguages({ includeInactive: false });
|
|
38
|
+
const countries = await modules.countries.findCountries({ includeInactive: false });
|
|
39
|
+
const bulkExporter = unchainedAPI.bulkExporter.createBulkExporter({ entity: payload.type });
|
|
40
|
+
await bulkExporter.validate(payload);
|
|
41
|
+
const locales = createLanguageDialectList(languages, countries);
|
|
42
|
+
const [result, error] = await bulkExporter.execute(payload, locales, unchainedAPI);
|
|
43
|
+
if (error) {
|
|
44
|
+
return {
|
|
45
|
+
success: false,
|
|
46
|
+
result: result,
|
|
47
|
+
error,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
success: true,
|
|
52
|
+
result,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
logger.error(err);
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
error: { name: err.name, message: err.message, stack: err.stack },
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
export default BulkExport;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {} from '@unchainedshop/core';
|
|
2
|
+
import { BulkExport } from "./adapter.js";
|
|
3
|
+
export const BulkExportPlugin = {
|
|
4
|
+
key: 'shop.unchained.worker-plugin.bulk-export',
|
|
5
|
+
label: 'Bulk Export Worker Plugin',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
adapters: [BulkExport],
|
|
8
|
+
};
|
|
9
|
+
export default BulkExportPlugin;
|
|
10
|
+
export { BulkExport } from "./adapter.js";
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { WorkerAdapter } from '@unchainedshop/core';
|
|
2
|
+
import { createLogger } from '@unchainedshop/logger';
|
|
3
|
+
const logger = createLogger('unchained:bulk-import');
|
|
4
|
+
export const BulkImportWorker = {
|
|
5
|
+
...WorkerAdapter,
|
|
6
|
+
key: 'shop.unchained.worker-plugin.bulk-import',
|
|
7
|
+
label: 'Bulk Import',
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
type: 'BULK_IMPORT',
|
|
10
|
+
maxParallelAllocations: 1,
|
|
11
|
+
doWork: async (rawPayload, unchainedAPI) => {
|
|
12
|
+
try {
|
|
13
|
+
const { createShouldUpsertIfIDExists = false, skipCacheInvalidation = false, updateShouldUpsertIfIDNotExists = false, } = rawPayload;
|
|
14
|
+
const bulkImporter = unchainedAPI.bulkImporter.createBulkImporter({
|
|
15
|
+
createShouldUpsertIfIDExists,
|
|
16
|
+
updateShouldUpsertIfIDNotExists,
|
|
17
|
+
skipCacheInvalidation,
|
|
18
|
+
});
|
|
19
|
+
if (rawPayload.payloadId) {
|
|
20
|
+
const readStream = await unchainedAPI.services.files.createDownloadStream({
|
|
21
|
+
fileId: rawPayload.payloadId,
|
|
22
|
+
});
|
|
23
|
+
if (!readStream) {
|
|
24
|
+
throw new Error('Could not create download stream from uploaded file');
|
|
25
|
+
}
|
|
26
|
+
await unchainedAPI.bulkImporter.pipeEventStream(readStream, bulkImporter, unchainedAPI);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
const { events } = rawPayload;
|
|
30
|
+
if (!events?.length)
|
|
31
|
+
throw new Error('No events submitted');
|
|
32
|
+
await events.reduce(async (currentEventPromise, nextEvent) => {
|
|
33
|
+
await currentEventPromise;
|
|
34
|
+
await bulkImporter.validate(nextEvent);
|
|
35
|
+
return bulkImporter.prepare(nextEvent, unchainedAPI);
|
|
36
|
+
}, Promise.resolve());
|
|
37
|
+
}
|
|
38
|
+
const [result, error] = await bulkImporter.execute();
|
|
39
|
+
await bulkImporter.invalidateCaches(unchainedAPI);
|
|
40
|
+
if (error) {
|
|
41
|
+
return {
|
|
42
|
+
success: false,
|
|
43
|
+
result: result,
|
|
44
|
+
error,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
success: true,
|
|
49
|
+
result: result,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
logger.error(err);
|
|
54
|
+
return {
|
|
55
|
+
success: false,
|
|
56
|
+
error: {
|
|
57
|
+
name: err.name,
|
|
58
|
+
message: err.message,
|
|
59
|
+
stack: err.stack,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
export default BulkImportWorker;
|