Lets consumers pass `() => import.meta.env.BASE_URL` without orval's CJS
bundle path blowing up on the top-level `import.meta` reference. The
getter is invoked at request time rather than factory time, so the
mutator file can be loaded by orval (which bundles to CJS) without
evaluating `import.meta`.
Closesuwe.admin/webapp-template#21 (scaffold side).
Bump to v0.5.0 — additive change (string form still works) but new
shape for `CoreFetchOptions.baseUrl` is a public API change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Orval's `client: 'fetch'` (with the no-`includeHttpResponseReturnType`
default) emits mutator signatures expecting the parsed body — so making
`'body'` the default means the no-arg `createCoreFetch()` form is the
right answer for the typical Orval-driven derived project. Callers that
need Response metadata opt in via `responseShape: 'wrapped'`.
Aligns README + docstring + the inline default. Tests updated to assert
default-`'body'` and explicit-`'wrapped'`.
Bump to 0.4.0 (BREAKING — default flipped). Downstream consumers on the
default need to either (a) add explicit `responseShape: 'wrapped'` to
preserve old behaviour, or (b) migrate callers to the body shape.
fewo-webapp's existing `responseShape: 'body'` override is now redundant
and will be dropped in a follow-up.
Closes#5
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
defineAdminConfig / defineGuestConfig were reading process.env.VITE_BASE,
but Vite does NOT populate process.env from .env files at config-evaluation
time — those go into import.meta.env for the client bundle only. So the
VITE_BASE that new-project.sh writes to frontend/.env.production was
silently ignored, base fell back to '/', and SPA assets 404'd behind the
Apache /projects/<name>/ proxy prefix (blank page on every public route).
Switch both factories to Vite's defineConfig + loadEnv pattern. A
process.env.VITE_BASE override still wins so CI invocations that
explicitly export the variable keep working.
Bumps to 0.3.6.
Closes#6
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Some test mocks expose .json() but not .clone() — cloning throws on
object mocks. Try .json() directly, fall back to .text(). Real Response
objects are unaffected (calling .json() twice would throw, but we only
call it once since we're on the error path).
Matches the common test pattern of mocking .json() for error responses
(vitest helpers often do that by default and don't bother with .text()).
The error path now clones the response, tries .json() first, and falls
back to .text() on parse failure. Populates both text and json for
formatError callers.
409 errors are always decorated with .status=409 and .body=<json>, even
when the consumer doesn't provide on409 — conflict resolvers at call
sites can still reach the payload.
Default 409 message is the body's .message field if present; otherwise
falls through to the usual format.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tests that vi.stubGlobal('fetch', ...) AFTER module import (standard
vitest pattern) couldn't see their stub because the factory captured
globalThis.fetch at createCoreFetch() time. Switch to a thin wrapper
that does the lookup per call.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New options to fit fewo's core-fetch contract:
responseShape: 'wrapped' | 'body' — 'body' matches orval's
includeHttpResponseReturnType:false
onNetworkFailure(req, error) — return a value to swallow fetch()
rejection; enables online-first +
enqueue-on-offline pattern (fewo)
formatError(req, resp, text, json) — override default error message
format (needed for localized 401/403
messages, conflict-body decoration)
409 errors throw an Error decorated with .status = 409 and .body = parsed
JSON so conflict resolvers at call sites can still inspect them.
Backwards-compatible: new options default to prior behaviour.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
createI18n({ bundles, defaultLocale, defaultTone, initialLocale,
initialTone, onMiss }) → { t, locale, tone, setLocale, setTone,
subscribe, getSnapshot }
Resolution order:
<cur-locale>-<cur-tone>
→ <cur-locale>
→ <default-locale>-<default-tone>
→ <default-locale>
→ raw key (onMiss logs first occurrence)
Typed keys via keyof on the caller-supplied Bundle generic. Tone
bundles are Partial<B> so overrides only need the strings that differ
from the locale bundle — the defaultLocale bundle is the only one
expected to be complete.
React bindings isolated in src/i18n-react.ts so the core ships without
a React peer dep. SSR-safe: constructor takes initial locale/tone
rather than reading from window.
Typecheck clean under strict tsc (ES2020/DOM).
Closes fewo-webapp#416
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Orval-mutator factory for derived projects. Baseline behaviour
(credentials, X-Requested-With, 204/JSON handling) baked in; four
hooks let consumers wire the app-specific concerns without forking:
baseUrl — Apache-proxy prefix (empty for root-hosted apps)
syncTables — table names that route mutations through a sync queue
onEnqueue — queue callback (returns true ⇒ skip network, 202 back)
on401 — session-invalidation redirect
on409 — conflict resolver (return value swallows the error)
fetchImpl — test injection
Typechecks clean with tsc --strict against ES2020/DOM lib. Exported as
'@uschuster/webapp-scaffold/core-fetch' so consumers import only what
they need.
Closes fewo-webapp#415
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bootstraps the shared frontend build glue for webapp-template-derived
projects:
bin/fetch-openapi.sh — pull Swagger JSON from a running backend
bin/postprocess-openapi.py — fix oatpp 1.3 rough edges before orval
bin/inject-hashed-filenames.py — rewrite HTML tags, config-driven
src/vite-config.ts — defineAdminConfig / defineGuestConfig
templates/orval.config.template.ts — starting point for derived repos
Package name @uschuster/webapp-scaffold. Consumed as a devDependency
through the internal Forgejo npm registry; binaries exposed for use in
package.json scripts. createCoreFetch + i18n deferred to v0.2 / v0.3.
Closes fewo-webapp#414
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>