@nexpress/core 0.1.0

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.
Files changed (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +69 -0
  3. package/dist/audit-54XLVCWD.js +14 -0
  4. package/dist/audit-54XLVCWD.js.map +1 -0
  5. package/dist/auth.d.ts +640 -0
  6. package/dist/auth.js +94 -0
  7. package/dist/auth.js.map +1 -0
  8. package/dist/can-YLUHRJAB.js +19 -0
  9. package/dist/can-YLUHRJAB.js.map +1 -0
  10. package/dist/chunk-2G264RCD.js +68 -0
  11. package/dist/chunk-2G264RCD.js.map +1 -0
  12. package/dist/chunk-2YDGE7YX.js +92 -0
  13. package/dist/chunk-2YDGE7YX.js.map +1 -0
  14. package/dist/chunk-473S4TER.js +538 -0
  15. package/dist/chunk-473S4TER.js.map +1 -0
  16. package/dist/chunk-4ZLMEKFX.js +18 -0
  17. package/dist/chunk-4ZLMEKFX.js.map +1 -0
  18. package/dist/chunk-55FU6WED.js +179 -0
  19. package/dist/chunk-55FU6WED.js.map +1 -0
  20. package/dist/chunk-6YI5K2TI.js +1959 -0
  21. package/dist/chunk-6YI5K2TI.js.map +1 -0
  22. package/dist/chunk-BHK3AD3Q.js +41 -0
  23. package/dist/chunk-BHK3AD3Q.js.map +1 -0
  24. package/dist/chunk-CRUQBZUF.js +39 -0
  25. package/dist/chunk-CRUQBZUF.js.map +1 -0
  26. package/dist/chunk-CTSQ7BRI.js +175 -0
  27. package/dist/chunk-CTSQ7BRI.js.map +1 -0
  28. package/dist/chunk-DK2JBJH7.js +81 -0
  29. package/dist/chunk-DK2JBJH7.js.map +1 -0
  30. package/dist/chunk-DP2PREDU.js +597 -0
  31. package/dist/chunk-DP2PREDU.js.map +1 -0
  32. package/dist/chunk-EQ2Z3KMD.js +24 -0
  33. package/dist/chunk-EQ2Z3KMD.js.map +1 -0
  34. package/dist/chunk-FZ7O6DWI.js +305 -0
  35. package/dist/chunk-FZ7O6DWI.js.map +1 -0
  36. package/dist/chunk-ISLYFQWL.js +1270 -0
  37. package/dist/chunk-ISLYFQWL.js.map +1 -0
  38. package/dist/chunk-JJL74ZPK.js +68 -0
  39. package/dist/chunk-JJL74ZPK.js.map +1 -0
  40. package/dist/chunk-JKXAPSU4.js +24 -0
  41. package/dist/chunk-JKXAPSU4.js.map +1 -0
  42. package/dist/chunk-KU5M27ZC.js +24 -0
  43. package/dist/chunk-KU5M27ZC.js.map +1 -0
  44. package/dist/chunk-LSHHRDVR.js +34 -0
  45. package/dist/chunk-LSHHRDVR.js.map +1 -0
  46. package/dist/chunk-M43PGOQY.js +715 -0
  47. package/dist/chunk-M43PGOQY.js.map +1 -0
  48. package/dist/chunk-MEJAHXIO.js +150 -0
  49. package/dist/chunk-MEJAHXIO.js.map +1 -0
  50. package/dist/chunk-NUCGHWCF.js +101 -0
  51. package/dist/chunk-NUCGHWCF.js.map +1 -0
  52. package/dist/chunk-OK5HOCQI.js +845 -0
  53. package/dist/chunk-OK5HOCQI.js.map +1 -0
  54. package/dist/chunk-OROPGO65.js +13 -0
  55. package/dist/chunk-OROPGO65.js.map +1 -0
  56. package/dist/chunk-PPAS4SZR.js +176 -0
  57. package/dist/chunk-PPAS4SZR.js.map +1 -0
  58. package/dist/chunk-PPBWRKO2.js +171 -0
  59. package/dist/chunk-PPBWRKO2.js.map +1 -0
  60. package/dist/chunk-PZ5AY32C.js +10 -0
  61. package/dist/chunk-PZ5AY32C.js.map +1 -0
  62. package/dist/chunk-QO7LAQZH.js +321 -0
  63. package/dist/chunk-QO7LAQZH.js.map +1 -0
  64. package/dist/chunk-QVJ2HCAX.js +225 -0
  65. package/dist/chunk-QVJ2HCAX.js.map +1 -0
  66. package/dist/chunk-RIPHIRPP.js +68 -0
  67. package/dist/chunk-RIPHIRPP.js.map +1 -0
  68. package/dist/chunk-S27S42QY.js +134 -0
  69. package/dist/chunk-S27S42QY.js.map +1 -0
  70. package/dist/chunk-SBCVAC2Z.js +40 -0
  71. package/dist/chunk-SBCVAC2Z.js.map +1 -0
  72. package/dist/chunk-TFJ4MKPH.js +694 -0
  73. package/dist/chunk-TFJ4MKPH.js.map +1 -0
  74. package/dist/chunk-THX3SHYA.js +75 -0
  75. package/dist/chunk-THX3SHYA.js.map +1 -0
  76. package/dist/chunk-UGQSQO5B.js +222 -0
  77. package/dist/chunk-UGQSQO5B.js.map +1 -0
  78. package/dist/chunk-V2UNHGAP.js +26 -0
  79. package/dist/chunk-V2UNHGAP.js.map +1 -0
  80. package/dist/chunk-VGTPQXNQ.js +2790 -0
  81. package/dist/chunk-VGTPQXNQ.js.map +1 -0
  82. package/dist/chunk-VNIHXQ7W.js +194 -0
  83. package/dist/chunk-VNIHXQ7W.js.map +1 -0
  84. package/dist/chunk-WV272MPW.js +31 -0
  85. package/dist/chunk-WV272MPW.js.map +1 -0
  86. package/dist/chunk-X5KKBOUS.js +26 -0
  87. package/dist/chunk-X5KKBOUS.js.map +1 -0
  88. package/dist/chunk-XANPEOJC.js +17 -0
  89. package/dist/chunk-XANPEOJC.js.map +1 -0
  90. package/dist/chunk-XPVQIHAQ.js +83 -0
  91. package/dist/chunk-XPVQIHAQ.js.map +1 -0
  92. package/dist/chunk-ZCINJSS4.js +75 -0
  93. package/dist/chunk-ZCINJSS4.js.map +1 -0
  94. package/dist/community.d.ts +1425 -0
  95. package/dist/community.js +206 -0
  96. package/dist/community.js.map +1 -0
  97. package/dist/config-2GDU7PCK.js +32 -0
  98. package/dist/config-2GDU7PCK.js.map +1 -0
  99. package/dist/context-MNZ4QXPC.js +16 -0
  100. package/dist/context-MNZ4QXPC.js.map +1 -0
  101. package/dist/db-schema.d.ts +4 -0
  102. package/dist/db-schema.js +102 -0
  103. package/dist/db-schema.js.map +1 -0
  104. package/dist/db.d.ts +7 -0
  105. package/dist/db.js +117 -0
  106. package/dist/db.js.map +1 -0
  107. package/dist/digest-SY42GQSU.js +17 -0
  108. package/dist/digest-SY42GQSU.js.map +1 -0
  109. package/dist/errors-5OS3S2J3.js +22 -0
  110. package/dist/errors-5OS3S2J3.js.map +1 -0
  111. package/dist/host-OBOI4MJK.js +51 -0
  112. package/dist/host-OBOI4MJK.js.map +1 -0
  113. package/dist/i18n.d.ts +301 -0
  114. package/dist/i18n.js +68 -0
  115. package/dist/i18n.js.map +1 -0
  116. package/dist/index-B6-_vr_m.d.ts +590 -0
  117. package/dist/index-CY55LC0u.d.ts +4722 -0
  118. package/dist/index-CeiTvwbp.d.ts +168 -0
  119. package/dist/index-XwP1ET8b.d.ts +61 -0
  120. package/dist/index.d.ts +2037 -0
  121. package/dist/index.js +2205 -0
  122. package/dist/index.js.map +1 -0
  123. package/dist/job-log-VZXWQUDK.js +24 -0
  124. package/dist/job-log-VZXWQUDK.js.map +1 -0
  125. package/dist/jobs.d.ts +4 -0
  126. package/dist/jobs.js +76 -0
  127. package/dist/jobs.js.map +1 -0
  128. package/dist/logger-DqGaOU_j.d.ts +29 -0
  129. package/dist/logger-S7REWDNE.js +16 -0
  130. package/dist/logger-S7REWDNE.js.map +1 -0
  131. package/dist/media.d.ts +5 -0
  132. package/dist/media.js +41 -0
  133. package/dist/media.js.map +1 -0
  134. package/dist/mentions-2IHFVSHW.js +23 -0
  135. package/dist/mentions-2IHFVSHW.js.map +1 -0
  136. package/dist/mutes-EWAE5FZR.js +21 -0
  137. package/dist/mutes-EWAE5FZR.js.map +1 -0
  138. package/dist/notification-prefs-VPJDU7I6.js +21 -0
  139. package/dist/notification-prefs-VPJDU7I6.js.map +1 -0
  140. package/dist/observability.d.ts +156 -0
  141. package/dist/observability.js +32 -0
  142. package/dist/observability.js.map +1 -0
  143. package/dist/profanity-adapter-NU2JQSLX.js +12 -0
  144. package/dist/profanity-adapter-NU2JQSLX.js.map +1 -0
  145. package/dist/queue-XE5BC75T.js +14 -0
  146. package/dist/queue-XE5BC75T.js.map +1 -0
  147. package/dist/rate-limit.d.ts +99 -0
  148. package/dist/rate-limit.js +14 -0
  149. package/dist/rate-limit.js.map +1 -0
  150. package/dist/registry-XIXDEPVI.js +31 -0
  151. package/dist/registry-XIXDEPVI.js.map +1 -0
  152. package/dist/reputation-JRL2YQHM.js +11 -0
  153. package/dist/reputation-JRL2YQHM.js.map +1 -0
  154. package/dist/routes.d.ts +43 -0
  155. package/dist/routes.js +12 -0
  156. package/dist/routes.js.map +1 -0
  157. package/dist/scheduled-CIQM57HT.js +20 -0
  158. package/dist/scheduled-CIQM57HT.js.map +1 -0
  159. package/dist/seo.d.ts +410 -0
  160. package/dist/seo.js +44 -0
  161. package/dist/seo.js.map +1 -0
  162. package/dist/settings-FOBIESPB.js +17 -0
  163. package/dist/settings-FOBIESPB.js.map +1 -0
  164. package/dist/spam-adapter-XX3G737Z.js +12 -0
  165. package/dist/spam-adapter-XX3G737Z.js.map +1 -0
  166. package/dist/strings-VAE47B2C.js +29 -0
  167. package/dist/strings-VAE47B2C.js.map +1 -0
  168. package/dist/templates-IFVJMCJ6.js +12 -0
  169. package/dist/templates-IFVJMCJ6.js.map +1 -0
  170. package/dist/types-TlsbXS0T.d.ts +871 -0
  171. package/package.json +129 -0
@@ -0,0 +1,21 @@
1
+ import {
2
+ getMutedTargetIds,
3
+ isMuted,
4
+ listMutes,
5
+ muteMember,
6
+ unmuteMember
7
+ } from "./chunk-NUCGHWCF.js";
8
+ import "./chunk-FZ7O6DWI.js";
9
+ import "./chunk-SBCVAC2Z.js";
10
+ import "./chunk-ZCINJSS4.js";
11
+ import "./chunk-XANPEOJC.js";
12
+ import "./chunk-M43PGOQY.js";
13
+ import "./chunk-PZ5AY32C.js";
14
+ export {
15
+ getMutedTargetIds,
16
+ isMuted,
17
+ listMutes,
18
+ muteMember,
19
+ unmuteMember
20
+ };
21
+ //# sourceMappingURL=mutes-EWAE5FZR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,21 @@
1
+ import {
2
+ getMemberNotificationPrefs,
3
+ isNotificationKindEnabled,
4
+ listNotificationKinds,
5
+ recordDigestSent,
6
+ registerNotificationKind,
7
+ setMemberNotificationPrefs
8
+ } from "./chunk-CTSQ7BRI.js";
9
+ import "./chunk-ZCINJSS4.js";
10
+ import "./chunk-XANPEOJC.js";
11
+ import "./chunk-M43PGOQY.js";
12
+ import "./chunk-PZ5AY32C.js";
13
+ export {
14
+ getMemberNotificationPrefs,
15
+ isNotificationKindEnabled,
16
+ listNotificationKinds,
17
+ recordDigestSent,
18
+ registerNotificationKind,
19
+ setMemberNotificationPrefs
20
+ };
21
+ //# sourceMappingURL=notification-prefs-VPJDU7I6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,156 @@
1
+ export { N as NpLogLevel, a as NpLogger, c as consoleLogger, g as getLogger, b as getScopedLogger, r as resetLogger, s as setLogger } from './logger-DqGaOU_j.js';
2
+
3
+ /**
4
+ * Pluggable error reporter. The default is a no-op so users who don't
5
+ * need third-party tracking pay nothing; production deployments can
6
+ * install a Sentry / Bugsnag / Honeybadger / Rollbar adapter via
7
+ * `setErrorReporter()`.
8
+ *
9
+ * The framework reports errors at three boundaries:
10
+ * 1. Unhandled exceptions in API route handlers (via `npErrorResponse`).
11
+ * 2. Plugin hook handlers that throw (via the plugin host).
12
+ * 3. pg-boss job handlers that throw (registered by the worker process).
13
+ *
14
+ * Reporters MUST NOT throw — exceptions inside `captureException` are
15
+ * caught and logged, never propagated.
16
+ */
17
+ interface NpErrorReportContext {
18
+ /**
19
+ * Free-form tags used by error trackers for filtering and grouping.
20
+ * E.g. `{ source: "api", route: "/api/collections/posts" }`.
21
+ */
22
+ tags?: Record<string, string>;
23
+ /** Optional user identity, populated when the error happened in a
24
+ * request context. */
25
+ user?: {
26
+ id?: string;
27
+ email?: string;
28
+ role?: string;
29
+ };
30
+ /** Arbitrary extra context — request body shape, plugin id, job name. */
31
+ extra?: Record<string, unknown>;
32
+ }
33
+ interface NpErrorReporter {
34
+ captureException(error: Error, context?: NpErrorReportContext): void | Promise<void>;
35
+ }
36
+ /** Default — does nothing. Replaceable via `setErrorReporter`. */
37
+ declare const noopErrorReporter: NpErrorReporter;
38
+ /** Replace the global error reporter. Call once at app boot. */
39
+ declare function setErrorReporter(reporter: NpErrorReporter): void;
40
+ /** Returns the currently-installed reporter. Defaults to no-op. */
41
+ declare function getErrorReporter(): NpErrorReporter;
42
+ /**
43
+ * Safe wrapper that swallows reporter exceptions so error reporting can
44
+ * never itself crash the host. Logs the underlying capture failure via
45
+ * `console.error` — using `getLogger()` here would risk a loop if the
46
+ * logger is also broken.
47
+ */
48
+ declare function reportError(error: Error, context?: NpErrorReportContext): Promise<void>;
49
+ /** Reset to the default no-op reporter. Tests use this to undo `setErrorReporter`. */
50
+ declare function resetErrorReporter(): void;
51
+
52
+ /**
53
+ * Inputs to {@link verifyStartupSafety}. The bootstrap layer
54
+ * (`packages/next/src/bootstrap.ts`) reads the resolved config and the
55
+ * relevant env vars and hands them in — keeping this helper a pure
56
+ * function of its input means it stays trivially testable and never
57
+ * accidentally reads `process.env` from a deeper code path.
58
+ */
59
+ interface NpStartupSafetyInput {
60
+ /** Storage adapter id chosen by `createStorageAdapter` (`local` or `s3`). */
61
+ storageAdapter: "local" | "s3";
62
+ /** Resolved auth secret. `null` when unset. */
63
+ secret: string | null;
64
+ /** `process.env.NODE_ENV` at boot — typically `"production"` / `"development"` / undefined. */
65
+ nodeEnv: string | undefined;
66
+ /**
67
+ * `process.env.NP_MULTI_NODE` at boot. When the operator opts into
68
+ * multi-node mode we tighten checks that are otherwise just hints.
69
+ */
70
+ multiNodeFlag: string | undefined;
71
+ /**
72
+ * True when the boot environment looks like a managed container
73
+ * runtime (Kubernetes / Fly.io / Render / similar). The bootstrap
74
+ * layer evaluates the well-known env vars and hands a single bool
75
+ * in so this helper stays a pure function. We use this together
76
+ * with `nodeEnv === "production"` to catch the common footgun
77
+ * where an operator deploys to a multi-replica platform and forgot
78
+ * to set `NP_MULTI_NODE=true`. Optional for back-compat with
79
+ * callers that don't supply it (treated as `false`).
80
+ */
81
+ containerEnv?: boolean;
82
+ /**
83
+ * Value of `NP_EMAIL_ADAPTER` at boot. Pass `null` when the env
84
+ * var is unset, the literal string when it is — we check the
85
+ * **operator's intent** rather than the live adapter because the
86
+ * adapter is configured later in the boot sequence (after the
87
+ * core-services step that runs this safety check). Use `null` /
88
+ * `"noop"` to mean "operator hasn't asked for a real adapter,
89
+ * warn in production." Custom adapters wired via
90
+ * `setEmailAdapter()` programmatically will surface a false
91
+ * positive here — the warning text calls that out.
92
+ */
93
+ emailAdapterEnv?: string | null;
94
+ /**
95
+ * Hostname extracted from `DATABASE_URL`. Optional for back-compat.
96
+ * When provided and the host looks like loopback (`localhost` /
97
+ * `127.0.0.1` / `::1`) AND `nodeEnv === "production"`, we warn —
98
+ * the operator likely shipped the dev DB connection string.
99
+ */
100
+ databaseHost?: string | null;
101
+ /**
102
+ * Resolved `SITE_URL` (or equivalent base URL) at boot. Optional
103
+ * for back-compat. When unset OR loopback-shaped in production,
104
+ * we warn — links, SEO canonical URLs, OAuth callbacks, sitemap
105
+ * URLs all anchor on this value.
106
+ */
107
+ siteUrl?: string | null;
108
+ /**
109
+ * Whether the operator has opted into a custom rate-limiter
110
+ * adapter via `setRateLimiter(...)`. `false` means the default
111
+ * `InMemoryRateLimiter` will be lazily installed on first use —
112
+ * fine for single-node, but per-node buckets in multi-replica
113
+ * deploys make the limit ~Nx looser than configured. Optional
114
+ * for back-compat; `undefined` skips the check.
115
+ */
116
+ rateLimiterCustom?: boolean;
117
+ }
118
+ /**
119
+ * Surfaces operationally-bitten misconfiguration as warnings during
120
+ * boot. The set is intentionally small — every entry has to map to
121
+ * a real failure mode that has either bitten the project or been
122
+ * called out in the deployment docs:
123
+ *
124
+ * - `LocalStorageAdapter` + `NP_MULTI_NODE=true`. Different nodes
125
+ * see different `./uploads` directories; uploads disappear
126
+ * between requests. (`docs/deployment.md` — Multi-node notes.)
127
+ * - `LocalStorageAdapter` + `NODE_ENV=production` + a managed-
128
+ * container env var (`KUBERNETES_SERVICE_HOST`, `FLY_REGION`,
129
+ * `RENDER_INSTANCE_ID`, `RAILWAY_ENVIRONMENT_NAME`, …). Same
130
+ * failure mode as above; this branch catches the operator who
131
+ * forgot to set `NP_MULTI_NODE` but is clearly running on a
132
+ * multi-replica platform.
133
+ * - `NODE_ENV=production` + missing or short `NP_SECRET`. Tokens
134
+ * signed with a weak secret are forgeable. We cap below 32 bytes
135
+ * because that's the floor `signJwt` documents.
136
+ * - `NODE_ENV=production` + `emailAdapterKind === "noop"` (#597).
137
+ * Transactional mail (password reset, email verify, member
138
+ * digests) silently dropped — operators expect those to deliver.
139
+ * - `NODE_ENV=production` + `databaseHost` looks like loopback
140
+ * (#597). `localhost` / `127.0.0.1` / `::1` in a prod deploy is
141
+ * almost always a stale dev `DATABASE_URL` that slipped through.
142
+ * - `NODE_ENV=production` + `siteUrl` unset or loopback-shaped
143
+ * (#597). Sitemap URLs, SEO canonical URLs, OAuth callbacks,
144
+ * transactional mail links all anchor on this — wrong value
145
+ * manifests as broken share links and unverifiable OAuth round-
146
+ * trips, which take a while for the operator to notice.
147
+ *
148
+ * Warnings go through {@link getScopedLogger} so production deploys
149
+ * that have called `setLogger(...)` get them in their structured-log
150
+ * pipeline (Datadog, Axiom, etc.) instead of stdout. Returns the list
151
+ * of emitted warning ids so callers can assert on them in tests; in
152
+ * production nothing inspects the return value.
153
+ */
154
+ declare function verifyStartupSafety(input: NpStartupSafetyInput): readonly string[];
155
+
156
+ export { type NpErrorReportContext, type NpErrorReporter, type NpStartupSafetyInput, getErrorReporter, noopErrorReporter, reportError, resetErrorReporter, setErrorReporter, verifyStartupSafety };
@@ -0,0 +1,32 @@
1
+ import {
2
+ verifyStartupSafety
3
+ } from "./chunk-2YDGE7YX.js";
4
+ import {
5
+ getErrorReporter,
6
+ noopErrorReporter,
7
+ reportError,
8
+ resetErrorReporter,
9
+ setErrorReporter
10
+ } from "./chunk-WV272MPW.js";
11
+ import {
12
+ consoleLogger,
13
+ getLogger,
14
+ getScopedLogger,
15
+ resetLogger,
16
+ setLogger
17
+ } from "./chunk-JJL74ZPK.js";
18
+ import "./chunk-PZ5AY32C.js";
19
+ export {
20
+ consoleLogger,
21
+ getErrorReporter,
22
+ getLogger,
23
+ getScopedLogger,
24
+ noopErrorReporter,
25
+ reportError,
26
+ resetErrorReporter,
27
+ resetLogger,
28
+ setErrorReporter,
29
+ setLogger,
30
+ verifyStartupSafety
31
+ };
32
+ //# sourceMappingURL=observability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,12 @@
1
+ import {
2
+ getProfanityAdapter,
3
+ resetProfanityAdapter,
4
+ setProfanityAdapter
5
+ } from "./chunk-KU5M27ZC.js";
6
+ import "./chunk-PZ5AY32C.js";
7
+ export {
8
+ getProfanityAdapter,
9
+ resetProfanityAdapter,
10
+ setProfanityAdapter
11
+ };
12
+ //# sourceMappingURL=profanity-adapter-NU2JQSLX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,14 @@
1
+ import {
2
+ enqueueJob,
3
+ getJobQueue,
4
+ getOptionalJobQueue,
5
+ setJobQueue
6
+ } from "./chunk-V2UNHGAP.js";
7
+ import "./chunk-PZ5AY32C.js";
8
+ export {
9
+ enqueueJob,
10
+ getJobQueue,
11
+ getOptionalJobQueue,
12
+ setJobQueue
13
+ };
14
+ //# sourceMappingURL=queue-XE5BC75T.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Phase 23.7 — pluggable rate-limiter adapter contract.
3
+ *
4
+ * The framework exposes a single `check(key, limit, windowMs)`
5
+ * call against the configured adapter; the proxy/middleware layer
6
+ * doesn't know whether the bucket is in-process, in Redis, or in
7
+ * a CDN's edge worker. That keeps `apps/web/src/proxy.ts` neutral
8
+ * to topology — single-node deploys keep the in-memory adapter,
9
+ * multi-node deploys swap in `@nexpress/rate-limiter-redis` (or
10
+ * any other implementation) at boot.
11
+ *
12
+ * The interface is intentionally tiny:
13
+ * - one method
14
+ * - synchronous-feeling shape but always async (Redis is)
15
+ * - no notion of bucket creation or expiry inspection
16
+ *
17
+ * That matches what NexPress's middleware actually needs and avoids
18
+ * baking assumptions about, e.g., sliding-window vs fixed-window
19
+ * semantics into the contract. Adapters pick whichever fits.
20
+ */
21
+ interface NpRateLimitDecision {
22
+ /** True when the request should be rejected (count exceeded). */
23
+ limited: boolean;
24
+ /**
25
+ * Seconds until the bucket resets. Set even when `limited` is
26
+ * false so callers can surface a `RateLimit-Reset` header (some
27
+ * clients expect it on every response, not just 429s). Adapters
28
+ * unable to compute it can omit the field — callers must tolerate
29
+ * missing values.
30
+ */
31
+ retryAfterSeconds?: number;
32
+ }
33
+ interface NpRateLimiterAdapter {
34
+ /**
35
+ * Increment the bucket identified by `key` and return whether
36
+ * the resulting count exceeds `limit` within `windowMs`.
37
+ *
38
+ * Implementations should make the increment-and-test
39
+ * indivisible *within their concurrency model*:
40
+ * - The default `InMemoryRateLimiter` relies on Node's
41
+ * single-threaded event loop — concurrent `check`s on the
42
+ * same Map key serialize naturally. Worker-thread or
43
+ * multi-process consumers need a different adapter.
44
+ * - `RedisRateLimiter` uses a Lua script so an `INCR` and
45
+ * its TTL arm happen in a single Redis call.
46
+ *
47
+ * `key` is opaque to the adapter — the framework composes it
48
+ * from (ip, route-pattern). Adapters should treat it as a
49
+ * binary-safe string and not parse it.
50
+ */
51
+ check(key: string, limit: number, windowMs: number): Promise<NpRateLimitDecision>;
52
+ /**
53
+ * Optional teardown hook for adapters that hold network
54
+ * connections or background timers (Redis client, cleanup
55
+ * intervals). Called by the bootstrap layer at process
56
+ * shutdown so e.g. a Redis pool drains cleanly. The framework
57
+ * never invokes this on the in-memory adapter — the cleanup
58
+ * timer there lives on `globalThis` for HMR durability.
59
+ */
60
+ shutdown?(): Promise<void>;
61
+ }
62
+
63
+ /**
64
+ * Default rate-limiter adapter. Same fixed-window behaviour the
65
+ * proxy already had before this lived behind an interface — a
66
+ * request in the first ms and one in the last ms of a window
67
+ * share the bucket. Single-node deploys keep this; multi-node
68
+ * deploys swap in `@nexpress/rate-limiter-redis` (or another
69
+ * adapter) at boot.
70
+ *
71
+ * Why store + janitor on `globalThis`: HMR re-evaluates this
72
+ * module on every save in dev, and a module-scoped Map would
73
+ * orphan the previous one from its cleanup interval (#315).
74
+ * Pinning both to `globalThis` keeps Map and janitor paired
75
+ * across reloads.
76
+ *
77
+ * Why the janitor arms lazily: importing this file alone
78
+ * shouldn't keep a Node process alive. CLI / one-shot scripts
79
+ * that pull in `@nexpress/core` for unrelated reasons shouldn't
80
+ * inherit a 60-second timer.
81
+ */
82
+ interface Bucket {
83
+ count: number;
84
+ resetAt: number;
85
+ }
86
+ declare global {
87
+ var __nx_rate_limit_store: Map<string, Bucket> | undefined;
88
+ var __nx_rate_limit_cleanup_handle: NodeJS.Timeout | undefined;
89
+ }
90
+ declare class InMemoryRateLimiter implements NpRateLimiterAdapter {
91
+ constructor();
92
+ check(key: string, limit: number, windowMs: number): Promise<NpRateLimitDecision>;
93
+ }
94
+
95
+ declare function setRateLimiter(adapter: NpRateLimiterAdapter | null): void;
96
+ declare function getRateLimiter(): NpRateLimiterAdapter;
97
+ declare function getOptionalRateLimiter(): NpRateLimiterAdapter | null;
98
+
99
+ export { InMemoryRateLimiter, type NpRateLimitDecision, type NpRateLimiterAdapter, getOptionalRateLimiter, getRateLimiter, setRateLimiter };
@@ -0,0 +1,14 @@
1
+ import {
2
+ InMemoryRateLimiter,
3
+ getOptionalRateLimiter,
4
+ getRateLimiter,
5
+ setRateLimiter
6
+ } from "./chunk-2G264RCD.js";
7
+ import "./chunk-PZ5AY32C.js";
8
+ export {
9
+ InMemoryRateLimiter,
10
+ getOptionalRateLimiter,
11
+ getRateLimiter,
12
+ setRateLimiter
13
+ };
14
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,31 @@
1
+ import {
2
+ NP_DEFAULT_SITE_ID,
3
+ createSite,
4
+ deleteSite,
5
+ ensureDefaultSite,
6
+ getDefaultSite,
7
+ getSiteByHostname,
8
+ getSiteById,
9
+ getSiteUsageSummary,
10
+ listSites,
11
+ resolveSiteForHostname,
12
+ updateSite
13
+ } from "./chunk-FZ7O6DWI.js";
14
+ import "./chunk-ZCINJSS4.js";
15
+ import "./chunk-XANPEOJC.js";
16
+ import "./chunk-M43PGOQY.js";
17
+ import "./chunk-PZ5AY32C.js";
18
+ export {
19
+ NP_DEFAULT_SITE_ID,
20
+ createSite,
21
+ deleteSite,
22
+ ensureDefaultSite,
23
+ getDefaultSite,
24
+ getSiteByHostname,
25
+ getSiteById,
26
+ getSiteUsageSummary,
27
+ listSites,
28
+ resolveSiteForHostname,
29
+ updateSite
30
+ };
31
+ //# sourceMappingURL=registry-XIXDEPVI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,11 @@
1
+ import {
2
+ applyReputation
3
+ } from "./chunk-THX3SHYA.js";
4
+ import "./chunk-JJL74ZPK.js";
5
+ import "./chunk-XANPEOJC.js";
6
+ import "./chunk-M43PGOQY.js";
7
+ import "./chunk-PZ5AY32C.js";
8
+ export {
9
+ applyReputation
10
+ };
11
+ //# sourceMappingURL=reputation-JRL2YQHM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Developer-declared custom-route registry. Hand-coded Next.js routes
3
+ * under `apps/web/src/app/(site)/*` are invisible to the framework
4
+ * (the catch-all `[[...slug]]` only knows about CMS pages, plugins
5
+ * declare their own routes via `definePlugin({ routes })`). Operators
6
+ * still need to discover and link to those hand-coded surfaces from
7
+ * the admin — the navigation editor in particular.
8
+ *
9
+ * App code declares each navigable hand-coded route with
10
+ * `registerCustomRoute(...)` at boot. The admin reads the registry
11
+ * via `getCustomRoutes()` to populate a Settings tab and the nav
12
+ * editor's URL autocomplete.
13
+ *
14
+ * Re-registering the same `path` overwrites silently — same HMR-safe
15
+ * convention as the block registry. The registry is process-scoped;
16
+ * sites in a multi-tenant deployment share the same set because all
17
+ * sites share the same code bundle.
18
+ */
19
+ interface NpCustomRoute {
20
+ /**
21
+ * The route's URL path. Must start with `/`. May include dynamic
22
+ * segments for documentation purposes (e.g. `/u/[username]`), but
23
+ * such routes won't appear as nav-link targets — the autocomplete
24
+ * filters them out because a literal href can't be derived.
25
+ */
26
+ path: string;
27
+ /** Short human label for the admin UI. */
28
+ label: string;
29
+ /** Optional one-line description. */
30
+ description?: string;
31
+ /**
32
+ * Optional Lucide icon name (lowercase kebab-case, matching the
33
+ * shared `BlockIcon` resolver). Defaults to `route` if unset.
34
+ */
35
+ icon?: string;
36
+ /** Optional grouping key for the admin list (e.g. "content", "community"). */
37
+ group?: string;
38
+ }
39
+ declare function registerCustomRoute(route: NpCustomRoute): void;
40
+ declare function getCustomRoutes(): NpCustomRoute[];
41
+ declare function clearCustomRoutes(): void;
42
+
43
+ export { type NpCustomRoute, clearCustomRoutes, getCustomRoutes, registerCustomRoute };
package/dist/routes.js ADDED
@@ -0,0 +1,12 @@
1
+ import {
2
+ clearCustomRoutes,
3
+ getCustomRoutes,
4
+ registerCustomRoute
5
+ } from "./chunk-X5KKBOUS.js";
6
+ import "./chunk-PZ5AY32C.js";
7
+ export {
8
+ clearCustomRoutes,
9
+ getCustomRoutes,
10
+ registerCustomRoute
11
+ };
12
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,20 @@
1
+ import {
2
+ publishScheduledDocuments
3
+ } from "./chunk-XPVQIHAQ.js";
4
+ import "./chunk-VGTPQXNQ.js";
5
+ import "./chunk-4ZLMEKFX.js";
6
+ import "./chunk-FZ7O6DWI.js";
7
+ import "./chunk-SBCVAC2Z.js";
8
+ import "./chunk-ZCINJSS4.js";
9
+ import "./chunk-WV272MPW.js";
10
+ import "./chunk-473S4TER.js";
11
+ import "./chunk-V2UNHGAP.js";
12
+ import "./chunk-OROPGO65.js";
13
+ import "./chunk-JJL74ZPK.js";
14
+ import "./chunk-XANPEOJC.js";
15
+ import "./chunk-M43PGOQY.js";
16
+ import "./chunk-PZ5AY32C.js";
17
+ export {
18
+ publishScheduledDocuments
19
+ };
20
+ //# sourceMappingURL=scheduled-CIQM57HT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}