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>
67 lines
2.4 KiB
Markdown
67 lines
2.4 KiB
Markdown
# @uschuster/webapp-scaffold
|
||
|
||
Shared frontend build glue for webapp-template-derived projects.
|
||
|
||
## What's in v0.1
|
||
|
||
| Path | Purpose |
|
||
|------|---------|
|
||
| `bin/fetch-openapi.sh` | Pull the oatpp Swagger spec from a running backend. Configurable via `OPENAPI_URL` / `APP_URL` / `APP_TEST_PORT`, optional Bearer via `APP_API_KEY`. JSON-validated. |
|
||
| `bin/postprocess-openapi.py` | Clean up oatpp 1.3's rough edges (missing `operationId`s, missing tags) before handing the spec to Orval. |
|
||
| `bin/inject-hashed-filenames.py` | Rewrite HTML script tags to point at Vite's manifest-declared hashed bundle. Config-driven so projects with multiple entry points (admin + guest) use a single invocation. |
|
||
| `src/vite-config.ts` | `defineAdminConfig({root, vendorChunks?, outDir?})` and `defineGuestConfig({root, entry?, vendorChunks?, outDir?})` helpers that bake in the `VITE_BASE`-driven prefix convention, manifest output, and the `static/{dist,guest/dist}` output layout the `StaticController` expects. |
|
||
| `templates/orval.config.template.ts` | Starting `orval.config.ts` for derived projects to copy-and-tweak. |
|
||
|
||
## Install
|
||
|
||
```json
|
||
{
|
||
"devDependencies": {
|
||
"@uschuster/webapp-scaffold": "^0.1.0"
|
||
}
|
||
}
|
||
```
|
||
|
||
Register the internal Forgejo npm registry (see your `~/.npmrc`):
|
||
|
||
```
|
||
@uschuster:registry=http://127.0.0.1:3000/api/packages/uwe.admin/npm/
|
||
```
|
||
|
||
## Consumer wiring
|
||
|
||
```ts
|
||
// frontend/vite.config.ts
|
||
import { defineAdminConfig } from '@uschuster/webapp-scaffold';
|
||
export default defineAdminConfig({ root: __dirname });
|
||
```
|
||
|
||
```sh
|
||
# frontend/package.json > scripts > codegen
|
||
webapp-scaffold-fetch-openapi && \
|
||
webapp-scaffold-postprocess-openapi && \
|
||
orval
|
||
```
|
||
|
||
## `createCoreFetch` (v0.2)
|
||
|
||
Orval's `client: 'fetch'` calls a mutator `coreFetch<T>(url, init)` and
|
||
expects `{data, status, headers}` back. `createCoreFetch(opts)` returns
|
||
such a function, with credentials/CSRF headers / 204 / content-type
|
||
handling already wired, and hooks for project-specific concerns:
|
||
|
||
```ts
|
||
import { createCoreFetch } from '@uschuster/webapp-scaffold/core-fetch';
|
||
|
||
export const coreFetch = createCoreFetch({
|
||
baseUrl: import.meta.env.BASE_URL,
|
||
syncTables: new Set(['bookings', 'persons', 'contacts']),
|
||
onEnqueue: (req) => syncQueue.push(req), // returns true ⇒ skip network
|
||
on401: () => window.location.assign('/admin'),
|
||
on409: (_req, body) => ({ conflict: JSON.parse(body) }),
|
||
});
|
||
```
|
||
|
||
## Roadmap
|
||
|
||
- **v0.3** — i18n system (de/en × formal/informal with fallback chain).
|