@objectstack/rest 4.0.5 → 4.1.1
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.cjs +1997 -79
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +153 -1
- package/dist/index.d.ts +153 -1
- package/dist/index.js +1997 -79
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.cts
CHANGED
|
@@ -221,7 +221,13 @@ declare class RestServer {
|
|
|
221
221
|
private defaultProjectIdProvider?;
|
|
222
222
|
private authServiceProvider?;
|
|
223
223
|
private objectQLProvider?;
|
|
224
|
-
|
|
224
|
+
private emailServiceProvider?;
|
|
225
|
+
private sharingServiceProvider?;
|
|
226
|
+
private reportsServiceProvider?;
|
|
227
|
+
private approvalsServiceProvider?;
|
|
228
|
+
private sharingRulesServiceProvider?;
|
|
229
|
+
private i18nServiceProvider?;
|
|
230
|
+
constructor(server: IHttpServer, protocol: ObjectStackProtocol, config?: RestServerConfig, kernelManager?: RestKernelManager, envRegistry?: RestEnvRegistry, defaultProjectIdProvider?: () => string | undefined, authServiceProvider?: (projectId?: string) => Promise<any | undefined>, objectQLProvider?: (projectId?: string) => Promise<any | undefined>, emailServiceProvider?: (projectId?: string) => Promise<any | undefined>, sharingServiceProvider?: (projectId?: string) => Promise<any | undefined>, reportsServiceProvider?: (projectId?: string) => Promise<any | undefined>, approvalsServiceProvider?: (projectId?: string) => Promise<any | undefined>, sharingRulesServiceProvider?: (projectId?: string) => Promise<any | undefined>, i18nServiceProvider?: (projectId?: string) => Promise<any | undefined>);
|
|
225
231
|
/**
|
|
226
232
|
* Resolve the protocol for a given request. When `projectId` is present
|
|
227
233
|
* and a KernelManager is wired, fetch the per-project kernel's
|
|
@@ -257,6 +263,16 @@ declare class RestServer {
|
|
|
257
263
|
* does not own per-app translation bundles.
|
|
258
264
|
*/
|
|
259
265
|
private resolveI18nService;
|
|
266
|
+
/**
|
|
267
|
+
* Reject anonymous requests with HTTP 401 when `api.requireAuth` is set.
|
|
268
|
+
* Returns `true` if the response was sent and the caller should stop
|
|
269
|
+
* processing. Returns `false` to continue.
|
|
270
|
+
*
|
|
271
|
+
* The check is intentionally narrow: only `context?.userId` counts as
|
|
272
|
+
* "authenticated". `isSystem` flags are never set on inbound HTTP
|
|
273
|
+
* requests (they're internal-only), so they cannot bypass this gate.
|
|
274
|
+
*/
|
|
275
|
+
private enforceAuth;
|
|
260
276
|
/**
|
|
261
277
|
* Resolve the request's execution context (RBAC/RLS/FLS) by looking up
|
|
262
278
|
* the better-auth session via the project's `auth` service. Returns
|
|
@@ -339,6 +355,142 @@ declare class RestServer {
|
|
|
339
355
|
* Register CRUD endpoints for data operations
|
|
340
356
|
*/
|
|
341
357
|
private registerCrudEndpoints;
|
|
358
|
+
/**
|
|
359
|
+
* Register object-specific action endpoints that don't fit the
|
|
360
|
+
* generic CRUD shape. These are domain operations (Salesforce
|
|
361
|
+
* convertLead, etc.) where the protocol implementation does its own
|
|
362
|
+
* multi-record orchestration and we just need a thin HTTP route.
|
|
363
|
+
*
|
|
364
|
+
* POST {basePath}/data/lead/:id/convert — M10.6 lead conversion.
|
|
365
|
+
*/
|
|
366
|
+
private registerDataActionEndpoints;
|
|
367
|
+
/**
|
|
368
|
+
* Register global cross-object search endpoint (M10.5).
|
|
369
|
+
* GET {basePath}/search?q=acme&objects=lead,account&limit=20&perObject=5
|
|
370
|
+
*/
|
|
371
|
+
private registerSearchEndpoints;
|
|
372
|
+
/**
|
|
373
|
+
* Register email endpoints (M11.B1 / M10.7).
|
|
374
|
+
*
|
|
375
|
+
* POST {basePath}/email/send — send a transactional email via the
|
|
376
|
+
* `IEmailService` provider registered by EmailServicePlugin. Returns
|
|
377
|
+
* 501 when no provider is wired so deployments without email
|
|
378
|
+
* configured fail cleanly.
|
|
379
|
+
*
|
|
380
|
+
* Request body:
|
|
381
|
+
* {
|
|
382
|
+
* to: "a@b.com" | ["a@b.com", { name, address }],
|
|
383
|
+
* from?: ..., cc?: ..., bcc?: ..., replyTo?: ...,
|
|
384
|
+
* subject: string,
|
|
385
|
+
* text?: string, html?: string, // at least one required
|
|
386
|
+
* attachments?: [{ filename, content, contentType?, cid? }],
|
|
387
|
+
* headers?: { [name]: value },
|
|
388
|
+
* relatedObject?: string, relatedId?: string,
|
|
389
|
+
* }
|
|
390
|
+
*/
|
|
391
|
+
private registerEmailEndpoints;
|
|
392
|
+
/**
|
|
393
|
+
* Register public (anonymous) form endpoints.
|
|
394
|
+
*
|
|
395
|
+
* Public forms are opt-in: a `FormView` becomes accessible to anonymous
|
|
396
|
+
* visitors only when `sharing.allowAnonymous === true` AND a
|
|
397
|
+
* `sharing.publicLink` slug is configured. Two routes are registered:
|
|
398
|
+
*
|
|
399
|
+
* GET {basePath}/forms/:slug → resolved form spec
|
|
400
|
+
* POST {basePath}/forms/:slug/submit → INSERT record (no auth required)
|
|
401
|
+
*
|
|
402
|
+
* Both routes bypass `enforceAuth` even when `requireAuth=true` on the
|
|
403
|
+
* deployment (e.g. ObjectOS multi-tenant). Security is delegated to the
|
|
404
|
+
* `guest_portal` permission set carried on the execution context — the
|
|
405
|
+
* SecurityPlugin enforces INSERT-only access to the target object. If
|
|
406
|
+
* the deployment hasn't registered a `guest_portal` profile, the
|
|
407
|
+
* security middleware falls open with `permissions: []` (no userId),
|
|
408
|
+
* matching the existing anonymous-access semantics; deployers must
|
|
409
|
+
* keep `requireAuth=true` deployments paired with a `guest_portal`
|
|
410
|
+
* profile (the CRM example does this) to enforce the INSERT-only
|
|
411
|
+
* contract.
|
|
412
|
+
*
|
|
413
|
+
* The matched FormView's parent ViewSchema is found by scanning
|
|
414
|
+
* `protocol.getMetaItems({ type: 'view' })`. For each entry we inspect
|
|
415
|
+
* `form.sharing` and every entry in `formViews`; the first FormView
|
|
416
|
+
* whose `sharing.publicLink` matches `/forms/:slug` (or just `:slug`)
|
|
417
|
+
* wins. The response carries the matched form view under `form` and
|
|
418
|
+
* the inferred target object, matching what the frontend's
|
|
419
|
+
* `mapViewSpecToEmbeddableConfig` expects.
|
|
420
|
+
*/
|
|
421
|
+
private registerFormEndpoints;
|
|
422
|
+
/**
|
|
423
|
+
* Register record-level sharing endpoints (M11.C17).
|
|
424
|
+
*
|
|
425
|
+
* Surfaces `ISharingService` over HTTP so the UI can list, create
|
|
426
|
+
* and revoke per-record grants without going through ObjectQL. The
|
|
427
|
+
* three routes mirror the share-management drawer in Salesforce /
|
|
428
|
+
* ServiceNow:
|
|
429
|
+
*
|
|
430
|
+
* GET {basePath}/data/:object/:id/shares
|
|
431
|
+
* POST {basePath}/data/:object/:id/shares
|
|
432
|
+
* DELETE {basePath}/data/:object/:id/shares/:shareId
|
|
433
|
+
*
|
|
434
|
+
* All three resolve via `sharingServiceProvider`; routes return 501
|
|
435
|
+
* when no sharing service is configured so a deployment without the
|
|
436
|
+
* `@objectstack/plugin-sharing` plugin fails cleanly.
|
|
437
|
+
*/
|
|
438
|
+
private registerSharingEndpoints;
|
|
439
|
+
/**
|
|
440
|
+
* Register sharing-rule endpoints (M10.17). Mirrors the existing
|
|
441
|
+
* sharing endpoints but operates on `sys_sharing_rule` rows.
|
|
442
|
+
*
|
|
443
|
+
* GET {basePath}/sharing/rules?object=&activeOnly=
|
|
444
|
+
* POST {basePath}/sharing/rules
|
|
445
|
+
* GET {basePath}/sharing/rules/:idOrName
|
|
446
|
+
* DELETE {basePath}/sharing/rules/:idOrName
|
|
447
|
+
* POST {basePath}/sharing/rules/:idOrName/evaluate
|
|
448
|
+
*
|
|
449
|
+
* Returns 501 when no sharing-rule service is configured.
|
|
450
|
+
*/
|
|
451
|
+
private registerSharingRuleEndpoints;
|
|
452
|
+
/**
|
|
453
|
+
* Register saved-report + scheduled-digest endpoints (M11.C16).
|
|
454
|
+
*
|
|
455
|
+
* Surfaces `IReportService` over HTTP so the UI can build,
|
|
456
|
+
* run, and schedule reports without dropping to ObjectQL. Routes
|
|
457
|
+
* live at the top of the API surface (alongside `/approvals` and
|
|
458
|
+
* `/sharing`) — reports are a tenant-wide capability, not a record
|
|
459
|
+
* on a specific CRUD object:
|
|
460
|
+
*
|
|
461
|
+
* GET {basePath}/reports?object=&ownerId=
|
|
462
|
+
* POST {basePath}/reports
|
|
463
|
+
* GET {basePath}/reports/:id
|
|
464
|
+
* DELETE {basePath}/reports/:id
|
|
465
|
+
* POST {basePath}/reports/:id/run
|
|
466
|
+
* POST {basePath}/reports/:id/schedule
|
|
467
|
+
* GET {basePath}/reports/:id/schedules
|
|
468
|
+
* DELETE {basePath}/reports/schedules/:scheduleId
|
|
469
|
+
*
|
|
470
|
+
* All routes return 501 when `reportsServiceProvider` is unset so
|
|
471
|
+
* a deployment without `@objectstack/plugin-reports` fails cleanly.
|
|
472
|
+
*/
|
|
473
|
+
private registerReportsEndpoints;
|
|
474
|
+
/**
|
|
475
|
+
* Register approval engine endpoints.
|
|
476
|
+
*
|
|
477
|
+
* Routes (all under {basePath}/approvals):
|
|
478
|
+
* GET /processes — list approval processes
|
|
479
|
+
* POST /processes — upsert (defineProcess)
|
|
480
|
+
* GET /processes/:id — get by id or name
|
|
481
|
+
* DELETE /processes/:id — delete process
|
|
482
|
+
* POST /requests — submit
|
|
483
|
+
* GET /requests — list (filters: status, object, recordId, approverId, submitterId)
|
|
484
|
+
* GET /requests/:id — get request
|
|
485
|
+
* POST /requests/:id/approve — approve current step
|
|
486
|
+
* POST /requests/:id/reject — reject current step
|
|
487
|
+
* POST /requests/:id/recall — recall (submitter only)
|
|
488
|
+
* GET /requests/:id/actions — audit trail
|
|
489
|
+
*
|
|
490
|
+
* Returns 501 when `approvalsServiceProvider` is unset so deployments
|
|
491
|
+
* without `@objectstack/plugin-approvals` fail cleanly.
|
|
492
|
+
*/
|
|
493
|
+
private registerApprovalsEndpoints;
|
|
342
494
|
/**
|
|
343
495
|
* Register batch operation endpoints
|
|
344
496
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -221,7 +221,13 @@ declare class RestServer {
|
|
|
221
221
|
private defaultProjectIdProvider?;
|
|
222
222
|
private authServiceProvider?;
|
|
223
223
|
private objectQLProvider?;
|
|
224
|
-
|
|
224
|
+
private emailServiceProvider?;
|
|
225
|
+
private sharingServiceProvider?;
|
|
226
|
+
private reportsServiceProvider?;
|
|
227
|
+
private approvalsServiceProvider?;
|
|
228
|
+
private sharingRulesServiceProvider?;
|
|
229
|
+
private i18nServiceProvider?;
|
|
230
|
+
constructor(server: IHttpServer, protocol: ObjectStackProtocol, config?: RestServerConfig, kernelManager?: RestKernelManager, envRegistry?: RestEnvRegistry, defaultProjectIdProvider?: () => string | undefined, authServiceProvider?: (projectId?: string) => Promise<any | undefined>, objectQLProvider?: (projectId?: string) => Promise<any | undefined>, emailServiceProvider?: (projectId?: string) => Promise<any | undefined>, sharingServiceProvider?: (projectId?: string) => Promise<any | undefined>, reportsServiceProvider?: (projectId?: string) => Promise<any | undefined>, approvalsServiceProvider?: (projectId?: string) => Promise<any | undefined>, sharingRulesServiceProvider?: (projectId?: string) => Promise<any | undefined>, i18nServiceProvider?: (projectId?: string) => Promise<any | undefined>);
|
|
225
231
|
/**
|
|
226
232
|
* Resolve the protocol for a given request. When `projectId` is present
|
|
227
233
|
* and a KernelManager is wired, fetch the per-project kernel's
|
|
@@ -257,6 +263,16 @@ declare class RestServer {
|
|
|
257
263
|
* does not own per-app translation bundles.
|
|
258
264
|
*/
|
|
259
265
|
private resolveI18nService;
|
|
266
|
+
/**
|
|
267
|
+
* Reject anonymous requests with HTTP 401 when `api.requireAuth` is set.
|
|
268
|
+
* Returns `true` if the response was sent and the caller should stop
|
|
269
|
+
* processing. Returns `false` to continue.
|
|
270
|
+
*
|
|
271
|
+
* The check is intentionally narrow: only `context?.userId` counts as
|
|
272
|
+
* "authenticated". `isSystem` flags are never set on inbound HTTP
|
|
273
|
+
* requests (they're internal-only), so they cannot bypass this gate.
|
|
274
|
+
*/
|
|
275
|
+
private enforceAuth;
|
|
260
276
|
/**
|
|
261
277
|
* Resolve the request's execution context (RBAC/RLS/FLS) by looking up
|
|
262
278
|
* the better-auth session via the project's `auth` service. Returns
|
|
@@ -339,6 +355,142 @@ declare class RestServer {
|
|
|
339
355
|
* Register CRUD endpoints for data operations
|
|
340
356
|
*/
|
|
341
357
|
private registerCrudEndpoints;
|
|
358
|
+
/**
|
|
359
|
+
* Register object-specific action endpoints that don't fit the
|
|
360
|
+
* generic CRUD shape. These are domain operations (Salesforce
|
|
361
|
+
* convertLead, etc.) where the protocol implementation does its own
|
|
362
|
+
* multi-record orchestration and we just need a thin HTTP route.
|
|
363
|
+
*
|
|
364
|
+
* POST {basePath}/data/lead/:id/convert — M10.6 lead conversion.
|
|
365
|
+
*/
|
|
366
|
+
private registerDataActionEndpoints;
|
|
367
|
+
/**
|
|
368
|
+
* Register global cross-object search endpoint (M10.5).
|
|
369
|
+
* GET {basePath}/search?q=acme&objects=lead,account&limit=20&perObject=5
|
|
370
|
+
*/
|
|
371
|
+
private registerSearchEndpoints;
|
|
372
|
+
/**
|
|
373
|
+
* Register email endpoints (M11.B1 / M10.7).
|
|
374
|
+
*
|
|
375
|
+
* POST {basePath}/email/send — send a transactional email via the
|
|
376
|
+
* `IEmailService` provider registered by EmailServicePlugin. Returns
|
|
377
|
+
* 501 when no provider is wired so deployments without email
|
|
378
|
+
* configured fail cleanly.
|
|
379
|
+
*
|
|
380
|
+
* Request body:
|
|
381
|
+
* {
|
|
382
|
+
* to: "a@b.com" | ["a@b.com", { name, address }],
|
|
383
|
+
* from?: ..., cc?: ..., bcc?: ..., replyTo?: ...,
|
|
384
|
+
* subject: string,
|
|
385
|
+
* text?: string, html?: string, // at least one required
|
|
386
|
+
* attachments?: [{ filename, content, contentType?, cid? }],
|
|
387
|
+
* headers?: { [name]: value },
|
|
388
|
+
* relatedObject?: string, relatedId?: string,
|
|
389
|
+
* }
|
|
390
|
+
*/
|
|
391
|
+
private registerEmailEndpoints;
|
|
392
|
+
/**
|
|
393
|
+
* Register public (anonymous) form endpoints.
|
|
394
|
+
*
|
|
395
|
+
* Public forms are opt-in: a `FormView` becomes accessible to anonymous
|
|
396
|
+
* visitors only when `sharing.allowAnonymous === true` AND a
|
|
397
|
+
* `sharing.publicLink` slug is configured. Two routes are registered:
|
|
398
|
+
*
|
|
399
|
+
* GET {basePath}/forms/:slug → resolved form spec
|
|
400
|
+
* POST {basePath}/forms/:slug/submit → INSERT record (no auth required)
|
|
401
|
+
*
|
|
402
|
+
* Both routes bypass `enforceAuth` even when `requireAuth=true` on the
|
|
403
|
+
* deployment (e.g. ObjectOS multi-tenant). Security is delegated to the
|
|
404
|
+
* `guest_portal` permission set carried on the execution context — the
|
|
405
|
+
* SecurityPlugin enforces INSERT-only access to the target object. If
|
|
406
|
+
* the deployment hasn't registered a `guest_portal` profile, the
|
|
407
|
+
* security middleware falls open with `permissions: []` (no userId),
|
|
408
|
+
* matching the existing anonymous-access semantics; deployers must
|
|
409
|
+
* keep `requireAuth=true` deployments paired with a `guest_portal`
|
|
410
|
+
* profile (the CRM example does this) to enforce the INSERT-only
|
|
411
|
+
* contract.
|
|
412
|
+
*
|
|
413
|
+
* The matched FormView's parent ViewSchema is found by scanning
|
|
414
|
+
* `protocol.getMetaItems({ type: 'view' })`. For each entry we inspect
|
|
415
|
+
* `form.sharing` and every entry in `formViews`; the first FormView
|
|
416
|
+
* whose `sharing.publicLink` matches `/forms/:slug` (or just `:slug`)
|
|
417
|
+
* wins. The response carries the matched form view under `form` and
|
|
418
|
+
* the inferred target object, matching what the frontend's
|
|
419
|
+
* `mapViewSpecToEmbeddableConfig` expects.
|
|
420
|
+
*/
|
|
421
|
+
private registerFormEndpoints;
|
|
422
|
+
/**
|
|
423
|
+
* Register record-level sharing endpoints (M11.C17).
|
|
424
|
+
*
|
|
425
|
+
* Surfaces `ISharingService` over HTTP so the UI can list, create
|
|
426
|
+
* and revoke per-record grants without going through ObjectQL. The
|
|
427
|
+
* three routes mirror the share-management drawer in Salesforce /
|
|
428
|
+
* ServiceNow:
|
|
429
|
+
*
|
|
430
|
+
* GET {basePath}/data/:object/:id/shares
|
|
431
|
+
* POST {basePath}/data/:object/:id/shares
|
|
432
|
+
* DELETE {basePath}/data/:object/:id/shares/:shareId
|
|
433
|
+
*
|
|
434
|
+
* All three resolve via `sharingServiceProvider`; routes return 501
|
|
435
|
+
* when no sharing service is configured so a deployment without the
|
|
436
|
+
* `@objectstack/plugin-sharing` plugin fails cleanly.
|
|
437
|
+
*/
|
|
438
|
+
private registerSharingEndpoints;
|
|
439
|
+
/**
|
|
440
|
+
* Register sharing-rule endpoints (M10.17). Mirrors the existing
|
|
441
|
+
* sharing endpoints but operates on `sys_sharing_rule` rows.
|
|
442
|
+
*
|
|
443
|
+
* GET {basePath}/sharing/rules?object=&activeOnly=
|
|
444
|
+
* POST {basePath}/sharing/rules
|
|
445
|
+
* GET {basePath}/sharing/rules/:idOrName
|
|
446
|
+
* DELETE {basePath}/sharing/rules/:idOrName
|
|
447
|
+
* POST {basePath}/sharing/rules/:idOrName/evaluate
|
|
448
|
+
*
|
|
449
|
+
* Returns 501 when no sharing-rule service is configured.
|
|
450
|
+
*/
|
|
451
|
+
private registerSharingRuleEndpoints;
|
|
452
|
+
/**
|
|
453
|
+
* Register saved-report + scheduled-digest endpoints (M11.C16).
|
|
454
|
+
*
|
|
455
|
+
* Surfaces `IReportService` over HTTP so the UI can build,
|
|
456
|
+
* run, and schedule reports without dropping to ObjectQL. Routes
|
|
457
|
+
* live at the top of the API surface (alongside `/approvals` and
|
|
458
|
+
* `/sharing`) — reports are a tenant-wide capability, not a record
|
|
459
|
+
* on a specific CRUD object:
|
|
460
|
+
*
|
|
461
|
+
* GET {basePath}/reports?object=&ownerId=
|
|
462
|
+
* POST {basePath}/reports
|
|
463
|
+
* GET {basePath}/reports/:id
|
|
464
|
+
* DELETE {basePath}/reports/:id
|
|
465
|
+
* POST {basePath}/reports/:id/run
|
|
466
|
+
* POST {basePath}/reports/:id/schedule
|
|
467
|
+
* GET {basePath}/reports/:id/schedules
|
|
468
|
+
* DELETE {basePath}/reports/schedules/:scheduleId
|
|
469
|
+
*
|
|
470
|
+
* All routes return 501 when `reportsServiceProvider` is unset so
|
|
471
|
+
* a deployment without `@objectstack/plugin-reports` fails cleanly.
|
|
472
|
+
*/
|
|
473
|
+
private registerReportsEndpoints;
|
|
474
|
+
/**
|
|
475
|
+
* Register approval engine endpoints.
|
|
476
|
+
*
|
|
477
|
+
* Routes (all under {basePath}/approvals):
|
|
478
|
+
* GET /processes — list approval processes
|
|
479
|
+
* POST /processes — upsert (defineProcess)
|
|
480
|
+
* GET /processes/:id — get by id or name
|
|
481
|
+
* DELETE /processes/:id — delete process
|
|
482
|
+
* POST /requests — submit
|
|
483
|
+
* GET /requests — list (filters: status, object, recordId, approverId, submitterId)
|
|
484
|
+
* GET /requests/:id — get request
|
|
485
|
+
* POST /requests/:id/approve — approve current step
|
|
486
|
+
* POST /requests/:id/reject — reject current step
|
|
487
|
+
* POST /requests/:id/recall — recall (submitter only)
|
|
488
|
+
* GET /requests/:id/actions — audit trail
|
|
489
|
+
*
|
|
490
|
+
* Returns 501 when `approvalsServiceProvider` is unset so deployments
|
|
491
|
+
* without `@objectstack/plugin-approvals` fail cleanly.
|
|
492
|
+
*/
|
|
493
|
+
private registerApprovalsEndpoints;
|
|
342
494
|
/**
|
|
343
495
|
* Register batch operation endpoints
|
|
344
496
|
*/
|