@beignet/core 0.0.12 → 0.0.14

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 (56) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +159 -9
  3. package/dist/client/client.d.ts.map +1 -1
  4. package/dist/client/client.js +29 -1
  5. package/dist/client/client.js.map +1 -1
  6. package/dist/entitlements/index.d.ts +234 -0
  7. package/dist/entitlements/index.d.ts.map +1 -0
  8. package/dist/entitlements/index.js +172 -0
  9. package/dist/entitlements/index.js.map +1 -0
  10. package/dist/error-reporting/index.d.ts +131 -0
  11. package/dist/error-reporting/index.d.ts.map +1 -0
  12. package/dist/error-reporting/index.js +112 -0
  13. package/dist/error-reporting/index.js.map +1 -0
  14. package/dist/flags/index.d.ts +293 -0
  15. package/dist/flags/index.d.ts.map +1 -0
  16. package/dist/flags/index.js +204 -0
  17. package/dist/flags/index.js.map +1 -0
  18. package/dist/locks/index.d.ts +155 -0
  19. package/dist/locks/index.d.ts.map +1 -0
  20. package/dist/locks/index.js +248 -0
  21. package/dist/locks/index.js.map +1 -0
  22. package/dist/payments/index.d.ts +430 -0
  23. package/dist/payments/index.d.ts.map +1 -0
  24. package/dist/payments/index.js +230 -0
  25. package/dist/payments/index.js.map +1 -0
  26. package/dist/ports/index.d.ts +61 -1
  27. package/dist/ports/index.d.ts.map +1 -1
  28. package/dist/ports/index.js +33 -0
  29. package/dist/ports/index.js.map +1 -1
  30. package/dist/ports/policy.d.ts +104 -0
  31. package/dist/ports/policy.d.ts.map +1 -1
  32. package/dist/ports/policy.js +102 -7
  33. package/dist/ports/policy.js.map +1 -1
  34. package/dist/search/index.d.ts +175 -0
  35. package/dist/search/index.d.ts.map +1 -0
  36. package/dist/search/index.js +344 -0
  37. package/dist/search/index.js.map +1 -0
  38. package/dist/server/server.d.ts.map +1 -1
  39. package/dist/server/server.js +9 -1
  40. package/dist/server/server.js.map +1 -1
  41. package/dist/testing/index.d.ts +46 -1
  42. package/dist/testing/index.d.ts.map +1 -1
  43. package/dist/testing/index.js +33 -1
  44. package/dist/testing/index.js.map +1 -1
  45. package/package.json +25 -1
  46. package/src/client/client.ts +33 -1
  47. package/src/entitlements/index.ts +479 -0
  48. package/src/error-reporting/index.ts +273 -0
  49. package/src/flags/index.ts +608 -0
  50. package/src/locks/index.ts +440 -0
  51. package/src/payments/index.ts +699 -0
  52. package/src/ports/index.ts +194 -0
  53. package/src/ports/policy.ts +272 -7
  54. package/src/search/index.ts +632 -0
  55. package/src/server/server.ts +15 -0
  56. package/src/testing/index.ts +83 -1
