Skip to content

Commit b22161b

Browse files
committed
add step selector
1 parent 400e559 commit b22161b

File tree

3 files changed

+146
-102
lines changed

3 files changed

+146
-102
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "polar-migrate",
3-
"version": "0.1.8",
3+
"version": "0.1.9",
44
"license": "Apache-2.0",
55
"bin": "bin/cli.js",
66
"type": "module",

src/cli.tsx

Lines changed: 115 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { variantsPrompt } from "./prompts/variants.js";
1717
import { authenticationMessage } from "./ui/authentication.js";
1818
import { customersMessage } from "./ui/customers.js";
1919
import { successMessage } from "./ui/success.js";
20+
import { stepsPrompt } from "./prompts/steps.js";
2021

2122
process.on("uncaughtException", (error) => {
2223
console.error(error);
@@ -51,30 +52,6 @@ meow(
5152
process.exit(1);
5253
}
5354

54-
const products = await lemon.listProducts({
55-
filter: {
56-
storeId: store.id,
57-
},
58-
});
59-
60-
const productVariants = (
61-
await Promise.all(
62-
products.data?.data?.map(async (product) => {
63-
const storeVariants = await lemon.listVariants({
64-
filter: {
65-
productId: product.id,
66-
},
67-
});
68-
return storeVariants.data?.data ?? [];
69-
}) ?? [],
70-
)
71-
).flat();
72-
73-
const variants = await variantsPrompt(
74-
productVariants,
75-
products.data?.data ?? [],
76-
);
77-
7855
const server = await serverPrompt();
7956

8057
await authenticationMessage();
@@ -85,106 +62,143 @@ meow(
8562
server,
8663
});
8764

65+
const variantWithProductMap = new Map<string, Product>();
66+
let productsCreated: { product: Product; variantId: string }[] = [];
67+
let discountsCreated: Discount[] = [];
68+
let customersCreated: Customer[] = [];
69+
70+
const steps = await stepsPrompt();
71+
8872
const organization = await resolveOrganization(polar, store.attributes.slug);
8973

90-
const createdProducts = await Promise.all(
91-
variants.map((variant) => {
92-
const lemonProduct = products.data?.data?.find(
93-
(product) => product.id === variant.attributes.product_id.toString(),
94-
);
74+
if (steps.includes("products")) {
75+
const products = await lemon.listProducts({
76+
filter: {
77+
storeId: store.id,
78+
},
79+
});
80+
81+
const productVariants = (
82+
await Promise.all(
83+
products.data?.data?.map(async (product) => {
84+
const storeVariants = await lemon.listVariants({
85+
filter: {
86+
productId: product.id,
87+
},
88+
});
89+
return storeVariants.data?.data ?? [];
90+
}) ?? [],
91+
)
92+
).flat();
93+
94+
const variants = await variantsPrompt(
95+
productVariants,
96+
products.data?.data ?? [],
97+
);
9598

96-
if (!lemonProduct) {
97-
console.error(`Product not found for variant ${variant.id}`);
98-
process.exit(1);
99-
}
99+
const createdProducts = await Promise.all(
100+
variants.map((variant) => {
101+
const lemonProduct = products.data?.data?.find(
102+
(product) => product.id === variant.attributes.product_id.toString(),
103+
);
100104

101-
return createProduct(polar, organization, variant, lemonProduct);
102-
}),
103-
);
105+
if (!lemonProduct) {
106+
console.error(`Product not found for variant ${variant.id}`);
107+
process.exit(1);
108+
}
104109

105-
const variantWithProductMap = new Map<string, Product>();
110+
return createProduct(polar, organization, variant, lemonProduct);
111+
}),
112+
);
106113

107-
for (const product of createdProducts) {
108-
variantWithProductMap.set(product.variantId, product.product);
114+
for (const product of createdProducts) {
115+
variantWithProductMap.set(product.variantId, product.product);
116+
}
117+
118+
productsCreated = createdProducts;
109119
}
110120

111-
const discounts = await listDiscounts({
112-
filter: {
113-
storeId: store.id,
114-
},
115-
include: ["variants"],
116-
});
121+
if (steps.includes("discounts")) {
122+
const discounts = await listDiscounts({
123+
filter: {
124+
storeId: store.id,
125+
},
126+
include: ["variants"],
127+
});
128+
129+
const publishedDiscounts =
130+
discounts.data?.data?.filter(
131+
(discount) => discount.attributes.status === "published",
132+
) ?? [];
133+
134+
try {
135+
discountsCreated = await Promise.all(
136+
publishedDiscounts.map((discount) => {
137+
const commonProps = {
138+
code: discount.attributes.code,
139+
duration: discount.attributes.duration,
140+
durationInMonths: discount.attributes.duration_in_months,
141+
name: discount.attributes.name,
142+
maxRedemptions: discount.attributes.is_limited_redemptions
143+
? Math.max(discount.attributes.max_redemptions, 1)
144+
: undefined,
145+
startsAt: discount.attributes.starts_at
146+
? new Date(discount.attributes.starts_at)
147+
: undefined,
148+
endsAt: discount.attributes.expires_at
149+
? new Date(discount.attributes.expires_at)
150+
: undefined,
151+
organizationId: organization.id,
152+
};
153+
154+
const productsToAssociateWithDiscount =
155+
discount.relationships.variants.data
156+
?.map((variant) => variantWithProductMap.get(variant.id)?.id)
157+
.filter((id): id is string => id !== undefined) ?? [];
158+
159+
if (discount.attributes.amount_type === "fixed") {
160+
return polar.discounts.create({
161+
...commonProps,
162+
amount: discount.attributes.amount,
163+
type: "fixed",
164+
products:
165+
productsToAssociateWithDiscount?.length > 0
166+
? productsToAssociateWithDiscount
167+
: undefined,
168+
});
169+
}
117170

118-
const publishedDiscounts =
119-
discounts.data?.data?.filter(
120-
(discount) => discount.attributes.status === "published",
121-
) ?? [];
122-
123-
let createdDiscounts: Discount[] = [];
124-
125-
try {
126-
createdDiscounts = await Promise.all(
127-
publishedDiscounts.map((discount) => {
128-
const commonProps = {
129-
code: discount.attributes.code,
130-
duration: discount.attributes.duration,
131-
durationInMonths: discount.attributes.duration_in_months,
132-
name: discount.attributes.name,
133-
maxRedemptions: discount.attributes.is_limited_redemptions
134-
? Math.max(discount.attributes.max_redemptions, 1)
135-
: undefined,
136-
startsAt: discount.attributes.starts_at
137-
? new Date(discount.attributes.starts_at)
138-
: undefined,
139-
endsAt: discount.attributes.expires_at
140-
? new Date(discount.attributes.expires_at)
141-
: undefined,
142-
organizationId: organization.id,
143-
};
144-
145-
const productsToAssociateWithDiscount =
146-
discount.relationships.variants.data
147-
?.map((variant) => variantWithProductMap.get(variant.id)?.id)
148-
.filter((id): id is string => id !== undefined) ?? [];
149-
150-
if (discount.attributes.amount_type === "fixed") {
151171
return polar.discounts.create({
152172
...commonProps,
153-
amount: discount.attributes.amount,
154-
type: "fixed",
173+
basisPoints: discount.attributes.amount * 100,
174+
type: "percentage",
155175
products:
156176
productsToAssociateWithDiscount?.length > 0
157177
? productsToAssociateWithDiscount
158178
: undefined,
159179
});
160-
}
180+
}),
181+
);
182+
} catch (e) {}
183+
}
161184

162-
return polar.discounts.create({
163-
...commonProps,
164-
basisPoints: discount.attributes.amount * 100,
165-
type: "percentage",
166-
products:
167-
productsToAssociateWithDiscount?.length > 0
168-
? productsToAssociateWithDiscount
169-
: undefined,
170-
});
171-
}),
185+
if (steps.includes("customers")) {
186+
const customers = await customersMessage(
187+
importCustomers(polar, store, organization),
172188
);
173-
} catch (e) {}
174189

175-
const customers = await customersMessage(
176-
importCustomers(polar, store, organization),
177-
);
190+
const customersWithoutNulls = customers.filter(
191+
(customer): customer is Customer => customer !== null,
192+
);
178193

179-
const customersWithoutNulls = customers.filter(
180-
(customer): customer is Customer => customer !== null,
181-
);
194+
customersCreated = customersWithoutNulls;
195+
}
182196

183197
await successMessage(
184198
organization,
185-
createdProducts.map((p) => p.product),
186-
createdDiscounts,
187-
customersWithoutNulls,
199+
productsCreated.map((p) => p.product),
200+
discountsCreated,
201+
customersCreated,
188202
server,
189203
);
190204

src/prompts/steps.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import prompts from "prompts";
2+
3+
export const stepsPrompt = async () => {
4+
const { steps } = await prompts([
5+
{
6+
type: "multiselect",
7+
name: "steps",
8+
message: "Select what to migrate",
9+
choices: [
10+
{
11+
title: "Products",
12+
value: "products",
13+
selected: true,
14+
},
15+
{
16+
title: "Discounts",
17+
value: "discounts",
18+
selected: true,
19+
},
20+
{
21+
title: "Customers",
22+
value: "customers",
23+
selected: true,
24+
},
25+
],
26+
},
27+
]);
28+
29+
return steps;
30+
};

0 commit comments

Comments
 (0)