@protobase/server 0.47.1 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/dist/admin-options.d.ts +2 -2
  2. package/dist/app-identity.d.ts +2 -2
  3. package/dist/app-name.d.ts +2 -0
  4. package/dist/auth-store.d.ts +3 -0
  5. package/dist/auth-store.js +3 -0
  6. package/dist/better-auth/auth-schema.d.ts +7 -8
  7. package/dist/better-auth/auth-schema.js +40 -42
  8. package/dist/better-auth/auth-settings.d.ts +8754 -0
  9. package/dist/better-auth/auth-settings.js +43 -0
  10. package/dist/better-auth/auth-tables.d.ts +1 -1
  11. package/dist/better-auth/auth-tables.js +11 -9
  12. package/dist/better-auth/authenticate-settings.d.ts +15 -0
  13. package/dist/better-auth/authenticate-settings.js +12 -0
  14. package/dist/better-auth/authenticator.d.ts +1 -1
  15. package/dist/better-auth/create-auth.d.ts +34 -14
  16. package/dist/better-auth/create-auth.js +27 -10
  17. package/dist/better-auth/mcp/mcp-auth-plugins.d.ts +2719 -0
  18. package/dist/better-auth/mcp/mcp-auth-plugins.js +68 -0
  19. package/dist/better-auth/mcp/mcp-plugins.d.ts +7 -2
  20. package/dist/better-auth/mcp/mcp-plugins.js +3 -68
  21. package/dist/better-auth/mcp/mcp-token-claims.js +1 -1
  22. package/dist/better-auth/organizations/store.d.ts +1 -0
  23. package/dist/better-auth/saml-plugin.d.ts +993 -0
  24. package/dist/better-auth/saml-plugin.js +36 -0
  25. package/dist/better-auth/saml-sign-in.d.ts +27 -1
  26. package/dist/better-auth/saml-sign-in.js +1 -33
  27. package/dist/better-auth/store/adoption.js +87 -0
  28. package/dist/better-auth/store/ddl.js +18 -0
  29. package/dist/better-auth/store/drift.d.ts +9 -0
  30. package/dist/better-auth/store/drift.js +18 -0
  31. package/dist/better-auth/store/migration-sql.js +15 -0
  32. package/dist/better-auth/store/migrations/001-core.js +80 -0
  33. package/dist/better-auth/store/migrations/002-two-factor.js +25 -0
  34. package/dist/better-auth/store/migrations/003-passkeys.js +29 -0
  35. package/dist/better-auth/store/migrations/004-sign-in-policy.js +22 -0
  36. package/dist/better-auth/store/migrations/005-staff-sign-in.js +25 -0
  37. package/dist/better-auth/store/migrations/006-organizations.js +50 -0
  38. package/dist/better-auth/store/migrations/007-mcp.js +150 -0
  39. package/dist/better-auth/store/migrations/index.js +22 -0
  40. package/dist/better-auth/store/migrations/migration.d.ts +3 -0
  41. package/dist/better-auth/store/migrations/migration.js +14 -0
  42. package/dist/better-auth/store/migrations-table.d.ts +7 -0
  43. package/dist/better-auth/store/migrations-table.js +23 -0
  44. package/dist/better-auth/store/resources-outside.d.ts +7 -0
  45. package/dist/better-auth/store/resources-outside.js +20 -0
  46. package/dist/better-auth/store/store-db.js +13 -0
  47. package/dist/better-auth/store/store-names.d.ts +2 -0
  48. package/dist/better-auth/store/store-names.js +14 -0
  49. package/dist/better-auth/store/table-names.d.ts +7 -0
  50. package/dist/better-auth/store/table-names.js +10 -0
  51. package/dist/better-auth/user-table.js +1 -1
  52. package/dist/better-auth/users.d.ts +2 -2
  53. package/dist/comments/comment-users.d.ts +1 -1
  54. package/dist/config-exports.d.ts +2 -0
  55. package/dist/config-exports.js +2 -0
  56. package/dist/create-admin.d.ts +6 -4
  57. package/dist/create-admin.js +3 -1
  58. package/dist/encryption/keyring.js +1 -1
  59. package/dist/files/options.d.ts +5 -8
  60. package/dist/files/provider-settings.d.ts +16 -0
  61. package/dist/files/provider-settings.js +17 -0
  62. package/dist/files/runtime.js +4 -4
  63. package/dist/forms/runtime.js +3 -3
  64. package/dist/index.d.ts +22 -19
  65. package/dist/index.js +11 -11
  66. package/dist/internal.d.ts +13 -0
  67. package/dist/internal.js +13 -0
  68. package/dist/jobs/declared-job.d.ts +24 -0
  69. package/dist/jobs/declared-job.js +26 -0
  70. package/dist/jobs/job-types.d.ts +2 -2
  71. package/dist/mcp/mcp-authenticator.js +3 -3
  72. package/dist/notifications/device-store-of.d.ts +2 -2
  73. package/dist/notifications/device-store-of.js +1 -1
  74. package/dist/notifications/device-store.d.ts +1 -1
  75. package/dist/notifications/device-store.js +1 -1
  76. package/dist/notifications/history-store-of.d.ts +2 -2
  77. package/dist/notifications/history-store-of.js +1 -1
  78. package/dist/notifications/history-store.d.ts +1 -1
  79. package/dist/notifications/history-store.js +1 -1
  80. package/dist/notifications/options.d.ts +3 -1
  81. package/dist/notifications/options.js +1 -1
  82. package/dist/notifications/schema.d.ts +3 -3
  83. package/dist/notifications/schema.js +8 -8
  84. package/dist/notifications/send-notification.js +1 -1
  85. package/dist/notifications/sender.d.ts +1 -1
  86. package/dist/notifications/sender.js +2 -2
  87. package/dist/notifications/senders-of.d.ts +1 -1
  88. package/dist/notifications/senders-of.js +1 -1
  89. package/dist/package.js +1 -1
  90. package/dist/webhooks/subscription.d.ts +1 -0
  91. package/dist/webhooks/table/options.d.ts +1 -1
  92. package/dist/webhooks/table/schema.d.ts +2 -2
  93. package/dist/webhooks/table/schema.js +2 -2
  94. package/dist/webhooks/table/webhook-table.js +2 -2
  95. package/dist/webhooks/table/webhooks-module.d.ts +108 -0
  96. package/dist/webhooks/table/webhooks-module.js +11 -0
  97. package/package.json +8 -5
  98. package/dist/better-auth/mcp/mcp-tables.js +0 -32
  99. package/dist/better-auth/snake-case-migration.js +0 -122
  100. package/dist/notifications/plugin.d.ts +0 -13
  101. package/dist/notifications/plugin.js +0 -16
  102. package/dist/project-config.d.ts +0 -54
  103. package/dist/project-config.js +0 -182
  104. package/dist/webhooks/table/plugin.d.ts +0 -10
  105. package/dist/webhooks/table/plugin.js +0 -18
