@rebuy/rebuy 3.17.0 → 3.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/analytics.d.ts +13 -3
- package/dist/server/analyticsSegments.d.ts +6 -0
- package/dist/server/index.cjs +31 -2
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.mjs +31 -2
- package/dist/server/requestSchemas.d.ts +22 -0
- package/dist/server/shared.d.ts +1 -1
- package/package.json +1 -1
|
@@ -25,7 +25,7 @@ declare const TAXONOMY: {
|
|
|
25
25
|
element_id: string;
|
|
26
26
|
experiment_type: string;
|
|
27
27
|
};
|
|
28
|
-
buildTags: ({ experimentId }: Record<string, unknown
|
|
28
|
+
buildTags: ({ experimentId }: Record<string, unknown>, input: AnalyticsInput) => string[] | undefined;
|
|
29
29
|
noun: "cart";
|
|
30
30
|
subject: "abtest";
|
|
31
31
|
usesWidgetId: false;
|
|
@@ -37,7 +37,7 @@ declare const TAXONOMY: {
|
|
|
37
37
|
buildMeta: ({ productId, variantId }: Record<string, unknown>) => {
|
|
38
38
|
[x: string]: true;
|
|
39
39
|
};
|
|
40
|
-
buildTags: ({ experimentId }: Record<string, unknown
|
|
40
|
+
buildTags: ({ experimentId }: Record<string, unknown>, input: AnalyticsInput) => string[] | undefined;
|
|
41
41
|
/** Under an experiment the add belongs to the VARIANT element, not the placeholder (React parity). */
|
|
42
42
|
buildWidgetId: ({ elementId }: Record<string, unknown>, input: {
|
|
43
43
|
events: {
|
|
@@ -49,6 +49,11 @@ declare const TAXONOMY: {
|
|
|
49
49
|
visitorId: string;
|
|
50
50
|
cartToken?: string | undefined;
|
|
51
51
|
checkoutToken?: string | undefined;
|
|
52
|
+
segments?: {
|
|
53
|
+
device?: string | undefined;
|
|
54
|
+
source?: string | undefined;
|
|
55
|
+
visitor?: string | undefined;
|
|
56
|
+
} | undefined;
|
|
52
57
|
widgetId?: string | undefined;
|
|
53
58
|
}) => string | undefined;
|
|
54
59
|
noun: "widget";
|
|
@@ -77,7 +82,7 @@ declare const TAXONOMY: {
|
|
|
77
82
|
verb: "tracking";
|
|
78
83
|
};
|
|
79
84
|
'widget-viewed': {
|
|
80
|
-
buildTags: ({ experimentId }: Record<string, unknown
|
|
85
|
+
buildTags: ({ experimentId }: Record<string, unknown>, input: AnalyticsInput) => string[] | undefined;
|
|
81
86
|
/** Under an experiment the view belongs to the VARIANT element, not the placeholder (React parity, same as added-to-cart) — else views credit the placeholder while adds credit the variant and per-widget conversion is meaningless. */
|
|
82
87
|
buildWidgetId: ({ elementId }: Record<string, unknown>, input: {
|
|
83
88
|
events: {
|
|
@@ -89,6 +94,11 @@ declare const TAXONOMY: {
|
|
|
89
94
|
visitorId: string;
|
|
90
95
|
cartToken?: string | undefined;
|
|
91
96
|
checkoutToken?: string | undefined;
|
|
97
|
+
segments?: {
|
|
98
|
+
device?: string | undefined;
|
|
99
|
+
source?: string | undefined;
|
|
100
|
+
visitor?: string | undefined;
|
|
101
|
+
} | undefined;
|
|
92
102
|
widgetId?: string | undefined;
|
|
93
103
|
}) => string | undefined;
|
|
94
104
|
noun: "widget";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type AnalyticsSegmentsInput } from '../server/requestSchemas';
|
|
2
|
+
/**
|
|
3
|
+
* One `<baseTag>.<dimension>.<bucket>` tag per segment whose bucket passes {@link SEGMENT_BUCKETS}; invalid
|
|
4
|
+
* or absent dimensions contribute nothing (so valid siblings still ride along).
|
|
5
|
+
*/
|
|
6
|
+
export declare const segmentTags: (baseTag: string, segments: AnalyticsSegmentsInput | undefined) => string[];
|
package/dist/server/index.cjs
CHANGED
|
@@ -22,6 +22,7 @@ var server_exports = {};
|
|
|
22
22
|
__export(server_exports, {
|
|
23
23
|
AnalyticsEventInputSchema: () => AnalyticsEventInputSchema,
|
|
24
24
|
AnalyticsInputSchema: () => AnalyticsInputSchema,
|
|
25
|
+
AnalyticsSegmentsInputSchema: () => AnalyticsSegmentsInputSchema,
|
|
25
26
|
CartInputSchema: () => CartInputSchema,
|
|
26
27
|
CartLineInputSchema: () => CartLineInputSchema,
|
|
27
28
|
DataSourceInputSchema: () => DataSourceInputSchema,
|
|
@@ -4542,6 +4543,19 @@ var validateGifts = async (input, ctx) => {
|
|
|
4542
4543
|
|
|
4543
4544
|
// src/server/analytics.ts
|
|
4544
4545
|
var import_es_toolkit7 = require("es-toolkit");
|
|
4546
|
+
|
|
4547
|
+
// src/server/analyticsSegments.ts
|
|
4548
|
+
var SEGMENT_BUCKETS = {
|
|
4549
|
+
device: ["desktop", "mobile"],
|
|
4550
|
+
source: ["direct", "email", "google_ads", "meta_social", "other", "sms"],
|
|
4551
|
+
visitor: ["new", "returning"]
|
|
4552
|
+
};
|
|
4553
|
+
var segmentTags = (baseTag, segments) => Object.entries(SEGMENT_BUCKETS).flatMap(([dimension, buckets]) => {
|
|
4554
|
+
const bucket = segments?.[dimension];
|
|
4555
|
+
return bucket !== void 0 && buckets.includes(bucket) ? [`${baseTag}.${dimension}.${bucket}`] : [];
|
|
4556
|
+
});
|
|
4557
|
+
|
|
4558
|
+
// src/server/analytics.ts
|
|
4545
4559
|
var EXPERIMENT_TYPE_MAP = {
|
|
4546
4560
|
CheckoutOffer: "checkout_offer",
|
|
4547
4561
|
Generic: "generic",
|
|
@@ -4549,7 +4563,11 @@ var EXPERIMENT_TYPE_MAP = {
|
|
|
4549
4563
|
SmartCart: "smart_cart",
|
|
4550
4564
|
Widget: "widget"
|
|
4551
4565
|
};
|
|
4552
|
-
var experimentTags = ({ experimentId }) =>
|
|
4566
|
+
var experimentTags = ({ experimentId }, input) => {
|
|
4567
|
+
if (experimentId == null) return void 0;
|
|
4568
|
+
const baseTag = `ABN.TEST.${experimentId}`;
|
|
4569
|
+
return [baseTag, ...segmentTags(baseTag, input.segments)];
|
|
4570
|
+
};
|
|
4553
4571
|
var TAXONOMY = {
|
|
4554
4572
|
"ab-test-viewed": {
|
|
4555
4573
|
// Only when BOTH ids are present — otherwise the template literal would emit "undefined.undefined".
|
|
@@ -4618,7 +4636,7 @@ var translateAnalyticsEvent = (event, input) => {
|
|
|
4618
4636
|
const taxonomy = TAXONOMY[event.name];
|
|
4619
4637
|
const properties = event.properties ?? {};
|
|
4620
4638
|
const meta = taxonomy.buildMeta?.(properties);
|
|
4621
|
-
const tags = taxonomy.buildTags?.(properties);
|
|
4639
|
+
const tags = taxonomy.buildTags?.(properties, input);
|
|
4622
4640
|
const definedNounId = taxonomy.buildDefinedNounId?.(properties);
|
|
4623
4641
|
const widgetId = taxonomy.buildWidgetId?.(properties, input) ?? input.widgetId;
|
|
4624
4642
|
const eventTime = toEngineEventTime(event.sentAt);
|
|
@@ -4886,12 +4904,23 @@ var AnalyticsEventInputSchema = import_zod30.z.object({
|
|
|
4886
4904
|
properties: import_zod30.z.record(import_zod30.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod30.z.unknown()).optional(),
|
|
4887
4905
|
sentAt: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
4888
4906
|
});
|
|
4907
|
+
var AnalyticsSegmentsInputSchema = import_zod30.z.object({
|
|
4908
|
+
device: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
|
|
4909
|
+
source: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
|
|
4910
|
+
visitor: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
|
|
4911
|
+
});
|
|
4889
4912
|
var AnalyticsInputSchema = import_zod30.z.object({
|
|
4890
4913
|
/** Rebuy cart token (the `r_cart_token` cart attribute), when available — primary aggregation key. */
|
|
4891
4914
|
cartToken: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
4892
4915
|
/** Shopify checkout token, when available — drives cart/checkout aggregation downstream. */
|
|
4893
4916
|
checkoutToken: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
4894
4917
|
events: import_zod30.z.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
|
|
4918
|
+
/**
|
|
4919
|
+
* Request-scoped like the tokens: one visitor's segments apply to every event in the batch. The container
|
|
4920
|
+
* degrades too (`null` is a realistic wire artifact of `attributes ? {…} : null`), so the degrade rule is
|
|
4921
|
+
* total: nothing about `segments` can cost the envelope.
|
|
4922
|
+
*/
|
|
4923
|
+
segments: AnalyticsSegmentsInputSchema.optional().catch(void 0),
|
|
4895
4924
|
shop: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
4896
4925
|
visitorId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
4897
4926
|
/** The widget id (smartBlockId) the events belong to. */
|
package/dist/server/index.d.ts
CHANGED
|
@@ -14,5 +14,5 @@ export { fetchUserConfig } from '../server/userConfig';
|
|
|
14
14
|
export { validateGifts } from '../server/giftValidation';
|
|
15
15
|
export { fetchMonetizeOffers, type MonetizeOffers } from '../server/monetizeOffers';
|
|
16
16
|
export { postAnalyticsEvents, translateAnalyticsEvent, type CabAnalyticsEventName } from '../server/analytics';
|
|
17
|
-
export { AnalyticsEventInputSchema, AnalyticsInputSchema, CartInputSchema, CartLineInputSchema, DataSourceInputSchema, GiftAdjustmentSchema, GiftInputSchema, GiftValidationInputSchema, GiftValidationResponseSchema, MonetizeInputSchema, MonetizeTransactionItemSchema, REQUEST_BOUNDS, UserConfigInputSchema, WidgetSettingsInputSchema, } from '../server/requestSchemas';
|
|
18
|
-
export { NotFoundError, REBUY_ENGINE_HOST, UpstreamError, type AnalyticsEventInput, type AnalyticsInput, type CartInput, type CartLineInput, type DataSourceInput, type GiftAdjustment, type GiftInput, type GiftValidationInput, type GiftValidationResponse, type MonetizeInput, type MonetizeTransactionItem, type ServerContext, type ServerDrift, type UpstreamFetch, type UserConfigInput, type WidgetSettingsInput, } from '../server/shared';
|
|
17
|
+
export { AnalyticsEventInputSchema, AnalyticsInputSchema, AnalyticsSegmentsInputSchema, CartInputSchema, CartLineInputSchema, DataSourceInputSchema, GiftAdjustmentSchema, GiftInputSchema, GiftValidationInputSchema, GiftValidationResponseSchema, MonetizeInputSchema, MonetizeTransactionItemSchema, REQUEST_BOUNDS, UserConfigInputSchema, WidgetSettingsInputSchema, } from '../server/requestSchemas';
|
|
18
|
+
export { NotFoundError, REBUY_ENGINE_HOST, UpstreamError, type AnalyticsEventInput, type AnalyticsInput, type AnalyticsSegmentsInput, type CartInput, type CartLineInput, type DataSourceInput, type GiftAdjustment, type GiftInput, type GiftValidationInput, type GiftValidationResponse, type MonetizeInput, type MonetizeTransactionItem, type ServerContext, type ServerDrift, type UpstreamFetch, type UserConfigInput, type WidgetSettingsInput, } from '../server/shared';
|
package/dist/server/index.mjs
CHANGED
|
@@ -4492,6 +4492,19 @@ var validateGifts = async (input, ctx) => {
|
|
|
4492
4492
|
|
|
4493
4493
|
// src/server/analytics.ts
|
|
4494
4494
|
import { chunk } from "es-toolkit";
|
|
4495
|
+
|
|
4496
|
+
// src/server/analyticsSegments.ts
|
|
4497
|
+
var SEGMENT_BUCKETS = {
|
|
4498
|
+
device: ["desktop", "mobile"],
|
|
4499
|
+
source: ["direct", "email", "google_ads", "meta_social", "other", "sms"],
|
|
4500
|
+
visitor: ["new", "returning"]
|
|
4501
|
+
};
|
|
4502
|
+
var segmentTags = (baseTag, segments) => Object.entries(SEGMENT_BUCKETS).flatMap(([dimension, buckets]) => {
|
|
4503
|
+
const bucket = segments?.[dimension];
|
|
4504
|
+
return bucket !== void 0 && buckets.includes(bucket) ? [`${baseTag}.${dimension}.${bucket}`] : [];
|
|
4505
|
+
});
|
|
4506
|
+
|
|
4507
|
+
// src/server/analytics.ts
|
|
4495
4508
|
var EXPERIMENT_TYPE_MAP = {
|
|
4496
4509
|
CheckoutOffer: "checkout_offer",
|
|
4497
4510
|
Generic: "generic",
|
|
@@ -4499,7 +4512,11 @@ var EXPERIMENT_TYPE_MAP = {
|
|
|
4499
4512
|
SmartCart: "smart_cart",
|
|
4500
4513
|
Widget: "widget"
|
|
4501
4514
|
};
|
|
4502
|
-
var experimentTags = ({ experimentId }) =>
|
|
4515
|
+
var experimentTags = ({ experimentId }, input) => {
|
|
4516
|
+
if (experimentId == null) return void 0;
|
|
4517
|
+
const baseTag = `ABN.TEST.${experimentId}`;
|
|
4518
|
+
return [baseTag, ...segmentTags(baseTag, input.segments)];
|
|
4519
|
+
};
|
|
4503
4520
|
var TAXONOMY = {
|
|
4504
4521
|
"ab-test-viewed": {
|
|
4505
4522
|
// Only when BOTH ids are present — otherwise the template literal would emit "undefined.undefined".
|
|
@@ -4568,7 +4585,7 @@ var translateAnalyticsEvent = (event, input) => {
|
|
|
4568
4585
|
const taxonomy = TAXONOMY[event.name];
|
|
4569
4586
|
const properties = event.properties ?? {};
|
|
4570
4587
|
const meta = taxonomy.buildMeta?.(properties);
|
|
4571
|
-
const tags = taxonomy.buildTags?.(properties);
|
|
4588
|
+
const tags = taxonomy.buildTags?.(properties, input);
|
|
4572
4589
|
const definedNounId = taxonomy.buildDefinedNounId?.(properties);
|
|
4573
4590
|
const widgetId = taxonomy.buildWidgetId?.(properties, input) ?? input.widgetId;
|
|
4574
4591
|
const eventTime = toEngineEventTime(event.sentAt);
|
|
@@ -4836,12 +4853,23 @@ var AnalyticsEventInputSchema = z30.object({
|
|
|
4836
4853
|
properties: z30.record(z30.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), z30.unknown()).optional(),
|
|
4837
4854
|
sentAt: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
4838
4855
|
});
|
|
4856
|
+
var AnalyticsSegmentsInputSchema = z30.object({
|
|
4857
|
+
device: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
|
|
4858
|
+
source: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
|
|
4859
|
+
visitor: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
|
|
4860
|
+
});
|
|
4839
4861
|
var AnalyticsInputSchema = z30.object({
|
|
4840
4862
|
/** Rebuy cart token (the `r_cart_token` cart attribute), when available — primary aggregation key. */
|
|
4841
4863
|
cartToken: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
4842
4864
|
/** Shopify checkout token, when available — drives cart/checkout aggregation downstream. */
|
|
4843
4865
|
checkoutToken: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
4844
4866
|
events: z30.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
|
|
4867
|
+
/**
|
|
4868
|
+
* Request-scoped like the tokens: one visitor's segments apply to every event in the batch. The container
|
|
4869
|
+
* degrades too (`null` is a realistic wire artifact of `attributes ? {…} : null`), so the degrade rule is
|
|
4870
|
+
* total: nothing about `segments` can cost the envelope.
|
|
4871
|
+
*/
|
|
4872
|
+
segments: AnalyticsSegmentsInputSchema.optional().catch(void 0),
|
|
4845
4873
|
shop: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
4846
4874
|
visitorId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
4847
4875
|
/** The widget id (smartBlockId) the events belong to. */
|
|
@@ -4850,6 +4878,7 @@ var AnalyticsInputSchema = z30.object({
|
|
|
4850
4878
|
export {
|
|
4851
4879
|
AnalyticsEventInputSchema,
|
|
4852
4880
|
AnalyticsInputSchema,
|
|
4881
|
+
AnalyticsSegmentsInputSchema,
|
|
4853
4882
|
CartInputSchema,
|
|
4854
4883
|
CartLineInputSchema,
|
|
4855
4884
|
DataSourceInputSchema,
|
|
@@ -331,6 +331,22 @@ export declare const AnalyticsEventInputSchema: z.ZodObject<{
|
|
|
331
331
|
properties: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
332
332
|
sentAt: z.ZodOptional<z.ZodString>;
|
|
333
333
|
}, z.core.$strip>;
|
|
334
|
+
/**
|
|
335
|
+
* The visitor's A/B segment buckets, RAW as onsite-js wrote them into the `_r_segment_{device,source,visitor}`
|
|
336
|
+
* cart attributes (the checkout sandbox can't compute them itself). Deliberately unvalidated here: the
|
|
337
|
+
* bucket allow-list lives in the tag translation (`analyticsSegments.ts`) so a stray value drops ONE tag,
|
|
338
|
+
* never the whole batch — and the extension bundle never has to carry a copy of the list. Cart attributes
|
|
339
|
+
* are shopper-writable, so even the size bound must degrade rather than fail: `.catch(undefined)` (the
|
|
340
|
+
* `cacheKey` precedent) turns an over-limit or non-string value into a missing segment instead of a
|
|
341
|
+
* rejected envelope. `STRING_ID_MAX` (not the fat `STRING_VALUE_MAX`) because every valid bucket is a
|
|
342
|
+
* short identifier — anything longer can only be junk, and the bound is a payload guard, not validation.
|
|
343
|
+
* Only present keys are sent; the client omits an absent attribute rather than sending an empty string.
|
|
344
|
+
*/
|
|
345
|
+
export declare const AnalyticsSegmentsInputSchema: z.ZodObject<{
|
|
346
|
+
device: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
347
|
+
source: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
348
|
+
visitor: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
349
|
+
}, z.core.$strip>;
|
|
334
350
|
/** Input for `postAnalyticsEvents`: a batch of events plus the request-scoped identity fields. */
|
|
335
351
|
export declare const AnalyticsInputSchema: z.ZodObject<{
|
|
336
352
|
cartToken: z.ZodOptional<z.ZodString>;
|
|
@@ -340,12 +356,18 @@ export declare const AnalyticsInputSchema: z.ZodObject<{
|
|
|
340
356
|
properties: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
341
357
|
sentAt: z.ZodOptional<z.ZodString>;
|
|
342
358
|
}, z.core.$strip>>;
|
|
359
|
+
segments: z.ZodCatch<z.ZodOptional<z.ZodObject<{
|
|
360
|
+
device: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
361
|
+
source: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
362
|
+
visitor: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
363
|
+
}, z.core.$strip>>>;
|
|
343
364
|
shop: z.ZodString;
|
|
344
365
|
visitorId: z.ZodString;
|
|
345
366
|
widgetId: z.ZodOptional<z.ZodString>;
|
|
346
367
|
}, z.core.$strip>;
|
|
347
368
|
export type AnalyticsEventInput = z.infer<typeof AnalyticsEventInputSchema>;
|
|
348
369
|
export type AnalyticsInput = z.infer<typeof AnalyticsInputSchema>;
|
|
370
|
+
export type AnalyticsSegmentsInput = z.infer<typeof AnalyticsSegmentsInputSchema>;
|
|
349
371
|
export type CartInput = z.infer<typeof CartInputSchema>;
|
|
350
372
|
export type CartLineInput = z.infer<typeof CartLineInputSchema>;
|
|
351
373
|
export type DataSourceInput = z.infer<typeof DataSourceInputSchema>;
|
package/dist/server/shared.d.ts
CHANGED
|
@@ -70,4 +70,4 @@ export declare class NotFoundError extends Error {
|
|
|
70
70
|
* requests against the exact contract the orchestrators are typed on. Kept re-exported here so the
|
|
71
71
|
* `@rebuy/rebuy/server` type surface is unchanged.
|
|
72
72
|
*/
|
|
73
|
-
export type { AnalyticsEventInput, AnalyticsInput, CartInput, CartLineInput, DataSourceInput, GiftAdjustment, GiftInput, GiftValidationInput, GiftValidationResponse, MonetizeInput, MonetizeTransactionItem, UserConfigInput, WidgetSettingsInput, } from '../server/requestSchemas';
|
|
73
|
+
export type { AnalyticsEventInput, AnalyticsInput, AnalyticsSegmentsInput, CartInput, CartLineInput, DataSourceInput, GiftAdjustment, GiftInput, GiftValidationInput, GiftValidationResponse, MonetizeInput, MonetizeTransactionItem, UserConfigInput, WidgetSettingsInput, } from '../server/requestSchemas';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebuy/rebuy",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.18.0",
|
|
4
4
|
"description": "Shared zod schemas, legacy-to-CAB widget transforms, and server orchestrators for Rebuy's Shopify consumers (rebuy-api, admin-nextjs, rebuy-shopify-extensions)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Rebuy, Inc.",
|