@doswiftly/cli 0.1.24 → 0.2.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.
Files changed (98) hide show
  1. package/dist/commands/check.js +2 -2
  2. package/dist/commands/deploy.d.ts.map +1 -1
  3. package/dist/commands/deploy.js +8 -5
  4. package/dist/commands/deploy.js.map +1 -1
  5. package/dist/commands/dev.d.ts +13 -0
  6. package/dist/commands/dev.d.ts.map +1 -1
  7. package/dist/commands/dev.js +155 -63
  8. package/dist/commands/dev.js.map +1 -1
  9. package/dist/commands/doctor.d.ts.map +1 -1
  10. package/dist/commands/doctor.js +3 -4
  11. package/dist/commands/doctor.js.map +1 -1
  12. package/dist/commands/init.d.ts.map +1 -1
  13. package/dist/commands/init.js +271 -166
  14. package/dist/commands/init.js.map +1 -1
  15. package/dist/commands/sdk.d.ts +1 -1
  16. package/dist/commands/sdk.js +3 -3
  17. package/dist/commands/sdk.js.map +1 -1
  18. package/dist/commands/template.d.ts.map +1 -1
  19. package/dist/commands/template.js +4 -31
  20. package/dist/commands/template.js.map +1 -1
  21. package/dist/commands/verify.js +5 -5
  22. package/dist/commands/verify.js.map +1 -1
  23. package/dist/index.js +2 -3
  24. package/dist/index.js.map +1 -1
  25. package/dist/lib/i18n.d.ts +12 -0
  26. package/dist/lib/i18n.d.ts.map +1 -1
  27. package/dist/lib/i18n.js +24 -0
  28. package/dist/lib/i18n.js.map +1 -1
  29. package/dist/lib/proxy-server.d.ts +22 -6
  30. package/dist/lib/proxy-server.d.ts.map +1 -1
  31. package/dist/lib/proxy-server.js +174 -75
  32. package/dist/lib/proxy-server.js.map +1 -1
  33. package/package.json +1 -1
  34. package/dist/commands/types.d.ts +0 -5
  35. package/dist/commands/types.d.ts.map +0 -1
  36. package/dist/commands/types.js +0 -82
  37. package/dist/commands/types.js.map +0 -1
  38. package/templates/storefront-minimal/.env.example +0 -10
  39. package/templates/storefront-minimal/.github/workflows/build-template.yml +0 -119
  40. package/templates/storefront-minimal/app/globals.css +0 -18
  41. package/templates/storefront-minimal/app/layout.tsx +0 -26
  42. package/templates/storefront-minimal/app/page.tsx +0 -93
  43. package/templates/storefront-minimal/lib/graphql-client.ts +0 -23
  44. package/templates/storefront-minimal/next.config.ts +0 -15
  45. package/templates/storefront-minimal/open-next.config.ts +0 -3
  46. package/templates/storefront-minimal/package.json +0 -30
  47. package/templates/storefront-minimal/postcss.config.mjs +0 -5
  48. package/templates/storefront-minimal/tailwind.config.ts +0 -14
  49. package/templates/storefront-minimal/tsconfig.json +0 -27
  50. package/templates/storefront-minimal/wrangler.toml +0 -24
  51. package/templates/storefront-nextjs/.env.example +0 -68
  52. package/templates/storefront-nextjs/.github/workflows/build-template.yml +0 -119
  53. package/templates/storefront-nextjs/README.md +0 -524
  54. package/templates/storefront-nextjs/app/account/orders/page.tsx +0 -216
  55. package/templates/storefront-nextjs/app/account/page.tsx +0 -167
  56. package/templates/storefront-nextjs/app/auth/login/page.tsx +0 -135
  57. package/templates/storefront-nextjs/app/auth/register/page.tsx +0 -212
  58. package/templates/storefront-nextjs/app/cart/page.tsx +0 -263
  59. package/templates/storefront-nextjs/app/categories/[slug]/page.tsx +0 -200
  60. package/templates/storefront-nextjs/app/categories/page.tsx +0 -58
  61. package/templates/storefront-nextjs/app/checkout/page.tsx +0 -351
  62. package/templates/storefront-nextjs/app/collections/[slug]/page.tsx +0 -158
  63. package/templates/storefront-nextjs/app/collections/page.tsx +0 -61
  64. package/templates/storefront-nextjs/app/globals.css +0 -98
  65. package/templates/storefront-nextjs/app/layout.tsx +0 -39
  66. package/templates/storefront-nextjs/app/page.tsx +0 -136
  67. package/templates/storefront-nextjs/app/products/[slug]/page.tsx +0 -119
  68. package/templates/storefront-nextjs/app/products/page.tsx +0 -107
  69. package/templates/storefront-nextjs/app/search/page.tsx +0 -127
  70. package/templates/storefront-nextjs/components/auth/auth-guard.tsx +0 -94
  71. package/templates/storefront-nextjs/components/commerce/add-to-cart-button.tsx +0 -77
  72. package/templates/storefront-nextjs/components/commerce/cart-icon.tsx +0 -29
  73. package/templates/storefront-nextjs/components/commerce/currency-selector.tsx +0 -217
  74. package/templates/storefront-nextjs/components/commerce/pagination.tsx +0 -62
  75. package/templates/storefront-nextjs/components/commerce/product-actions.tsx +0 -135
  76. package/templates/storefront-nextjs/components/commerce/product-filters.tsx +0 -109
  77. package/templates/storefront-nextjs/components/commerce/product-price.tsx +0 -375
  78. package/templates/storefront-nextjs/components/commerce/search-input.tsx +0 -178
  79. package/templates/storefront-nextjs/components/commerce/sort-select.tsx +0 -64
  80. package/templates/storefront-nextjs/components/commerce/variant-selector.tsx +0 -210
  81. package/templates/storefront-nextjs/components/layout/footer.tsx +0 -107
  82. package/templates/storefront-nextjs/components/layout/header.tsx +0 -104
  83. package/templates/storefront-nextjs/components/providers.tsx +0 -62
  84. package/templates/storefront-nextjs/lib/auth/routes.ts +0 -52
  85. package/templates/storefront-nextjs/lib/currency.tsx +0 -140
  86. package/templates/storefront-nextjs/lib/format.ts +0 -159
  87. package/templates/storefront-nextjs/lib/graphql-queries.ts +0 -629
  88. package/templates/storefront-nextjs/lib/hooks.ts +0 -30
  89. package/templates/storefront-nextjs/middleware.ts +0 -80
  90. package/templates/storefront-nextjs/next.config.ts +0 -37
  91. package/templates/storefront-nextjs/open-next.config.ts +0 -3
  92. package/templates/storefront-nextjs/package.dev.json +0 -30
  93. package/templates/storefront-nextjs/package.json +0 -32
  94. package/templates/storefront-nextjs/package.json.template +0 -32
  95. package/templates/storefront-nextjs/postcss.config.mjs +0 -8
  96. package/templates/storefront-nextjs/tailwind.config.ts +0 -111
  97. package/templates/storefront-nextjs/tsconfig.json +0 -27
  98. package/templates/storefront-nextjs/wrangler.toml +0 -24
