@ima-jin/config 0.7.0 → 0.8.13
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/dist/{index.mjs → index.cjs} +356 -19
- package/dist/index.d.cts +485 -0
- package/dist/index.d.ts +485 -0
- package/dist/index.js +195 -166
- package/next-headers.cjs +57 -0
- package/package.json +17 -10
- package/src/base-path.ts +10 -10
- package/src/brand.ts +12 -0
- package/src/cors.ts +8 -1
- package/src/dashboard-redirect-middleware.ts +56 -0
- package/src/forest-config.ts +51 -0
- package/src/handles.ts +3 -3
- package/src/index.ts +16 -1
- package/src/node-self.ts +45 -0
- package/src/rate-limit.ts +54 -0
- package/src/registry-service-url.ts +54 -0
- package/src/security-headers.ts +45 -0
- package/src/services.ts +65 -6
- package/src/session.ts +28 -1
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CSP host-source list corresponding to ORIGIN_PATTERN (prod).
|
|
5
|
+
* Used by security-headers.ts to build frame-ancestors directives.
|
|
6
|
+
* If the allowed-origin set changes, update ORIGIN_PATTERN and this constant together.
|
|
7
|
+
*/
|
|
8
|
+
declare const ALLOWED_FRAME_ORIGINS = "https://*.imajin.ai https://imajin.ai";
|
|
9
|
+
declare function isAllowedOrigin(origin: string | null): boolean;
|
|
10
|
+
declare function corsHeaders(request: NextRequest): Record<string, string>;
|
|
11
|
+
declare function corsOptions(request: NextRequest): NextResponse;
|
|
12
|
+
declare function withCors(response: NextResponse, request: NextRequest): NextResponse;
|
|
13
|
+
declare function validateOrigin(request: NextRequest): boolean;
|
|
14
|
+
|
|
15
|
+
interface StandaloneDashboardMiddlewareOptions {
|
|
16
|
+
/** Service name used to build the hub tab URL (`/auth/<service>`). */
|
|
17
|
+
service: string;
|
|
18
|
+
/**
|
|
19
|
+
* Whether to also answer CORS preflight and stamp CORS headers on every
|
|
20
|
+
* other request — matches the app's pre-existing `/api/:path*` CORS
|
|
21
|
+
* middleware (#1525). Defaults to `true`; pass `false` for an app (e.g.
|
|
22
|
+
* dykil) that never had one.
|
|
23
|
+
*/
|
|
24
|
+
cors?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Shared standalone-dashboard-to-hub redirect body (#2332, carved out of
|
|
28
|
+
* #2275), used by every userspace service app's `middleware.ts` so the
|
|
29
|
+
* redirect + CORS pass-through logic isn't duplicated six times over.
|
|
30
|
+
*
|
|
31
|
+
* Each app still declares its own literal `export const config = { matcher:
|
|
32
|
+
* [...] }` — Next.js statically extracts `matcher` from the middleware
|
|
33
|
+
* file's AST at build time (see
|
|
34
|
+
* `next/dist/build/analysis/extract-const-value.js`: it only understands
|
|
35
|
+
* literal object/array/string/etc. expressions, not a function call or a
|
|
36
|
+
* destructured import) — so the matcher itself can't be factored out here
|
|
37
|
+
* without Next silently falling back to its default, unrestricted matcher.
|
|
38
|
+
* Only the function *body* is shared.
|
|
39
|
+
*
|
|
40
|
+
* The redirect is unconditional: a 308 to `/auth/<service>`, preserving the
|
|
41
|
+
* query string. The embedded rendering path `<ServiceEmbed>` loads
|
|
42
|
+
* (`?embed=hub&did=...`, see `apps/kernel/app/auth/lib/service-registry.ts`'s
|
|
43
|
+
* `buildEmbedSrc`) never reaches this function at all — it's excluded
|
|
44
|
+
* declaratively by each app's `matcher.missing` clause.
|
|
45
|
+
*/
|
|
46
|
+
declare function standaloneDashboardMiddleware(request: NextRequest, { service, cors }: StandaloneDashboardMiddlewareOptions): NextResponse;
|
|
47
|
+
|
|
48
|
+
type HeaderEntry = {
|
|
49
|
+
key: string;
|
|
50
|
+
value: string;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Tier 1 — hard deny framing.
|
|
54
|
+
* Use on credential and auth-sensitive pages that must never be embedded.
|
|
55
|
+
*/
|
|
56
|
+
declare function tier1Headers(): HeaderEntry[];
|
|
57
|
+
/**
|
|
58
|
+
* Tier 2 — allow framing by Imajin origins only.
|
|
59
|
+
* Use on routes embedded by the auth hub (service dashboards, document viewer, surveys).
|
|
60
|
+
* Does not include X-Frame-Options — it cannot express an allow-list, and SAMEORIGIN
|
|
61
|
+
* would break cross-subdomain framing. CSP frame-ancestors does the work here.
|
|
62
|
+
*/
|
|
63
|
+
declare function tier2Headers(): HeaderEntry[];
|
|
64
|
+
/**
|
|
65
|
+
* Tier 3 — baseline hardening.
|
|
66
|
+
* Safe to apply on every route in every app.
|
|
67
|
+
*/
|
|
68
|
+
declare function tier3Headers(): HeaderEntry[];
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Human-facing product display name.
|
|
72
|
+
*
|
|
73
|
+
* This is the ONLY place the "(α)" (alpha) stage marker lives — flip it here
|
|
74
|
+
* (e.g. to "(β)" or drop it for GA) and every consumer (BuildInfo, nav bars,
|
|
75
|
+
* page titles/metadata, auth screens, email templates, etc.) picks it up.
|
|
76
|
+
*
|
|
77
|
+
* Do NOT use this for DIDs, URLs, package names, event names, localStorage
|
|
78
|
+
* keys, env vars, or any other code identifier — those stay as literal
|
|
79
|
+
* 'imajin' strings. This constant is display-text only.
|
|
80
|
+
*/
|
|
81
|
+
declare const APP_DISPLAY_NAME = "imajin (\u03B1)";
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Canonical service manifest — infra/build-time topology for all Imajin
|
|
85
|
+
* services (dev/prod ports, Postgres schema, deployment tier, Caddy/pm2
|
|
86
|
+
* routing, docs sync, `/registry/api/specs`). These consumers run without a
|
|
87
|
+
* live identity/DB context (build scripts, edge config, port-based
|
|
88
|
+
* routing), so this stays a static, synchronously-importable array.
|
|
89
|
+
*
|
|
90
|
+
* NOT the nav authority (#2425): which apps an authenticated identity sees
|
|
91
|
+
* in the kernel hub (auth submenu, launcher, home tiles) is now derived
|
|
92
|
+
* from `registry.apps` (#1990) via `apps/kernel/src/lib/kernel/app-nav.ts`,
|
|
93
|
+
* not from this file — a disabled/pruned app disappears from nav by
|
|
94
|
+
* flipping registry state, independent of whether it still has a row here
|
|
95
|
+
* for port/Caddy purposes. Consumers: registry specs, Caddy config, pm2
|
|
96
|
+
* ecosystem, docs sync.
|
|
97
|
+
*/
|
|
98
|
+
type ServiceTier = "core" | "imajin";
|
|
99
|
+
type ServiceVisibility = "public" | "authenticated" | "creator" | "internal";
|
|
100
|
+
type ServiceCategory = "kernel" | "core" | "creator" | "developer" | "infrastructure" | "meta";
|
|
101
|
+
interface ServiceDefinition {
|
|
102
|
+
/** Subdomain / app directory name */
|
|
103
|
+
name: string;
|
|
104
|
+
/** Human-readable label */
|
|
105
|
+
label: string;
|
|
106
|
+
/** Description */
|
|
107
|
+
description: string;
|
|
108
|
+
/** Emoji icon */
|
|
109
|
+
icon: string;
|
|
110
|
+
/** Dev port (3xxx) */
|
|
111
|
+
devPort: number;
|
|
112
|
+
/** Prod port (7xxx) */
|
|
113
|
+
prodPort: number;
|
|
114
|
+
/** Postgres schema name (null if no DB) */
|
|
115
|
+
schema: string | null;
|
|
116
|
+
/** Deployment tier */
|
|
117
|
+
tier: ServiceTier;
|
|
118
|
+
/** Visibility in launcher / nav */
|
|
119
|
+
visibility: ServiceVisibility;
|
|
120
|
+
/** Grouping category */
|
|
121
|
+
category: ServiceCategory;
|
|
122
|
+
/** External URL override (bypasses subdomain convention) */
|
|
123
|
+
externalUrl?: string;
|
|
124
|
+
/** Path on www service (env-aware — resolves against www's URL at runtime) */
|
|
125
|
+
wwwPath?: string;
|
|
126
|
+
}
|
|
127
|
+
declare const SERVICES: readonly ServiceDefinition[];
|
|
128
|
+
/** Get a service definition by name */
|
|
129
|
+
declare function getService(name: string): ServiceDefinition | undefined;
|
|
130
|
+
/** Get the port for a service in a given environment */
|
|
131
|
+
declare function getPort(name: string, env?: "dev" | "prod"): number | undefined;
|
|
132
|
+
/** Get internal URL for a service (server-side calls) */
|
|
133
|
+
declare function getServiceUrl(name: string, env?: "dev" | "prod"): string | undefined;
|
|
134
|
+
/** Get the public URL for a service.
|
|
135
|
+
* Localhost-aware: if domain contains "localhost" or prefix is "http://localhost:",
|
|
136
|
+
* returns http://localhost:{devPort} using the canonical port map.
|
|
137
|
+
*/
|
|
138
|
+
declare function getPublicUrl(name: string, options?: {
|
|
139
|
+
prefix?: string;
|
|
140
|
+
domain?: string;
|
|
141
|
+
}): string;
|
|
142
|
+
/**
|
|
143
|
+
* Build the public URL for a service using raw env vars.
|
|
144
|
+
* Convenience wrapper around getPublicUrl that handles NEXT_PUBLIC_SERVICE_PREFIX
|
|
145
|
+
* and NEXT_PUBLIC_DOMAIN directly (no need to strip protocol).
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* buildPublicUrl('www') → uses env vars, localhost-aware
|
|
149
|
+
* buildPublicUrl('auth', prefix, domain) → explicit values
|
|
150
|
+
*/
|
|
151
|
+
declare function buildPublicUrl(name: string, servicePrefix?: string, domain?: string): string;
|
|
152
|
+
/**
|
|
153
|
+
* Build an ABSOLUTE public URL for a service — for use OUTSIDE the browser
|
|
154
|
+
* origin: email links, Stripe/webhook return/success URLs, externally shared
|
|
155
|
+
* links, and cross-node links. Unlike buildPublicUrl(), this never returns a
|
|
156
|
+
* relative path.
|
|
157
|
+
*
|
|
158
|
+
* Resolution order:
|
|
159
|
+
* 1. explicit NEXT_PUBLIC_{NAME}_URL env var (only if already absolute)
|
|
160
|
+
* 2. localhost dev → http://localhost:{devPort} from the canonical port map
|
|
161
|
+
* 3. otherwise an absolute https URL derived from NEXT_PUBLIC_SERVICE_PREFIX
|
|
162
|
+
* + NEXT_PUBLIC_DOMAIN via getPublicUrl()
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* buildPublicUrlAbsolute('chat') → https://jin.imajin.ai/chat (single-domain)
|
|
166
|
+
* buildPublicUrlAbsolute('kernel') → https://jin.imajin.ai (node root)
|
|
167
|
+
*/
|
|
168
|
+
declare function buildPublicUrlAbsolute(name: string): string;
|
|
169
|
+
/** All service names */
|
|
170
|
+
declare const SERVICE_NAMES: string[];
|
|
171
|
+
/** Services filtered by tier */
|
|
172
|
+
declare function servicesByTier(tier: ServiceTier): ServiceDefinition[];
|
|
173
|
+
/** Services filtered by visibility */
|
|
174
|
+
declare function servicesByVisibility(visibility: ServiceVisibility): ServiceDefinition[];
|
|
175
|
+
/**
|
|
176
|
+
* Build a map of service name → internal URL from env vars with fallback to port convention.
|
|
177
|
+
* Env var pattern: `{NAME}_SERVICE_URL` (e.g. `AUTH_SERVICE_URL`)
|
|
178
|
+
*/
|
|
179
|
+
declare function buildServiceUrlMap(env: Record<string, string | undefined>, mode?: "dev" | "prod"): Record<string, string>;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Session cookie configuration — single source of truth.
|
|
183
|
+
*
|
|
184
|
+
* Every service that reads or writes the session cookie should import from here
|
|
185
|
+
* instead of hardcoding 'imajin_session'.
|
|
186
|
+
*/
|
|
187
|
+
/** The session cookie name. Use a different name per environment to prevent collisions. */
|
|
188
|
+
declare function getSessionCookieName(env?: "dev" | "prod"): string;
|
|
189
|
+
/** Default cookie name — resolves at import time based on environment */
|
|
190
|
+
declare const SESSION_COOKIE_NAME: string;
|
|
191
|
+
/** Cookie options for cross-subdomain sessions.
|
|
192
|
+
* When called with no argument, auto-detects from IMAJIN_ENV (same logic as getSessionCookieName).
|
|
193
|
+
* Accepts optional "dev" | "prod" override for explicit control.
|
|
194
|
+
*
|
|
195
|
+
* Localhost-aware: when SERVICE_PREFIX contains "localhost", uses
|
|
196
|
+
* settings compatible with HTTP on localhost (no domain, not secure, lax sameSite).
|
|
197
|
+
*
|
|
198
|
+
* See {@link isHostScoped} for the `SESSION_COOKIE_SCOPE=host` opt-in that
|
|
199
|
+
* narrows the deployed cookie to host-only instead of `.imajin.ai`.
|
|
200
|
+
*/
|
|
201
|
+
declare function getSessionCookieOptions(env?: "dev" | "prod"): {
|
|
202
|
+
name: string;
|
|
203
|
+
options: {
|
|
204
|
+
maxAge: number;
|
|
205
|
+
domain?: string | undefined;
|
|
206
|
+
httpOnly: boolean;
|
|
207
|
+
secure: boolean;
|
|
208
|
+
sameSite: "lax" | "none";
|
|
209
|
+
path: string;
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* basePath-aware utilities for userspace apps running behind Next.js basePath.
|
|
215
|
+
*
|
|
216
|
+
* Next.js `basePath` auto-prefixes <Link> and router.push() but NOT:
|
|
217
|
+
* - fetch() calls
|
|
218
|
+
* - <a href=""> tags
|
|
219
|
+
* - globalThis.location assignments
|
|
220
|
+
*
|
|
221
|
+
* These utilities read NEXT_PUBLIC_BASE_PATH (set automatically by Next.js
|
|
222
|
+
* when basePath is configured) and prepend it where needed.
|
|
223
|
+
*
|
|
224
|
+
* Usage:
|
|
225
|
+
* import { apiFetch, apiUrl } from '@ima-jin/config';
|
|
226
|
+
*
|
|
227
|
+
* // Instead of: fetch('/api/listings')
|
|
228
|
+
* apiFetch('/api/listings')
|
|
229
|
+
*
|
|
230
|
+
* // For <a> tags or globalThis.location:
|
|
231
|
+
* <a href={apiUrl('/dashboard')}>Dashboard</a>
|
|
232
|
+
* globalThis.location.href = apiUrl('/dashboard');
|
|
233
|
+
*/
|
|
234
|
+
/**
|
|
235
|
+
* Prepend basePath to any root-relative path.
|
|
236
|
+
*
|
|
237
|
+
* apiUrl('/api/listings') → '/market/api/listings' (with basePath: '/market')
|
|
238
|
+
* apiUrl('/dashboard') → '/market/dashboard'
|
|
239
|
+
* apiUrl('/api/listings') → '/api/listings' (standalone, no basePath)
|
|
240
|
+
*/
|
|
241
|
+
declare function apiUrl(path: string): string;
|
|
242
|
+
/**
|
|
243
|
+
* basePath-aware fetch wrapper. Drop-in replacement for fetch() with
|
|
244
|
+
* root-relative paths.
|
|
245
|
+
*
|
|
246
|
+
* apiFetch('/api/listings') → fetch('/market/api/listings')
|
|
247
|
+
* apiFetch('/api/listings', { ... }) → fetch('/market/api/listings', { ... })
|
|
248
|
+
*
|
|
249
|
+
* Absolute URLs (http://, https://) are passed through unchanged.
|
|
250
|
+
*
|
|
251
|
+
* For server-side service-to-service calls, forward the X-Correlation-Id header
|
|
252
|
+
* so the full request chain shares one ID. apiFetch is browser-side too, so it
|
|
253
|
+
* can't read headers here automatically — pass it explicitly via init.headers
|
|
254
|
+
* when calling from a withLogger handler:
|
|
255
|
+
*
|
|
256
|
+
* apiFetch('/api/something', {
|
|
257
|
+
* headers: { 'x-correlation-id': correlationId },
|
|
258
|
+
* });
|
|
259
|
+
*
|
|
260
|
+
* see: automatic correlationId forwarding on outbound apiFetch/fetch calls from
|
|
261
|
+
* withLogger handlers is not yet wired up.
|
|
262
|
+
*/
|
|
263
|
+
declare function apiFetch(path: string, init?: RequestInit): Promise<Response>;
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Simple sliding-window in-memory rate limiter.
|
|
267
|
+
* Safe for single-process Next.js. Per-worker in multi-worker setups (acceptable).
|
|
268
|
+
*/
|
|
269
|
+
declare function rateLimit(key: string, limit: number, windowMs: number): {
|
|
270
|
+
limited: boolean;
|
|
271
|
+
retryAfter: number;
|
|
272
|
+
};
|
|
273
|
+
declare function getClientIP(request: Request): string;
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Minimal public node metadata returned by GET /registry/api/node/self.
|
|
277
|
+
* Mirrors the subset of `relay.relay_config` the registry service exposes
|
|
278
|
+
* publicly — never the private config (profile artifact JWS, etc).
|
|
279
|
+
*/
|
|
280
|
+
interface NodeSelfInfo {
|
|
281
|
+
/** This node's own DID (did:imajin:...). */
|
|
282
|
+
did: string;
|
|
283
|
+
/** DID of the human/entity operating this node, if configured. */
|
|
284
|
+
nodeOperatorDid: string | null;
|
|
285
|
+
/** Node fee, in basis points, applied to .fair settlements on this node. */
|
|
286
|
+
nodeFeeBps: number | null;
|
|
287
|
+
/** Buyer credit, in basis points, applied to .fair settlements on this node. */
|
|
288
|
+
buyerCreditBps: number | null;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Fetch this node's public identity + .fair fee config from the registry
|
|
292
|
+
* service (`GET /registry/api/node/self`, #2000).
|
|
293
|
+
*
|
|
294
|
+
* Replaces raw `relay.relay_config` SQL reads that were duplicated across
|
|
295
|
+
* coffee, learn, events, and market (audit item 8 of #1983). Returns null on
|
|
296
|
+
* any failure — network error, non-2xx response (e.g. 503 when the node
|
|
297
|
+
* identity hasn't been bootstrapped yet) — so callers can fall back to
|
|
298
|
+
* defaults exactly as they did when the raw SQL row was missing. A non-2xx
|
|
299
|
+
* response is logged with the URL actually hit (no secrets) so a
|
|
300
|
+
* misconfigured REGISTRY_SERVICE_URL prefix is visible instead of failing
|
|
301
|
+
* silently (#2046).
|
|
302
|
+
*/
|
|
303
|
+
declare function getNodeSelf(): Promise<NodeSelfInfo | null>;
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Single resolver for the registry service's base URL (#2061 — kernel was
|
|
307
|
+
* the last `REGISTRY_URL` holdout after #2048 established the
|
|
308
|
+
* `*_SERVICE_URL` convention).
|
|
309
|
+
*
|
|
310
|
+
* The returned value always includes the `/registry` path prefix, like
|
|
311
|
+
* every other `*_SERVICE_URL` (#2046) — callers append only the endpoint
|
|
312
|
+
* path (e.g. `/api/node/self`, `/relay/operations`).
|
|
313
|
+
*
|
|
314
|
+
* Precedence:
|
|
315
|
+
* 1. `REGISTRY_SERVICE_URL` — the current convention.
|
|
316
|
+
* 2. `REGISTRY_URL` — deprecated kernel-only legacy name. Used if set,
|
|
317
|
+
* but logs a one-time deprecation warning per process.
|
|
318
|
+
* 3. `http://localhost:${PORT || 3000}/registry` — the mode-aware
|
|
319
|
+
* fallback (PORT is 3000 in dev, 7000 in prod) that
|
|
320
|
+
* `relay-well-known.ts` already used before this consolidation.
|
|
321
|
+
*/
|
|
322
|
+
declare function registryServiceUrl(): string;
|
|
323
|
+
/**
|
|
324
|
+
* True when the registry URL is explicitly configured via either the
|
|
325
|
+
* current (`REGISTRY_SERVICE_URL`) or deprecated (`REGISTRY_URL`) env var.
|
|
326
|
+
*
|
|
327
|
+
* `registryServiceUrl()` always returns a value (it falls back to a
|
|
328
|
+
* localhost guess), so callers that previously guarded on
|
|
329
|
+
* `!process.env.REGISTRY_URL` to skip/no-op when the registry isn't
|
|
330
|
+
* configured should check this instead.
|
|
331
|
+
*/
|
|
332
|
+
declare function hasRegistryServiceUrl(): boolean;
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Public forest-group (scope) config exposed by
|
|
336
|
+
* `GET /api/forest/{groupDid}/config/public` on the profile service. Only
|
|
337
|
+
* the field relevant to `.fair` fee-split calculation is modeled here — the
|
|
338
|
+
* rest of the config (enabledServices, landingService, etc.) is a
|
|
339
|
+
* community-settings concern, not a shared SDK concern.
|
|
340
|
+
*/
|
|
341
|
+
interface ForestScopeConfig {
|
|
342
|
+
/** Group's configured revenue-share fee, in basis points (0-500). Null if unset. */
|
|
343
|
+
scopeFeeBps: number | null;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Fetch a forest group's public scope-fee config from the profile service
|
|
347
|
+
* (`GET /api/forest/{groupDid}/config/public`, documented in
|
|
348
|
+
* `apps/kernel/api-spec/profile.yaml`).
|
|
349
|
+
*
|
|
350
|
+
* Replaces raw `profile.forest_config` SQL reads that were duplicated
|
|
351
|
+
* across coffee, learn, and market (audit item 9 of #1983, #2001). Returns
|
|
352
|
+
* null on any failure — network error, non-2xx response — so callers can
|
|
353
|
+
* fall back to the same `scopeFeeBps: null` default they used when the raw
|
|
354
|
+
* SQL row was missing.
|
|
355
|
+
*/
|
|
356
|
+
declare function getForestScopeConfig(groupDid: string): Promise<ForestScopeConfig | null>;
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Handle validation and normalization.
|
|
360
|
+
*
|
|
361
|
+
* Handles are node-scoped today, globally unique via DFOS chain in the future.
|
|
362
|
+
* Pattern: lowercase alphanumeric + dots, hyphens, underscores. 3-30 chars.
|
|
363
|
+
* No leading/trailing dots or hyphens. No consecutive dots or hyphens.
|
|
364
|
+
*/
|
|
365
|
+
/** Regex: the full allowed character set, length enforced */
|
|
366
|
+
declare const HANDLE_PATTERN: RegExp;
|
|
367
|
+
/** HTML input pattern attribute (no anchors, no flags) */
|
|
368
|
+
declare const HANDLE_INPUT_PATTERN: string;
|
|
369
|
+
/** Characters allowed in handles — use in onChange filters */
|
|
370
|
+
declare const HANDLE_ALLOWED_CHARS: RegExp;
|
|
371
|
+
/** Reserved handles that cannot be claimed */
|
|
372
|
+
declare const RESERVED_HANDLES: Set<string>;
|
|
373
|
+
/** Validate handle format (does NOT check reserved or uniqueness) */
|
|
374
|
+
declare function isValidHandle(handle: string): boolean;
|
|
375
|
+
/** Check if handle is reserved */
|
|
376
|
+
declare function isReservedHandle(handle: string): boolean;
|
|
377
|
+
/** Normalize input: lowercase, strip disallowed chars */
|
|
378
|
+
declare function normalizeHandleInput(value: string): string;
|
|
379
|
+
/** Validation error message */
|
|
380
|
+
declare const HANDLE_ERROR = "Handle must be 3-30 characters: lowercase letters, numbers, dots, hyphens, underscores";
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Centralized public route paths.
|
|
384
|
+
* Every service imports from here — change the prefix once, changes everywhere.
|
|
385
|
+
*
|
|
386
|
+
* Note: These are the *public-facing* URL paths (after any proxy/basePath
|
|
387
|
+
* stripping). Internal Next.js file paths may differ (e.g. kernel profiles
|
|
388
|
+
* are in `app/profile/p/[handle]` but the public URL is `/p/[handle]`).
|
|
389
|
+
*/
|
|
390
|
+
declare const eventPath: (eventId: string) => string;
|
|
391
|
+
declare const eventEditPath: (eventId: string) => string;
|
|
392
|
+
declare const eventRegisterPath: (eventId: string, ticketId: string) => string;
|
|
393
|
+
declare const eventMyTicketsPath: (eventId: string) => string;
|
|
394
|
+
declare const eventCheckoutSuccessPath: (eventId: string) => string;
|
|
395
|
+
declare const eventAdminPath: (eventId: string) => string;
|
|
396
|
+
declare const eventsDashboardPath: () => string;
|
|
397
|
+
declare const eventsCreatePath: () => string;
|
|
398
|
+
declare const eventsCheckoutSuccessPath: () => string;
|
|
399
|
+
declare const eventsAdminListPath: () => string;
|
|
400
|
+
declare const eventUrl: (baseUrl: string, eventId: string) => string;
|
|
401
|
+
declare const eventEditUrl: (baseUrl: string, eventId: string) => string;
|
|
402
|
+
declare const eventRegisterUrl: (baseUrl: string, eventId: string, ticketId: string) => string;
|
|
403
|
+
declare const eventMyTicketsUrl: (baseUrl: string, eventId: string) => string;
|
|
404
|
+
declare const profilePath: (handle: string) => string;
|
|
405
|
+
declare const profileEditPath: () => string;
|
|
406
|
+
declare const profileLoginPath: () => string;
|
|
407
|
+
declare const profileRegisterPath: () => string;
|
|
408
|
+
declare const profileUrl: (baseUrl: string, handle: string) => string;
|
|
409
|
+
declare const authLoginPath: () => string;
|
|
410
|
+
declare const authRegisterPath: () => string;
|
|
411
|
+
declare const authOnboardPath: () => string;
|
|
412
|
+
declare const authSettingsPath: () => string;
|
|
413
|
+
declare const authSecurityPath: () => string;
|
|
414
|
+
declare const authGroupSettingsPath: (groupDid: string) => string;
|
|
415
|
+
declare const authGroupsPath: () => string;
|
|
416
|
+
declare const authNewGroupPath: () => string;
|
|
417
|
+
declare const authAgentsPath: () => string;
|
|
418
|
+
declare const authAppsPath: () => string;
|
|
419
|
+
declare const authAttestationsPath: () => string;
|
|
420
|
+
declare const authAuthorizePath: () => string;
|
|
421
|
+
declare const authDeveloperAppsPath: () => string;
|
|
422
|
+
declare const authDeveloperAppPath: (appId: string) => string;
|
|
423
|
+
declare const authMembersPath: () => string;
|
|
424
|
+
declare const authNotificationsPath: () => string;
|
|
425
|
+
declare const authStubsPath: (did: string) => string;
|
|
426
|
+
declare const authNewStubPath: () => string;
|
|
427
|
+
declare const chatConversationsPath: () => string;
|
|
428
|
+
declare const chatConversationPath: (type: string, slug: string) => string;
|
|
429
|
+
declare const chatPath: () => string;
|
|
430
|
+
declare const connectionsPath: () => string;
|
|
431
|
+
declare const connectionsInvitePath: (did: string, code: string) => string;
|
|
432
|
+
declare const connectionsPodPath: (id: string) => string;
|
|
433
|
+
declare const payPath: () => string;
|
|
434
|
+
declare const payHistoryPath: () => string;
|
|
435
|
+
declare const payPayoutsPath: () => string;
|
|
436
|
+
declare const payTopupPath: () => string;
|
|
437
|
+
declare const payTopupSuccessPath: () => string;
|
|
438
|
+
declare const mediaPath: () => string;
|
|
439
|
+
declare const learnCoursePath: (slug: string) => string;
|
|
440
|
+
declare const learnCourseLessonPath: (slug: string, lessonId: string) => string;
|
|
441
|
+
declare const learnCoursePresentPath: (slug: string) => string;
|
|
442
|
+
declare const learnDashboardPath: () => string;
|
|
443
|
+
declare const learnCourseDashboardPath: (slug: string) => string;
|
|
444
|
+
declare const learnCourseStudentsPath: (slug: string) => string;
|
|
445
|
+
declare const learnHandlePath: (handle: string) => string;
|
|
446
|
+
declare const coffeeHandlePath: (handle: string) => string;
|
|
447
|
+
declare const coffeeDashboardPath: () => string;
|
|
448
|
+
declare const coffeeEditPath: () => string;
|
|
449
|
+
declare const coffeeSuccessPath: () => string;
|
|
450
|
+
declare const dykilHandlePath: (handle: string) => string;
|
|
451
|
+
declare const dykilSurveyPath: (handle: string, surveyId: string) => string;
|
|
452
|
+
declare const dykilCreatePath: () => string;
|
|
453
|
+
declare const dykilDashboardPath: () => string;
|
|
454
|
+
declare const dykilResultsPath: (id: string) => string;
|
|
455
|
+
declare const dykilEmbedPath: (surveyId: string) => string;
|
|
456
|
+
declare const linksHandlePath: (handle: string) => string;
|
|
457
|
+
declare const linksDashboardPath: () => string;
|
|
458
|
+
declare const linksEditPath: () => string;
|
|
459
|
+
declare const marketListingPath: (id: string) => string;
|
|
460
|
+
declare const marketListingEditPath: (id: string) => string;
|
|
461
|
+
declare const marketNewListingPath: () => string;
|
|
462
|
+
declare const marketSellerPath: (handle: string) => string;
|
|
463
|
+
declare const marketCheckoutSuccessPath: () => string;
|
|
464
|
+
declare const marketDashboardPath: () => string;
|
|
465
|
+
declare const marketSettingsPath: () => string;
|
|
466
|
+
declare const articlesPath: () => string;
|
|
467
|
+
declare const articleAuthorPath: (handle: string) => string;
|
|
468
|
+
declare const articlePath: (handle: string, slug: string) => string;
|
|
469
|
+
declare const registryPath: () => string;
|
|
470
|
+
declare const registryDocsPath: () => string;
|
|
471
|
+
declare const buildPath: () => string;
|
|
472
|
+
declare const bumpPath: () => string;
|
|
473
|
+
declare const bugsPath: () => string;
|
|
474
|
+
declare const bugsAdminPath: () => string;
|
|
475
|
+
declare const healthPath: () => string;
|
|
476
|
+
declare const privacyPath: () => string;
|
|
477
|
+
declare const whitepaperPath: () => string;
|
|
478
|
+
declare const subscribePath: () => string;
|
|
479
|
+
declare const developerGuidePath: () => string;
|
|
480
|
+
declare const docsPath: () => string;
|
|
481
|
+
declare const projectPath: () => string;
|
|
482
|
+
declare const notifyPath: () => string;
|
|
483
|
+
declare const notifySettingsPath: () => string;
|
|
484
|
+
|
|
485
|
+
export { ALLOWED_FRAME_ORIGINS, APP_DISPLAY_NAME, type ForestScopeConfig, HANDLE_ALLOWED_CHARS, HANDLE_ERROR, HANDLE_INPUT_PATTERN, HANDLE_PATTERN, type NodeSelfInfo, RESERVED_HANDLES, SERVICES, SERVICE_NAMES, SESSION_COOKIE_NAME, type ServiceCategory, type ServiceDefinition, type ServiceTier, type ServiceVisibility, type StandaloneDashboardMiddlewareOptions, apiFetch, apiUrl, articleAuthorPath, articlePath, articlesPath, authAgentsPath, authAppsPath, authAttestationsPath, authAuthorizePath, authDeveloperAppPath, authDeveloperAppsPath, authGroupSettingsPath, authGroupsPath, authLoginPath, authMembersPath, authNewGroupPath, authNewStubPath, authNotificationsPath, authOnboardPath, authRegisterPath, authSecurityPath, authSettingsPath, authStubsPath, bugsAdminPath, bugsPath, buildPath, buildPublicUrl, buildPublicUrlAbsolute, buildServiceUrlMap, bumpPath, chatConversationPath, chatConversationsPath, chatPath, coffeeDashboardPath, coffeeEditPath, coffeeHandlePath, coffeeSuccessPath, connectionsInvitePath, connectionsPath, connectionsPodPath, corsHeaders, corsOptions, developerGuidePath, docsPath, dykilCreatePath, dykilDashboardPath, dykilEmbedPath, dykilHandlePath, dykilResultsPath, dykilSurveyPath, eventAdminPath, eventCheckoutSuccessPath, eventEditPath, eventEditUrl, eventMyTicketsPath, eventMyTicketsUrl, eventPath, eventRegisterPath, eventRegisterUrl, eventUrl, eventsAdminListPath, eventsCheckoutSuccessPath, eventsCreatePath, eventsDashboardPath, getClientIP, getForestScopeConfig, getNodeSelf, getPort, getPublicUrl, getService, getServiceUrl, getSessionCookieName, getSessionCookieOptions, hasRegistryServiceUrl, healthPath, isAllowedOrigin, isReservedHandle, isValidHandle, learnCourseDashboardPath, learnCourseLessonPath, learnCoursePath, learnCoursePresentPath, learnCourseStudentsPath, learnDashboardPath, learnHandlePath, linksDashboardPath, linksEditPath, linksHandlePath, marketCheckoutSuccessPath, marketDashboardPath, marketListingEditPath, marketListingPath, marketNewListingPath, marketSellerPath, marketSettingsPath, mediaPath, normalizeHandleInput, notifyPath, notifySettingsPath, payHistoryPath, payPath, payPayoutsPath, payTopupPath, payTopupSuccessPath, privacyPath, profileEditPath, profileLoginPath, profilePath, profileRegisterPath, profileUrl, projectPath, rateLimit, registryDocsPath, registryPath, registryServiceUrl, servicesByTier, servicesByVisibility, standaloneDashboardMiddleware, subscribePath, tier1Headers, tier2Headers, tier3Headers, validateOrigin, whitepaperPath, withCors };
|