@@ -71,6 +71,7 @@ export function definePolicy(policies) {
71
71
  */
72
72
  export function createGate(options) {
73
73
  const registry = new Map();
74
+ const observeDecision = createDecisionObserver(options.onDecision);
74
75
  for (const definition of options.policies) {
75
76
  for (const [ability, resolver] of Object.entries(definition.policies)) {
76
77
  if (registry.has(ability)) {
@@ -79,28 +80,73 @@ export function createGate(options) {
79
80
  registry.set(ability, resolver);
80
81
  }
81
82
  }
82
- async function inspect(ctx, ability, subject) {
83
+ async function evaluate(ctx, ability, subject, source = "inspect", batchKey) {
84
+ const startedAt = policyNow();
83
85
  const resolver = registry.get(ability);
84
86
  if (!resolver) {
85
- return deny({
87
+ const decision = deny({
86
88
  reason: `No policy registered for "${ability}".`,
87
89
  code: "POLICY_NOT_FOUND",
88
90
  });
91
+ observeDecision({
92
+ source,
93
+ batchKey,
94
+ ctx,
95
+ ability,
96
+ subject,
97
+ decision,
98
+ durationMs: policyNow() - startedAt,
99
+ });
100
+ return decision;
101
+ }
102
+ try {
103
+ const result = await resolver(ctx, subject);
104
+ const decision = normalizeDecision(result);
105
+ observeDecision({
106
+ source,
107
+ batchKey,
108
+ ctx,
109
+ ability,
110
+ subject,
111
+ decision,
112
+ durationMs: policyNow() - startedAt,
113
+ });
114
+ return decision;
115
+ }
116
+ catch (error) {
117
+ observeDecision({
118
+ source,
119
+ batchKey,
120
+ ctx,
121
+ ability,
122
+ subject,
123
+ error,
124
+ durationMs: policyNow() - startedAt,
125
+ });
126
+ throw error;
89
127
  }
90
- const result = await resolver(ctx, subject);
91
- return normalizeDecision(result);
92
128
  }
93
129
  async function authorize(ctx, ability, subject) {
94
- const decision = await inspect(ctx, ability, subject);
130
+ const decision = await evaluate(ctx, ability, subject, "authorize");
95
131
  if (decision.allowed)
96
132
  return decision;
97
133
  const thrown = await options.onDeny?.(decision, { ctx, ability, subject });
98
134
  throw thrown ?? new GateAuthorizationError(decision);
99
135
  }
136
+ async function inspectMany(ctx, checks, source) {
137
+ const decisions = {};
138
+ for (const [batchKey, check] of Object.entries(checks)) {
139
+ const [ability, subject] = check;
140
+ decisions[batchKey] = await evaluate(ctx, ability, subject, source, batchKey);
141
+ }
142
+ return decisions;
143
+ }
100
144
  function bind(ctx) {
101
145
  return {
102
146
  can: async (ability, ...subject) => gate.can(ctx, ability, ...subject),
147
+ canMany: async (checks) => gate.canMany(ctx, checks),
103
148
  inspect: async (ability, ...subject) => gate.inspect(ctx, ability, ...subject),
149
+ inspectMany: async (checks) => gate.inspectMany(ctx, checks),
104
150
  authorize: async (ability, ...subject) => gate.authorize(ctx, ability, ...subject),
105
151
  };
106
152
  }
@@ -118,9 +164,19 @@ export function createGate(options) {
118
164
  bind,
119
165
  attach,
120
166
  async can(ctx, ability, ...subject) {
121
- return (await inspect(ctx, ability, firstSubject(subject))).allowed;
167
+ return (await evaluate(ctx, ability, firstSubject(subject), "can"))
168
+ .allowed;
169
+ },
170
+ async canMany(ctx, checks) {
171
+ const decisions = await inspectMany(ctx, checks, "canMany");
172
+ const result = {};
173
+ for (const [key, decision] of Object.entries(decisions)) {
174
+ result[key] = decision.allowed;
175
+ }
176
+ return result;
122
177
  },
123
- inspect: async (ctx, ability, ...subject) => inspect(ctx, ability, firstSubject(subject)),
178
+ inspect: async (ctx, ability, ...subject) => evaluate(ctx, ability, firstSubject(subject), "inspect"),
179
+ inspectMany: async (ctx, checks) => inspectMany(ctx, checks, "inspectMany"),
124
180
  authorize: async (ctx, ability, ...subject) => authorize(ctx, ability, firstSubject(subject)),
125
181
  };
126
182
  return gate;
@@ -134,4 +190,43 @@ function normalizeDecision(result) {
134
190
  function firstSubject(subject) {
135
191
  return subject[0];
136
192
  }
193
+ function policyNow() {
194
+ return typeof performance !== "undefined" ? performance.now() : Date.now();
195
+ }
196
+ function contextStringField(ctx, field) {
197
+ if (!ctx || typeof ctx !== "object")
198
+ return undefined;
199
+ const value = ctx[field];
200
+ return typeof value === "string" ? value : undefined;
201
+ }
202
+ function enrichObservation(observation) {
203
+ return {
204
+ ...observation,
205
+ requestId: contextStringField(observation.ctx, "requestId"),
206
+ traceId: contextStringField(observation.ctx, "traceId"),
207
+ spanId: contextStringField(observation.ctx, "spanId"),
208
+ parentSpanId: contextStringField(observation.ctx, "parentSpanId"),
209
+ traceparent: contextStringField(observation.ctx, "traceparent"),
210
+ };
211
+ }
212
+ function isPromiseLike(value) {
213
+ return (value !== null &&
214
+ (typeof value === "object" || typeof value === "function") &&
215
+ typeof value.then === "function");
216
+ }
217
+ function createDecisionObserver(observer) {
218
+ return (observation) => {
219
+ if (!observer)
220
+ return;
221
+ try {
222
+ const result = observer(enrichObservation(observation));
223
+ if (isPromiseLike(result)) {
224
+ Promise.resolve(result).catch(() => undefined);
225
+ }
226
+ }
227
+ catch {
228
+ // Observers are diagnostic only and must not affect authorization.
229
+ }
230
+ };
231
+ }
137
232
  //# sourceMappingURL=policy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/ports/policy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/ports/policy.ts"],"names":[],"mappings":"AA6XA;;GAEG;AACH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IACtC,IAAI,CAAS;IACb,MAAM,GAAG,GAAG,CAAC;IACb,OAAO,CAAW;IAE3B,YAAY,WAA+B,IAAI,EAAE;QAC/C,KAAK,CAAC,QAAQ,CAAC,MAAM,IAAI,WAAW,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,WAAW,CAAC;QACzC,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;IAClC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,KAAK;IACnB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,IAAI,CAClB,gBAA+D;IAE/D,IAAI,OAAO,gBAAgB,KAAK,QAAQ,EAAE,CAAC;QACzC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACtD,CAAC;IAED,OAAO;QACL,OAAO,EAAE,KAAK;QACd,GAAG,gBAAgB;KACpB,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,YAAY,CAE1B,QAAmB;IACnB,OAAO,EAAE,QAAQ,EAAE,CAAC;AACtB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAIxB,OAA+C;IAE/C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;IACnD,MAAM,eAAe,GAAG,sBAAsB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAEnE,KAAK,MAAM,UAAU,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QAC1C,KAAK,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtE,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,mBAAmB,OAAO,0BAA0B,CAAC,CAAC;YACxE,CAAC;YAED,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,KAAK,UAAU,QAAQ,CACrB,GAAa,EACb,OAAe,EACf,OAAiB,EACjB,SAA6B,SAAS,EACtC,QAAiB;QAEjB,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,QAAQ,GAAG,IAAI,CAAC;gBACpB,MAAM,EAAE,6BAA6B,OAAO,IAAI;gBAChD,IAAI,EAAE,kBAAkB;aACzB,CAAC,CAAC;YAEH,eAAe,CAAC;gBACd,MAAM;gBACN,QAAQ;gBACR,GAAG;gBACH,OAAO;gBACP,OAAO;gBACP,QAAQ;gBACR,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS;aACpC,CAAC,CAAC;YAEH,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,GAAY,EAAE,OAAgB,CAAC,CAAC;YAC9D,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAE3C,eAAe,CAAC;gBACd,MAAM;gBACN,QAAQ;gBACR,GAAG;gBACH,OAAO;gBACP,OAAO;gBACP,QAAQ;gBACR,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS;aACpC,CAAC,CAAC;YAEH,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,eAAe,CAAC;gBACd,MAAM;gBACN,QAAQ;gBACR,GAAG;gBACH,OAAO;gBACP,OAAO;gBACP,KAAK;gBACL,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS;aACpC,CAAC,CAAC;YAEH,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,UAAU,SAAS,CACtB,GAAa,EACb,OAAe,EACf,OAAiB;QAEjB,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;QACpE,IAAI,QAAQ,CAAC,OAAO;YAAE,OAAO,QAAQ,CAAC;QAEtC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3E,MAAM,MAAM,IAAI,IAAI,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,UAAU,WAAW,CACxB,GAAa,EACb,MAAc,EACd,MAAiC;QAEjC,MAAM,SAAS,GAAiC,EAAE,CAAC;QAEnD,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,KAG1B,CAAC;YACF,SAAS,CAAC,QAAQ,CAAC,GAAG,MAAM,QAAQ,CAClC,GAAG,EACH,OAAO,EACP,OAAO,EACP,MAAM,EACN,QAAQ,CACT,CAAC;QACJ,CAAC;QAED,OAAO,SAA2C,CAAC;IACrD,CAAC;IAED,SAAS,IAAI,CAAC,GAAa;QACzB,OAAO;YACL,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;YACtE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC;YACpD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,EAAE,CACrC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;YACxC,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC;YAC5D,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,EAAE,CACvC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;SAC3C,CAAC;IACJ,CAAC;IAED,SAAS,MAAM,CACb,GAAM;QAEN,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE;YACjC,YAAY,EAAE,IAAI;YAClB,UAAU,EAAE,KAAK;YACjB,GAAG;gBACD,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;SACF,CAAC,CAAC;QAEH,OAAO,GAAiC,CAAC;IAC3C,CAAC;IAED,MAAM,IAAI,GAAkC;QAC1C,IAAI;QACJ,MAAM;QACN,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,OAAO;YAChC,OAAO,CAAC,MAAM,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC;iBAChE,OAAO,CAAC;QACb,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM;YACvB,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;YAC5D,MAAM,MAAM,GAA4B,EAAE,CAAC;YAE3C,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;gBACxD,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC;YACjC,CAAC;YAED,OAAO,MAA8C,CAAC;QACxD,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,EAAE,CAC1C,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;QAC1D,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,CAAC;QAC3E,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,EAAE,CAC5C,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;KACjD,CAAC;IAEF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAwB;IACjD,IAAI,OAAO,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACnC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,OAA2B;IAC/C,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,OAAO,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;AAC7E,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAY,EAAE,KAAa;IACrD,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACtD,MAAM,KAAK,GAAI,GAA+B,CAAC,KAAK,CAAC,CAAC;IACtD,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED,SAAS,iBAAiB,CACxB,WAA8C;IAE9C,OAAO;QACL,GAAG,WAAW;QACd,SAAS,EAAE,kBAAkB,CAAC,WAAW,CAAC,GAAG,EAAE,WAAW,CAAC;QAC3D,OAAO,EAAE,kBAAkB,CAAC,WAAW,CAAC,GAAG,EAAE,SAAS,CAAC;QACvD,MAAM,EAAE,kBAAkB,CAAC,WAAW,CAAC,GAAG,EAAE,QAAQ,CAAC;QACrD,YAAY,EAAE,kBAAkB,CAAC,WAAW,CAAC,GAAG,EAAE,cAAc,CAAC;QACjE,WAAW,EAAE,kBAAkB,CAAC,WAAW,CAAC,GAAG,EAAE,aAAa,CAAC;KAChE,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,CACL,KAAK,KAAK,IAAI;QACd,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,UAAU,CAAC;QAC1D,OAAQ,KAA4B,CAAC,IAAI,KAAK,UAAU,CACzD,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAC7B,QAAoD;IAEpD,OAAO,CAAC,WAAW,EAAE,EAAE;QACrB,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,QAAQ,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,CAAC;YACxD,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,mEAAmE;QACrE,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * @beignet/core/search
3
+ *
4
+ * Provider-neutral search primitives for Beignet applications.
5
+ */
6
+ /**
7
+ * Primitive values accepted in indexed documents and provider-neutral filters.
8
+ */
9
+ export type SearchPrimitive = null | boolean | number | string;
10
+ /**
11
+ * JSON-like values accepted in indexed documents.
12
+ */
13
+ export type SearchValue = SearchPrimitive | readonly SearchValue[] | {
14
+ readonly [key: string]: SearchValue;
15
+ };
16
+ /**
17
+ * Minimal document shape accepted by search indexes.
18
+ */
19
+ export type SearchDocumentBase = {
20
+ id: string;
21
+ };
22
+ /**
23
+ * General search document shape.
24
+ */
25
+ export type SearchDocument = SearchDocumentBase & {
26
+ readonly [field: string]: SearchValue | undefined;
27
+ };
28
+ type SearchField<TDocument extends SearchDocumentBase> = Extract<keyof TDocument, string>;
29
+ /**
30
+ * Provider-neutral index definition.
31
+ */
32
+ export type SearchIndexDef<TDocument extends SearchDocumentBase = SearchDocument> = {
33
+ name: string;
34
+ primaryKey: SearchField<TDocument>;
35
+ searchableAttributes?: readonly SearchField<TDocument>[];
36
+ filterableAttributes?: readonly SearchField<TDocument>[];
37
+ sortableAttributes?: readonly SearchField<TDocument>[];
38
+ displayedAttributes?: readonly SearchField<TDocument>[];
39
+ metadata?: Record<string, unknown>;
40
+ };
41
+ /**
42
+ * Options accepted when defining a search index.
43
+ */
44
+ export type DefineSearchIndexOptions<TDocument extends SearchDocumentBase> = Omit<SearchIndexDef<TDocument>, "name" | "primaryKey"> & {
45
+ primaryKey?: SearchField<TDocument>;
46
+ };
47
+ /**
48
+ * Provider-neutral filter values.
49
+ */
50
+ export type SearchFilterValue = SearchPrimitive | readonly Exclude<SearchPrimitive, null>[];
51
+ /**
52
+ * Provider-neutral exact-match filters.
53
+ */
54
+ export type SearchFilters = Record<string, SearchFilterValue>;
55
+ /**
56
+ * Provider-neutral sort expression. Use `field:asc` or `field:desc`.
57
+ */
58
+ export type SearchSort = `${string}:asc` | `${string}:desc` | (string & {});
59
+ /**
60
+ * Query accepted by search providers.
61
+ */
62
+ export type SearchQuery = {
63
+ query?: string;
64
+ filters?: SearchFilters;
65
+ sort?: readonly SearchSort[];
66
+ facets?: readonly string[];
67
+ limit?: number;
68
+ offset?: number;
69
+ };
70
+ /**
71
+ * Page metadata returned from search providers.
72
+ */
73
+ export type SearchResultPage = {
74
+ kind: "offset";
75
+ limit: number;
76
+ offset: number;
77
+ total?: number;
78
+ hasMore: boolean;
79
+ };
80
+ /**
81
+ * Search result payload.
82
+ */
83
+ export type SearchResults<TDocument extends SearchDocumentBase> = {
84
+ hits: TDocument[];
85
+ query: string;
86
+ page: SearchResultPage;
87
+ processingTimeMs?: number;
88
+ facets?: Record<string, Record<string, number>>;
89
+ };
90
+ /**
91
+ * Result returned after indexing documents.
92
+ */
93
+ export type SearchIndexResult = {
94
+ indexed: number;
95
+ taskId?: string | number;
96
+ };
97
+ /**
98
+ * Result returned after deleting indexed documents.
99
+ */
100
+ export type SearchDeleteResult = {
101
+ deleted: number;
102
+ taskId?: string | number;
103
+ };
104
+ /**
105
+ * App-facing search port.
106
+ */
107
+ export type SearchPort = {
108
+ configureIndex<TDocument extends SearchDocumentBase>(index: SearchIndexDef<TDocument>): Promise<void>;
109
+ indexDocuments<TDocument extends SearchDocumentBase>(index: SearchIndexDef<TDocument>, documents: TDocument | readonly TDocument[]): Promise<SearchIndexResult>;
110
+ deleteDocuments<TDocument extends SearchDocumentBase>(index: SearchIndexDef<TDocument>, ids: string | readonly string[]): Promise<SearchDeleteResult>;
111
+ clearIndex<TDocument extends SearchDocumentBase>(index: SearchIndexDef<TDocument>): Promise<SearchDeleteResult>;
112
+ search<TDocument extends SearchDocumentBase>(index: SearchIndexDef<TDocument>, query: SearchQuery): Promise<SearchResults<TDocument>>;
113
+ };
114
+ /**
115
+ * Captured memory index state exposed for tests.
116
+ */
117
+ export type MemorySearchIndexState<TDocument extends SearchDocumentBase = SearchDocument> = {
118
+ definition?: SearchIndexDef<TDocument>;
119
+ documents: Map<string, TDocument>;
120
+ };
121
+ /**
122
+ * In-memory search port exposed for assertions in tests.
123
+ */
124
+ export type MemorySearchPort = SearchPort & {
125
+ indexes: Map<string, MemorySearchIndexState>;
126
+ reset(index?: SearchIndexDef): void;
127
+ };
128
+ /**
129
+ * Options for the in-memory search adapter.
130
+ */
131
+ export type CreateMemorySearchOptions = {
132
+ now?: () => Date;
133
+ };
134
+ /**
135
+ * Options for the in-memory search provider.
136
+ */
137
+ export type MemorySearchProviderOptions = CreateMemorySearchOptions & {
138
+ name?: string;
139
+ };
140
+ /**
141
+ * Ports contributed by the memory search provider.
142
+ */
143
+ export interface MemorySearchProviderPorts {
144
+ search: SearchPort;
145
+ }
146
+ /**
147
+ * Error thrown when search inputs are invalid.
148
+ */
149
+ export declare class SearchOptionsError extends Error {
150
+ constructor(message: string);
151
+ }
152
+ /**
153
+ * Define a typed search index.
154
+ */
155
+ export declare function defineSearchIndex<TDocument extends SearchDocumentBase = SearchDocument>(name: string, options?: DefineSearchIndexOptions<TDocument>): SearchIndexDef<TDocument>;
156
+ /**
157
+ * Index documents through any `SearchPort`.
158
+ */
159
+ export declare function indexSearchDocuments<TDocument extends SearchDocumentBase>(search: SearchPort, index: SearchIndexDef<TDocument>, documents: TDocument | readonly TDocument[]): Promise<SearchIndexResult>;
160
+ /**
161
+ * Query documents through any `SearchPort`.
162
+ */
163
+ export declare function searchDocuments<TDocument extends SearchDocumentBase>(search: SearchPort, index: SearchIndexDef<TDocument>, query: SearchQuery): Promise<SearchResults<TDocument>>;
164
+ /**
165
+ * Create an in-memory search port for tests and single-process development.
166
+ */
167
+ export declare function createMemorySearch(_options?: CreateMemorySearchOptions): MemorySearchPort;
168
+ /**
169
+ * Create a provider that contributes an in-memory search port.
170
+ */
171
+ export declare function createMemorySearchProvider(options?: MemorySearchProviderOptions): import("../providers/provider.js").ServiceProvider<unknown, import("@standard-schema/spec").StandardSchemaV1<void, void>, {
172
+ search: SearchPort;
173
+ }, unknown, void>;
174
+ export {};
175
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/search/index.ts"],"names":[],"mappings":"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"}