@doswiftly/cli 0.2.1 → 0.2.6
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/CHANGELOG.md +260 -0
- package/README.md +1 -1
- package/bin/doswiftly.js +0 -0
- package/dist/commands/dev.d.ts +7 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +110 -51
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/env.d.ts.map +1 -1
- package/dist/commands/env.js +11 -1
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/init.js +2 -2
- package/dist/commands/inspect.d.ts.map +1 -1
- package/dist/commands/inspect.js +5 -1
- package/dist/commands/inspect.js.map +1 -1
- package/dist/commands/proxy.d.ts.map +1 -1
- package/dist/commands/proxy.js +7 -1
- package/dist/commands/proxy.js.map +1 -1
- package/dist/commands/template.js +1 -1
- package/dist/config/types.d.ts +8 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/api-url.d.ts +77 -8
- package/dist/lib/api-url.d.ts.map +1 -1
- package/dist/lib/api-url.js +54 -12
- package/dist/lib/api-url.js.map +1 -1
- package/dist/lib/config.d.ts +1 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +9 -12
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/i18n.d.ts +24 -0
- package/dist/lib/i18n.d.ts.map +1 -1
- package/dist/lib/i18n.js +48 -0
- package/dist/lib/i18n.js.map +1 -1
- package/dist/lib/proxy-server.d.ts +26 -0
- package/dist/lib/proxy-server.d.ts.map +1 -1
- package/dist/lib/proxy-server.js +70 -0
- package/dist/lib/proxy-server.js.map +1 -1
- package/package.json +13 -12
- package/templates/storefront-nextjs-shadcn/app/[locale]/products/[slug]/product-client.tsx +87 -2
- package/templates/storefront-nextjs-shadcn/app/[locale]/products/products-client.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/codegen.ts +1 -1
- package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +18 -0
- package/templates/storefront-nextjs-shadcn/components/cart/cart-line.fragment.graphql +17 -1
- package/templates/storefront-nextjs-shadcn/components/home/collection-card.fragment.graphql +2 -1
- package/templates/storefront-nextjs-shadcn/components/layout/category-node.fragment.graphql +2 -1
- package/templates/storefront-nextjs-shadcn/components/product/add-to-cart-button.tsx +23 -3
- package/templates/storefront-nextjs-shadcn/components/product/filter-active-pills.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/product/filter-mobile-sheet.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/product/product-card.fragment.graphql +2 -1
- package/templates/storefront-nextjs-shadcn/components/product/product-configurator.fragment.graphql +43 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-configurator.tsx +282 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-detail.fragment.graphql +8 -1
- package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +7 -3
- package/templates/storefront-nextjs-shadcn/components/product/product-variant.fragment.graphql +2 -1
- package/templates/storefront-nextjs-shadcn/graphql/custom.example.graphql +100 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-actions.ts +26 -5
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +26 -0
- package/templates/storefront-nextjs-shadcn/lib/image-loader.ts +12 -0
- package/templates/storefront-nextjs-shadcn/next.config.ts +6 -17
- package/templates/storefront-nextjs-shadcn/package.json +2 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7846bdb: Fix `doswiftly dev` port pre-flight on Windows (and any host where another
|
|
8
|
+
process binds the port on IPv6 `::` only): the probe now checks IPv4 and
|
|
9
|
+
IPv6 in parallel and requires BOTH free before marking a port as available.
|
|
10
|
+
Previously an IPv6-only conflict (common on Windows, where Next.js binds
|
|
11
|
+
`::` by default) slipped past the IPv4-only probe — the banner advertised
|
|
12
|
+
`http://localhost:3000` and the framework immediately crashed with
|
|
13
|
+
`EADDRINUSE :::3000`. With this fix `doswiftly dev` falls back to the next
|
|
14
|
+
free port (3001, 3002, …) as documented.
|
|
15
|
+
|
|
16
|
+
Also ship `CHANGELOG.md` inside the npm tarball. Previous releases packed
|
|
17
|
+
only `dist`/`bin`/`templates` (and `schema.graphql`/operations for
|
|
18
|
+
`storefront-operations`, `dist` for `storefront-sdk`), so consumers who
|
|
19
|
+
`npm install @doswiftly/cli` got a version number with no user-visible
|
|
20
|
+
release notes.
|
|
21
|
+
|
|
22
|
+
## 0.2.5
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- e3174bb: Fix `doswiftly dev` to handle two common papercuts out of the box.
|
|
27
|
+
|
|
28
|
+
**Port pre-flight + auto-fallback.** `doswiftly dev` now probes the requested port
|
|
29
|
+
(default `3000`) before spawning the framework and auto-falls back to the next free
|
|
30
|
+
port up to `+10` (e.g. `3000 → 3001 → 3002`) — no more `EADDRINUSE` crashes when
|
|
31
|
+
another process already owns the default port. The banner is printed after the port
|
|
32
|
+
is reserved, so the advertised URL always matches what the framework actually binds.
|
|
33
|
+
Pass `--strict-port` (or set `dev.strictPort: true` in `doswiftly.config.ts`) to
|
|
34
|
+
fail fast instead of falling back.
|
|
35
|
+
|
|
36
|
+
**Active profile now wins over `api.url`.** `doswiftly env use <profile>` used to be
|
|
37
|
+
silently ignored for `doswiftly dev`, `inspect`, and `proxy` when `doswiftly.config.ts`
|
|
38
|
+
contained an `api.url` (which every scaffold sets). The precedence is now:
|
|
39
|
+
`DOSWIFTLY_API_URL` / `NEXT_PUBLIC_API_URL` shell env > active profile >
|
|
40
|
+
`doswiftly.config.ts` `api.url` > `.env.local` > default. `doswiftly deploy`
|
|
41
|
+
keeps its existing behaviour (project config wins unless `DOSWIFTLY_API_URL` is set).
|
|
42
|
+
|
|
43
|
+
Extras shipped alongside the fixes:
|
|
44
|
+
- `--strict-port` flag on `doswiftly dev`.
|
|
45
|
+
- The dev banner reports where the API URL came from
|
|
46
|
+
(e.g. `API: http://localhost:8000 (from profile "dev")`).
|
|
47
|
+
- `doswiftly env use` prints a one-line hint when the active profile overrides
|
|
48
|
+
`api.url` from `doswiftly.config.ts`.
|
|
49
|
+
- A warning when your `package.json` dev script hardcodes a port
|
|
50
|
+
(e.g. `"dev": "next dev -p 3000"`) that may override the CLI-supplied port.
|
|
51
|
+
|
|
52
|
+
All notable changes to `@doswiftly/cli` will be documented in this file.
|
|
53
|
+
|
|
54
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
55
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
56
|
+
|
|
57
|
+
## [0.2.4] - 2026-04-20
|
|
58
|
+
|
|
59
|
+
### Fixed
|
|
60
|
+
|
|
61
|
+
- **`doswiftly dev` no longer crashes with `EADDRINUSE` when the dev port is in use.**
|
|
62
|
+
The CLI now probes the requested port (default `3000`) before starting the framework and
|
|
63
|
+
auto-falls back to the next free port up to `+10` (so `3000 → 3001 → 3002`). The banner is
|
|
64
|
+
printed after the port is bound, so `Storefront: http://localhost:3001` always matches what
|
|
65
|
+
actually starts. Opt out with `--strict-port` on the command or `dev.strictPort: true` in
|
|
66
|
+
`doswiftly.config.ts` to fail fast instead.
|
|
67
|
+
- **`doswiftly env use <profile>` now takes precedence over `api.url` in `doswiftly.config.ts`
|
|
68
|
+
for `doswiftly dev`, `inspect`, and `proxy`.** Previously, the project config silently
|
|
69
|
+
overrode the active profile, so switching to a `dev` profile with `API: http://localhost:8000`
|
|
70
|
+
still hit the production URL configured at scaffold time. Shell env vars (`DOSWIFTLY_API_URL`,
|
|
71
|
+
`NEXT_PUBLIC_API_URL`) stay on top for CI/CD and ad-hoc overrides. `doswiftly deploy`
|
|
72
|
+
behaviour is unchanged.
|
|
73
|
+
|
|
74
|
+
### Added
|
|
75
|
+
|
|
76
|
+
- **`--strict-port` flag and `dev.strictPort` config field** for `doswiftly dev`. When set,
|
|
77
|
+
the command fails with an actionable error (including the blocking port and the hint to
|
|
78
|
+
pass `--port <N>`) instead of auto-falling back.
|
|
79
|
+
- **Banner now reports where the API URL came from** (e.g. `API: http://localhost:8000
|
|
80
|
+
(from profile "dev")`), making it easier to diagnose unexpected target URLs.
|
|
81
|
+
- **`doswiftly env use` surfaces a one-line notice** when the project's `doswiftly.config.ts`
|
|
82
|
+
hardcodes a different `api.url` than the active profile, so you know the profile is
|
|
83
|
+
intentionally taking over.
|
|
84
|
+
- **Warning for hardcoded port in your `dev` script.** When `package.json` has
|
|
85
|
+
`"dev": "next dev -p 3000"` (or similar), the CLI warns in CI logs that the hardcoded port
|
|
86
|
+
may override `--port` / `PORT` env.
|
|
87
|
+
|
|
88
|
+
## [0.2.3] - 2026-04-17
|
|
89
|
+
|
|
90
|
+
### Security
|
|
91
|
+
|
|
92
|
+
- Bump `axios` to `^1.15.0` to resolve GHSA-3p68-rc4w-qgx5 (NO_PROXY normalization bypass → SSRF) and GHSA-fvcv-3m26-pcqx (cloud metadata exfiltration via header injection).
|
|
93
|
+
|
|
94
|
+
## [0.2.2] - 2026-04-12
|
|
95
|
+
|
|
96
|
+
### Changed
|
|
97
|
+
|
|
98
|
+
- **Default `@doswiftly/storefront-operations` dependency bumped `^1.0.0` → `^5.0.0`.** New storefronts
|
|
99
|
+
scaffolded via `doswiftly init` / `doswiftly template` now pull the per-location
|
|
100
|
+
`storeAvailability` surface out of the box. Existing storefronts on older operations keep working —
|
|
101
|
+
bump the dependency manually and re-run `pnpm install` when you're ready to adopt it.
|
|
102
|
+
- **Storefront template (`storefront-nextjs-shadcn`): BOPIS example in `custom.example.graphql`
|
|
103
|
+
rewritten to the new API.** The `storeAvailability(first, near, locationType)` field on
|
|
104
|
+
`ProductVariant` replaces the previous per-location lookup, and the example now demonstrates the
|
|
105
|
+
`@inContext(preferredLocationId)` operation directive plus a `GetPickupLocations` store picker
|
|
106
|
+
query.
|
|
107
|
+
|
|
108
|
+
## [0.2.1] - 2026-04-10
|
|
109
|
+
|
|
110
|
+
### Fixed
|
|
111
|
+
|
|
112
|
+
- **Dev proxy: strip Referer header alongside Origin.** The CSRF origin middleware on the
|
|
113
|
+
production backend validates both `Origin` and `Referer` headers. The proxy was only stripping
|
|
114
|
+
`Origin`, so the browser's `Referer: http://localhost:3000` was forwarded and rejected as
|
|
115
|
+
an unknown origin. Now both are stripped, making proxied requests appear as server-to-server.
|
|
116
|
+
|
|
117
|
+
## [0.2.0] - 2026-04-10
|
|
118
|
+
|
|
119
|
+
### Added
|
|
120
|
+
|
|
121
|
+
- **Init: adopt flow for existing projects.** Running `doswiftly init` in a non-empty directory
|
|
122
|
+
now detects the existing project and offers to connect it to DoSwiftly without copying template
|
|
123
|
+
files. Creates `doswiftly.config.ts`, merges `.env.local`, and optionally installs SDK packages.
|
|
124
|
+
- **Dev: automatic API proxy for CORS-free development.** `doswiftly dev` now auto-starts a local
|
|
125
|
+
proxy when the API URL points to a remote server, eliminating CORS errors during local development.
|
|
126
|
+
The proxy forwards all headers and runs transparently — no code changes needed in the storefront.
|
|
127
|
+
|
|
128
|
+
### Changed
|
|
129
|
+
|
|
130
|
+
- **Renamed "Commerce SDK" to "Storefront SDK"** across all CLI output, command descriptions,
|
|
131
|
+
and help text to match the actual package name (`@doswiftly/storefront-sdk`).
|
|
132
|
+
- **Doctor: accepts `storefront-sdk` OR `storefront-operations`** as valid DoSwiftly dependencies
|
|
133
|
+
(matching deploy command logic).
|
|
134
|
+
- **Dev: framework-agnostic dev command.** `doswiftly dev` now reads `scripts.dev` from
|
|
135
|
+
`package.json` instead of hardcoding `next dev`.
|
|
136
|
+
- **Proxy: full header forwarding.** The proxy now forwards all request/response headers
|
|
137
|
+
(except hop-by-hop), including SDK headers, cookies, and Set-Cookie.
|
|
138
|
+
|
|
139
|
+
### Removed
|
|
140
|
+
|
|
141
|
+
- **Deprecated templates `storefront-nextjs` and `storefront-minimal`** removed from the package.
|
|
142
|
+
Only `storefront-nextjs-shadcn` (Next.js 16 + shadcn/ui) is shipped. These templates had
|
|
143
|
+
broken dependencies and outdated SDK references.
|
|
144
|
+
- **Dead code:** removed duplicate `sdkVersionCommand` in `types.ts`, removed unused
|
|
145
|
+
`COMMERCE_SDK_VERSION` placeholder from init and template commands.
|
|
146
|
+
|
|
147
|
+
### Fixed
|
|
148
|
+
|
|
149
|
+
- **Verify/Check: fixed `env:generate` → `env generate`** in help text (commands use spaces, not colons).
|
|
150
|
+
|
|
151
|
+
## [0.1.24] - 2026-04-10
|
|
152
|
+
|
|
153
|
+
### Fixed
|
|
154
|
+
|
|
155
|
+
- **Deploy: fix esbuild version detection using `pnpm ls` instead of binary/require().**
|
|
156
|
+
Both `pnpm exec esbuild --version` and `require('esbuild/package.json')` fail silently
|
|
157
|
+
in pnpm strict mode for transitive deps. Now uses `pnpm ls esbuild --parseable` which
|
|
158
|
+
queries pnpm's own dependency graph — works regardless of hoisting or strict mode config.
|
|
159
|
+
- **Deploy: suggest highest installed esbuild version in fix instructions.** Instead of
|
|
160
|
+
a hardcoded `>=0.17.0`, the error message now suggests the highest esbuild version
|
|
161
|
+
already in the dependency tree (e.g. `0.25.4` from `@opennextjs/cloudflare`).
|
|
162
|
+
|
|
163
|
+
## [0.1.23] - 2026-04-10
|
|
164
|
+
|
|
165
|
+
### Added
|
|
166
|
+
|
|
167
|
+
- **Deploy: early detection of incompatible esbuild versions.** If a transitive dependency
|
|
168
|
+
(e.g. `react-email`) pulls in esbuild <0.16.10 (lacks subpath alias support), CLI now
|
|
169
|
+
detects this before the build and exits with an actionable error message explaining how
|
|
170
|
+
to add an override. Uses the same `pnpm exec` resolution pattern as wrangler.
|
|
171
|
+
|
|
172
|
+
### Removed
|
|
173
|
+
|
|
174
|
+
- Removed auto-override of merchant's `package.json` (0.1.20-0.1.22). The approach was
|
|
175
|
+
unreliable across pnpm configurations and overstepped CLI's responsibility — dependency
|
|
176
|
+
management belongs to the project owner, not the deploy tool.
|
|
177
|
+
|
|
178
|
+
## [0.1.19] - 2026-04-08
|
|
179
|
+
|
|
180
|
+
### Fixed
|
|
181
|
+
|
|
182
|
+
- Deploy: improved Cloudflare WAF/Bot protection error diagnostics with CF-Ray ID and hints.
|
|
183
|
+
- Deploy: better error formatting for HTML error pages from Cloudflare.
|
|
184
|
+
|
|
185
|
+
## [0.1.18] - 2026-04-05
|
|
186
|
+
|
|
187
|
+
### Added
|
|
188
|
+
|
|
189
|
+
- Deploy: `[observability]` section in generated `wrangler.toml` — logs persisted in Cloudflare Dashboard.
|
|
190
|
+
- Deploy: `[images]` binding for Next.js `/_next/image` optimization via Cloudflare Images.
|
|
191
|
+
|
|
192
|
+
## [0.1.17] - 2026-03-28
|
|
193
|
+
|
|
194
|
+
### Fixed
|
|
195
|
+
|
|
196
|
+
- Deploy: added Wrangler re-bundle step (`wrangler deploy --dry-run --outdir`) to convert
|
|
197
|
+
`require()` calls to ESM imports. Without this, CF Workers throw
|
|
198
|
+
`Dynamic require of "node:crypto" is not supported`.
|
|
199
|
+
- Deploy: CLI now auto-installs `wrangler` if not present in the project.
|
|
200
|
+
- Deploy: only `.js`, `.mjs`, `.wasm` files are copied from Wrangler output (skips `.map`, `README`).
|
|
201
|
+
|
|
202
|
+
### Changed
|
|
203
|
+
|
|
204
|
+
- Deploy: CLI generates `wrangler.toml` automatically, overwriting merchant's version to ensure
|
|
205
|
+
correct worker name, compatibility flags, and ASSETS binding.
|
|
206
|
+
- Deploy: CLI generates `open-next.config.ts` (required by `@opennextjs/cloudflare` 1.17+).
|
|
207
|
+
|
|
208
|
+
## [0.1.16] - 2026-03-20
|
|
209
|
+
|
|
210
|
+
### Added
|
|
211
|
+
|
|
212
|
+
- `doswiftly upgrade` — user-friendly wrapper for template migration commands.
|
|
213
|
+
- `doswiftly migrate check/apply/diff` — template update management.
|
|
214
|
+
|
|
215
|
+
## [0.1.15] - 2026-03-15
|
|
216
|
+
|
|
217
|
+
### Added
|
|
218
|
+
|
|
219
|
+
- `doswiftly auth github` — GitHub account linking via device flow.
|
|
220
|
+
- `doswiftly auth token` — deploy token generation for CI/CD pipelines.
|
|
221
|
+
- `doswiftly template create/register/publish/validate` — SaaS developer template management.
|
|
222
|
+
|
|
223
|
+
## [0.1.14] - 2026-03-10
|
|
224
|
+
|
|
225
|
+
### Added
|
|
226
|
+
|
|
227
|
+
- `doswiftly preview create/list/stop/logs/open` — preview environment management.
|
|
228
|
+
- `doswiftly config domain add/remove/list` — custom domain management.
|
|
229
|
+
|
|
230
|
+
## [0.1.13] - 2026-03-05
|
|
231
|
+
|
|
232
|
+
### Added
|
|
233
|
+
|
|
234
|
+
- `doswiftly deploy run/status/rollback/logs` — Track 2 deployment pipeline.
|
|
235
|
+
- Content-hash manifest for incremental uploads (only changed assets uploaded).
|
|
236
|
+
- Idempotency keys for safe retries.
|
|
237
|
+
|
|
238
|
+
## [0.1.12] - 2026-02-28
|
|
239
|
+
|
|
240
|
+
### Added
|
|
241
|
+
|
|
242
|
+
- `doswiftly env add/use/list/generate/delete/set` — environment profile management.
|
|
243
|
+
- `doswiftly doctor` — project health diagnostics.
|
|
244
|
+
- `doswiftly check` — dependency validation.
|
|
245
|
+
|
|
246
|
+
## [0.1.11] - 2026-02-20
|
|
247
|
+
|
|
248
|
+
### Added
|
|
249
|
+
|
|
250
|
+
- `doswiftly dev` — development server with automatic env injection from API.
|
|
251
|
+
- `doswiftly config pull/show` — configuration management.
|
|
252
|
+
|
|
253
|
+
## [0.1.10] - 2026-02-15
|
|
254
|
+
|
|
255
|
+
### Added
|
|
256
|
+
|
|
257
|
+
- `doswiftly init` — interactive project scaffolding with template selection.
|
|
258
|
+
- `doswiftly auth login/logout` — OAuth authentication.
|
|
259
|
+
- `doswiftly whoami` — current context display.
|
|
260
|
+
- `doswiftly verify` — project verification.
|
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ doswiftly auth login # Login to DoSwiftly
|
|
|
21
21
|
doswiftly dev # Start development server
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
Your storefront will be running at `http://localhost:3000
|
|
24
|
+
Your storefront will be running at `http://localhost:3000` (or the next available port if 3000 is in use).
|
|
25
25
|
|
|
26
26
|
## Commands Overview
|
|
27
27
|
|
package/bin/doswiftly.js
CHANGED
|
File without changes
|
package/dist/commands/dev.d.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
interface DevOptions {
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Commander now coerces `--port` via `Number.parseInt`, but programmatic
|
|
4
|
+
* callers (tests, SDK embeds) may still pass a string. Accept both and
|
|
5
|
+
* coerce inside `devCommand`.
|
|
6
|
+
*/
|
|
7
|
+
port?: number | string;
|
|
3
8
|
host?: string;
|
|
4
9
|
open?: boolean;
|
|
10
|
+
strictPort?: boolean;
|
|
5
11
|
}
|
|
6
12
|
/**
|
|
7
13
|
* Detect the dev command and port/host args from package.json.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAgBA,UAAU,UAAU;IAClB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAcD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAqCjC;AAqCD,wBAAsB,UAAU,CAAC,OAAO,GAAE,UAAe,iBAiKxD"}
|
package/dist/commands/dev.js
CHANGED
|
@@ -3,8 +3,11 @@ import ora from "ora";
|
|
|
3
3
|
import { execa } from "execa";
|
|
4
4
|
import { existsSync, readFileSync } from "fs";
|
|
5
5
|
import { readLocalConfigSync } from "../lib/config.js";
|
|
6
|
-
import {
|
|
7
|
-
import { isRemoteUrl, findFreePort, startProxyServer } from "../lib/proxy-server.js";
|
|
6
|
+
import { resolveApiUrl } from "../lib/api-url.js";
|
|
7
|
+
import { isRemoteUrl, findFreePort, findSequentialFreePort, PortRangeExhaustedError, startProxyServer, } from "../lib/proxy-server.js";
|
|
8
|
+
import { logger } from "../lib/logger.js";
|
|
9
|
+
import { t } from "../lib/i18n.js";
|
|
10
|
+
const PORT_FALLBACK_MAX_ATTEMPTS = 10;
|
|
8
11
|
/**
|
|
9
12
|
* Read a non-commented env var value from a dotenv file content.
|
|
10
13
|
* Returns null if not found or commented out.
|
|
@@ -34,8 +37,15 @@ export function detectDevCommand(port, host) {
|
|
|
34
37
|
catch {
|
|
35
38
|
return { bin: "pnpm", args: ["dev"] };
|
|
36
39
|
}
|
|
37
|
-
// If scripts.dev exists, delegate — port/host set via env (PORT, HOST)
|
|
40
|
+
// If scripts.dev exists, delegate — port/host set via env (PORT, HOST).
|
|
41
|
+
// If the script hardcodes a port (e.g. `next dev -p 3000`), the env var
|
|
42
|
+
// cannot override it — surface a warning so the developer can diagnose.
|
|
38
43
|
if (pkg.scripts?.dev) {
|
|
44
|
+
const hardcoded = /(?:-p|--port)\s+\d+/.exec(pkg.scripts.dev);
|
|
45
|
+
if (hardcoded) {
|
|
46
|
+
logger.warn(t().devScriptsDevHardcodedPort(hardcoded[0]));
|
|
47
|
+
logger.ghWarning(t().devScriptsDevHardcodedPort(hardcoded[0]), "scripts.dev hardcoded port");
|
|
48
|
+
}
|
|
39
49
|
return { bin: "pnpm", args: ["run", "dev"] };
|
|
40
50
|
}
|
|
41
51
|
// No scripts.dev — detect framework and use correct flag syntax
|
|
@@ -52,56 +62,94 @@ export function detectDevCommand(port, host) {
|
|
|
52
62
|
return { bin: "pnpm", args: ["dev"] };
|
|
53
63
|
}
|
|
54
64
|
/**
|
|
55
|
-
*
|
|
65
|
+
* Render the provenance tag for the resolved API URL (e.g. `(from profile "dev")`).
|
|
56
66
|
*/
|
|
57
|
-
function
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (existsSync(".env.local")) {
|
|
70
|
-
const content = readFileSync(".env.local", "utf-8");
|
|
71
|
-
const value = readEnvVar(content, "NEXT_PUBLIC_API_URL");
|
|
72
|
-
if (value)
|
|
73
|
-
return value;
|
|
67
|
+
function describeApiUrlSource(resolution) {
|
|
68
|
+
switch (resolution.source) {
|
|
69
|
+
case "env":
|
|
70
|
+
return t().devApiSourceEnv(resolution.envVarName ?? "");
|
|
71
|
+
case "profile":
|
|
72
|
+
return t().devApiSourceProfile(resolution.profileName ?? "");
|
|
73
|
+
case "localConfig":
|
|
74
|
+
return t().devApiSourceLocalConfig;
|
|
75
|
+
case "dotEnvLocal":
|
|
76
|
+
return t().devApiSourceDotEnvLocal;
|
|
77
|
+
case "fallback":
|
|
78
|
+
return t().devApiSourceFallback;
|
|
74
79
|
}
|
|
75
|
-
return "http://localhost:8000";
|
|
76
80
|
}
|
|
77
81
|
/**
|
|
78
|
-
* Resolve shop slug from config sources.
|
|
82
|
+
* Resolve shop slug from project-scoped config sources. Profiles intentionally
|
|
83
|
+
* do not carry a slug (the slug is a property of the project, not the env).
|
|
79
84
|
*/
|
|
80
|
-
function resolveShopSlug(localConfig) {
|
|
85
|
+
function resolveShopSlug(localConfig, dotEnvLocal) {
|
|
81
86
|
if (process.env.NEXT_PUBLIC_SHOP_SLUG)
|
|
82
87
|
return process.env.NEXT_PUBLIC_SHOP_SLUG;
|
|
83
88
|
if (localConfig?.shop?.slug)
|
|
84
89
|
return localConfig.shop.slug;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (value)
|
|
89
|
-
return value;
|
|
90
|
-
}
|
|
90
|
+
const fromEnvLocal = readEnvVar(dotEnvLocal, "NEXT_PUBLIC_SHOP_SLUG");
|
|
91
|
+
if (fromEnvLocal)
|
|
92
|
+
return fromEnvLocal;
|
|
91
93
|
return "demo-shop";
|
|
92
94
|
}
|
|
93
95
|
export async function devCommand(options = {}) {
|
|
94
96
|
// Read local config (non-fatal if missing — adopt flow may not have config yet)
|
|
95
97
|
const localConfig = readLocalConfigSync();
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
//
|
|
98
|
+
const dotEnvLocal = existsSync(".env.local")
|
|
99
|
+
? readFileSync(".env.local", "utf-8")
|
|
100
|
+
: "";
|
|
101
|
+
// Unified precedence: shell env > active profile > doswiftly.config.ts > .env.local > default.
|
|
102
|
+
// The previous dev-local resolver put local config above profile, which silently
|
|
103
|
+
// ignored `doswiftly env use <profile>` when the project config had an api.url.
|
|
104
|
+
const apiResolution = resolveApiUrl({
|
|
105
|
+
envVarNames: ["NEXT_PUBLIC_API_URL", "DOSWIFTLY_API_URL"],
|
|
106
|
+
localConfigUrl: localConfig?.api?.url,
|
|
107
|
+
dotEnvLocalUrl: readEnvVar(dotEnvLocal, "NEXT_PUBLIC_API_URL") ?? undefined,
|
|
108
|
+
fallback: "http://localhost:8000",
|
|
109
|
+
});
|
|
110
|
+
const apiUrl = apiResolution.url;
|
|
111
|
+
const shopSlug = resolveShopSlug(localConfig, dotEnvLocal);
|
|
112
|
+
// Commander parses --port with Number.parseInt so options.port is already a
|
|
113
|
+
// number here. Defense-in-depth: coerce anything coming in as a string
|
|
114
|
+
// (future refactors, direct programmatic callers) and validate the range so
|
|
115
|
+
// `NaN` never reaches findSequentialFreePort's arithmetic.
|
|
116
|
+
const rawPort = options.port ?? localConfig?.dev?.port ?? 3000;
|
|
117
|
+
const requestedPort = typeof rawPort === "string" ? Number.parseInt(rawPort, 10) : rawPort;
|
|
118
|
+
if (!Number.isInteger(requestedPort) || requestedPort < 1 || requestedPort > 65535) {
|
|
119
|
+
console.error(chalk.red(`Invalid port: ${rawPort}`));
|
|
120
|
+
console.error(chalk.gray(" Port must be an integer between 1 and 65535."));
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
const host = options.host ?? "localhost";
|
|
124
|
+
const strictPort = Boolean(options.strictPort ?? localConfig?.dev?.strictPort);
|
|
125
|
+
// Pre-flight: find a free port before printing the banner so what we advertise
|
|
126
|
+
// matches what the framework will actually bind.
|
|
127
|
+
let actualPort;
|
|
128
|
+
try {
|
|
129
|
+
actualPort = await findSequentialFreePort(requestedPort, PORT_FALLBACK_MAX_ATTEMPTS, "0.0.0.0");
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
if (error instanceof PortRangeExhaustedError) {
|
|
133
|
+
console.error(chalk.red(t().devPortRangeExhausted(error.start, error.end)));
|
|
134
|
+
console.error(chalk.gray(` ${t().devPortRangeHint}`));
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
if (actualPort !== requestedPort) {
|
|
140
|
+
if (strictPort) {
|
|
141
|
+
console.error(chalk.red(t().devPortInUseStrict(requestedPort)));
|
|
142
|
+
console.error(chalk.gray(` ${t().devPortInUseStrictHint}`));
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
logger.warn(t().devPortFallback(requestedPort, actualPort));
|
|
146
|
+
console.log(chalk.gray(` ${t().devPortFallbackHint}`));
|
|
147
|
+
}
|
|
148
|
+
// Determine if we need a proxy (remote API → local proxy to bypass CORS)
|
|
101
149
|
let proxyUrl = null;
|
|
102
150
|
let proxyServer = null;
|
|
103
151
|
if (isRemoteUrl(apiUrl)) {
|
|
104
|
-
const spinner = ora(
|
|
152
|
+
const spinner = ora(t().devProxyStarting).start();
|
|
105
153
|
try {
|
|
106
154
|
const proxyPort = await findFreePort(4001);
|
|
107
155
|
proxyServer = await startProxyServer({
|
|
@@ -111,36 +159,47 @@ export async function devCommand(options = {}) {
|
|
|
111
159
|
quiet: true,
|
|
112
160
|
});
|
|
113
161
|
proxyUrl = `http://localhost:${proxyPort}`;
|
|
114
|
-
spinner.succeed(chalk.green(
|
|
162
|
+
spinner.succeed(chalk.green(t().devProxyStarted));
|
|
115
163
|
}
|
|
116
164
|
catch (error) {
|
|
117
|
-
spinner.fail(chalk.red(
|
|
165
|
+
spinner.fail(chalk.red(t().devProxyFailed));
|
|
118
166
|
console.error(chalk.gray(` ${error.message}`));
|
|
119
|
-
console.log(chalk.yellow(
|
|
167
|
+
console.log(chalk.yellow(`\n ${t().devProxyContinuingNoProxy}\n`));
|
|
120
168
|
}
|
|
121
169
|
}
|
|
122
|
-
// Display info
|
|
123
|
-
|
|
170
|
+
// Display info — banner is printed *after* pre-flight so it reflects the
|
|
171
|
+
// port we actually bound plus the API URL we actually resolved.
|
|
172
|
+
const effectiveApiUrl = proxyUrl ?? apiUrl;
|
|
173
|
+
const apiSource = describeApiUrlSource(apiResolution);
|
|
124
174
|
console.log("");
|
|
125
|
-
console.log(chalk.bold.blue(
|
|
126
|
-
console.log(` ${chalk.bold(
|
|
175
|
+
console.log(chalk.bold.blue(` ${t().devHeader}\n`));
|
|
176
|
+
console.log(` ${chalk.bold(t().devLabelStorefront)} ${chalk.cyan(`http://${host}:${actualPort}`)}`);
|
|
127
177
|
if (proxyUrl) {
|
|
128
|
-
console.log(` ${chalk.bold(
|
|
129
|
-
console.log(
|
|
178
|
+
console.log(` ${chalk.bold(t().devLabelApiProxy)} ${chalk.cyan(proxyUrl)} ${chalk.gray(`(${apiSource})`)}`);
|
|
179
|
+
console.log(chalk.gray(` -> ${apiUrl}`));
|
|
130
180
|
}
|
|
131
181
|
else {
|
|
132
|
-
console.log(` ${chalk.bold(
|
|
182
|
+
console.log(` ${chalk.bold(t().devLabelApi)} ${chalk.cyan(apiUrl)} ${chalk.gray(`(${apiSource})`)}`);
|
|
183
|
+
}
|
|
184
|
+
console.log(` ${chalk.bold(t().devLabelShop)} ${chalk.cyan(shopSlug)}`);
|
|
185
|
+
// Surface a one-line hint when the project config hardcodes an api.url that
|
|
186
|
+
// the active profile overrides — helps the developer understand why the
|
|
187
|
+
// banner differs from what's in doswiftly.config.ts. (When source=profile,
|
|
188
|
+
// apiResolution.url equals the profile's apiUrl — no need to re-query.)
|
|
189
|
+
if (apiResolution.source === "profile" &&
|
|
190
|
+
localConfig?.api?.url &&
|
|
191
|
+
localConfig.api.url !== apiResolution.url) {
|
|
192
|
+
console.log(chalk.gray(` ${t().envProfileOverridesConfig}`));
|
|
133
193
|
}
|
|
134
|
-
console.log(` ${chalk.bold("Shop:")} ${chalk.cyan(shopSlug)}`);
|
|
135
194
|
console.log("");
|
|
136
195
|
// Detect dev command (includes framework-specific port/host flags)
|
|
137
|
-
const devCmd = detectDevCommand(
|
|
196
|
+
const devCmd = detectDevCommand(actualPort, host);
|
|
138
197
|
// Build env — set PORT/HOST as fallback for frameworks that read from env
|
|
139
198
|
const env = {
|
|
140
199
|
...process.env,
|
|
141
200
|
NEXT_PUBLIC_API_URL: effectiveApiUrl,
|
|
142
201
|
NEXT_PUBLIC_SHOP_SLUG: shopSlug,
|
|
143
|
-
PORT: String(
|
|
202
|
+
PORT: String(actualPort),
|
|
144
203
|
HOST: host,
|
|
145
204
|
};
|
|
146
205
|
// Start dev server
|
|
@@ -151,7 +210,7 @@ export async function devCommand(options = {}) {
|
|
|
151
210
|
});
|
|
152
211
|
// Clean shutdown: kill proxy + dev server on SIGINT
|
|
153
212
|
const cleanup = () => {
|
|
154
|
-
console.log(chalk.yellow(
|
|
213
|
+
console.log(chalk.yellow(`\n\n ${t().devStopping}\n`));
|
|
155
214
|
devProcess.kill("SIGINT");
|
|
156
215
|
if (proxyServer)
|
|
157
216
|
proxyServer.close();
|
|
@@ -167,7 +226,7 @@ export async function devCommand(options = {}) {
|
|
|
167
226
|
proxyServer.close();
|
|
168
227
|
const exitCode = error.exitCode;
|
|
169
228
|
if (exitCode && exitCode !== 0 && exitCode !== 130) {
|
|
170
|
-
console.error(chalk.red(`\n
|
|
229
|
+
console.error(chalk.red(`\n ${t().devExitedCode(exitCode)}\n`));
|
|
171
230
|
process.exit(exitCode);
|
|
172
231
|
}
|
|
173
232
|
}
|
package/dist/commands/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/commands/env.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/commands/env.ts"],"names":[],"mappings":"AAkBA;;GAEG;AACH,wBAAsB,cAAc,kBAsCnC;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,iBAgEhD;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,iBAkDhD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,kBA4CvC;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,iBA4B/D;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM,iBAyCnD"}
|
package/dist/commands/env.js
CHANGED
|
@@ -2,6 +2,8 @@ import { input, select, confirm } from '@inquirer/prompts';
|
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import { existsSync, writeFileSync } from 'fs';
|
|
4
4
|
import { listProfiles, getActiveProfile, getProfile, addProfile, setActiveProfile, deleteProfile, generateEnvContent, setProfileVariable, getProjectShopSlug, } from '../lib/env-storage.js';
|
|
5
|
+
import { readLocalConfigSync } from '../lib/config.js';
|
|
6
|
+
import { t } from '../lib/i18n.js';
|
|
5
7
|
/**
|
|
6
8
|
* List all environment profiles
|
|
7
9
|
*/
|
|
@@ -124,7 +126,15 @@ export async function envUseCommand(name) {
|
|
|
124
126
|
: chalk.gray('not logged in');
|
|
125
127
|
console.log(chalk.green(`\n✔ Switched to profile "${profile.name}"`));
|
|
126
128
|
console.log(chalk.gray(` API: ${profile.apiUrl}`));
|
|
127
|
-
console.log(chalk.gray(` Account: ${accountInfo}
|
|
129
|
+
console.log(chalk.gray(` Account: ${accountInfo}`));
|
|
130
|
+
// Warn when the local project config carries a different api.url — the
|
|
131
|
+
// profile wins for dev/inspect/proxy, which used to silently surprise
|
|
132
|
+
// developers who expected doswiftly.config.ts to always be authoritative.
|
|
133
|
+
const localConfig = readLocalConfigSync();
|
|
134
|
+
if (localConfig?.api?.url && localConfig.api.url !== profile.apiUrl) {
|
|
135
|
+
console.log(chalk.gray(` ℹ ${t().envProfileOverridesConfig}`));
|
|
136
|
+
}
|
|
137
|
+
console.log('');
|
|
128
138
|
}
|
|
129
139
|
catch (error) {
|
|
130
140
|
console.error(chalk.red(`\n✖ ${error.message}\n`));
|