docs: add verified package usage examples
This commit is contained in:
@@ -122,6 +122,8 @@ try {
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
### Return generated JSON from an API route
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// app/api/summarize.ts — summarize posted text
|
// app/api/summarize.ts — summarize posted text
|
||||||
import { createAI } from "@wrnexus/ai";
|
import { createAI } from "@wrnexus/ai";
|
||||||
@@ -137,6 +139,23 @@ export const POST = async (ctx) => {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Stream a chat response to the browser
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// app/api/chat.ts
|
||||||
|
import { createAI } from "@wrnexus/ai";
|
||||||
|
|
||||||
|
const ai = createAI({ model: "claude-sonnet-5" });
|
||||||
|
|
||||||
|
export const POST = async (ctx) => {
|
||||||
|
const { messages } = await ctx.req.json();
|
||||||
|
return ai.streamResponse(messages, {
|
||||||
|
system: "Answer using concise Markdown.",
|
||||||
|
maxTokens: 1_500,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
## Requirements / Notes
|
## Requirements / Notes
|
||||||
|
|
||||||
- **Bun-only.** Uses `fetch`, `ReadableStream`, `TextDecoder`/`TextEncoder`, and
|
- **Bun-only.** Uses `fetch`, `ReadableStream`, `TextDecoder`/`TextEncoder`, and
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ai",
|
"name": "@wrnexus/ai",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
|
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/authz",
|
"name": "@wrnexus/authz",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/authz — part of the WrNexus framework.",
|
"description": "@wrnexus/authz — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -188,6 +188,47 @@ Runs the app's tests with `bun test`. Defaults to the `test` profile (config + `
|
|||||||
wrnexus test . --watch
|
wrnexus test . --watch
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Create and run a single application
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bunx @wrnexus/cli create customer-portal
|
||||||
|
cd customer-portal
|
||||||
|
bun install
|
||||||
|
bun run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add routes and shared UI to an existing app
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wrnexus generate page reports/monthly
|
||||||
|
wrnexus generate api reports/export
|
||||||
|
wrnexus generate component report-filter
|
||||||
|
wrnexus generate routes
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create a multi-app workspace and add another app
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wrnexus workspace company-suite
|
||||||
|
cd company-suite
|
||||||
|
wrnexus workspace add reports --domain=reports.localhost
|
||||||
|
bun install
|
||||||
|
wrnexus gateway --port=3000
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `http://reports.localhost:3000`; the gateway selects `apps/reports` from the
|
||||||
|
request host.
|
||||||
|
|
||||||
|
### Upgrade with migrations and verification
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wrnexus update --latest --dry-run
|
||||||
|
wrnexus update --latest
|
||||||
|
wrnexus doctor
|
||||||
|
```
|
||||||
|
|
||||||
## Profiles
|
## Profiles
|
||||||
|
|
||||||
Pass `--profile=<name>` to `dev`, `build`, `db` (or set `WRNEXUS_PROFILE`) to select a config profile. The CLI publishes `WRNEXUS_PROFILE` so config loaders and the dev child pick it up, and loads that profile's `.env` cascade (`.env`, `.env.local`, `.env.<profile>`, `.env.<profile>.local`) into `process.env`.
|
Pass `--profile=<name>` to `dev`, `build`, `db` (or set `WRNEXUS_PROFILE`) to select a config profile. The CLI publishes `WRNEXUS_PROFILE` so config loaders and the dev child pick it up, and loads that profile's `.env` cascade (`.env`, `.env.local`, `.env.<profile>`, `.env.<profile>.local`) into `process.env`.
|
||||||
|
|||||||
+11
-11
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/cli",
|
"name": "@wrnexus/cli",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/cli — part of the WrNexus framework.",
|
"description": "@wrnexus/cli — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -28,16 +28,16 @@
|
|||||||
"wrnexus": "./dist/index.js"
|
"wrnexus": "./dist/index.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.2.23",
|
"@wrnexus/core": "^0.2.24",
|
||||||
"@wrnexus/router": "^0.2.23",
|
"@wrnexus/router": "^0.2.24",
|
||||||
"@wrnexus/csr": "^0.2.23",
|
"@wrnexus/csr": "^0.2.24",
|
||||||
"@wrnexus/compiler": "^0.2.23",
|
"@wrnexus/compiler": "^0.2.24",
|
||||||
"@wrnexus/styles": "^0.2.23",
|
"@wrnexus/styles": "^0.2.24",
|
||||||
"@wrnexus/dev-server": "^0.2.23",
|
"@wrnexus/dev-server": "^0.2.24",
|
||||||
"@wrnexus/ui": "^0.2.23",
|
"@wrnexus/ui": "^0.2.24",
|
||||||
"@wrnexus/validation": "^0.2.23",
|
"@wrnexus/validation": "^0.2.24",
|
||||||
"@wrnexus/i18n": "^0.2.23",
|
"@wrnexus/i18n": "^0.2.24",
|
||||||
"@wrnexus/db": "^0.2.23"
|
"@wrnexus/db": "^0.2.24"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/compiler",
|
"name": "@wrnexus/compiler",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/compiler — part of the WrNexus framework.",
|
"description": "@wrnexus/compiler — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/core",
|
"name": "@wrnexus/core",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/core — part of the WrNexus framework.",
|
"description": "@wrnexus/core — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/csr",
|
"name": "@wrnexus/csr",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/csr — part of the WrNexus framework.",
|
"description": "@wrnexus/csr — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.2.23"
|
"@wrnexus/core": "^0.2.24"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/db",
|
"name": "@wrnexus/db",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/db — part of the WrNexus framework.",
|
"description": "@wrnexus/db — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/dev-server",
|
"name": "@wrnexus/dev-server",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/dev-server — part of the WrNexus framework.",
|
"description": "@wrnexus/dev-server — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -25,18 +25,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.2.23",
|
"@wrnexus/core": "^0.2.24",
|
||||||
"@wrnexus/router": "^0.2.23",
|
"@wrnexus/router": "^0.2.24",
|
||||||
"@wrnexus/ssr": "^0.2.23",
|
"@wrnexus/ssr": "^0.2.24",
|
||||||
"@wrnexus/csr": "^0.2.23",
|
"@wrnexus/csr": "^0.2.24",
|
||||||
"@wrnexus/compiler": "^0.2.23",
|
"@wrnexus/compiler": "^0.2.24",
|
||||||
"@wrnexus/styles": "^0.2.23",
|
"@wrnexus/styles": "^0.2.24",
|
||||||
"@wrnexus/ui": "^0.2.23",
|
"@wrnexus/ui": "^0.2.24",
|
||||||
"@wrnexus/validation": "^0.2.23",
|
"@wrnexus/validation": "^0.2.24",
|
||||||
"@wrnexus/i18n": "^0.2.23",
|
"@wrnexus/i18n": "^0.2.24",
|
||||||
"@wrnexus/db": "^0.2.23",
|
"@wrnexus/db": "^0.2.24",
|
||||||
"@wrnexus/pubsub": "^0.2.23",
|
"@wrnexus/pubsub": "^0.2.24",
|
||||||
"@wrnexus/uploader": "^0.2.23"
|
"@wrnexus/uploader": "^0.2.24"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/encryption",
|
"name": "@wrnexus/encryption",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/encryption — part of the WrNexus framework.",
|
"description": "@wrnexus/encryption — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ bun add @wrnexus/helpers
|
|||||||
The package is private, so the machine must be authenticated to the `wrnexus` npm
|
The package is private, so the machine must be authenticated to the `wrnexus` npm
|
||||||
organization.
|
organization.
|
||||||
|
|
||||||
## Forward-auth login redirects
|
## Usage
|
||||||
|
|
||||||
|
### Redirect an unauthenticated forward-auth request
|
||||||
|
|
||||||
The gateway calls an SSO verifier on a different URL from the original application.
|
The gateway calls an SSO verifier on a different URL from the original application.
|
||||||
These helpers reconstruct the original URL from the gateway headers and safely place it
|
These helpers reconstruct the original URL from the gateway headers and safely place it
|
||||||
@@ -42,15 +44,29 @@ Location: http://sso.localhost:3000/login?returnTo=http%3A%2F%2Fadmin.localhost%
|
|||||||
|
|
||||||
Always list the application hosts that are valid redirect destinations. Forwarded host
|
Always list the application hosts that are valid redirect destinations. Forwarded host
|
||||||
headers are rejected when `allowedHosts` is absent or does not match, preventing an open
|
headers are rejected when `allowedHosts` is absent or does not match, preventing an open
|
||||||
redirect. A callback can support dynamic tenant domains:
|
redirect.
|
||||||
|
|
||||||
The SSO hostname is the login destination, not an `allowedHosts` entry. For example,
|
The SSO hostname is the login destination, not an `allowedHosts` entry. For example,
|
||||||
when protecting `admin.localhost:3000`, keep `admin.localhost:3000` in the allowlist even
|
when protecting `admin.localhost:3000`, keep `admin.localhost:3000` in the allowlist even
|
||||||
though the verifier runs at `sso.localhost:3000`. WRNexus preserves both hosts across a
|
though the verifier runs at `sso.localhost:3000`. WRNexus preserves both hosts across a
|
||||||
nested gateway request.
|
nested gateway request.
|
||||||
|
|
||||||
|
### Support dynamic tenant domains
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
allowedHosts: (host) => host.endsWith(".example.test");
|
import type { Context } from "@wrnexus/core";
|
||||||
|
import { getOriginalRequestOrigin, redirectToLogin } from "@wrnexus/helpers";
|
||||||
|
|
||||||
|
export const GET = async (ctx: Context) => {
|
||||||
|
const allowedHosts = (host: string) => host === "example.test" || host.endsWith(".example.test");
|
||||||
|
|
||||||
|
console.info("Authentication requested by", getOriginalRequestOrigin(ctx, { allowedHosts }));
|
||||||
|
return redirectToLogin(ctx, "https://auth.example.test/login", {
|
||||||
|
allowedHosts,
|
||||||
|
returnToParam: "continue",
|
||||||
|
status: 303,
|
||||||
|
});
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/helpers",
|
"name": "@wrnexus/helpers",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
|
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.2.23"
|
"@wrnexus/core": "^0.2.24"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/i18n",
|
"name": "@wrnexus/i18n",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/i18n — part of the WrNexus framework.",
|
"description": "@wrnexus/i18n — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.2.23"
|
"@wrnexus/core": "^0.2.24"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/jwt",
|
"name": "@wrnexus/jwt",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/jwt — part of the WrNexus framework.",
|
"description": "@wrnexus/jwt — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
+70
-11
@@ -1,24 +1,83 @@
|
|||||||
# @wrnexus/mobile
|
# @wrnexus/mobile
|
||||||
|
|
||||||
SSR-safe access to Capacitor plugins from WrNexus browser code.
|
> SSR-safe access to Capacitor plugins from WRNexusJS browser code.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
`@wrnexus/mobile` keeps optional native imports out of server rendering while giving
|
||||||
|
browser-owned modules one consistent registry for Capacitor plugins. During SSR,
|
||||||
|
`mobile.isNative()` is `false` and `mobile.platform()` is `"web"`.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Install a plugin through the WRNexusJS CLI so the web and native projects stay aligned:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
wrnexus mobile add @capacitor/camera
|
wrnexus mobile add @capacitor/camera @capacitor/haptics
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Register and invoke a Capacitor plugin
|
||||||
|
|
||||||
|
Import Capacitor packages only from browser-owned code, never from API routes or SSR
|
||||||
|
helpers.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { Camera } from "@capacitor/camera";
|
import { Camera, CameraResultType } from "@capacitor/camera";
|
||||||
import { mobile } from "@wrnexus/mobile";
|
import { mobile } from "@wrnexus/mobile";
|
||||||
|
|
||||||
if (mobile.isNative()) {
|
mobile.registerPlugin("Camera", Camera);
|
||||||
mobile.registerPlugin("Camera", Camera);
|
|
||||||
const photo = await mobile.invoke("Camera", "getPhoto", { resultType: "uri" });
|
export async function takePhoto() {
|
||||||
|
if (!mobile.isNative()) return null;
|
||||||
|
return mobile.invoke("Camera", "getPhoto", {
|
||||||
|
quality: 85,
|
||||||
|
resultType: CameraResultType.Uri,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`isNative()` is false and `platform()` is `web` during SSR. `plugin()` returns
|
### Provide a browser fallback
|
||||||
`undefined` when unavailable; `requirePlugin()` and `invoke()` throw an
|
|
||||||
actionable `MobileUnavailableError`.
|
|
||||||
|
|
||||||
Import and register Capacitor packages only from browser-owned code. Do not
|
`whenNative` runs the first callback only in a Capacitor WebView and can return a
|
||||||
import them in server routes, SSR helpers, or other Bun-only modules.
|
web/SSR-safe fallback everywhere else.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { Haptics, ImpactStyle } from "@capacitor/haptics";
|
||||||
|
import { mobile } from "@wrnexus/mobile";
|
||||||
|
|
||||||
|
mobile.registerPlugin("Haptics", Haptics);
|
||||||
|
|
||||||
|
export const confirmAction = () =>
|
||||||
|
mobile.whenNative(
|
||||||
|
() => mobile.invoke("Haptics", "impact", { style: ImpactStyle.Medium }),
|
||||||
|
() => navigator.vibrate?.(30),
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read an optional plugin without throwing
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { NetworkPlugin } from "@capacitor/network";
|
||||||
|
import { mobile } from "@wrnexus/mobile";
|
||||||
|
|
||||||
|
const network = mobile.plugin<NetworkPlugin>("Network");
|
||||||
|
const status = network ? await network.getStatus() : { connected: true, connectionType: "unknown" };
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
- `registerPlugin(name, instance)` registers a browser-imported plugin.
|
||||||
|
- `plugin(name)` returns a plugin or `undefined`; `requirePlugin(name)` throws when absent.
|
||||||
|
- `invoke(plugin, method, options?)` calls a registered method and returns its result.
|
||||||
|
- `whenNative(native, fallback?)` selects native behavior without breaking SSR.
|
||||||
|
- `isNative()` and `platform()` report the current Capacitor environment.
|
||||||
|
|
||||||
|
Unavailable required plugins throw `MobileUnavailableError` with an actionable message.
|
||||||
|
|
||||||
|
## Requirements / Notes
|
||||||
|
|
||||||
|
- Capacitor plugin imports must remain in browser-owned modules.
|
||||||
|
- `@wrnexus/mobile` re-exports `native` from `@wrnexus/native` for applications that
|
||||||
|
prefer the higher-level cross-platform capability API.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/mobile",
|
"name": "@wrnexus/mobile",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/mobile — part of the WrNexus framework.",
|
"description": "@wrnexus/mobile — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/native": "^0.2.23"
|
"@wrnexus/native": "^0.2.24"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
|
|||||||
@@ -1,17 +1,85 @@
|
|||||||
# @wrnexus/native
|
# @wrnexus/native
|
||||||
|
|
||||||
Cross-platform capabilities for browsers, Capacitor WebViews, and compiled native apps.
|
> Cross-platform capabilities for browsers, Capacitor WebViews, and compiled native apps.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
`@wrnexus/native` exposes capabilities by name so application code can ask what the
|
||||||
|
current platform supports before presenting an action. Browser capabilities use Web
|
||||||
|
APIs; mobile capabilities use installed Capacitor plugins. `platform()` returns
|
||||||
|
`"server"` during SSR, `"browser"` on the web, and the Capacitor platform in a native
|
||||||
|
WebView.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun add @wrnexus/native
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Share a page when the platform supports it
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { native } from "@wrnexus/native";
|
import { native } from "@wrnexus/native";
|
||||||
|
|
||||||
if (native.supports("share")) await native.run("share", { title: "WrNexus", url: location.href });
|
export async function shareCurrentPage() {
|
||||||
|
if (!native.supports("share")) return false;
|
||||||
|
await native.run("share", {
|
||||||
|
title: document.title,
|
||||||
|
url: location.href,
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Built-ins include `camera`, `clipboard.write`, `share`, `geolocation`, `network`,
|
### Register an application-specific capability
|
||||||
`haptics`, storage, filesystem, notifications, and device information. Browser
|
|
||||||
capabilities use Web APIs; mobile capabilities use installed Capacitor plugins.
|
|
||||||
|
|
||||||
`platform()` returns `server` during SSR, `browser` on the web, and the Capacitor
|
`register` returns an unregister function, which is useful for tests and temporary
|
||||||
platform in a native WebView. Unsupported operations reject with
|
feature modules.
|
||||||
`NativeUnavailableError`; use `supports()` before presenting optional UI.
|
|
||||||
|
```ts
|
||||||
|
import { native } from "@wrnexus/native";
|
||||||
|
|
||||||
|
const unregister = native.register("orders.scan", {
|
||||||
|
browser: {
|
||||||
|
supported: () => typeof window !== "undefined",
|
||||||
|
run: async ({ orderId }: { orderId: string }) => {
|
||||||
|
const code = window.prompt(`Scan code for order ${orderId}`);
|
||||||
|
return { code };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await native.run<{ code: string | null }>("orders.scan", { orderId: "ord_42" });
|
||||||
|
unregister();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Target browser or mobile behavior explicitly
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { native } from "@wrnexus/native";
|
||||||
|
|
||||||
|
const canUseMobileCamera = native.supports("camera", "mobile");
|
||||||
|
const position = await native.run(
|
||||||
|
"geolocation",
|
||||||
|
{ enableHighAccuracy: true },
|
||||||
|
{ target: "browser" },
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
- `supports(name, target?)` checks availability without running the capability.
|
||||||
|
- `run(name, options?, runOptions?)` executes it or rejects with `NativeUnavailableError`.
|
||||||
|
- `register(name, capability)` adds or overrides a capability and returns cleanup.
|
||||||
|
- `registered()` lists capability names; `clearRegistry()` resets the registry.
|
||||||
|
- `isMobile()` and `platform()` report the current target safely during SSR.
|
||||||
|
|
||||||
|
Built-ins include `camera`, `clipboard.write`, `share`, `geolocation`, `network`,
|
||||||
|
`haptics`, storage, filesystem, notifications, and device information.
|
||||||
|
|
||||||
|
## Requirements / Notes
|
||||||
|
|
||||||
|
Use `supports()` before showing optional controls. Mobile capabilities require their
|
||||||
|
matching Capacitor plugins to be installed and registered by the application.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/native",
|
"name": "@wrnexus/native",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/native — part of the WrNexus framework.",
|
"description": "@wrnexus/native — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/oauth",
|
"name": "@wrnexus/oauth",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/oauth — part of the WrNexus framework.",
|
"description": "@wrnexus/oauth — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/pubsub",
|
"name": "@wrnexus/pubsub",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/pubsub — part of the WrNexus framework.",
|
"description": "@wrnexus/pubsub — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/queue",
|
"name": "@wrnexus/queue",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/queue — part of the WrNexus framework.",
|
"description": "@wrnexus/queue — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/reactive",
|
"name": "@wrnexus/reactive",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/reactive — part of the WrNexus framework.",
|
"description": "@wrnexus/reactive — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/router",
|
"name": "@wrnexus/router",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/router — part of the WrNexus framework.",
|
"description": "@wrnexus/router — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/compiler": "^0.2.23",
|
"@wrnexus/compiler": "^0.2.24",
|
||||||
"@wrnexus/core": "^0.2.23"
|
"@wrnexus/core": "^0.2.24"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ type SeoConfig = {
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
### Render an SEO-ready application page
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { renderDocument } from "@wrnexus/ssr";
|
import { renderDocument } from "@wrnexus/ssr";
|
||||||
|
|
||||||
@@ -98,6 +100,23 @@ return new Response(html, {
|
|||||||
|
|
||||||
The produced document has `<title>About Us — Acme</title>`, the SEO/Open Graph/Twitter tags derived from the merged metadata, a `modulepreload` link and module `<script>` for each entry in `scripts`, and the body wrapped in `<div id="app">`.
|
The produced document has `<title>About Us — Acme</title>`, the SEO/Open Graph/Twitter tags derived from the merged metadata, a `modulepreload` link and module `<script>` for each entry in `scripts`, and the body wrapped in `<div id="app">`.
|
||||||
|
|
||||||
|
### Add trusted framework assets and boot data
|
||||||
|
|
||||||
|
Use `extraHead` and `extraBody` only for HTML generated by your application or the
|
||||||
|
framework. User-provided values belong in `meta`, where they are escaped.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const html = renderDocument({
|
||||||
|
meta: { title: "Dashboard", robots: "noindex" },
|
||||||
|
body: dashboardHtml,
|
||||||
|
url: ctx.url,
|
||||||
|
extraHead: '<link rel="stylesheet" href="/_wrnexus/admin.css">',
|
||||||
|
extraBody: `<script type="application/json" id="boot">${JSON.stringify(bootData).replaceAll("<", "\\u003c")}</script>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
return new Response(html, { headers: { "content-type": "text/html; charset=utf-8" } });
|
||||||
|
```
|
||||||
|
|
||||||
## Requirements / Notes
|
## Requirements / Notes
|
||||||
|
|
||||||
- **Server-only.** This module never imports or touches the DOM and is safe to keep out of client bundles.
|
- **Server-only.** This module never imports or touches the DOM and is safe to keep out of client bundles.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ssr",
|
"name": "@wrnexus/ssr",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/ssr — part of the WrNexus framework.",
|
"description": "@wrnexus/ssr — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.2.23"
|
"@wrnexus/core": "^0.2.24"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/styles",
|
"name": "@wrnexus/styles",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/styles — part of the WrNexus framework.",
|
"description": "@wrnexus/styles — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/uploader": "^0.2.23"
|
"@wrnexus/uploader": "^0.2.24"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/test",
|
"name": "@wrnexus/test",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/test — part of the WrNexus framework.",
|
"description": "@wrnexus/test — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/tracking",
|
"name": "@wrnexus/tracking",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/tracking — part of the WrNexus framework.",
|
"description": "@wrnexus/tracking — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ui",
|
"name": "@wrnexus/ui",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/ui — part of the WrNexus framework.",
|
"description": "@wrnexus/ui — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
"./ui.css": "./ui.css"
|
"./ui.css": "./ui.css"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.2.23"
|
"@wrnexus/core": "^0.2.24"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ with one function call, drop a drag-and-drop widget on a page, and serve files b
|
|||||||
private. Zero external dependencies (S3 is signed with a built-in AWS SigV4 implementation, like the
|
private. Zero external dependencies (S3 is signed with a built-in AWS SigV4 implementation, like the
|
||||||
rest of the framework).
|
rest of the framework).
|
||||||
|
|
||||||
## Configure
|
## Usage
|
||||||
|
|
||||||
|
### Configure local and S3 stores
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// wrnexus.config.ts
|
// wrnexus.config.ts
|
||||||
@@ -40,7 +42,7 @@ const config: AppConfig = {
|
|||||||
export default config;
|
export default config;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Upload (server)
|
### Upload from an API route or server function
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// app/api/upload.ts — one-liner
|
// app/api/upload.ts — one-liner
|
||||||
@@ -60,7 +62,7 @@ Uploads are validated (size + type), stored under a random, collision-proof, pat
|
|||||||
(the client filename is never used as a path), and — for public stores — returned with a servable
|
(the client filename is never used as a path), and — for public stores — returned with a servable
|
||||||
`url`.
|
`url`.
|
||||||
|
|
||||||
## Widget (client)
|
### Add a client upload widget
|
||||||
|
|
||||||
Drop the element anywhere; the runtime (drag-and-drop, per-file progress, success/failed states) is
|
Drop the element anywhere; the runtime (drag-and-drop, per-file progress, success/failed states) is
|
||||||
auto-injected on pages that contain `data-uploader`:
|
auto-injected on pages that contain `data-uploader`:
|
||||||
@@ -92,7 +94,7 @@ It dispatches bubbling events you can listen for:
|
|||||||
- `wrnexus:upload` — `detail: { file, result: { key, url, name, size, type } }`
|
- `wrnexus:upload` — `detail: { file, result: { key, url, name, size, type } }`
|
||||||
- `wrnexus:upload-error` — `detail: { file, error }`
|
- `wrnexus:upload-error` — `detail: { file, error }`
|
||||||
|
|
||||||
## Serve files
|
### Serve private files behind application authentication
|
||||||
|
|
||||||
- **Public + local** → served automatically at `/__wrnexus/uploads/<store>/<key>` (immutable cache).
|
- **Public + local** → served automatically at `/__wrnexus/uploads/<store>/<key>` (immutable cache).
|
||||||
- **Public + S3** → `url` is the bucket/CDN URL directly.
|
- **Public + S3** → `url` is the bucket/CDN URL directly.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/uploader",
|
"name": "@wrnexus/uploader",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/uploader — part of the WrNexus framework.",
|
"description": "@wrnexus/uploader — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.2.23"
|
"@wrnexus/core": "^0.2.24"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/validation",
|
"name": "@wrnexus/validation",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/validation — part of the WrNexus framework.",
|
"description": "@wrnexus/validation — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ try {
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
### Return generated JSON from an API route
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// app/api/summarize.ts — summarize posted text
|
// app/api/summarize.ts — summarize posted text
|
||||||
import { createAI } from "@wrnexus/ai";
|
import { createAI } from "@wrnexus/ai";
|
||||||
@@ -137,6 +139,23 @@ export const POST = async (ctx) => {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Stream a chat response to the browser
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// app/api/chat.ts
|
||||||
|
import { createAI } from "@wrnexus/ai";
|
||||||
|
|
||||||
|
const ai = createAI({ model: "claude-sonnet-5" });
|
||||||
|
|
||||||
|
export const POST = async (ctx) => {
|
||||||
|
const { messages } = await ctx.req.json();
|
||||||
|
return ai.streamResponse(messages, {
|
||||||
|
system: "Answer using concise Markdown.",
|
||||||
|
maxTokens: 1_500,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
## Requirements / Notes
|
## Requirements / Notes
|
||||||
|
|
||||||
- **Bun-only.** Uses `fetch`, `ReadableStream`, `TextDecoder`/`TextEncoder`, and
|
- **Bun-only.** Uses `fetch`, `ReadableStream`, `TextDecoder`/`TextEncoder`, and
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ai",
|
"name": "@wrnexus/ai",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
|
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/authz",
|
"name": "@wrnexus/authz",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -188,6 +188,47 @@ Runs the app's tests with `bun test`. Defaults to the `test` profile (config + `
|
|||||||
wrnexus test . --watch
|
wrnexus test . --watch
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Create and run a single application
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bunx @wrnexus/cli create customer-portal
|
||||||
|
cd customer-portal
|
||||||
|
bun install
|
||||||
|
bun run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add routes and shared UI to an existing app
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wrnexus generate page reports/monthly
|
||||||
|
wrnexus generate api reports/export
|
||||||
|
wrnexus generate component report-filter
|
||||||
|
wrnexus generate routes
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create a multi-app workspace and add another app
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wrnexus workspace company-suite
|
||||||
|
cd company-suite
|
||||||
|
wrnexus workspace add reports --domain=reports.localhost
|
||||||
|
bun install
|
||||||
|
wrnexus gateway --port=3000
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `http://reports.localhost:3000`; the gateway selects `apps/reports` from the
|
||||||
|
request host.
|
||||||
|
|
||||||
|
### Upgrade with migrations and verification
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wrnexus update --latest --dry-run
|
||||||
|
wrnexus update --latest
|
||||||
|
wrnexus doctor
|
||||||
|
```
|
||||||
|
|
||||||
## Profiles
|
## Profiles
|
||||||
|
|
||||||
Pass `--profile=<name>` to `dev`, `build`, `db` (or set `WRNEXUS_PROFILE`) to select a config profile. The CLI publishes `WRNEXUS_PROFILE` so config loaders and the dev child pick it up, and loads that profile's `.env` cascade (`.env`, `.env.local`, `.env.<profile>`, `.env.<profile>.local`) into `process.env`.
|
Pass `--profile=<name>` to `dev`, `build`, `db` (or set `WRNEXUS_PROFILE`) to select a config profile. The CLI publishes `WRNEXUS_PROFILE` so config loaders and the dev child pick it up, and loads that profile's `.env` cascade (`.env`, `.env.local`, `.env.<profile>`, `.env.<profile>.local`) into `process.env`.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/cli",
|
"name": "@wrnexus/cli",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -288,6 +288,14 @@ const MIGRATIONS: Migration[] = [
|
|||||||
// Explicit no-op: updating @wrnexus/validation is sufficient.
|
// Explicit no-op: updating @wrnexus/validation is sufficient.
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
version: "0.2.24",
|
||||||
|
id: "package-usage-documentation",
|
||||||
|
description: "No project-file changes; package usage documentation is expanded",
|
||||||
|
apply() {
|
||||||
|
// Explicit no-op: this release updates package and portal documentation only.
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/** Release tooling uses this to require an explicit migration entry per version. */
|
/** Release tooling uses this to require an explicit migration entry per version. */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/compiler",
|
"name": "@wrnexus/compiler",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/core",
|
"name": "@wrnexus/core",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/csr",
|
"name": "@wrnexus/csr",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/db",
|
"name": "@wrnexus/db",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/dev-server",
|
"name": "@wrnexus/dev-server",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/encryption",
|
"name": "@wrnexus/encryption",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ bun add @wrnexus/helpers
|
|||||||
The package is private, so the machine must be authenticated to the `wrnexus` npm
|
The package is private, so the machine must be authenticated to the `wrnexus` npm
|
||||||
organization.
|
organization.
|
||||||
|
|
||||||
## Forward-auth login redirects
|
## Usage
|
||||||
|
|
||||||
|
### Redirect an unauthenticated forward-auth request
|
||||||
|
|
||||||
The gateway calls an SSO verifier on a different URL from the original application.
|
The gateway calls an SSO verifier on a different URL from the original application.
|
||||||
These helpers reconstruct the original URL from the gateway headers and safely place it
|
These helpers reconstruct the original URL from the gateway headers and safely place it
|
||||||
@@ -42,15 +44,29 @@ Location: http://sso.localhost:3000/login?returnTo=http%3A%2F%2Fadmin.localhost%
|
|||||||
|
|
||||||
Always list the application hosts that are valid redirect destinations. Forwarded host
|
Always list the application hosts that are valid redirect destinations. Forwarded host
|
||||||
headers are rejected when `allowedHosts` is absent or does not match, preventing an open
|
headers are rejected when `allowedHosts` is absent or does not match, preventing an open
|
||||||
redirect. A callback can support dynamic tenant domains:
|
redirect.
|
||||||
|
|
||||||
The SSO hostname is the login destination, not an `allowedHosts` entry. For example,
|
The SSO hostname is the login destination, not an `allowedHosts` entry. For example,
|
||||||
when protecting `admin.localhost:3000`, keep `admin.localhost:3000` in the allowlist even
|
when protecting `admin.localhost:3000`, keep `admin.localhost:3000` in the allowlist even
|
||||||
though the verifier runs at `sso.localhost:3000`. WRNexus preserves both hosts across a
|
though the verifier runs at `sso.localhost:3000`. WRNexus preserves both hosts across a
|
||||||
nested gateway request.
|
nested gateway request.
|
||||||
|
|
||||||
|
### Support dynamic tenant domains
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
allowedHosts: (host) => host.endsWith(".example.test");
|
import type { Context } from "@wrnexus/core";
|
||||||
|
import { getOriginalRequestOrigin, redirectToLogin } from "@wrnexus/helpers";
|
||||||
|
|
||||||
|
export const GET = async (ctx: Context) => {
|
||||||
|
const allowedHosts = (host: string) => host === "example.test" || host.endsWith(".example.test");
|
||||||
|
|
||||||
|
console.info("Authentication requested by", getOriginalRequestOrigin(ctx, { allowedHosts }));
|
||||||
|
return redirectToLogin(ctx, "https://auth.example.test/login", {
|
||||||
|
allowedHosts,
|
||||||
|
returnToParam: "continue",
|
||||||
|
status: 303,
|
||||||
|
});
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/helpers",
|
"name": "@wrnexus/helpers",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
|
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/i18n",
|
"name": "@wrnexus/i18n",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/jwt",
|
"name": "@wrnexus/jwt",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
+70
-11
@@ -1,24 +1,83 @@
|
|||||||
# @wrnexus/mobile
|
# @wrnexus/mobile
|
||||||
|
|
||||||
SSR-safe access to Capacitor plugins from WrNexus browser code.
|
> SSR-safe access to Capacitor plugins from WRNexusJS browser code.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
`@wrnexus/mobile` keeps optional native imports out of server rendering while giving
|
||||||
|
browser-owned modules one consistent registry for Capacitor plugins. During SSR,
|
||||||
|
`mobile.isNative()` is `false` and `mobile.platform()` is `"web"`.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Install a plugin through the WRNexusJS CLI so the web and native projects stay aligned:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
wrnexus mobile add @capacitor/camera
|
wrnexus mobile add @capacitor/camera @capacitor/haptics
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Register and invoke a Capacitor plugin
|
||||||
|
|
||||||
|
Import Capacitor packages only from browser-owned code, never from API routes or SSR
|
||||||
|
helpers.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { Camera } from "@capacitor/camera";
|
import { Camera, CameraResultType } from "@capacitor/camera";
|
||||||
import { mobile } from "@wrnexus/mobile";
|
import { mobile } from "@wrnexus/mobile";
|
||||||
|
|
||||||
if (mobile.isNative()) {
|
mobile.registerPlugin("Camera", Camera);
|
||||||
mobile.registerPlugin("Camera", Camera);
|
|
||||||
const photo = await mobile.invoke("Camera", "getPhoto", { resultType: "uri" });
|
export async function takePhoto() {
|
||||||
|
if (!mobile.isNative()) return null;
|
||||||
|
return mobile.invoke("Camera", "getPhoto", {
|
||||||
|
quality: 85,
|
||||||
|
resultType: CameraResultType.Uri,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`isNative()` is false and `platform()` is `web` during SSR. `plugin()` returns
|
### Provide a browser fallback
|
||||||
`undefined` when unavailable; `requirePlugin()` and `invoke()` throw an
|
|
||||||
actionable `MobileUnavailableError`.
|
|
||||||
|
|
||||||
Import and register Capacitor packages only from browser-owned code. Do not
|
`whenNative` runs the first callback only in a Capacitor WebView and can return a
|
||||||
import them in server routes, SSR helpers, or other Bun-only modules.
|
web/SSR-safe fallback everywhere else.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { Haptics, ImpactStyle } from "@capacitor/haptics";
|
||||||
|
import { mobile } from "@wrnexus/mobile";
|
||||||
|
|
||||||
|
mobile.registerPlugin("Haptics", Haptics);
|
||||||
|
|
||||||
|
export const confirmAction = () =>
|
||||||
|
mobile.whenNative(
|
||||||
|
() => mobile.invoke("Haptics", "impact", { style: ImpactStyle.Medium }),
|
||||||
|
() => navigator.vibrate?.(30),
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read an optional plugin without throwing
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { NetworkPlugin } from "@capacitor/network";
|
||||||
|
import { mobile } from "@wrnexus/mobile";
|
||||||
|
|
||||||
|
const network = mobile.plugin<NetworkPlugin>("Network");
|
||||||
|
const status = network ? await network.getStatus() : { connected: true, connectionType: "unknown" };
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
- `registerPlugin(name, instance)` registers a browser-imported plugin.
|
||||||
|
- `plugin(name)` returns a plugin or `undefined`; `requirePlugin(name)` throws when absent.
|
||||||
|
- `invoke(plugin, method, options?)` calls a registered method and returns its result.
|
||||||
|
- `whenNative(native, fallback?)` selects native behavior without breaking SSR.
|
||||||
|
- `isNative()` and `platform()` report the current Capacitor environment.
|
||||||
|
|
||||||
|
Unavailable required plugins throw `MobileUnavailableError` with an actionable message.
|
||||||
|
|
||||||
|
## Requirements / Notes
|
||||||
|
|
||||||
|
- Capacitor plugin imports must remain in browser-owned modules.
|
||||||
|
- `@wrnexus/mobile` re-exports `native` from `@wrnexus/native` for applications that
|
||||||
|
prefer the higher-level cross-platform capability API.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/mobile",
|
"name": "@wrnexus/mobile",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,17 +1,85 @@
|
|||||||
# @wrnexus/native
|
# @wrnexus/native
|
||||||
|
|
||||||
Cross-platform capabilities for browsers, Capacitor WebViews, and compiled native apps.
|
> Cross-platform capabilities for browsers, Capacitor WebViews, and compiled native apps.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
`@wrnexus/native` exposes capabilities by name so application code can ask what the
|
||||||
|
current platform supports before presenting an action. Browser capabilities use Web
|
||||||
|
APIs; mobile capabilities use installed Capacitor plugins. `platform()` returns
|
||||||
|
`"server"` during SSR, `"browser"` on the web, and the Capacitor platform in a native
|
||||||
|
WebView.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun add @wrnexus/native
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Share a page when the platform supports it
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { native } from "@wrnexus/native";
|
import { native } from "@wrnexus/native";
|
||||||
|
|
||||||
if (native.supports("share")) await native.run("share", { title: "WrNexus", url: location.href });
|
export async function shareCurrentPage() {
|
||||||
|
if (!native.supports("share")) return false;
|
||||||
|
await native.run("share", {
|
||||||
|
title: document.title,
|
||||||
|
url: location.href,
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Built-ins include `camera`, `clipboard.write`, `share`, `geolocation`, `network`,
|
### Register an application-specific capability
|
||||||
`haptics`, storage, filesystem, notifications, and device information. Browser
|
|
||||||
capabilities use Web APIs; mobile capabilities use installed Capacitor plugins.
|
|
||||||
|
|
||||||
`platform()` returns `server` during SSR, `browser` on the web, and the Capacitor
|
`register` returns an unregister function, which is useful for tests and temporary
|
||||||
platform in a native WebView. Unsupported operations reject with
|
feature modules.
|
||||||
`NativeUnavailableError`; use `supports()` before presenting optional UI.
|
|
||||||
|
```ts
|
||||||
|
import { native } from "@wrnexus/native";
|
||||||
|
|
||||||
|
const unregister = native.register("orders.scan", {
|
||||||
|
browser: {
|
||||||
|
supported: () => typeof window !== "undefined",
|
||||||
|
run: async ({ orderId }: { orderId: string }) => {
|
||||||
|
const code = window.prompt(`Scan code for order ${orderId}`);
|
||||||
|
return { code };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await native.run<{ code: string | null }>("orders.scan", { orderId: "ord_42" });
|
||||||
|
unregister();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Target browser or mobile behavior explicitly
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { native } from "@wrnexus/native";
|
||||||
|
|
||||||
|
const canUseMobileCamera = native.supports("camera", "mobile");
|
||||||
|
const position = await native.run(
|
||||||
|
"geolocation",
|
||||||
|
{ enableHighAccuracy: true },
|
||||||
|
{ target: "browser" },
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
- `supports(name, target?)` checks availability without running the capability.
|
||||||
|
- `run(name, options?, runOptions?)` executes it or rejects with `NativeUnavailableError`.
|
||||||
|
- `register(name, capability)` adds or overrides a capability and returns cleanup.
|
||||||
|
- `registered()` lists capability names; `clearRegistry()` resets the registry.
|
||||||
|
- `isMobile()` and `platform()` report the current target safely during SSR.
|
||||||
|
|
||||||
|
Built-ins include `camera`, `clipboard.write`, `share`, `geolocation`, `network`,
|
||||||
|
`haptics`, storage, filesystem, notifications, and device information.
|
||||||
|
|
||||||
|
## Requirements / Notes
|
||||||
|
|
||||||
|
Use `supports()` before showing optional controls. Mobile capabilities require their
|
||||||
|
matching Capacitor plugins to be installed and registered by the application.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/native",
|
"name": "@wrnexus/native",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/oauth",
|
"name": "@wrnexus/oauth",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/pubsub",
|
"name": "@wrnexus/pubsub",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/queue",
|
"name": "@wrnexus/queue",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/reactive",
|
"name": "@wrnexus/reactive",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/router",
|
"name": "@wrnexus/router",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ type SeoConfig = {
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
### Render an SEO-ready application page
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { renderDocument } from "@wrnexus/ssr";
|
import { renderDocument } from "@wrnexus/ssr";
|
||||||
|
|
||||||
@@ -98,6 +100,23 @@ return new Response(html, {
|
|||||||
|
|
||||||
The produced document has `<title>About Us — Acme</title>`, the SEO/Open Graph/Twitter tags derived from the merged metadata, a `modulepreload` link and module `<script>` for each entry in `scripts`, and the body wrapped in `<div id="app">`.
|
The produced document has `<title>About Us — Acme</title>`, the SEO/Open Graph/Twitter tags derived from the merged metadata, a `modulepreload` link and module `<script>` for each entry in `scripts`, and the body wrapped in `<div id="app">`.
|
||||||
|
|
||||||
|
### Add trusted framework assets and boot data
|
||||||
|
|
||||||
|
Use `extraHead` and `extraBody` only for HTML generated by your application or the
|
||||||
|
framework. User-provided values belong in `meta`, where they are escaped.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const html = renderDocument({
|
||||||
|
meta: { title: "Dashboard", robots: "noindex" },
|
||||||
|
body: dashboardHtml,
|
||||||
|
url: ctx.url,
|
||||||
|
extraHead: '<link rel="stylesheet" href="/_wrnexus/admin.css">',
|
||||||
|
extraBody: `<script type="application/json" id="boot">${JSON.stringify(bootData).replaceAll("<", "\\u003c")}</script>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
return new Response(html, { headers: { "content-type": "text/html; charset=utf-8" } });
|
||||||
|
```
|
||||||
|
|
||||||
## Requirements / Notes
|
## Requirements / Notes
|
||||||
|
|
||||||
- **Server-only.** This module never imports or touches the DOM and is safe to keep out of client bundles.
|
- **Server-only.** This module never imports or touches the DOM and is safe to keep out of client bundles.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ssr",
|
"name": "@wrnexus/ssr",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/styles",
|
"name": "@wrnexus/styles",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/test",
|
"name": "@wrnexus/test",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/tracking",
|
"name": "@wrnexus/tracking",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ui",
|
"name": "@wrnexus/ui",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ with one function call, drop a drag-and-drop widget on a page, and serve files b
|
|||||||
private. Zero external dependencies (S3 is signed with a built-in AWS SigV4 implementation, like the
|
private. Zero external dependencies (S3 is signed with a built-in AWS SigV4 implementation, like the
|
||||||
rest of the framework).
|
rest of the framework).
|
||||||
|
|
||||||
## Configure
|
## Usage
|
||||||
|
|
||||||
|
### Configure local and S3 stores
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// wrnexus.config.ts
|
// wrnexus.config.ts
|
||||||
@@ -40,7 +42,7 @@ const config: AppConfig = {
|
|||||||
export default config;
|
export default config;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Upload (server)
|
### Upload from an API route or server function
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// app/api/upload.ts — one-liner
|
// app/api/upload.ts — one-liner
|
||||||
@@ -60,7 +62,7 @@ Uploads are validated (size + type), stored under a random, collision-proof, pat
|
|||||||
(the client filename is never used as a path), and — for public stores — returned with a servable
|
(the client filename is never used as a path), and — for public stores — returned with a servable
|
||||||
`url`.
|
`url`.
|
||||||
|
|
||||||
## Widget (client)
|
### Add a client upload widget
|
||||||
|
|
||||||
Drop the element anywhere; the runtime (drag-and-drop, per-file progress, success/failed states) is
|
Drop the element anywhere; the runtime (drag-and-drop, per-file progress, success/failed states) is
|
||||||
auto-injected on pages that contain `data-uploader`:
|
auto-injected on pages that contain `data-uploader`:
|
||||||
@@ -92,7 +94,7 @@ It dispatches bubbling events you can listen for:
|
|||||||
- `wrnexus:upload` — `detail: { file, result: { key, url, name, size, type } }`
|
- `wrnexus:upload` — `detail: { file, result: { key, url, name, size, type } }`
|
||||||
- `wrnexus:upload-error` — `detail: { file, error }`
|
- `wrnexus:upload-error` — `detail: { file, error }`
|
||||||
|
|
||||||
## Serve files
|
### Serve private files behind application authentication
|
||||||
|
|
||||||
- **Public + local** → served automatically at `/__wrnexus/uploads/<store>/<key>` (immutable cache).
|
- **Public + local** → served automatically at `/__wrnexus/uploads/<store>/<key>` (immutable cache).
|
||||||
- **Public + S3** → `url` is the bucket/CDN URL directly.
|
- **Public + S3** → `url` is the bucket/CDN URL directly.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/uploader",
|
"name": "@wrnexus/uploader",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/validation",
|
"name": "@wrnexus/validation",
|
||||||
"version": "0.2.23",
|
"version": "0.2.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
Reference in New Issue
Block a user