@usegraft/contracts 0.2.0 → 1.0.0-beta.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.
- package/README.md +1 -1
- package/dist/index.d.ts +100 -1
- package/dist/index.js +24 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,4 +33,4 @@ throw new GraftError({
|
|
|
33
33
|
|
|
34
34
|
---
|
|
35
35
|
|
|
36
|
-
MIT. [Repository](https://github.com/AndersonDesign1/graft) · [Changelog](https://github.com/AndersonDesign1/graft/blob/
|
|
36
|
+
MIT. [Repository](https://github.com/AndersonDesign1/graft) · [Changelog](https://github.com/AndersonDesign1/graft/blob/main/packages/contracts/CHANGELOG.md)
|
package/dist/index.d.ts
CHANGED
|
@@ -292,4 +292,103 @@ type RegistryItemDescriptor = z.infer<typeof RegistryItemDescriptor>;
|
|
|
292
292
|
*/
|
|
293
293
|
declare const STATIC_INDEX_DEFAULT_PATH = ".graft/index.db";
|
|
294
294
|
|
|
295
|
-
|
|
295
|
+
/**
|
|
296
|
+
* Record the socket address a request came from. Called by an adapter that owns
|
|
297
|
+
* the connection — never from anything that merely receives a Request.
|
|
298
|
+
*/
|
|
299
|
+
declare function setRequestPeer(request: Request, address: string): void;
|
|
300
|
+
/** The recorded peer address, or undefined when no adapter registered one. */
|
|
301
|
+
declare function getRequestPeer(request: Request): string | undefined;
|
|
302
|
+
/**
|
|
303
|
+
* The rate-limit identity for a caller with no verified actor.
|
|
304
|
+
*
|
|
305
|
+
* Lives here rather than beside one handler because more than one surface
|
|
306
|
+
* needs it — `createFunctionsHandler` for anonymous function calls, and
|
|
307
|
+
* `createContentApiHandler` for a read endpoint that never authenticates at
|
|
308
|
+
* all — and the rule it encodes is the kind that must not be reimplemented
|
|
309
|
+
* twice. `.greptile/rules.md` names it as a security invariant precisely
|
|
310
|
+
* because the obvious reading of `x-forwarded-for` is the wrong one.
|
|
311
|
+
*
|
|
312
|
+
* Never reads the header unless the deployment declares how many proxies it
|
|
313
|
+
* controls, and then counts from the RIGHT: entries are appended, so the
|
|
314
|
+
* rightmost were added by infrastructure closest to us. A client can prepend
|
|
315
|
+
* anything it likes and never reach that far.
|
|
316
|
+
*/
|
|
317
|
+
declare function rateIdentity(request: Request, trustedProxyHops: number): string;
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* The content-index read contract.
|
|
321
|
+
*
|
|
322
|
+
* These types used to live in `@usegraft/db`, which made them unreachable
|
|
323
|
+
* without depending on the Postgres package — and `ContentRow` in particular
|
|
324
|
+
* was `typeof contentIndex.$inferSelect`, derived from a Drizzle table. So the
|
|
325
|
+
* shape every reader returns was defined by one implementation's storage
|
|
326
|
+
* schema, and any consumer that merely wanted to *describe* a row (the HTTP
|
|
327
|
+
* transport, the browser client) had to install a database driver to say so.
|
|
328
|
+
*
|
|
329
|
+
* They live here because this is the layer every package already shares.
|
|
330
|
+
* `@usegraft/db` now proves its table still matches this contract rather than
|
|
331
|
+
* defining it, which is the direction the dependency should have run in from
|
|
332
|
+
* the start: the seam owns the shape, the implementation conforms to it.
|
|
333
|
+
*/
|
|
334
|
+
/** One row of the authored-content index. */
|
|
335
|
+
interface ContentRow {
|
|
336
|
+
branchId: string;
|
|
337
|
+
collection: string;
|
|
338
|
+
slug: string;
|
|
339
|
+
/** Validated frontmatter. */
|
|
340
|
+
data: Record<string, unknown>;
|
|
341
|
+
/** Authored MDX source, byte-for-byte as written. */
|
|
342
|
+
body: string;
|
|
343
|
+
contentHash: string;
|
|
344
|
+
sourcePath: string;
|
|
345
|
+
/** Soft-delete marker. Readers exclude these. */
|
|
346
|
+
deleted: boolean;
|
|
347
|
+
updatedAt: Date;
|
|
348
|
+
/** The FTS vector, when the implementation has one. */
|
|
349
|
+
search: string | null;
|
|
350
|
+
}
|
|
351
|
+
interface ReaderReadOptions {
|
|
352
|
+
collection: string;
|
|
353
|
+
/** When set, read a single document; otherwise the whole collection. */
|
|
354
|
+
slug?: string;
|
|
355
|
+
limit?: number;
|
|
356
|
+
offset?: number;
|
|
357
|
+
/** Branch to read; defaults to "main". Static readers serve their compiled branch regardless. */
|
|
358
|
+
branch?: string;
|
|
359
|
+
}
|
|
360
|
+
interface ReaderSearchOptions {
|
|
361
|
+
/** Websearch-syntax query: words, "quoted phrases", `or`, -exclusions. */
|
|
362
|
+
query: string;
|
|
363
|
+
/** Restrict to these collections; defaults to all. */
|
|
364
|
+
collections?: string[];
|
|
365
|
+
/** Max hits, best-ranked first. Defaults to 20. */
|
|
366
|
+
limit?: number;
|
|
367
|
+
branch?: string;
|
|
368
|
+
}
|
|
369
|
+
interface ContentSearchHit {
|
|
370
|
+
row: ContentRow;
|
|
371
|
+
/** Relevance rank: slug beats frontmatter beats body prose. */
|
|
372
|
+
rank: number;
|
|
373
|
+
/** Body fragment(s) with matches wrapped in `<b>…</b>`. */
|
|
374
|
+
snippet: string;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* The seam between "who serves content reads" and "where the index lives".
|
|
378
|
+
* Implemented by the Postgres reader, the compiled SQLite artifact, and the
|
|
379
|
+
* HTTP reader in `@usegraft/content-api`.
|
|
380
|
+
*/
|
|
381
|
+
interface ContentIndexReader {
|
|
382
|
+
readContent(options: ReaderReadOptions): Promise<ContentRow[]>;
|
|
383
|
+
searchContent(options: ReaderSearchOptions): Promise<ContentSearchHit[]>;
|
|
384
|
+
close(): Promise<void>;
|
|
385
|
+
}
|
|
386
|
+
/** What one compile changed, by slug. */
|
|
387
|
+
interface ChangeSet {
|
|
388
|
+
added: string[];
|
|
389
|
+
changed: string[];
|
|
390
|
+
removed: string[];
|
|
391
|
+
unchanged: number;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export { type ChangeSet, CollectionDescriptor, ContentAuthority, type ContentIndexReader, type ContentRow, type ContentSearchHit, EditorComponentList, EditorComponentSpec, type ErrorCode, ErrorCodes, FieldDescriptor, FunctionDescriptor, GraftError, type GraftErrorJSON, type GraftErrorOptions, type ReaderReadOptions, type ReaderSearchOptions, RegistryFileDescriptor, RegistryFileRole, RegistryItemDescriptor, RegistryItemType, STATIC_INDEX_DEFAULT_PATH, SchemaDescription, getRequestPeer, rateIdentity, setRequestPeer };
|
package/dist/index.js
CHANGED
|
@@ -176,6 +176,26 @@ var RegistryItemDescriptor = z.object({
|
|
|
176
176
|
|
|
177
177
|
// src/paths.ts
|
|
178
178
|
var STATIC_INDEX_DEFAULT_PATH = ".graft/index.db";
|
|
179
|
+
|
|
180
|
+
// src/peer.ts
|
|
181
|
+
var peers = /* @__PURE__ */ new WeakMap();
|
|
182
|
+
function setRequestPeer(request, address) {
|
|
183
|
+
peers.set(request, address);
|
|
184
|
+
}
|
|
185
|
+
function getRequestPeer(request) {
|
|
186
|
+
return peers.get(request);
|
|
187
|
+
}
|
|
188
|
+
function rateIdentity(request, trustedProxyHops) {
|
|
189
|
+
if (trustedProxyHops > 0) {
|
|
190
|
+
const forwarded = request.headers.get("x-forwarded-for");
|
|
191
|
+
if (forwarded) {
|
|
192
|
+
const hops = forwarded.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
193
|
+
const trusted = hops[hops.length - trustedProxyHops];
|
|
194
|
+
if (trusted) return trusted;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return getRequestPeer(request) ?? "unknown";
|
|
198
|
+
}
|
|
179
199
|
export {
|
|
180
200
|
CollectionDescriptor,
|
|
181
201
|
ContentAuthority,
|
|
@@ -190,5 +210,8 @@ export {
|
|
|
190
210
|
RegistryItemDescriptor,
|
|
191
211
|
RegistryItemType,
|
|
192
212
|
STATIC_INDEX_DEFAULT_PATH,
|
|
193
|
-
SchemaDescription
|
|
213
|
+
SchemaDescription,
|
|
214
|
+
getRequestPeer,
|
|
215
|
+
rateIdentity,
|
|
216
|
+
setRequestPeer
|
|
194
217
|
};
|