@@ -1,216 +0,0 @@
1
- "use client";
2
-
3
- import Link from "next/link";
4
- import { useCustomer } from "@doswiftly/storefront-sdk/graphql/client";
5
- import { useAuth } from "@doswiftly/storefront-sdk/graphql/react";
6
- import { AuthGuard } from "@/components/auth/auth-guard";
7
-
8
- function OrdersContent() {
9
- const { customerToken } = useAuth();
10
- const { data, isLoading } = useCustomer(
11
- { customerAccessToken: customerToken! },
12
- { enabled: !!customerToken }
13
- );
14
-
15
- if (isLoading) {
16
- return (
17
- <div className="container mx-auto px-4 py-8">
18
- <div className="flex items-center justify-center py-12">
19
- <div className="h-8 w-8 animate-spin rounded-full border-4 border-gray-200 border-t-gray-900" />
20
- </div>
21
- </div>
22
- );
23
- }
24
-
25
- const orders = data?.customer?.orders?.edges?.map((edge) => edge.node) ?? [];
26
-
27
- // Map status to display text and color
28
- const getFinancialStatusDisplay = (status: string) => {
29
- const statusMap: Record<string, { text: string; className: string }> = {
30
- PAID: { text: "Paid", className: "bg-green-100 text-green-800" },
31
- PENDING: { text: "Pending", className: "bg-yellow-100 text-yellow-800" },
32
- AUTHORIZED: {
33
- text: "Authorized",
34
- className: "bg-blue-100 text-blue-800",
35
- },
36
- REFUNDED: { text: "Refunded", className: "bg-gray-100 text-gray-800" },
37
- PARTIALLY_REFUNDED: {
38
- text: "Partially Refunded",
39
- className: "bg-orange-100 text-orange-800",
40
- },
41
- VOIDED: { text: "Voided", className: "bg-red-100 text-red-800" },
42
- };
43
- return (
44
- statusMap[status] ?? {
45
- text: status,
46
- className: "bg-gray-100 text-gray-800",
47
- }
48
- );
49
- };
50
-
51
- const getFulfillmentStatusDisplay = (status: string) => {
52
- const statusMap: Record<string, { text: string; className: string }> = {
53
- FULFILLED: {
54
- text: "Fulfilled",
55
- className: "bg-green-100 text-green-800",
56
- },
57
- UNFULFILLED: {
58
- text: "Unfulfilled",
59
- className: "bg-yellow-100 text-yellow-800",
60
- },
61
- PARTIALLY_FULFILLED: {
62
- text: "Partially Fulfilled",
63
- className: "bg-blue-100 text-blue-800",
64
- },
65
- SCHEDULED: {
66
- text: "Scheduled",
67
- className: "bg-purple-100 text-purple-800",
68
- },
69
- };
70
- return (
71
- statusMap[status] ?? {
72
- text: status,
73
- className: "bg-gray-100 text-gray-800",
74
- }
75
- );
76
- };
77
-
78
- return (
79
- <div className="container mx-auto px-4 py-8">
80
- {/* Breadcrumb */}
81
- <nav className="mb-4 text-sm">
82
- <ol className="flex items-center gap-2">
83
- <li>
84
- <Link href="/account" className="text-gray-500 hover:text-gray-700">
85
- Account
86
- </Link>
87
- </li>
88
- <li className="text-gray-400">/</li>
89
- <li className="text-gray-900">Orders</li>
90
- </ol>
91
- </nav>
92
-
93
- {/* Page Header */}
94
- <h1 className="mb-8 text-3xl font-bold text-gray-900">Order History</h1>
95
-
96
- {/* Orders List */}
97
- {orders.length === 0 ? (
98
- <div className="rounded-lg border border-gray-200 p-12 text-center">
99
- <p className="mb-4 text-gray-500">
100
- You haven&apos;t placed any orders yet.
101
- </p>
102
- <Link
103
- href="/products"
104
- className="inline-block rounded-lg bg-gray-900 px-6 py-3 font-medium text-white hover:bg-gray-800"
105
- >
106
- Start Shopping
107
- </Link>
108
- </div>
109
- ) : (
110
- <div className="space-y-4">
111
- {orders.map((order) => {
112
- const financialStatus = getFinancialStatusDisplay(
113
- order.financialStatus
114
- );
115
- const fulfillmentStatus = getFulfillmentStatusDisplay(
116
- order.fulfillmentStatus
117
- );
118
- const date = new Date(order.processedAt);
119
-
120
- return (
121
- <div
122
- key={order.id}
123
- className="rounded-lg border border-gray-200 p-6"
124
- >
125
- {/* Order Header */}
126
- <div className="mb-4 flex flex-wrap items-start justify-between gap-4">
127
- <div>
128
- <p className="text-lg font-semibold text-gray-900">
129
- Order #{order.orderNumber}
130
- </p>
131
- <p className="text-sm text-gray-500">
132
- {date.toLocaleDateString("en-US", {
133
- year: "numeric",
134
- month: "long",
135
- day: "numeric",
136
- })}
137
- </p>
138
- </div>
139
- <div className="flex flex-wrap gap-2">
140
- <span
141
- className={`rounded-full px-3 py-1 text-xs font-medium ${financialStatus.className}`}
142
- >
143
- {financialStatus.text}
144
- </span>
145
- <span
146
- className={`rounded-full px-3 py-1 text-xs font-medium ${fulfillmentStatus.className}`}
147
- >
148
- {fulfillmentStatus.text}
149
- </span>
150
- </div>
151
- </div>
152
-
153
- {/* Order Details */}
154
- <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
155
- <div>
156
- <span className="text-sm text-gray-500">Items</span>
157
- <p className="font-medium text-gray-900">
158
- {order.lineItemsCount}{" "}
159
- {order.lineItemsCount === 1 ? "item" : "items"}
160
- </p>
161
- </div>
162
- <div>
163
- <span className="text-sm text-gray-500">Subtotal</span>
164
- <p className="font-medium text-gray-900">
165
- {order.subtotalPrice.currencyCode}{" "}
166
- {order.subtotalPrice.amount}
167
- </p>
168
- </div>
169
- {order.totalShipping && (
170
- <div>
171
- <span className="text-sm text-gray-500">Shipping</span>
172
- <p className="font-medium text-gray-900">
173
- {order.totalShipping.currencyCode}{" "}
174
- {order.totalShipping.amount}
175
- </p>
176
- </div>
177
- )}
178
- <div>
179
- <span className="text-sm text-gray-500">Total</span>
180
- <p className="font-medium text-gray-900">
181
- {order.totalPrice.currencyCode} {order.totalPrice.amount}
182
- </p>
183
- </div>
184
- </div>
185
-
186
- {/* Shipping Address */}
187
- {order.shippingAddress && (
188
- <div className="mt-4 border-t border-gray-200 pt-4">
189
- <span className="text-sm text-gray-500">Ship to</span>
190
- <p className="text-sm text-gray-900">
191
- {order.shippingAddress.firstName}{" "}
192
- {order.shippingAddress.lastName},{" "}
193
- {order.shippingAddress.address1},{" "}
194
- {order.shippingAddress.city},{" "}
195
- {order.shippingAddress.province}{" "}
196
- {order.shippingAddress.zip},{" "}
197
- {order.shippingAddress.country}
198
- </p>
199
- </div>
200
- )}
201
- </div>
202
- );
203
- })}
204
- </div>
205
- )}
206
- </div>
207
- );
208
- }
209
-
210
- export default function OrdersPage() {
211
- return (
212
- <AuthGuard>
213
- <OrdersContent />
214
- </AuthGuard>
215
- );
216
- }
@@ -1,167 +0,0 @@
1
- "use client";
2
-
3
- import Link from "next/link";
4
- import { useRouter } from "next/navigation";
5
- import { useAuth, useLogout } from "@doswiftly/storefront-sdk/graphql/react";
6
- import { useCustomer } from "@doswiftly/storefront-sdk/graphql/client";
7
- import { AuthGuard } from "@/components/auth/auth-guard";
8
-
9
- function AccountContent() {
10
- const router = useRouter();
11
- const { customerToken } = useAuth();
12
- const { logout } = useLogout();
13
- const { data, isLoading } = useCustomer(
14
- { customerAccessToken: customerToken! },
15
- { enabled: !!customerToken }
16
- );
17
-
18
- const handleLogout = () => {
19
- logout();
20
- router.push("/");
21
- };
22
-
23
- if (isLoading) {
24
- return (
25
- <div className="container mx-auto px-4 py-8">
26
- <div className="flex items-center justify-center py-12">
27
- <div className="h-8 w-8 animate-spin rounded-full border-4 border-gray-200 border-t-gray-900" />
28
- </div>
29
- </div>
30
- );
31
- }
32
-
33
- const customer = data?.customer;
34
-
35
- return (
36
- <div className="container mx-auto px-4 py-8">
37
- {/* Page Header */}
38
- <div className="mb-8 flex items-center justify-between">
39
- <h1 className="text-3xl font-bold text-gray-900">My Account</h1>
40
- <button
41
- onClick={handleLogout}
42
- className="rounded-lg border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50"
43
- >
44
- Logout
45
- </button>
46
- </div>
47
-
48
- {/* Account Grid */}
49
- <div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
50
- {/* Profile Card */}
51
- <div className="rounded-lg border border-gray-200 p-6">
52
- <h2 className="mb-4 text-lg font-semibold text-gray-900">Profile</h2>
53
- <div className="space-y-3">
54
- <div>
55
- <span className="text-sm text-gray-500">Name</span>
56
- <p className="font-medium text-gray-900">
57
- {customer?.firstName && customer?.lastName
58
- ? `${customer.firstName} ${customer.lastName}`
59
- : "Not set"}
60
- </p>
61
- </div>
62
- <div>
63
- <span className="text-sm text-gray-500">Email</span>
64
- <p className="font-medium text-gray-900">{customer?.email}</p>
65
- </div>
66
- {customer?.phone && (
67
- <div>
68
- <span className="text-sm text-gray-500">Phone</span>
69
- <p className="font-medium text-gray-900">{customer.phone}</p>
70
- </div>
71
- )}
72
- </div>
73
- </div>
74
-
75
- {/* Orders Card */}
76
- <Link
77
- href="/account/orders"
78
- className="rounded-lg border border-gray-200 p-6 transition hover:border-gray-300 hover:shadow-sm"
79
- >
80
- <h2 className="mb-2 text-lg font-semibold text-gray-900">Orders</h2>
81
- <p className="text-sm text-gray-600">
82
- View your order history and track shipments
83
- </p>
84
- <div className="mt-4 flex items-center text-sm font-medium text-gray-900">
85
- View orders
86
- <svg
87
- className="ml-2 h-4 w-4"
88
- fill="none"
89
- viewBox="0 0 24 24"
90
- stroke="currentColor"
91
- >
92
- <path
93
- strokeLinecap="round"
94
- strokeLinejoin="round"
95
- strokeWidth={2}
96
- d="M9 5l7 7-7 7"
97
- />
98
- </svg>
99
- </div>
100
- </Link>
101
-
102
- {/* Addresses Card */}
103
- <Link
104
- href="/account/addresses"
105
- className="rounded-lg border border-gray-200 p-6 transition hover:border-gray-300 hover:shadow-sm"
106
- >
107
- <h2 className="mb-2 text-lg font-semibold text-gray-900">
108
- Addresses
109
- </h2>
110
- <p className="text-sm text-gray-600">
111
- Manage your shipping and billing addresses
112
- </p>
113
- <div className="mt-4 flex items-center text-sm font-medium text-gray-900">
114
- Manage addresses
115
- <svg
116
- className="ml-2 h-4 w-4"
117
- fill="none"
118
- viewBox="0 0 24 24"
119
- stroke="currentColor"
120
- >
121
- <path
122
- strokeLinecap="round"
123
- strokeLinejoin="round"
124
- strokeWidth={2}
125
- d="M9 5l7 7-7 7"
126
- />
127
- </svg>
128
- </div>
129
- </Link>
130
- </div>
131
-
132
- {/* Default Addresses */}
133
- {customer?.defaultAddress && (
134
- <div className="mt-8">
135
- <h2 className="mb-4 text-lg font-semibold text-gray-900">
136
- Default Address
137
- </h2>
138
- <div className="rounded-lg border border-gray-200 p-4">
139
- <p className="text-gray-900">
140
- {customer.defaultAddress.firstName}{" "}
141
- {customer.defaultAddress.lastName}
142
- </p>
143
- <p className="text-gray-600">{customer.defaultAddress.address1}</p>
144
- {customer.defaultAddress.address2 && (
145
- <p className="text-gray-600">
146
- {customer.defaultAddress.address2}
147
- </p>
148
- )}
149
- <p className="text-gray-600">
150
- {customer.defaultAddress.city}, {customer.defaultAddress.province}{" "}
151
- {customer.defaultAddress.zip}
152
- </p>
153
- <p className="text-gray-600">{customer.defaultAddress.country}</p>
154
- </div>
155
- </div>
156
- )}
157
- </div>
158
- );
159
- }
160
-
161
- export default function AccountPage() {
162
- return (
163
- <AuthGuard>
164
- <AccountContent />
165
- </AuthGuard>
166
- );
167
- }
@@ -1,135 +0,0 @@
1
- "use client";
2
-
3
- import { useState, FormEvent, Suspense } from "react";
4
- import Link from "next/link";
5
- import { useRouter, useSearchParams } from "next/navigation";
6
- import { useLogin } from "@doswiftly/storefront-sdk/graphql/react";
7
- import { AuthGuard } from "@/components/auth/auth-guard";
8
-
9
- function LoginFormContent() {
10
- const router = useRouter();
11
- const searchParams = useSearchParams();
12
- const login = useLogin();
13
-
14
- const [email, setEmail] = useState("");
15
- const [password, setPassword] = useState("");
16
- const [error, setError] = useState<string | null>(null);
17
-
18
- const handleSubmit = async (e: FormEvent) => {
19
- e.preventDefault();
20
- setError(null);
21
-
22
- try {
23
- const result = await login.mutateAsync({
24
- input: { email, password },
25
- });
26
-
27
- // Check for user errors
28
- const userErrors = result.customerAccessTokenCreate?.userErrors;
29
- if (userErrors && userErrors.length > 0) {
30
- setError(userErrors[0].message);
31
- return;
32
- }
33
-
34
- // Success - redirect to original page or account
35
- const redirectTo = searchParams.get("redirect") || "/account";
36
- router.push(redirectTo);
37
- } catch (err) {
38
- setError("Login failed. Please try again.");
39
- }
40
- };
41
-
42
- return (
43
- <div className="container mx-auto flex min-h-[60vh] items-center justify-center px-4">
44
- <div className="w-full max-w-md">
45
- <h1 className="mb-8 text-center text-3xl font-bold text-gray-900">
46
- Login
47
- </h1>
48
-
49
- {error && (
50
- <div className="mb-6 rounded-lg bg-red-50 p-4 text-red-700">
51
- {error}
52
- </div>
53
- )}
54
-
55
- <form onSubmit={handleSubmit} className="space-y-6">
56
- <div>
57
- <label
58
- htmlFor="email"
59
- className="mb-2 block text-sm font-medium text-gray-900"
60
- >
61
- Email
62
- </label>
63
- <input
64
- type="email"
65
- id="email"
66
- value={email}
67
- onChange={(e) => setEmail(e.target.value)}
68
- required
69
- className="w-full rounded-lg border border-gray-300 px-4 py-3 focus:border-gray-900 focus:outline-none"
70
- placeholder="your@email.com"
71
- />
72
- </div>
73
-
74
- <div>
75
- <label
76
- htmlFor="password"
77
- className="mb-2 block text-sm font-medium text-gray-900"
78
- >
79
- Password
80
- </label>
81
- <input
82
- type="password"
83
- id="password"
84
- value={password}
85
- onChange={(e) => setPassword(e.target.value)}
86
- required
87
- className="w-full rounded-lg border border-gray-300 px-4 py-3 focus:border-gray-900 focus:outline-none"
88
- placeholder="••••••••"
89
- />
90
- </div>
91
-
92
- <button
93
- type="submit"
94
- disabled={login.isPending}
95
- className="w-full rounded-lg bg-gray-900 py-3 font-medium text-white transition hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-50"
96
- >
97
- {login.isPending ? "Logging in..." : "Login"}
98
- </button>
99
- </form>
100
-
101
- <p className="mt-6 text-center text-sm text-gray-600">
102
- Don&apos;t have an account?{" "}
103
- <Link
104
- href="/auth/register"
105
- className="font-medium text-gray-900 hover:underline"
106
- >
107
- Register
108
- </Link>
109
- </p>
110
- </div>
111
- </div>
112
- );
113
- }
114
-
115
- function LoginForm() {
116
- return (
117
- <Suspense
118
- fallback={
119
- <div className="container mx-auto flex min-h-[60vh] items-center justify-center px-4">
120
- <div className="h-8 w-8 animate-spin rounded-full border-4 border-gray-200 border-t-gray-900" />
121
- </div>
122
- }
123
- >
124
- <LoginFormContent />
125
- </Suspense>
126
- );
127
- }
128
-
129
- export default function LoginPage() {
130
- return (
131
- <AuthGuard requireGuest>
132
- <LoginForm />
133
- </AuthGuard>
134
- );
135
- }