@@ -0,0 +1,108 @@
1
+ import { WebhooksOptions } from "./options.js";
2
+ //#region src/webhooks/table/webhooks-module.d.ts
3
+ /**
4
+ * What `webhooks` in `protobase.config.ts` adds to the app's resources: the Webhook subscriptions and Webhook deliveries
5
+ * pages, over a `webhooks` schema that `protobase migration` writes, and the delivery log with `deliveryLog`. Who may
6
+ * create subscriptions is the resources' access (`webhook_subscriptions.create`, ...); each delivers as its owner.
7
+ */
8
+ export declare const webhooksModule: (options?: WebhooksOptions) => {
9
+ webhookDeliveryLog?: import("@protobase/schema").ResourceBuilder<{
10
+ readonly id: import("@protobase/schema").Field<string>;
11
+ readonly subscription_id: import("@protobase/schema").Field<string | number>;
12
+ readonly tenant_id: import("@protobase/schema").Field<string | null>;
13
+ readonly event_id: import("@protobase/schema").Field<string>;
14
+ readonly event_type: import("@protobase/schema").Field<string>;
15
+ readonly status: import("@protobase/schema").Field<"failed" | "delivered">;
16
+ readonly attempt: import("@protobase/schema").Field<number>;
17
+ readonly status_code: import("@protobase/schema").Field<number | null>;
18
+ readonly response: import("@protobase/schema").Field<string | null>;
19
+ readonly duration_ms: import("@protobase/schema").Field<number>;
20
+ readonly at: import("@protobase/schema").Field<string>;
21
+ }, import("@protobase/schema").Ref<"id", string>> | undefined;
22
+ webhookDeliveryLogView?: import("@protobase/schema").ViewBuilder<import("@protobase/schema").ResourceBuilder<{
23
+ readonly id: import("@protobase/schema").Field<string>;
24
+ readonly subscription_id: import("@protobase/schema").Field<string | number>;
25
+ readonly tenant_id: import("@protobase/schema").Field<string | null>;
26
+ readonly event_id: import("@protobase/schema").Field<string>;
27
+ readonly event_type: import("@protobase/schema").Field<string>;
28
+ readonly status: import("@protobase/schema").Field<"failed" | "delivered">;
29
+ readonly attempt: import("@protobase/schema").Field<number>;
30
+ readonly status_code: import("@protobase/schema").Field<number | null>;
31
+ readonly response: import("@protobase/schema").Field<string | null>;
32
+ readonly duration_ms: import("@protobase/schema").Field<number>;
33
+ readonly at: import("@protobase/schema").Field<string>;
34
+ }, import("@protobase/schema").Ref<"id", string>>> | undefined;
35
+ webhookSubscriptions: import("@protobase/schema").ResourceBuilder<{
36
+ readonly id: import("@protobase/schema").Field<string>;
37
+ readonly name: import("@protobase/schema").Field<string>;
38
+ readonly events: import("@protobase/schema").Field<string>;
39
+ readonly url: import("@protobase/schema").Field<string>;
40
+ readonly filter: import("@protobase/schema").Field<string | null>;
41
+ readonly headers: import("@protobase/schema").Field<import("zod").JSONType>;
42
+ readonly payload: import("@protobase/schema").Field<"full" | "thin">;
43
+ readonly enabled: import("@protobase/schema").Field<boolean>;
44
+ readonly secret: import("@protobase/schema").Field<string>;
45
+ readonly previous_secret: null;
46
+ readonly previous_secret_until: null;
47
+ readonly tenant_id: import("@protobase/schema").Field<string | null>;
48
+ readonly owner_id: import("@protobase/schema").Field<string | null>;
49
+ readonly disabled_reason: import("@protobase/schema").Field<string | null>;
50
+ readonly last_success_at: import("@protobase/schema").Field<string | null>;
51
+ readonly failing_since: import("@protobase/schema").Field<string | null>;
52
+ readonly created_at: import("@protobase/schema").Field<string>;
53
+ readonly updated_at: import("@protobase/schema").Field<string>;
54
+ readonly rotate_secret: import("@protobase/schema").Field<boolean>;
55
+ readonly send_test: import("@protobase/schema").Field<boolean>;
56
+ readonly resend_failed: import("@protobase/schema").Field<boolean>;
57
+ }, import("@protobase/schema").Ref<"id", string>>;
58
+ webhookSubscriptionsView: import("@protobase/schema").ViewBuilder<import("@protobase/schema").ResourceBuilder<{
59
+ readonly id: import("@protobase/schema").Field<string>;
60
+ readonly name: import("@protobase/schema").Field<string>;
61
+ readonly events: import("@protobase/schema").Field<string>;
62
+ readonly url: import("@protobase/schema").Field<string>;
63
+ readonly filter: import("@protobase/schema").Field<string | null>;
64
+ readonly headers: import("@protobase/schema").Field<import("zod").JSONType>;
65
+ readonly payload: import("@protobase/schema").Field<"full" | "thin">;
66
+ readonly enabled: import("@protobase/schema").Field<boolean>;
67
+ readonly secret: import("@protobase/schema").Field<string>;
68
+ readonly previous_secret: null;
69
+ readonly previous_secret_until: null;
70
+ readonly tenant_id: import("@protobase/schema").Field<string | null>;
71
+ readonly owner_id: import("@protobase/schema").Field<string | null>;
72
+ readonly disabled_reason: import("@protobase/schema").Field<string | null>;
73
+ readonly last_success_at: import("@protobase/schema").Field<string | null>;
74
+ readonly failing_since: import("@protobase/schema").Field<string | null>;
75
+ readonly created_at: import("@protobase/schema").Field<string>;
76
+ readonly updated_at: import("@protobase/schema").Field<string>;
77
+ readonly rotate_secret: import("@protobase/schema").Field<boolean>;
78
+ readonly send_test: import("@protobase/schema").Field<boolean>;
79
+ readonly resend_failed: import("@protobase/schema").Field<boolean>;
80
+ }, import("@protobase/schema").Ref<"id", string>>>;
81
+ webhookDeliveries: import("@protobase/schema").ResourceBuilder<{
82
+ readonly id: import("@protobase/schema").Field<string>;
83
+ readonly subscription_id: import("@protobase/schema").Field<string | number>;
84
+ readonly tenant_id: import("@protobase/schema").Field<string | null>;
85
+ readonly event_type: import("@protobase/schema").Field<string>;
86
+ readonly event_id: import("@protobase/schema").Field<string>;
87
+ readonly status: import("@protobase/schema").Field<"waiting" | "failed">;
88
+ readonly attempt: import("@protobase/schema").Field<number>;
89
+ readonly next_attempt: import("@protobase/schema").Field<string | null>;
90
+ readonly last_error: import("@protobase/schema").Field<string | null>;
91
+ readonly created_at: import("@protobase/schema").Field<string>;
92
+ readonly resend: import("@protobase/schema").Field<boolean>;
93
+ }, import("@protobase/schema").Ref<"id", string>>;
94
+ webhookDeliveriesView: import("@protobase/schema").ViewBuilder<import("@protobase/schema").ResourceBuilder<{
95
+ readonly id: import("@protobase/schema").Field<string>;
96
+ readonly subscription_id: import("@protobase/schema").Field<string | number>;
97
+ readonly tenant_id: import("@protobase/schema").Field<string | null>;
98
+ readonly event_type: import("@protobase/schema").Field<string>;
99
+ readonly event_id: import("@protobase/schema").Field<string>;
100
+ readonly status: import("@protobase/schema").Field<"waiting" | "failed">;
101
+ readonly attempt: import("@protobase/schema").Field<number>;
102
+ readonly next_attempt: import("@protobase/schema").Field<string | null>;
103
+ readonly last_error: import("@protobase/schema").Field<string | null>;
104
+ readonly created_at: import("@protobase/schema").Field<string>;
105
+ readonly resend: import("@protobase/schema").Field<boolean>;
106
+ }, import("@protobase/schema").Ref<"id", string>>>;
107
+ };
108
+ //#endregion
@@ -0,0 +1,11 @@
1
+ import { webhooksSchema } from "./options.js";
2
+ import { webhookResources } from "@protobase/schema/internal";
3
+ //#region src/webhooks/table/webhooks-module.ts
4
+ /**
5
+ * What `webhooks` in `protobase.config.ts` adds to the app's resources: the Webhook subscriptions and Webhook deliveries
6
+ * pages, over a `webhooks` schema that `protobase migration` writes, and the delivery log with `deliveryLog`. Who may
7
+ * create subscriptions is the resources' access (`webhook_subscriptions.create`, ...); each delivers as its owner.
8
+ */
9
+ const webhooksModule = (options = {}) => webhookResources(webhooksSchema(options), { deliveryLog: Boolean(options.deliveryLog) });
10
+ //#endregion
11
+ export { webhooksModule };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/server",
3
- "version": "0.47.1",
3
+ "version": "0.49.0",
4
4
  "description": "The Protobase REST API as a Hono app, with Better Auth sign-in.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -16,8 +16,11 @@
