@rebasepro/server 0.13.0 → 0.13.1-canary.g06dbe5b
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/{admin_block-CcSGdH7M.js → admin_block-H86dCPsj.js} +62 -2
- package/dist/admin_block-H86dCPsj.js.map +1 -0
- package/dist/api/ast-schema-editor.d.ts +74 -6
- package/dist/api/errors.d.ts +0 -6
- package/dist/api/openapi-generator.d.ts +14 -0
- package/dist/api/rest/api-generator.d.ts +1 -1
- package/dist/api/rest/idempotency.d.ts +62 -4
- package/dist/api/rest/query-parser.d.ts +15 -1
- package/dist/api/rest/write-validation.d.ts +52 -9
- package/dist/auth/adapter-middleware.d.ts +3 -1
- package/dist/auth/apple-oauth.d.ts +16 -11
- package/dist/auth/bitbucket-oauth.d.ts +2 -4
- package/dist/auth/builtin-auth-adapter.d.ts +2 -0
- package/dist/auth/discord-oauth.d.ts +5 -6
- package/dist/auth/facebook-oauth.d.ts +2 -4
- package/dist/auth/github-oauth.d.ts +2 -4
- package/dist/auth/gitlab-oauth.d.ts +6 -4
- package/dist/auth/google-oauth.d.ts +1 -0
- package/dist/auth/index.d.ts +8 -1
- package/dist/auth/interfaces.d.ts +68 -1
- package/dist/auth/jwt.d.ts +40 -0
- package/dist/auth/linkedin-oauth.d.ts +2 -4
- package/dist/auth/mfa-gate.d.ts +42 -0
- package/dist/auth/mfa-routes.d.ts +26 -1
- package/dist/auth/mfa.d.ts +16 -0
- package/dist/auth/microsoft-oauth.d.ts +19 -4
- package/dist/auth/oauth-code-flow.d.ts +66 -0
- package/dist/auth/oauth-signin-policy.d.ts +61 -0
- package/dist/auth/oidc-id-token.d.ts +61 -0
- package/dist/auth/rate-limiter.d.ts +37 -2
- package/dist/auth/rls-scope.d.ts +25 -0
- package/dist/auth/routes.d.ts +8 -0
- package/dist/auth/slack-oauth.d.ts +2 -4
- package/dist/auth/spotify-oauth.d.ts +2 -4
- package/dist/auth/twitter-oauth.d.ts +2 -5
- package/dist/{auth-CuC9M2x6.js → auth-DkAHqvf5.js} +1604 -391
- package/dist/auth-DkAHqvf5.js.map +1 -0
- package/dist/{backup-CVggVhR2.js → backup-DLluVyuA.js} +2 -2
- package/dist/{backup-CVggVhR2.js.map → backup-DLluVyuA.js.map} +1 -1
- package/dist/boot/boot.d.ts +19 -0
- package/dist/boot/ddl-bootstrap.d.ts +70 -0
- package/dist/{contract-routes-Dj8i5AiM.js → contract-routes-BB1U05sS.js} +3 -3
- package/dist/{contract-routes-Dj8i5AiM.js.map → contract-routes-BB1U05sS.js.map} +1 -1
- package/dist/cron/cron-scheduler.d.ts +8 -3
- package/dist/cron/define-cron.d.ts +17 -3
- package/dist/{cron-loader-B1S2MCSl.js → cron-loader-3U5aGILy.js} +2 -2
- package/dist/{cron-loader-B1S2MCSl.js.map → cron-loader-3U5aGILy.js.map} +1 -1
- package/dist/{cron-routes-CrQ0tK-_.js → cron-routes-rZgwlOz4.js} +2 -2
- package/dist/{cron-routes-CrQ0tK-_.js.map → cron-routes-rZgwlOz4.js.map} +1 -1
- package/dist/{cron-scheduler-B3RFt0HS.js → cron-scheduler-FJAaCAXm.js} +30 -5
- package/dist/cron-scheduler-FJAaCAXm.js.map +1 -0
- package/dist/{cron-store-BywZsyfZ.js → cron-store-9NmUDfzL.js} +66 -47
- package/dist/cron-store-9NmUDfzL.js.map +1 -0
- package/dist/ddl-bootstrap-BhXbTnBl.js +183 -0
- package/dist/ddl-bootstrap-BhXbTnBl.js.map +1 -0
- package/dist/email/html.d.ts +54 -0
- package/dist/email/index.d.ts +3 -0
- package/dist/email/link-base.d.ts +39 -0
- package/dist/email/smtp-email-service.d.ts +7 -1
- package/dist/email/templates.d.ts +9 -1
- package/dist/email/types.d.ts +11 -1
- package/dist/{errors-CgkCzoj7.js → errors-B1WZEdsK.js} +3 -11
- package/dist/errors-B1WZEdsK.js.map +1 -0
- package/dist/function-loader-D1SwtCa5.js +139 -0
- package/dist/function-loader-D1SwtCa5.js.map +1 -0
- package/dist/{function-routes-C0cLIy3N.js → function-routes-Btcez1T-.js} +18 -6
- package/dist/function-routes-Btcez1T-.js.map +1 -0
- package/dist/functions/define-function.d.ts +25 -6
- package/dist/functions/function-loader.d.ts +23 -0
- package/dist/functions/function-routes.d.ts +7 -1
- package/dist/functions/request-timeout.d.ts +34 -0
- package/dist/history/history-routes.d.ts +6 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.es.js +1960 -794
- package/dist/index.es.js.map +1 -1
- package/dist/init/docs.d.ts +10 -1
- package/dist/init/process-safety.d.ts +25 -0
- package/dist/init.d.ts +27 -0
- package/dist/{jwt-DD6EtpGj.js → jwt-Cuq6MwNy.js} +70 -8
- package/dist/jwt-Cuq6MwNy.js.map +1 -0
- package/dist/logger-DfvF_8r-.js +190 -0
- package/dist/logger-DfvF_8r-.js.map +1 -0
- package/dist/openapi-generator-BQxxxDpb.js +865 -0
- package/dist/openapi-generator-BQxxxDpb.js.map +1 -0
- package/dist/request-timeout-RivJsME0.js +65 -0
- package/dist/request-timeout-RivJsME0.js.map +1 -0
- package/dist/schema-editor-routes-DZFKGXgq.js +437 -0
- package/dist/schema-editor-routes-DZFKGXgq.js.map +1 -0
- package/dist/serve-spa.d.ts +5 -4
- package/dist/services/outbound-url-guard.d.ts +53 -0
- package/dist/services/routed-realtime-service.d.ts +10 -2
- package/dist/services/webhook-service.d.ts +76 -1
- package/dist/singleton.d.ts +25 -8
- package/dist/{src-Cum9kox5.js → src-By48Ffg0.js} +322 -70
- package/dist/src-By48Ffg0.js.map +1 -0
- package/dist/{src-_qQ3RNCK.js → src-Ca6NhxKs.js} +79 -2
- package/dist/src-Ca6NhxKs.js.map +1 -0
- package/dist/storage/LocalStorageController.d.ts +12 -1
- package/dist/storage/image-transform.d.ts +57 -0
- package/dist/storage/keys.d.ts +98 -0
- package/dist/storage/routes.d.ts +11 -0
- package/dist/storage/tus-handler.d.ts +7 -1
- package/dist/utils/logger.d.ts +18 -0
- package/dist/utils/logging.d.ts +0 -4
- package/dist/utils/sql.d.ts +11 -6
- package/package.json +7 -6
- package/dist/admin_block-CcSGdH7M.js.map +0 -1
- package/dist/auth-CuC9M2x6.js.map +0 -1
- package/dist/backend-CIxN4FVm.js +0 -15
- package/dist/backend-CIxN4FVm.js.map +0 -1
- package/dist/cron-scheduler-B3RFt0HS.js.map +0 -1
- package/dist/cron-store-BywZsyfZ.js.map +0 -1
- package/dist/errors-CgkCzoj7.js.map +0 -1
- package/dist/function-loader-B_1fYfUY.js +0 -86
- package/dist/function-loader-B_1fYfUY.js.map +0 -1
- package/dist/function-routes-C0cLIy3N.js.map +0 -1
- package/dist/jwt-DD6EtpGj.js.map +0 -1
- package/dist/logger-BYU66ENZ.js +0 -94
- package/dist/logger-BYU66ENZ.js.map +0 -1
- package/dist/openapi-generator-BEwyiaAr.js +0 -597
- package/dist/openapi-generator-BEwyiaAr.js.map +0 -1
- package/dist/schema-editor-routes-CbF20Mf1.js +0 -248
- package/dist/schema-editor-routes-CbF20Mf1.js.map +0 -1
- package/dist/src-Cum9kox5.js.map +0 -1
- package/dist/src-_qQ3RNCK.js.map +0 -1
|
@@ -44,6 +44,7 @@ var ADMIN_COLLECTION_KEYS = [
|
|
|
44
44
|
"defaultSize",
|
|
45
45
|
"defaultViewMode",
|
|
46
46
|
"disableDefaultActions",
|
|
47
|
+
"display",
|
|
47
48
|
"enabledViews",
|
|
48
49
|
"entityActions",
|
|
49
50
|
"entityViews",
|
|
@@ -54,6 +55,7 @@ var ADMIN_COLLECTION_KEYS = [
|
|
|
54
55
|
"formAutoSave",
|
|
55
56
|
"formView",
|
|
56
57
|
"group",
|
|
58
|
+
"hideFromEntityViews",
|
|
57
59
|
"hideFromNavigation",
|
|
58
60
|
"hideIdFromCollection",
|
|
59
61
|
"hideIdFromForm",
|
|
@@ -118,7 +120,65 @@ var ADMIN_PROPERTY_KEYS = [
|
|
|
118
120
|
"urlPreview",
|
|
119
121
|
"widget"
|
|
120
122
|
];
|
|
123
|
+
/**
|
|
124
|
+
* Move flattened admin keys back down into the `admin` block.
|
|
125
|
+
*
|
|
126
|
+
* The admin panel works with a *flat* view model — the block merged onto the
|
|
127
|
+
* collection — so what comes back from a form has `icon` and `defaultViewMode`
|
|
128
|
+
* at the top level while `admin` still holds whatever the file was loaded with.
|
|
129
|
+
* This is the way back.
|
|
130
|
+
*
|
|
131
|
+
* **The top-level value wins.** It is the one the form just wrote; the block is
|
|
132
|
+
* the copy the collection was loaded with, and preferring it resolves every edit
|
|
133
|
+
* in favour of the value the user changed away from.
|
|
134
|
+
*
|
|
135
|
+
* This lives here, next to the key lists, because it had two implementations —
|
|
136
|
+
* `toAdminCollectionConfig` in `@rebasepro/admin-types` and `nestAdminKeys` in
|
|
137
|
+
* `@rebasepro/server`'s schema editor — that agreed on everything except that
|
|
138
|
+
* precedence, which is the only part that decides whether a save is visible.
|
|
139
|
+
*
|
|
140
|
+
* @group Models
|
|
141
|
+
*/
|
|
142
|
+
function nestAdminKeysOf(source, adminKeys) {
|
|
143
|
+
const keys = new Set(adminKeys);
|
|
144
|
+
const top = {};
|
|
145
|
+
const block = { ...source.admin ?? {} };
|
|
146
|
+
for (const [key, value] of Object.entries(source)) {
|
|
147
|
+
if (key === "admin") continue;
|
|
148
|
+
if (keys.has(key)) block[key] = value;
|
|
149
|
+
else top[key] = value;
|
|
150
|
+
}
|
|
151
|
+
if (Object.keys(block).length > 0) top.admin = block;
|
|
152
|
+
return top;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* {@link nestAdminKeysOf} for a collection.
|
|
156
|
+
*
|
|
157
|
+
* @group Models
|
|
158
|
+
*/
|
|
159
|
+
function nestAdminCollectionKeys(collection) {
|
|
160
|
+
return nestAdminKeysOf(collection, ADMIN_COLLECTION_KEYS);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* {@link nestAdminKeysOf} for a property, applied to its children too.
|
|
164
|
+
*
|
|
165
|
+
* A map property carries `properties`, an array property carries `of`, and both
|
|
166
|
+
* hold properties with `admin` blocks of their own. A flat `readOnly` left on a
|
|
167
|
+
* child is as dead — and as fatal at the next boot — as one left on the parent,
|
|
168
|
+
* so the walk goes all the way down.
|
|
169
|
+
*
|
|
170
|
+
* @group Models
|
|
171
|
+
*/
|
|
172
|
+
function nestAdminPropertyKeys(property) {
|
|
173
|
+
const nested = nestAdminKeysOf(property, ADMIN_PROPERTY_KEYS);
|
|
174
|
+
const children = nested.properties;
|
|
175
|
+
if (children && typeof children === "object" && !Array.isArray(children)) nested.properties = Object.fromEntries(Object.entries(children).map(([key, child]) => [key, child && typeof child === "object" && !Array.isArray(child) ? nestAdminPropertyKeys(child) : child]));
|
|
176
|
+
const of = nested.of;
|
|
177
|
+
if (Array.isArray(of)) nested.of = of.map((entry) => entry && typeof entry === "object" && !Array.isArray(entry) ? nestAdminPropertyKeys(entry) : entry);
|
|
178
|
+
else if (of && typeof of === "object") nested.of = nestAdminPropertyKeys(of);
|
|
179
|
+
return nested;
|
|
180
|
+
}
|
|
121
181
|
//#endregion
|
|
122
|
-
export { ADMIN_PROPERTY_KEYS as n, ADMIN_COLLECTION_KEYS as t };
|
|
182
|
+
export { nestAdminPropertyKeys as i, ADMIN_PROPERTY_KEYS as n, nestAdminCollectionKeys as r, ADMIN_COLLECTION_KEYS as t };
|
|
123
183
|
|
|
124
|
-
//# sourceMappingURL=admin_block-
|
|
184
|
+
//# sourceMappingURL=admin_block-H86dCPsj.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin_block-H86dCPsj.js","names":[],"sources":["../../types/src/types/admin_block.ts"],"sourcesContent":["/**\n * The keys of a collection's admin block, as data.\n *\n * There is no *type* for the block in this package any more, and that is the point:\n * `admin` is not declared on `BaseCollectionConfig` or on any property here, so a\n * BaaS install cannot even write one. `@rebasepro/admin-types` adds the field back by\n * declaration merging, which is why installing it is what makes the admin surface\n * appear.\n *\n * The *list* still has to live here, because three runtime consumers need it and two\n * of them are core — see below.\n */\n\n/**\n * Every key that belongs inside a collection's `admin` block, as data.\n *\n * The type that describes these fields is `AdminCollectionOptions` in\n * `@rebasepro/admin-types`, and it is erased at build time — but three runtime\n * consumers need the list, and two of them are core:\n *\n * - `serializeCollections`, to drop the block from the contract\n * - the ts-morph schema editor in `@rebasepro/server`, which rewrites collection\n * files on disk from the admin panel and has to know where each key goes. A key\n * missing from this list gets written to the *top level* of the file, where the\n * backend ignores it and the panel never finds it again.\n * - the `collections-admin-block` codemod\n *\n * `@rebasepro/admin-types` re-exports this and asserts it names only real option\n * keys; the count is pinned by a test there.\n *\n * @group Models\n */\nexport const ADMIN_COLLECTION_KEYS = [\n \"Actions\",\n \"additionalFields\",\n \"alwaysApplyDefaultValues\",\n \"components\",\n \"defaultEntityAction\",\n \"defaultFilter\",\n \"defaultSelectedView\",\n \"defaultSize\",\n \"defaultViewMode\",\n \"disableDefaultActions\",\n \"display\",\n \"enabledViews\",\n \"entityActions\",\n \"entityViews\",\n \"exportable\",\n \"filterPresets\",\n \"fixedFilter\",\n \"form\",\n \"formAutoSave\",\n \"formView\",\n \"group\",\n \"hideFromEntityViews\",\n \"hideFromNavigation\",\n \"hideIdFromCollection\",\n \"hideIdFromForm\",\n \"icon\",\n \"includeJsonView\",\n \"inlineEditing\",\n \"kanban\",\n \"listProperties\",\n \"localChangesBackup\",\n \"openEntityMode\",\n \"orderProperty\",\n \"pagination\",\n \"previewProperties\",\n \"propertiesOrder\",\n \"selectionController\",\n \"selectionEnabled\",\n \"sideDialogWidth\",\n \"sort\",\n \"titleProperty\"\n] as const;\n\n/** A key of a collection's `admin` block. @group Models */\nexport type AdminCollectionKey = typeof ADMIN_COLLECTION_KEYS[number];\n\n/**\n * Every key that belongs inside a *property's* `admin` block, as data.\n *\n * The union of `AdminPropertyOptions` and its per-type extensions\n * (`AdminStringOptions`, `AdminArrayOptions`, …) in `@rebasepro/admin-types`.\n * It lives here for the same reason {@link ADMIN_COLLECTION_KEYS} does: the\n * runtime consumers are core packages that the BaaS guard forbids from\n * importing `@rebasepro/admin-types`. Here it is the boot-time collection\n * validator in `@rebasepro/server`, which has to tell \"you left `readOnly` at\n * the top of the property, where nothing reads it\" apart from \"you invented a\n * key we have never heard of\".\n *\n * `@rebasepro/admin-types` re-exports this and asserts it names only real\n * option keys.\n *\n * @group Models\n */\nexport const ADMIN_PROPERTY_KEYS = [\n \"canAddElements\",\n \"clearable\",\n \"columnWidth\",\n \"customProps\",\n \"disabled\",\n \"expanded\",\n \"Field\",\n \"Filter\",\n \"filterOperators\",\n \"fixedFilter\",\n \"hideFromCollection\",\n \"includeEntityLink\",\n \"includeId\",\n \"markdown\",\n \"minimalistView\",\n \"multiline\",\n \"Preview\",\n \"previewAsTag\",\n \"previewProperties\",\n \"readOnly\",\n \"sortable\",\n \"span\",\n \"spreadChildren\",\n \"urlPreview\",\n \"widget\",\n] as const;\n\n/** A key of a property's `admin` block. @group Models */\nexport type AdminPropertyKey = typeof ADMIN_PROPERTY_KEYS[number];\n\n/**\n * Move flattened admin keys back down into the `admin` block.\n *\n * The admin panel works with a *flat* view model — the block merged onto the\n * collection — so what comes back from a form has `icon` and `defaultViewMode`\n * at the top level while `admin` still holds whatever the file was loaded with.\n * This is the way back.\n *\n * **The top-level value wins.** It is the one the form just wrote; the block is\n * the copy the collection was loaded with, and preferring it resolves every edit\n * in favour of the value the user changed away from.\n *\n * This lives here, next to the key lists, because it had two implementations —\n * `toAdminCollectionConfig` in `@rebasepro/admin-types` and `nestAdminKeys` in\n * `@rebasepro/server`'s schema editor — that agreed on everything except that\n * precedence, which is the only part that decides whether a save is visible.\n *\n * @group Models\n */\nexport function nestAdminKeysOf(\n source: Record<string, unknown>,\n adminKeys: readonly string[]\n): Record<string, unknown> {\n const keys = new Set<string>(adminKeys);\n const top: Record<string, unknown> = {};\n const block: Record<string, unknown> = { ...((source.admin as Record<string, unknown> | undefined) ?? {}) };\n\n for (const [key, value] of Object.entries(source)) {\n if (key === \"admin\") continue;\n if (keys.has(key)) block[key] = value;\n else top[key] = value;\n }\n\n if (Object.keys(block).length > 0) top.admin = block;\n return top;\n}\n\n/**\n * {@link nestAdminKeysOf} for a collection.\n *\n * @group Models\n */\nexport function nestAdminCollectionKeys(collection: Record<string, unknown>): Record<string, unknown> {\n return nestAdminKeysOf(collection, ADMIN_COLLECTION_KEYS);\n}\n\n/**\n * {@link nestAdminKeysOf} for a property, applied to its children too.\n *\n * A map property carries `properties`, an array property carries `of`, and both\n * hold properties with `admin` blocks of their own. A flat `readOnly` left on a\n * child is as dead — and as fatal at the next boot — as one left on the parent,\n * so the walk goes all the way down.\n *\n * @group Models\n */\nexport function nestAdminPropertyKeys(property: Record<string, unknown>): Record<string, unknown> {\n const nested = nestAdminKeysOf(property, ADMIN_PROPERTY_KEYS);\n\n const children = nested.properties;\n if (children && typeof children === \"object\" && !Array.isArray(children)) {\n nested.properties = Object.fromEntries(\n Object.entries(children as Record<string, unknown>).map(([key, child]) => [\n key,\n child && typeof child === \"object\" && !Array.isArray(child)\n ? nestAdminPropertyKeys(child as Record<string, unknown>)\n : child\n ])\n );\n }\n\n const of = nested.of;\n if (Array.isArray(of)) {\n nested.of = of.map(entry => entry && typeof entry === \"object\" && !Array.isArray(entry)\n ? nestAdminPropertyKeys(entry as Record<string, unknown>)\n : entry);\n } else if (of && typeof of === \"object\") {\n nested.of = nestAdminPropertyKeys(of as Record<string, unknown>);\n }\n\n return nested;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAa,wBAAwB;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACJ;;;;;;;;;;;;;;;;;;AAsBA,IAAa,sBAAsB;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACJ;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,gBACZ,QACA,WACuB;CACvB,MAAM,OAAO,IAAI,IAAY,SAAS;CACtC,MAAM,MAA+B,CAAC;CACtC,MAAM,QAAiC,EAAE,GAAK,OAAO,SAAiD,CAAC,EAAG;CAE1G,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAAG;EAC/C,IAAI,QAAQ,SAAS;EACrB,IAAI,KAAK,IAAI,GAAG,GAAG,MAAM,OAAO;OAC3B,IAAI,OAAO;CACpB;CAEA,IAAI,OAAO,KAAK,KAAK,CAAC,CAAC,SAAS,GAAG,IAAI,QAAQ;CAC/C,OAAO;AACX;;;;;;AAOA,SAAgB,wBAAwB,YAA8D;CAClG,OAAO,gBAAgB,YAAY,qBAAqB;AAC5D;;;;;;;;;;;AAYA,SAAgB,sBAAsB,UAA4D;CAC9F,MAAM,SAAS,gBAAgB,UAAU,mBAAmB;CAE5D,MAAM,WAAW,OAAO;CACxB,IAAI,YAAY,OAAO,aAAa,YAAY,CAAC,MAAM,QAAQ,QAAQ,GACnE,OAAO,aAAa,OAAO,YACvB,OAAO,QAAQ,QAAmC,CAAC,CAAC,KAAK,CAAC,KAAK,WAAW,CACtE,KACA,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IACpD,sBAAsB,KAAgC,IACtD,KACV,CAAC,CACL;CAGJ,MAAM,KAAK,OAAO;CAClB,IAAI,MAAM,QAAQ,EAAE,GAChB,OAAO,KAAK,GAAG,KAAI,UAAS,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAChF,sBAAsB,KAAgC,IACtD,KAAK;MACR,IAAI,MAAM,OAAO,OAAO,UAC3B,OAAO,KAAK,sBAAsB,EAA6B;CAGnE,OAAO;AACX"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Move presentation keys into the `admin` block.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* The rule itself lives in `@rebasepro/types`, next to `ADMIN_COLLECTION_KEYS`,
|
|
5
|
+
* because `@rebasepro/admin-types` has to apply the identical one on the panel's
|
|
6
|
+
* side and this package cannot import that one. Two copies used to exist and
|
|
7
|
+
* they disagreed about precedence, which decided whether a presentation edit was
|
|
8
|
+
* saved or silently reverted to the value the user had just changed away from.
|
|
9
9
|
*/
|
|
10
10
|
export declare function nestAdminKeys(collectionData: Record<string, unknown>): Record<string, unknown>;
|
|
11
11
|
export declare class AstSchemaEditor {
|
|
@@ -22,10 +22,78 @@ export declare class AstSchemaEditor {
|
|
|
22
22
|
*/
|
|
23
23
|
private safePath;
|
|
24
24
|
private getCollectionFile;
|
|
25
|
+
/**
|
|
26
|
+
* Find the object literal a collection is declared with, through whatever
|
|
27
|
+
* wraps it.
|
|
28
|
+
*
|
|
29
|
+
* `defineCollection({ … })` is the shape `rebase init` writes and the one the
|
|
30
|
+
* docs recommend; `satisfies` / `as` / parentheses are the other ways an
|
|
31
|
+
* author can dress the same literal. Returning `null` for any of them meant
|
|
32
|
+
* the three callers below each failed differently, and the worst of them
|
|
33
|
+
* overwrote the file.
|
|
34
|
+
*/
|
|
35
|
+
private unwrapCollectionObject;
|
|
25
36
|
private getCollectionObject;
|
|
37
|
+
/**
|
|
38
|
+
* The collection's object literal, or a refusal that says what to do.
|
|
39
|
+
*
|
|
40
|
+
* Every caller needs this to be all-or-nothing: a missing object literal used
|
|
41
|
+
* to mean "throw", "report success and do nothing" and "recreate the file
|
|
42
|
+
* from scratch" depending on which method you called.
|
|
43
|
+
*/
|
|
44
|
+
private requireCollectionObject;
|
|
45
|
+
private unreadableFileMessage;
|
|
46
|
+
/** Look a key up on an object literal, quoted or not. */
|
|
47
|
+
private findProperty;
|
|
48
|
+
private static quoteKey;
|
|
49
|
+
private static isPlainObject;
|
|
26
50
|
private convertJsonToAstString;
|
|
51
|
+
/**
|
|
52
|
+
* Write only the keys the patch names, leaving every sibling alone.
|
|
53
|
+
*
|
|
54
|
+
* A patch says what changed, not what the collection is. The panel sends one
|
|
55
|
+
* — `{ propertiesOrder }` is what adding a column posts — and rewriting the
|
|
56
|
+
* `admin` block from it deleted the collection's icon, group, list columns
|
|
57
|
+
* and kanban config in the same write.
|
|
58
|
+
*/
|
|
59
|
+
private mergeIntoObjectLiteral;
|
|
27
60
|
saveProperty(collectionId: string, propertyKey: string, propertyConfig: Record<string, unknown>): Promise<void>;
|
|
28
61
|
deleteProperty(collectionId: string, propertyKey: string): Promise<void>;
|
|
29
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Write a collection back to its file.
|
|
64
|
+
*
|
|
65
|
+
* `partial` is the difference between "this is the collection" and "this is
|
|
66
|
+
* what changed about it". The panel sends both — a full save from the editor
|
|
67
|
+
* dialog, and a one-key patch whenever a property is added, deleted or
|
|
68
|
+
* reordered — and they cannot be told apart by looking at the payload. Read
|
|
69
|
+
* as a full save, a patch deletes everything it does not mention, including
|
|
70
|
+
* `securityRules`; the loader then hands the collection the directory
|
|
71
|
+
* default, which in the scaffold is `access: "public"`.
|
|
72
|
+
*/
|
|
73
|
+
saveCollection(collectionId: string, collectionData: Record<string, unknown>, options?: {
|
|
74
|
+
partial?: boolean;
|
|
75
|
+
}): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Write the collection-level `relations` array.
|
|
78
|
+
*
|
|
79
|
+
* Relations are the one key whose values are not all data: `target` is a
|
|
80
|
+
* thunk in the file, and the panel sends the target collection's slug (or,
|
|
81
|
+
* for a relation it did not touch, nothing at all — `JSON.stringify` drops
|
|
82
|
+
* the function). So each entry's target is resolved in that order: a slug
|
|
83
|
+
* becomes `() => xCollection` plus the import it needs, and anything else
|
|
84
|
+
* falls back to the thunk already in the file.
|
|
85
|
+
*
|
|
86
|
+
* This used to be a `continue` with a comment saying relations were handled
|
|
87
|
+
* elsewhere. Nothing handled them; every edit in the Relations tab was
|
|
88
|
+
* dropped without a word.
|
|
89
|
+
*/
|
|
90
|
+
private writeRelations;
|
|
91
|
+
/**
|
|
92
|
+
* `() => targetCollection` for a target named by its slug, importing it if
|
|
93
|
+
* the file does not already.
|
|
94
|
+
*/
|
|
95
|
+
private targetThunk;
|
|
96
|
+
private hasDefaultImport;
|
|
97
|
+
private getDefaultExportName;
|
|
30
98
|
deleteCollection(collectionId: string): Promise<void>;
|
|
31
99
|
}
|
package/dist/api/errors.d.ts
CHANGED
|
@@ -55,12 +55,6 @@ export interface RebaseApiError extends Error {
|
|
|
55
55
|
code?: string;
|
|
56
56
|
details?: unknown;
|
|
57
57
|
}
|
|
58
|
-
/**
|
|
59
|
-
* Type guard for errors that carry optional API metadata (statusCode, code, details).
|
|
60
|
-
* Returns true for any Error instance — the optional properties are then
|
|
61
|
-
* checked via normal property access.
|
|
62
|
-
*/
|
|
63
|
-
export declare function isRebaseApiError(error: unknown): error is RebaseApiError;
|
|
64
58
|
/**
|
|
65
59
|
* Hono error-handling middleware (`app.onError`).
|
|
66
60
|
* Converts any error into the canonical `{ error: { message, code } }` shape.
|
|
@@ -12,5 +12,19 @@ export interface OpenApiGeneratorOptions {
|
|
|
12
12
|
basePath?: string;
|
|
13
13
|
/** Whether auth is enabled on data routes. Defaults to true. */
|
|
14
14
|
requireAuth?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* The list-pagination bounds the REST layer applies, so the spec states the
|
|
17
|
+
* ones a request will actually meet.
|
|
18
|
+
*
|
|
19
|
+
* These were hardcoded as `default: 20, maximum: 100` — neither of which
|
|
20
|
+
* the server has ever used. The spec drives the API Explorer and is what a
|
|
21
|
+
* generated client is built from, so an understated ceiling is a request
|
|
22
|
+
* the client refuses to make, and an overstated one is a 400 nobody
|
|
23
|
+
* predicted.
|
|
24
|
+
*/
|
|
25
|
+
listLimits?: {
|
|
26
|
+
defaultLimit?: number;
|
|
27
|
+
maxLimit?: number;
|
|
28
|
+
};
|
|
15
29
|
}
|
|
16
30
|
export declare function generateOpenApiSpec(collections: CollectionConfig[], options?: OpenApiGeneratorOptions): Record<string, unknown>;
|
|
@@ -54,7 +54,7 @@ export declare class RestApiGenerator {
|
|
|
54
54
|
* Needed so a nested write can be checked against a schema at all. Without
|
|
55
55
|
* it these routes skipped `assertKnownWriteFields` entirely, which is why a
|
|
56
56
|
* typo `POST /posts` rejected with a 400 while the same typo on
|
|
57
|
-
* `POST /authors/1/posts`
|
|
57
|
+
* `POST /authors/1/posts` was dropped from the statement and answered 201.
|
|
58
58
|
*
|
|
59
59
|
* Returns `undefined` rather than throwing when the path cannot be walked:
|
|
60
60
|
* the driver raises the authoritative error a moment later, and duplicating
|
|
@@ -1,9 +1,67 @@
|
|
|
1
1
|
import { DataDriver } from "@rebasepro/types";
|
|
2
|
+
/**
|
|
3
|
+
* What a key was claimed *for*, so presenting it on a different request is
|
|
4
|
+
* caught instead of silently replaying the first one's answer.
|
|
5
|
+
*
|
|
6
|
+
* Nothing about the request used to enter the key, so `createMany(rows, { key })`
|
|
7
|
+
* followed by `deleteMany(ids, { key })` — the reusable business id the docs
|
|
8
|
+
* recommended — answered the delete with the create's `200` body and deleted
|
|
9
|
+
* nothing. Method and path separate the routes; the body separates a re-run
|
|
10
|
+
* carrying corrected rows from the retry of an unanswered one, which is the
|
|
11
|
+
* difference between "here is your earlier answer" and silently discarding a
|
|
12
|
+
* correction.
|
|
13
|
+
*/
|
|
14
|
+
export declare function requestFingerprint(method: string, path: string, body: unknown): string;
|
|
15
|
+
/**
|
|
16
|
+
* What a caller may do with a key.
|
|
17
|
+
*
|
|
18
|
+
* `claimed` is the only outcome that permits the write. Recalling and then
|
|
19
|
+
* writing was not atomic: two requests carrying one key both missed the recall,
|
|
20
|
+
* both wrote, and `ON CONFLICT DO NOTHING` protected only the second row in
|
|
21
|
+
* *this* table — the duplicate row in the caller's collection, which is the
|
|
22
|
+
* thing the mechanism exists to prevent, was inserted anyway. The offline queue
|
|
23
|
+
* is shared across tabs, so two tabs reconnecting together is the ordinary case
|
|
24
|
+
* rather than an exotic one.
|
|
25
|
+
*/
|
|
26
|
+
export type IdempotencyClaim =
|
|
27
|
+
/** This key has already been answered; serve that answer again. */
|
|
28
|
+
{
|
|
29
|
+
status: "replay";
|
|
30
|
+
response: unknown;
|
|
31
|
+
}
|
|
32
|
+
/** Another request holds this key and has not answered yet. */
|
|
33
|
+
| {
|
|
34
|
+
status: "in-flight";
|
|
35
|
+
}
|
|
36
|
+
/** This key is live, but it was claimed for a different request. */
|
|
37
|
+
| {
|
|
38
|
+
status: "mismatch";
|
|
39
|
+
}
|
|
40
|
+
/** The key is ours; do the write, then `complete` or `release` it. */
|
|
41
|
+
| {
|
|
42
|
+
status: "claimed";
|
|
43
|
+
};
|
|
2
44
|
export interface IdempotencyStore {
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Take the key if it is free, atomically. Never throws — a store that
|
|
47
|
+
* cannot answer reports `claimed`, which degrades to no idempotency rather
|
|
48
|
+
* than to a refused write.
|
|
49
|
+
*
|
|
50
|
+
* `fingerprint` says what the key is being claimed for (see
|
|
51
|
+
* {@link requestFingerprint}); a live key presented with a different one is
|
|
52
|
+
* a reused key, not a replay, and is reported as `mismatch`.
|
|
53
|
+
*/
|
|
54
|
+
claim(key: string, uid: string | undefined, fingerprint: string): Promise<IdempotencyClaim>;
|
|
55
|
+
/** Record what this key answered. Never throws. */
|
|
56
|
+
complete(key: string, uid: string | undefined, response: unknown): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Give the key back after the write it was claimed for failed.
|
|
59
|
+
*
|
|
60
|
+
* Without this a transient failure strands the key until its lease runs
|
|
61
|
+
* out, turning one failed write into a minute of refused retries. The lease
|
|
62
|
+
* is the floor, not the mechanism: it only covers the exits no code runs on.
|
|
63
|
+
*/
|
|
64
|
+
release(key: string, uid: string | undefined): Promise<void>;
|
|
7
65
|
}
|
|
8
66
|
/**
|
|
9
67
|
* Returns `undefined` when the driver cannot run SQL, which disables the whole
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ListLimitBounds } from "@rebasepro/types";
|
|
1
2
|
import { QueryOptions } from "../types";
|
|
2
3
|
export declare const mapOperator: (op: string) => import("@rebasepro/types").WhereFilterOp | null;
|
|
3
4
|
export { DEFAULT_LIST_LIMIT, DEFAULT_VECTOR_LIST_LIMIT, MAX_LIST_LIMIT } from "@rebasepro/types";
|
|
@@ -13,9 +14,22 @@ export interface ListLimitOptions {
|
|
|
13
14
|
* text-search reads — a vector search falls back to its own default (10).
|
|
14
15
|
*/
|
|
15
16
|
defaultLimit?: number;
|
|
16
|
-
/**
|
|
17
|
+
/** Largest `?limit` a client may ask for. A larger one is a 400, not a clamp. */
|
|
17
18
|
maxLimit?: number;
|
|
18
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* {@link resolveClientListLimit} for an HTTP route: the same bounds, answered
|
|
22
|
+
* with a 400 rather than a 500.
|
|
23
|
+
*
|
|
24
|
+
* The shared resolver throws a `ListLimitError`, which carries `status` — but
|
|
25
|
+
* the Hono error handler discriminates on `statusCode`, so an unconverted one
|
|
26
|
+
* reaches the client as `INTERNAL_ERROR` with its message stripped, telling the
|
|
27
|
+
* caller nothing about the parameter it got wrong. Every REST list ingress
|
|
28
|
+
* routes its `limit` through here so all of them name the ceiling the same way.
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveListLimitParam(rawLimit: number | string | null | undefined, opts?: ListLimitBounds & {
|
|
31
|
+
vectorSearch?: boolean;
|
|
32
|
+
}): number;
|
|
19
33
|
/**
|
|
20
34
|
* Parse query parameters into QueryOptions
|
|
21
35
|
*/
|
|
@@ -2,10 +2,18 @@ import { CollectionConfig } from "@rebasepro/types";
|
|
|
2
2
|
/**
|
|
3
3
|
* Reject a write naming a field the collection does not have.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* An unknown key does *not* reach the INSERT and come back as `column "titel"
|
|
6
|
+
* does not exist`, which is what this comment used to claim. Drizzle builds
|
|
7
|
+
* INSERT and UPDATE from the table's own column list, so a key the table does
|
|
8
|
+
* not carry is left out of the statement: the write answers 201 having stored
|
|
9
|
+
* nothing under that name. A typo is a request problem, it belongs in a 400,
|
|
10
|
+
* and nothing below this was ever going to raise one.
|
|
11
|
+
*
|
|
12
|
+
* This is the config-level check and it is skipped on several paths (see the
|
|
13
|
+
* `strictWrites` bail below, and the auth-adapter contract at the call site).
|
|
14
|
+
* `assertWritableColumns` in the Postgres driver is the backstop every write
|
|
15
|
+
* passes through, including in-process `rebase.data` writes that never come
|
|
16
|
+
* near this layer.
|
|
9
17
|
*
|
|
10
18
|
* What counts as known:
|
|
11
19
|
* - a declared property (for an introspected BaaS collection these *are* the
|
|
@@ -20,6 +28,34 @@ export declare function assertKnownWriteFields(values: Record<string, unknown>,
|
|
|
20
28
|
rowIndex?: number;
|
|
21
29
|
extraKnownFields?: readonly string[];
|
|
22
30
|
}): void;
|
|
31
|
+
/**
|
|
32
|
+
* Reject a write whose values break the constraints the collection declares.
|
|
33
|
+
*
|
|
34
|
+
* `validation.min`, `max`, `matches`, `positive`, `integer` and the date and
|
|
35
|
+
* array bounds were read by exactly three things: the DDL generators (for
|
|
36
|
+
* `integer` and for a `varchar` width), and the admin's client-side form. No
|
|
37
|
+
* layer on the write path looked at them, no `CHECK` constraint was emitted,
|
|
38
|
+
* and the generated OpenAPI published every one of them as `minimum`,
|
|
39
|
+
* `maximum`, `minLength`, `maxLength` and `pattern`. So the docs' own example —
|
|
40
|
+
* `price: { type: "number", validation: { min: 0 } }` — accepted `-5000` with a
|
|
41
|
+
* 201 while the spec said it would not, and any client or gateway generated
|
|
42
|
+
* from that spec believed the server was checking.
|
|
43
|
+
*
|
|
44
|
+
* Only `required` is left to the database, where it is a NOT NULL: a partial
|
|
45
|
+
* update legitimately omits keys, and this function sees one request's values,
|
|
46
|
+
* not the row they land on.
|
|
47
|
+
*
|
|
48
|
+
* A value of the wrong *type* is not this function's business — that reaches
|
|
49
|
+
* Postgres, which types every column and gives a 400 through the driver's
|
|
50
|
+
* SQLSTATE mapping. Constraints are checked against values of the right type,
|
|
51
|
+
* plus the numeric-string form a JSON body may carry for a number column.
|
|
52
|
+
*
|
|
53
|
+
* Every failing field is reported at once. A form that fixes one field per
|
|
54
|
+
* round trip is the reason validation errors get ignored.
|
|
55
|
+
*/
|
|
56
|
+
export declare function assertWriteValuesValid(values: Record<string, unknown>, collection: CollectionConfig, options?: {
|
|
57
|
+
rowIndex?: number;
|
|
58
|
+
}): void;
|
|
23
59
|
/**
|
|
24
60
|
* Narrow response rows to the fields the caller asked for.
|
|
25
61
|
*
|
|
@@ -33,11 +69,18 @@ export declare function assertKnownWriteFields(values: Record<string, unknown>,
|
|
|
33
69
|
* This shapes the *response*, which is what the parameter says it does; it is
|
|
34
70
|
* not a column pushdown, so it saves bandwidth rather than database work.
|
|
35
71
|
*
|
|
36
|
-
*
|
|
37
|
-
* the admin table, realtime reconciliation, the offline
|
|
38
|
-
* arrives without one is not a smaller row, it is an
|
|
39
|
-
* `fields=title` and being unable to open the record
|
|
40
|
-
* answer than one extra key.
|
|
72
|
+
* The collection's key always survives. Rows are addressed by it everywhere
|
|
73
|
+
* above this layer — the admin table, realtime reconciliation, the offline
|
|
74
|
+
* cache — and a row that arrives without one is not a smaller row, it is an
|
|
75
|
+
* unusable one. Asking for `fields=title` and being unable to open the record
|
|
76
|
+
* you clicked is a worse answer than one extra key.
|
|
77
|
+
*
|
|
78
|
+
* That is a statement about the key, not about the name `id`: a collection
|
|
79
|
+
* keyed on `slug`, or on `user_id + role_id`, was projected down to the fields
|
|
80
|
+
* asked for and nothing else, which is the very outcome the paragraph above
|
|
81
|
+
* describes. `assertKnownWriteFields` one function up already has a dedicated
|
|
82
|
+
* error for collections with no `id` column, so this layer had no excuse for
|
|
83
|
+
* assuming one.
|
|
41
84
|
*/
|
|
42
85
|
export declare function projectResponseFields<T extends Record<string, unknown>>(rows: T[], fields: readonly string[] | undefined, collection: CollectionConfig, options?: {
|
|
43
86
|
include?: readonly string[];
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* 1. Checks for API key tokens (`rk_` prefix) first — these are Rebase-level
|
|
10
10
|
* 2. Falls back to `adapter.verifyRequest(request)` to resolve the user
|
|
11
11
|
* 3. Scopes the DataDriver via `withAuth()` for RLS
|
|
12
|
-
* 4.
|
|
12
|
+
* 4. Rejects a presented-but-unverifiable token with 401, whatever
|
|
13
|
+
* `requireAuth` says
|
|
14
|
+
* 5. Enforces auth (401) when `requireAuth` is true and no user is found
|
|
13
15
|
*
|
|
14
16
|
* The behavior is identical to `createAuthMiddleware()` — only the
|
|
15
17
|
* token verification strategy is pluggable.
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import type { OAuthProvider } from "./interfaces";
|
|
2
|
+
import { type OAuthCodeFlowPayload } from "./oauth-code-flow";
|
|
3
|
+
/** Extra field Apple's client sends that no other provider has. */
|
|
4
|
+
export interface AppleCodeFlowPayload extends OAuthCodeFlowPayload {
|
|
5
|
+
/**
|
|
6
|
+
* Apple sends the user's *name* only on the first authorization, so the
|
|
7
|
+
* frontend has to forward it. It is display data and nothing else — the
|
|
8
|
+
* identity email comes from the id_token, never from the request body.
|
|
9
|
+
*/
|
|
10
|
+
user?: {
|
|
11
|
+
name?: {
|
|
12
|
+
firstName?: string;
|
|
13
|
+
lastName?: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
}
|
|
2
17
|
/**
|
|
3
18
|
* Creates an Apple Sign In OAuth Provider integration.
|
|
4
19
|
*
|
|
@@ -17,14 +32,4 @@ export declare function createAppleProvider(config: {
|
|
|
17
32
|
keyId: string;
|
|
18
33
|
/** The raw PEM contents of the .p8 private key file */
|
|
19
34
|
privateKey: string;
|
|
20
|
-
}): OAuthProvider<
|
|
21
|
-
code: string;
|
|
22
|
-
redirectUri: string;
|
|
23
|
-
user?: {
|
|
24
|
-
name?: {
|
|
25
|
-
firstName?: string;
|
|
26
|
-
lastName?: string;
|
|
27
|
-
};
|
|
28
|
-
email?: string;
|
|
29
|
-
};
|
|
30
|
-
}>;
|
|
35
|
+
}): OAuthProvider<AppleCodeFlowPayload>;
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import type { OAuthProvider } from "./interfaces";
|
|
2
|
+
import { type OAuthCodeFlowPayload } from "./oauth-code-flow";
|
|
2
3
|
/**
|
|
3
4
|
* Creates a Bitbucket OAuth Provider integration (OAuth 2.0 consumer).
|
|
4
5
|
*/
|
|
5
6
|
export declare function createBitbucketProvider(config: {
|
|
6
7
|
clientId: string;
|
|
7
8
|
clientSecret: string;
|
|
8
|
-
}): OAuthProvider<
|
|
9
|
-
code: string;
|
|
10
|
-
redirectUri: string;
|
|
11
|
-
}>;
|
|
9
|
+
}): OAuthProvider<OAuthCodeFlowPayload>;
|
|
@@ -45,6 +45,8 @@ export interface BuiltinAuthAdapterConfig {
|
|
|
45
45
|
defaultRole?: string;
|
|
46
46
|
/** OAuth providers to register. */
|
|
47
47
|
oauthProviders?: OAuthProvider<unknown>[];
|
|
48
|
+
/** Redirect URIs the OAuth routes accept, for every provider. */
|
|
49
|
+
allowedRedirectUris?: string[];
|
|
48
50
|
/** Static service key for server-to-server auth. */
|
|
49
51
|
serviceKey?: string;
|
|
50
52
|
/** Auth hooks for customizing password, credentials, lifecycle, etc. */
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type { OAuthProvider } from "./interfaces";
|
|
2
|
+
import { type OAuthCodeFlowPayload } from "./oauth-code-flow";
|
|
2
3
|
/**
|
|
3
4
|
* Creates a Discord OAuth2 Provider integration.
|
|
4
5
|
*
|
|
5
|
-
* Uses the authorization code flow
|
|
6
|
-
*
|
|
6
|
+
* Uses the authorization code flow (with PKCE when the client supplies a
|
|
7
|
+
* verifier). Requires the "identify" and "email" scopes to retrieve the
|
|
8
|
+
* user's email and profile information.
|
|
7
9
|
*/
|
|
8
10
|
export declare function createDiscordProvider(config: {
|
|
9
11
|
clientId: string;
|
|
10
12
|
clientSecret: string;
|
|
11
|
-
}): OAuthProvider<
|
|
12
|
-
code: string;
|
|
13
|
-
redirectUri: string;
|
|
14
|
-
}>;
|
|
13
|
+
}): OAuthProvider<OAuthCodeFlowPayload>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { OAuthProvider } from "./interfaces";
|
|
2
|
+
import { type OAuthCodeFlowPayload } from "./oauth-code-flow";
|
|
2
3
|
/**
|
|
3
4
|
* Creates a Facebook / Meta OAuth Provider integration.
|
|
4
5
|
*
|
|
@@ -8,7 +9,4 @@ import type { OAuthProvider } from "./interfaces";
|
|
|
8
9
|
export declare function createFacebookProvider(config: {
|
|
9
10
|
clientId: string;
|
|
10
11
|
clientSecret: string;
|
|
11
|
-
}): OAuthProvider<
|
|
12
|
-
code: string;
|
|
13
|
-
redirectUri: string;
|
|
14
|
-
}>;
|
|
12
|
+
}): OAuthProvider<OAuthCodeFlowPayload>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { OAuthProvider } from "./interfaces";
|
|
2
|
+
import { type OAuthCodeFlowPayload } from "./oauth-code-flow";
|
|
2
3
|
/**
|
|
3
4
|
* Creates a GitHub OAuth Provider integration.
|
|
4
5
|
*
|
|
@@ -9,7 +10,4 @@ import type { OAuthProvider } from "./interfaces";
|
|
|
9
10
|
export declare function createGitHubProvider(config: {
|
|
10
11
|
clientId: string;
|
|
11
12
|
clientSecret: string;
|
|
12
|
-
}): OAuthProvider<
|
|
13
|
-
code: string;
|
|
14
|
-
redirectUri: string;
|
|
15
|
-
}>;
|
|
13
|
+
}): OAuthProvider<OAuthCodeFlowPayload>;
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import type { OAuthProvider } from "./interfaces";
|
|
2
|
+
import { type OAuthCodeFlowPayload } from "./oauth-code-flow";
|
|
2
3
|
/**
|
|
3
4
|
* Creates a GitLab OAuth Provider integration.
|
|
4
5
|
* Works with both GitLab.com and self-hosted instances.
|
|
6
|
+
*
|
|
7
|
+
* `baseUrl` is configuration only and must stay that way: a caller-supplied
|
|
8
|
+
* instance URL would make this provider an SSRF primitive and an
|
|
9
|
+
* arbitrary-identity oracle in one step.
|
|
5
10
|
*/
|
|
6
11
|
export declare function createGitLabProvider(config: {
|
|
7
12
|
clientId: string;
|
|
8
13
|
clientSecret: string;
|
|
9
14
|
baseUrl?: string;
|
|
10
|
-
}): OAuthProvider<
|
|
11
|
-
code: string;
|
|
12
|
-
redirectUri: string;
|
|
13
|
-
}>;
|
|
15
|
+
}): OAuthProvider<OAuthCodeFlowPayload>;
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from "./interfaces";
|
|
2
|
-
export { configureJwt, generateAccessToken, verifyAccessToken, generateRefreshToken, hashRefreshToken, getRefreshTokenExpiry, getAccessTokenExpiry, generateDownloadToken, verifyDownloadToken } from "./jwt";
|
|
2
|
+
export { configureJwt, isJwtConfigured, generateAccessToken, verifyAccessToken, generateRefreshToken, hashRefreshToken, getRefreshTokenExpiry, getAccessTokenExpiry, generateDownloadToken, verifyDownloadToken } from "./jwt";
|
|
3
3
|
export type { JwtConfig, AccessTokenPayload, DownloadTokenPayload } from "./jwt";
|
|
4
4
|
export { hashPassword, verifyPassword, validatePasswordStrength } from "./password";
|
|
5
5
|
export { safeCompare } from "./crypto-utils";
|
|
@@ -21,6 +21,13 @@ export { createGitLabProvider } from "./gitlab-oauth";
|
|
|
21
21
|
export { createBitbucketProvider } from "./bitbucket-oauth";
|
|
22
22
|
export { createSlackProvider } from "./slack-oauth";
|
|
23
23
|
export { createSpotifyProvider } from "./spotify-oauth";
|
|
24
|
+
export type { AppleCodeFlowPayload } from "./apple-oauth";
|
|
25
|
+
export { oauthCodeFlowSchema, pkceTokenParams, providerVerifiedEmail } from "./oauth-code-flow";
|
|
26
|
+
export type { OAuthCodeFlowPayload } from "./oauth-code-flow";
|
|
27
|
+
export { verifyOidcIdToken, tryVerifyOidcIdToken } from "./oidc-id-token";
|
|
28
|
+
export type { OidcIdTokenClaims, VerifyOidcIdTokenOptions } from "./oidc-id-token";
|
|
29
|
+
export { decideOAuthAutoLink, isRedirectUriAllowed } from "./oauth-signin-policy";
|
|
30
|
+
export type { AutoLinkDecision, AutoLinkRefusal } from "./oauth-signin-policy";
|
|
24
31
|
export { requireAuth, requireAdmin, optionalAuth, extractUserFromToken, createAuthMiddleware, queryTokenAuth, fileTokenAuth } from "./middleware";
|
|
25
32
|
export type { AuthMiddlewareOptions, AuthResult } from "./middleware";
|
|
26
33
|
export { createAuthRoutes } from "./routes";
|