16
16
  },
17
17
  "exports": {
18
18
  ".": "./dist/index.js",
19
+ "./auth-store": "./dist/auth-store.js",
20
+ "./config-exports": "./dist/config-exports.js",
19
21
  "./email": "./dist/email.js",
20
- "./vapid": "./dist/vapid.js"
22
+ "./vapid": "./dist/vapid.js",
23
+ "./internal": "./dist/internal.js"
21
24
  },
22
25
  "types": "./dist/index.d.ts",
23
26
  "files": [
@@ -37,9 +40,9 @@
37
40
  "@better-auth/passkey": "^1.7.12",
38
41
  "@better-auth/sso": "^1.7.12",
39
42
  "@modelcontextprotocol/server": "^2.3.1",
40
- "@protobase/layout": "0.47.1",
41
- "@protobase/query": "0.47.1",
42
- "@protobase/schema": "0.47.1",
43
+ "@protobase/layout": "0.49.0",
44
+ "@protobase/query": "0.49.0",
45
+ "@protobase/schema": "0.49.0",
43
46
  "@react-email/render": "^2.1.0",
44
47
  "@scalar/hono-api-reference": "^0.12.10",
45
48
  "@sentry/core": "^11.7.0",
@@ -1,32 +0,0 @@
1
- import { pluginNames } from "../snake-case-names.js";
2
- //#region src/better-auth/mcp/mcp-tables.ts
3
- /** The database names of MCP's tables. */
4
- const mcpTableNames = Object.values(pluginNames.mcp).map(({ modelName }) => modelName);
5
- const mcpTablesPlugin = {
6
- id: "protobase-mcp-tables",
7
- schema: Object.fromEntries(Object.entries(pluginNames.mcp).map(([model, { modelName }]) => [model, {
8
- modelName,
9
- fields: {}
10
- }]))
11
- };
12
- /** The auth's options, which with MCP off also name MCP's tables, for a plan that tells whether they are left over. */
13
- const withMcpTables = (auth) => auth.mcp ? auth.options : {
14
- ...auth.options,
15
- plugins: [...auth.options.plugins ?? [], mcpTablesPlugin]
16
- };
17
- /** The MCP tables the store still has while MCP is off, from a plan made with `withMcpTables`; none with MCP on. */
18
- const leftoverMcpTables = (auth, { toBeCreated }) => {
19
- if (auth.mcp) return [];
20
- const missing = new Set(toBeCreated.map(({ table }) => table));
21
- return mcpTableNames.filter((table) => !missing.has(table));
22
- };
23
- const schemaName = /^[a-z_][a-z0-9_]*$/;
24
- /** The statement that drops MCP's tables, in `schema` or the connection's current one. */
25
- const dropMcpTables = (schema) => {
26
- if (schema !== void 0 && !schemaName.test(schema)) throw new Error(`Invalid auth schema name "${schema}"`);
27
- const s = schema === void 0 ? "" : `"${schema}".`;
28
- return `-- MCP is off: dropping the tables of its OAuth provider disconnects every MCP client and forgets every grant.
29
- drop table if exists ${mcpTableNames.map((table) => `${s}"${table}"`).join(", ")};`;
30
- };
31
- //#endregion
32
- export { dropMcpTables, leftoverMcpTables, mcpTableNames, withMcpTables };
@@ -1,122 +0,0 @@
1
- //#region src/better-auth/snake-case-migration.ts
2
- const schemaName = /^[a-z_][a-z0-9_]*$/;
3
- /**
4
- * The migration that renames the auth store of Protobase 0.6 in place, from Better Auth's camelCase names to the
5
- * snake_case ones of `snake-case-names.ts`: tables, columns, and the indexes and constraints named after them. Data,
6
- * defaults, keys and indexes stay as they are. On a store that has the snake_case names already it does nothing, so a
7
- * project's migrations can carry it after an auth migration written with them. `schema` is the store's schema, the
8
- * connection's current one when left out.
9
- */
10
- const snakeCaseMigration = (schema) => {
11
- if (schema !== void 0 && !schemaName.test(schema)) throw new Error(`Invalid auth schema name "${schema}"`);
12
- const s = schema === void 0 ? "" : `"${schema}".`;
13
- const current = schema === void 0 ? "current_schema()" : `'${schema}'`;
14
- return `-- Renames the auth store of Protobase 0.6 to snake_case. A store set up with the snake_case names has no "emailVerified"
15
- -- and is left as it is.
16
- do $$
17
- declare
18
- constraint_row record;
19
- begin
20
- if not exists (select from information_schema.columns where table_schema = ${current} and table_name = 'user' and column_name = 'emailVerified') then
21
- return;
22
- end if;
23
-
24
- alter table ${s}"twoFactor" rename to two_factor;
25
- alter table ${s}"signInPolicy" rename to sign_in_policy;
26
- alter table ${s}"staffSignIn" rename to staff_sign_in;
27
-
28
- alter table ${s}"user" rename column "emailVerified" to email_verified;
29
- alter table ${s}"user" rename column "createdAt" to created_at;
30
- alter table ${s}"user" rename column "updatedAt" to updated_at;
31
- alter table ${s}"user" rename column "banReason" to ban_reason;
32
- alter table ${s}"user" rename column "banExpires" to ban_expires;
33
- alter table ${s}"user" rename column "twoFactorEnabled" to two_factor_enabled;
34
-
35
- alter table ${s}session rename column "expiresAt" to expires_at;
36
- alter table ${s}session rename column "createdAt" to created_at;
37
- alter table ${s}session rename column "updatedAt" to updated_at;
38
- alter table ${s}session rename column "ipAddress" to ip_address;
39
- alter table ${s}session rename column "userAgent" to user_agent;
40
- alter table ${s}session rename column "userId" to user_id;
41
- alter table ${s}session rename column "impersonatedBy" to impersonated_by;
42
-
43
- alter table ${s}account rename column "accountId" to account_id;
44
- alter table ${s}account rename column "providerId" to provider_id;
45
- alter table ${s}account rename column "userId" to user_id;
46
- alter table ${s}account rename column "accessToken" to access_token;
47
- alter table ${s}account rename column "refreshToken" to refresh_token;
48
- alter table ${s}account rename column "idToken" to id_token;
49
- alter table ${s}account rename column "accessTokenExpiresAt" to access_token_expires_at;
50
- alter table ${s}account rename column "refreshTokenExpiresAt" to refresh_token_expires_at;
51
- alter table ${s}account rename column "createdAt" to created_at;
52
- alter table ${s}account rename column "updatedAt" to updated_at;
53
-
54
- alter table ${s}verification rename column "expiresAt" to expires_at;
55
- alter table ${s}verification rename column "createdAt" to created_at;
56
- alter table ${s}verification rename column "updatedAt" to updated_at;
57
-
58
- alter table ${s}jwks rename column "publicKey" to public_key;
59
- alter table ${s}jwks rename column "privateKey" to private_key;
60
- alter table ${s}jwks rename column "createdAt" to created_at;
61
- alter table ${s}jwks rename column "expiresAt" to expires_at;
62
-
63
- alter table ${s}two_factor rename column "backupCodes" to backup_codes;
64
- alter table ${s}two_factor rename column "userId" to user_id;
65
- alter table ${s}two_factor rename column "failedVerificationCount" to failed_verification_count;
66
- alter table ${s}two_factor rename column "lockedUntil" to locked_until;
67
-
68
- alter table ${s}passkey rename column "publicKey" to public_key;
69
- alter table ${s}passkey rename column "userId" to user_id;
70
- alter table ${s}passkey rename column "credentialID" to credential_id;
71
- alter table ${s}passkey rename column "deviceType" to device_type;
72
- alter table ${s}passkey rename column "backedUp" to backed_up;
73
- alter table ${s}passkey rename column "createdAt" to created_at;
74
-
75
- alter table ${s}sign_in_policy rename column "emailCode" to email_code;
76
- alter table ${s}sign_in_policy rename column "twoFactor" to two_factor;
77
- alter table ${s}sign_in_policy rename column "staffAccess" to staff_access;
78
- alter table ${s}sign_in_policy rename column "platformSignIn" to platform_sign_in;
79
- alter table ${s}sign_in_policy rename column "createdAt" to created_at;
80
- alter table ${s}sign_in_policy rename column "createdBy" to created_by;
81
-
82
- alter table ${s}staff_sign_in rename column "userId" to user_id;
83
- alter table ${s}staff_sign_in rename column "userEmail" to user_email;
84
- alter table ${s}staff_sign_in rename column "staffName" to staff_name;
85
- alter table ${s}staff_sign_in rename column "staffSubject" to staff_subject;
86
- alter table ${s}staff_sign_in rename column "sessionId" to session_id;
87
- alter table ${s}staff_sign_in rename column "startedAt" to started_at;
88
- alter table ${s}staff_sign_in rename column "expiresAt" to expires_at;
89
- alter table ${s}staff_sign_in rename column "endedAt" to ended_at;
90
-
91
- -- A primary key's index takes the new name with it.
92
- alter table ${s}two_factor rename constraint "twoFactor_pkey" to two_factor_pkey;
93
- alter table ${s}sign_in_policy rename constraint "signInPolicy_pkey" to sign_in_policy_pkey;
94
- alter table ${s}staff_sign_in rename constraint "staffSignIn_pkey" to staff_sign_in_pkey;
95
- alter table ${s}session rename constraint "session_userId_fkey" to session_user_id_fkey;
96
- alter table ${s}account rename constraint "account_userId_fkey" to account_user_id_fkey;
97
- alter table ${s}two_factor rename constraint "twoFactor_userId_fkey" to two_factor_user_id_fkey;
98
- alter table ${s}passkey rename constraint "passkey_userId_fkey" to passkey_user_id_fkey;
99
-
100
- alter index ${s}"session_userId_idx" rename to session_user_id_idx;
101
- alter index ${s}"account_userId_idx" rename to account_user_id_idx;
102
- alter index ${s}"twoFactor_secret_idx" rename to two_factor_secret_idx;
103
- alter index ${s}"twoFactor_userId_idx" rename to two_factor_user_id_idx;
104
- alter index ${s}"passkey_userId_idx" rename to passkey_user_id_idx;
105
- alter index ${s}"passkey_credentialID_idx" rename to passkey_credential_id_idx;
106
-
107
- -- Postgres 18 names each not-null constraint after its table and column, as "user_emailVerified_not_null"; earlier
108
- -- versions keep no such constraints, so there is nothing to rename there.
109
- for constraint_row in
110
- select c.conrelid::regclass as table_name, c.conname as old_name, t.relname || '_' || a.attname || '_not_null' as new_name
111
- from pg_constraint c
112
- join pg_class t on t.oid = c.conrelid
113
- join pg_attribute a on a.attrelid = c.conrelid and a.attnum = c.conkey[1]
114
- where c.contype = 'n' and t.relnamespace = (select oid from pg_namespace where nspname = ${current}) and c.conname ~ '[A-Z]'
115
- loop
116
- execute format('alter table %s rename constraint %I to %I', constraint_row.table_name, constraint_row.old_name, constraint_row.new_name);
117
- end loop;
118
- end
119
- $$;`;
120
- };
121
- //#endregion
122
- export { snakeCaseMigration };
@@ -1,13 +0,0 @@
1
- import { NotificationsOptions } from "./options.js";
2
- import { ProjectConfig } from "../project-config.js";
3
- //#region src/notifications/plugin.d.ts
4
- /**
5
- * Notifications: `extends: [notifications()]` in `protobase.config.ts`. It keeps each user's devices, in the
6
- * `notifications.devices` table that `protobase migration` writes or in the `store` given, and serves the endpoints
7
- * through which a signed-in user registers and removes their own (`devicesPath`). It keeps each user's inbox
8
- * notifications in the `notifications.history` table or the `historyStore` given, and serves the endpoints through which
9
- * a signed-in user lists theirs and marks them read (`historyPath`). It delivers through `senders`, by default the
10
- * built-in ones whose environment is set (see `notificationSenders`).
11
- */
12
- export declare const notifications: (options?: NotificationsOptions) => ProjectConfig;
13
- //#endregion
@@ -1,16 +0,0 @@
1
- import { checkNotificationsOptions } from "./options.js";
2
- //#region src/notifications/plugin.ts
3
- /**
4
- * Notifications: `extends: [notifications()]` in `protobase.config.ts`. It keeps each user's devices, in the
5
- * `notifications.devices` table that `protobase migration` writes or in the `store` given, and serves the endpoints
6
- * through which a signed-in user registers and removes their own (`devicesPath`). It keeps each user's inbox
7
- * notifications in the `notifications.history` table or the `historyStore` given, and serves the endpoints through which
8
- * a signed-in user lists theirs and marks them read (`historyPath`). It delivers through `senders`, by default the
9
- * built-in ones whose environment is set (see `notificationSenders`).
10
- */
11
- const notifications = (options = {}) => ({
12
- name: "protobase-notifications",
13
- notifications: checkNotificationsOptions(options)
14
- });
15
- //#endregion
16
- export { notifications };
@@ -1,54 +0,0 @@
1
- import { MobileConfig } from "./mobile-config.js";
2
- import { AppIdentity } from "./app-identity.js";
3
- import { AdminAuth } from "./better-auth/create-auth.js";
4
- import { EventsOptions } from "./changes/events-options.js";
5
- import { Authenticator } from "./types.js";
6
- import { HistoryOptions } from "./history/options.js";
7
- import { WebhooksOptions } from "./webhooks/table/options.js";
8
- import { NotificationsOptions } from "./notifications/options.js";
9
- import { FilesOptions } from "./files/options.js";
10
- import { FunctionSource } from "./functions/define-function.js";
11
- import { AdminOptions } from "./admin-options.js";
12
- import { Db } from "@protobase/query";
13
- //#region src/project-config.d.ts
14
- /** What `protobase.config.ts` may default-export. Everything is optional. */
15
- export type ProjectConfig = {
16
- /** Names the config in errors, such as two configs defining the same tool; an extension should set it. */
17
- name?: string;
18
- /** Configs this one extends: merged in order before it (see `mergeConfig`). */
19
- extends?: ProjectConfig[];
20
- /** The config module, e.g. `import * as config from './config'`; default: ./config/index.ts and ./config/*\/ui.ts. */
21
- config?: Record<string, unknown>;
22
- db?: Db;
23
- authenticate?: Authenticator;
24
- /** A Better Auth instance; createAdmin mounts its routes under /api/auth. */
25
- auth?: AdminAuth;
26
- /** The API functions, each served at `/api/functions/<name>`; default: one per file in ./functions. */
27
- functions?: Record<string, FunctionSource>;
28
- /** Where file fields keep their bytes: providers by name, retention and the signing secret (see `FilesOptions`). */
29
- files?: FilesOptions;
30
- /** Where the changes that resources' events are raised from are captured (see `EventsOptions`). */
31
- events?: EventsOptions;
32
- /** How long the history of resources with `.history()` is kept (see `HistoryOptions`). */
33
- history?: HistoryOptions;
34
- /** Webhook subscriptions made in the admin app; set by `extends: [webhooks()]` (see `WebhooksOptions`). */
35
- webhooks?: WebhooksOptions;
36
- /** Notifications and each user's devices; set by `extends: [notifications()]` (see `NotificationsOptions`). */
37
- notifications?: NotificationsOptions;
38
- /** The module of the app's jobs, e.g. `import * as jobs from './config/jobs'`: every `defineJob` it exports. */
39
- jobs?: Record<string, unknown>;
40
- /** The app's iOS and Android build (see `MobileConfig`): `protobase mobile` needs it, and the API answers the app's origins. */
41
- mobile?: MobileConfig;
42
- /** The installed app's colours (see `AppIdentity`), which its web manifest carries. */
43
- app?: AppIdentity;
44
- options?: AdminOptions;
45
- };
46
- /** Typed identity, for `export default defineConfig({ extends: [...], config, auth, ... })` in `protobase.config.ts`. */
47
- export declare const defineConfig: (config: ProjectConfig) => ProjectConfig;
48
- /**
49
- * One config from several, each after the ones it `extends`, the last being the app's own. Named things are all kept:
50
- * resources, views and pages of the config modules, functions, jobs, assistant tools, file providers; one name defined by two configs is an error naming
51
- * both. Write hooks run in the same order. Every other value is the last config's that sets it, so the app's own wins.
52
- */
53
- export declare const mergeConfig: (...configs: ProjectConfig[]) => ProjectConfig;
54
- //#endregion
@@ -1,182 +0,0 @@
1
- import { jobDefinitions } from "./jobs/define-job.js";
2
- import { isSubscription } from "./webhooks/subscription.js";
3
- import { isPageDefinition } from "@protobase/layout";
4
- //#region src/project-config.ts
5
- /** Typed identity, for `export default defineConfig({ extends: [...], config, auth, ... })` in `protobase.config.ts`. */
6
- const defineConfig = (config) => config;
7
- const lastSet = (objects) => Object.fromEntries(objects.flatMap((object) => Object.entries(object)).filter(([, value]) => value !== void 0));
8
- const flatten = (config, label) => [...(config.extends ?? []).flatMap((parent, index) => flatten(parent, parent.name ?? `${label} extends[${index}]`)), {
9
- config,
10
- label
11
- }];
12
- const checkUnique = (kind, entries) => {
13
- const seen = /* @__PURE__ */ new Map();
14
- for (const { name, value, label } of entries) {
15
- const first = seen.get(name);
16
- if (first && first.value !== value) throw new Error(`${kind} "${name}" is defined twice, ${first.label === label ? `in ${label}` : `by ${first.label} and by ${label}`}; rename one of them`);
17
- if (!first) seen.set(name, {
18
- value,
19
- label
20
- });
21
- }
22
- };
23
- const mergedModule = (named) => {
24
- const withModule = named.filter(({ config }) => config.config);
25
- if (withModule.length === 0) return void 0;
26
- const exports = withModule.flatMap(({ config, label }) => Object.entries(config.config).map(([key, value]) => ({
27
- key,
28
- value,
29
- label
30
- })));
31
- const values = exports.map((entry) => ({
32
- ...entry,
33
- value: entry.value
34
- }));
35
- checkUnique("The resource", values.filter(({ value }) => typeof value?.recordSchema === "function" && typeof value.toModel === "function").map(({ value, label }) => ({
36
- name: String(value.toModel().name),
37
- value,
38
- label
39
- })));
40
- checkUnique("The page", exports.filter(({ value }) => isPageDefinition(value)).map(({ value, label }) => ({
41
- name: value.name,
42
- value,
43
- label
44
- })));
45
- checkUnique("The subscription", exports.filter(({ value }) => isSubscription(value)).map(({ value, label }) => ({
46
- name: value.name,
47
- value,
48
- label
49
- })));
50
- const menus = values.filter(({ value }) => typeof value?.toUserMenuModel === "function");
51
- if (new Set(menus.map(({ value }) => value)).size > 1) throw new Error(`Only one config may export a user menu; ${menus.map(({ label }) => label).join(" and ")} each do`);
52
- const module = {};
53
- const own = withModule.at(-1).label;
54
- for (const { key, value, label } of exports) {
55
- if (Object.values(module).includes(value)) continue;
56
- module[label === own ? key : `${label}:${key}`] = value;
57
- }
58
- return module;
59
- };
60
- const mergedAssistant = (named) => {
61
- const options = named.map(({ config, label }) => ({
62
- assistant: config.options?.assistant,
63
- label
64
- })).filter(({ assistant }) => assistant !== void 0);
65
- if (options.length === 0) return void 0;
66
- if (options.at(-1).assistant === false) return false;
67
- const after = options.slice(options.findLastIndex(({ assistant }) => assistant === false) + 1);
68
- const tools = after.flatMap(({ assistant, label }) => (assistant.tools ?? []).map((tool) => ({
69
- tool,
70
- label
71
- })));
72
- checkUnique("The assistant tool", tools.map(({ tool, label }) => ({
73
- name: tool.name,
74
- value: tool,
75
- label
76
- })));
77
- return {
78
- ...lastSet(after.map(({ assistant }) => assistant)),
79
- ...tools.length > 0 && { tools: tools.map(({ tool }) => tool) }
80
- };
81
- };
82
- const mergedFunctions = (named) => {
83
- const all = named.flatMap(({ config, label }) => Object.entries(config.functions ?? {}).map(([name, value]) => ({
84
- name,
85
- value,
86
- label
87
- })));
88
- if (all.length === 0) return void 0;
89
- checkUnique("The function", all);
90
- return Object.fromEntries(all.map(({ name, value }) => [name, value]));
91
- };
92
- const mergedFiles = (named) => {
93
- const all = named.flatMap(({ config, label }) => config.files ? [{
94
- files: config.files,
95
- label
96
- }] : []);
97
- if (all.length === 0) return void 0;
98
- const providers = all.flatMap(({ files, label }) => Object.entries(files.providers ?? {}).map(([name, value]) => ({
99
- name,
100
- value,
101
- label
102
- })));
103
- checkUnique("The file provider", providers);
104
- const trustedHosts = [...new Set(all.flatMap(({ files }) => files.trustedHosts ?? []))];
105
- const { retention, secret, sharp } = lastSet(all.map(({ files }) => ({
106
- retention: files.retention,
107
- secret: files.secret,
108
- sharp: files.sharp
109
- })));
110
- return {
111
- ...providers.length > 0 && { providers: Object.fromEntries(providers.map(({ name, value }) => [name, value])) },
112
- ...retention !== void 0 && { retention },
113
- ...secret !== void 0 && { secret },
114
- ...sharp !== void 0 && { sharp },
115
- ...trustedHosts.length > 0 && { trustedHosts }
116
- };
117
- };
118
- const mergedJobs = (named) => {
119
- const all = named.flatMap(({ config, label }) => jobDefinitions(config.jobs ?? {}).map((value) => ({
120
- name: value.name,
121
- value,
122
- label
123
- })));
124
- if (all.length === 0) return void 0;
125
- checkUnique("The job", all);
126
- return Object.fromEntries(all.map(({ name, value }) => [name, value]));
127
- };
128
- const mergedOptions = (named) => {
129
- const all = named.flatMap(({ config }) => config.options ? [config.options] : []);
130
- if (all.length === 0) return void 0;
131
- const writeHooks = all.flatMap((options) => options.writeHooks ?? []);
132
- const assistant = mergedAssistant(named);
133
- return {
134
- ...lastSet(all),
135
- ...writeHooks.length > 0 && { writeHooks },
136
- ...assistant !== void 0 && { assistant }
137
- };
138
- };
139
- /**
140
- * One config from several, each after the ones it `extends`, the last being the app's own. Named things are all kept:
141
- * resources, views and pages of the config modules, functions, jobs, assistant tools, file providers; one name defined by two configs is an error naming
142
- * both. Write hooks run in the same order. Every other value is the last config's that sets it, so the app's own wins.
143
- */
144
- const mergeConfig = (...configs) => {
145
- const named = configs.flatMap((config, index) => flatten(config, config.name ?? `config ${index + 1}`));
146
- const { db, authenticate, auth, events, history, webhooks, notifications, mobile, app } = lastSet(named.map(({ config }) => ({
147
- db: config.db,
148
- authenticate: config.authenticate,
149
- auth: config.auth,
150
- events: config.events,
151
- history: config.history,
152
- webhooks: config.webhooks,
153
- notifications: config.notifications,
154
- mobile: config.mobile,
155
- app: config.app
156
- })));
157
- const module = mergedModule(named);
158
- const functions = mergedFunctions(named);
159
- const files = mergedFiles(named);
160
- const jobs = mergedJobs(named);
161
- const options = mergedOptions(named);
162
- const name = configs.at(-1)?.name;
163
- return {
164
- ...name && { name },
165
- ...module && { config: module },
166
- ...db && { db },
167
- ...authenticate && { authenticate },
168
- ...auth && { auth },
169
- ...functions && { functions },
170
- ...files && { files },
171
- ...events && { events },
172
- ...history && { history },
173
- ...webhooks && { webhooks },
174
- ...notifications && { notifications },
175
- ...jobs && { jobs },
176
- ...mobile && { mobile },
177
- ...app && { app },
178
- ...options && { options }
179
- };
180
- };
181
- //#endregion
182
- export { defineConfig, mergeConfig };
@@ -1,10 +0,0 @@
1
- import { WebhooksOptions } from "./options.js";
2
- import { ProjectConfig } from "../../project-config.js";
3
- //#region src/webhooks/table/plugin.d.ts
4
- /**
5
- * Webhook subscriptions made in the admin app: `extends: [webhooks()]` in `protobase.config.ts`. It adds the Webhook
6
- * subscriptions and Webhook deliveries pages, over a `webhooks` schema that `protobase migration` writes. Who may
7
- * create subscriptions is the resources' access (`webhook_subscriptions.create`, ...); each delivers as its owner.
8
- */
9
- export declare const webhooks: (options?: WebhooksOptions) => ProjectConfig;
10
- //#endregion
@@ -1,18 +0,0 @@
1
- import { webhooksSchema } from "./options.js";
2
- import { webhookResources } from "@protobase/schema/internal";
3
- //#region src/webhooks/table/plugin.ts
4
- /**
5
- * Webhook subscriptions made in the admin app: `extends: [webhooks()]` in `protobase.config.ts`. It adds the Webhook
6
- * subscriptions and Webhook deliveries pages, over a `webhooks` schema that `protobase migration` writes. Who may
7
- * create subscriptions is the resources' access (`webhook_subscriptions.create`, ...); each delivers as its owner.
8
- */
9
- const webhooks = (options = {}) => {
10
- const schema = webhooksSchema(options);
11
- return {
12
- name: "protobase-webhooks",
13
- config: webhookResources(schema, { deliveryLog: Boolean(options.deliveryLog) }),
14
- webhooks: options
15
- };
16
- };
17
- //#endregion
18
- export { webhooks };