@odla-ai/chapter 0.48.0 → 0.48.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 +62 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -20
- package/dist/index.d.ts +22 -20
- package/dist/index.js +62 -21
- package/dist/index.js.map +1 -1
- package/dist/worker/index.cjs +183 -126
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.js +183 -126
- package/dist/worker/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1230,7 +1230,9 @@ interface ChapterRunbookHints {
|
|
|
1230
1230
|
* Build the one CLI-consumable integration for a chapter/hub: the crm_*
|
|
1231
1231
|
* namespaces + crm_config seed + route probe, merged with the chapter's own
|
|
1232
1232
|
* namespaces and a guarded `groups`-row seed. Drop it in odla.config.mjs's
|
|
1233
|
-
* `integrations` array.
|
|
1233
|
+
* `integrations` array. Claim/private-Clerk policies also seed the exact role
|
|
1234
|
+
* ladder and metadata source for Studio. Seeds are insert-only: when changing
|
|
1235
|
+
* auth policy, reconcile that stored policy explicitly before enabling editing.
|
|
1234
1236
|
*/
|
|
1235
1237
|
declare function createChapterIntegration(chapter: Chapter, options?: ChapterIntegrationOptions): ChapterIntegrationDescriptor;
|
|
1236
1238
|
|
|
@@ -1248,7 +1250,7 @@ declare function createChapterIntegration(chapter: Chapter, options?: ChapterInt
|
|
|
1248
1250
|
* `superAdminSource: "odla"` uses reserved `$users` and adds no app namespace. A `"claim"`
|
|
1249
1251
|
* chapter therefore emits the reference namespace set — `applications`,
|
|
1250
1252
|
* `groups`, `meetings`, `emailLog`, `stripeEventReceipts`,
|
|
1251
|
-
* `subscriptionCheckoutIntents`, `superAdmins` — with
|
|
1253
|
+
* `subscriptionCheckoutIntents`, `chapterAccountPolicy`, `superAdmins` — with
|
|
1252
1254
|
* no `admins` table. */
|
|
1253
1255
|
declare function chapterDb(mode: ChapterMode, auth: ResolvedAuth, includeNetworkNotes?: boolean, application?: ResolvedApplication, includeSignupControl?: boolean, includeMemberContent?: boolean, includeBuilderLibrary?: boolean, includeLeaderAdmissions?: boolean, includeNetworkPersonRegistry?: boolean, includeNetworkCommercialReadModel?: boolean): {
|
|
1254
1256
|
schema: DbSchema;
|
|
@@ -2567,7 +2569,7 @@ declare function hasDisclaimerAck(fields: Record<string, unknown>): boolean;
|
|
|
2567
2569
|
* them. Pure; returns `undefined` when there is nothing to write.
|
|
2568
2570
|
*/
|
|
2569
2571
|
declare function applicantProfile(chapter: Chapter, fields: Record<string, unknown>): Record<string, unknown> | undefined;
|
|
2570
|
-
/** A validated submission, or a
|
|
2572
|
+
/** A validated submission, or a validation/duplicate-email error the route returns.
|
|
2571
2573
|
* `disclaimerAckAt` reports what THIS request recorded — a number when consent
|
|
2572
2574
|
* was stamped, `null` when none was supplied. It is always present so a missing
|
|
2573
2575
|
* consent record is visible in the response rather than silently absent from a
|
|
@@ -2581,6 +2583,8 @@ type SubmitResult = {
|
|
|
2581
2583
|
} | {
|
|
2582
2584
|
ok: false;
|
|
2583
2585
|
error: string;
|
|
2586
|
+
code?: string;
|
|
2587
|
+
status?: number;
|
|
2584
2588
|
};
|
|
2585
2589
|
/**
|
|
2586
2590
|
* Submit a membership application (B2 + B3). Validates the configured required
|
|
@@ -2590,6 +2594,9 @@ type SubmitResult = {
|
|
|
2590
2594
|
* create two applications. The application id is derived from that same stable
|
|
2591
2595
|
* input, so the duplicate response returns the first request's canonical id
|
|
2592
2596
|
* rather than a fresh, nonexistent one. Idempotency is package-enforced.
|
|
2597
|
+
* A unique normalized signup email key prevents concurrent submissions with
|
|
2598
|
+
* different ids from creating two applications; a conflict returns status 409.
|
|
2599
|
+
* Apply the current Chapter schema before deploying this writer.
|
|
2593
2600
|
* `now`/`newId` are injected (deterministic in tests).
|
|
2594
2601
|
*/
|
|
2595
2602
|
declare function submitApplication(db: ChapterDb, chapter: Chapter, fields: Record<string, unknown>, opts: {
|
|
@@ -3072,16 +3079,15 @@ type StripeResult = StripeRequestResult<Record<string, unknown>>;
|
|
|
3072
3079
|
* of each re-deriving the auth + encoding. */
|
|
3073
3080
|
declare function stripeCall(sk: string, method: "GET" | "POST" | "DELETE", path: string, params?: Record<string, unknown>, idempotencyKey?: string): Promise<StripeResult>;
|
|
3074
3081
|
|
|
3075
|
-
/** The outcome of
|
|
3076
|
-
*
|
|
3077
|
-
* state we wanted anyway. */
|
|
3082
|
+
/** The outcome of provisioning. An existing identifier is a conflict unless
|
|
3083
|
+
* the account proves it belongs to the original application being retried. */
|
|
3078
3084
|
interface ClerkResult {
|
|
3079
3085
|
ok: boolean;
|
|
3080
3086
|
status: number;
|
|
3081
3087
|
/** Stable Clerk user id returned by a successful fresh account create. */
|
|
3082
3088
|
userId?: string;
|
|
3083
3089
|
existed?: boolean;
|
|
3084
|
-
/**
|
|
3090
|
+
/** Legacy result field; signup never refreshes an existing account. */
|
|
3085
3091
|
refreshed?: boolean;
|
|
3086
3092
|
}
|
|
3087
3093
|
/** Inputs for a Clerk invitation. */
|
|
@@ -3100,9 +3106,8 @@ declare function clerkInviteRequest(input: ClerkInviteInput): {
|
|
|
3100
3106
|
path: string;
|
|
3101
3107
|
body: Record<string, unknown>;
|
|
3102
3108
|
};
|
|
3103
|
-
/** POST
|
|
3104
|
-
*
|
|
3105
|
-
* reporting a failure the caller would have to special-case. */
|
|
3109
|
+
/** POST a new invitation. Existing identifiers and all validation failures are
|
|
3110
|
+
* rejected; invitations never authorize changes to an existing account. */
|
|
3106
3111
|
declare function createClerkInvitation(secretKey: string, input: ClerkInviteInput, fetchImpl?: typeof fetch): Promise<ClerkResult>;
|
|
3107
3112
|
/** Inputs for a server-side Clerk user create. */
|
|
3108
3113
|
interface ClerkUserInput {
|
|
@@ -3113,9 +3118,8 @@ interface ClerkUserInput {
|
|
|
3113
3118
|
publicMetadata?: Record<string, unknown>;
|
|
3114
3119
|
/** Backend-only account signals and profile data. */
|
|
3115
3120
|
privateMetadata?: Record<string, unknown>;
|
|
3116
|
-
/**
|
|
3117
|
-
*
|
|
3118
|
-
* values on a newly-created user. Defaults to the create metadata. */
|
|
3121
|
+
/** @deprecated Ignored. Use an explicitly authorized metadata update for repairs;
|
|
3122
|
+
* signup must never modify an account found by email. */
|
|
3119
3123
|
repairMetadata?: ClerkMetadataInput;
|
|
3120
3124
|
}
|
|
3121
3125
|
/** Build the Clerk Backend API user-create request. The account is created
|
|
@@ -3137,15 +3141,13 @@ declare function updateClerkUserMetadata(secretKey: string, userId: string, inpu
|
|
|
3137
3141
|
/** Look a Clerk account up by email and merge its metadata.
|
|
3138
3142
|
*
|
|
3139
3143
|
* Returns `false` when no matching user can be resolved or Clerk rejects the
|
|
3140
|
-
* lookup or update.
|
|
3141
|
-
*
|
|
3144
|
+
* lookup or update. This is an explicit administrative repair primitive;
|
|
3145
|
+
* never call it from public signup or use email knowledge as authorization.
|
|
3142
3146
|
*/
|
|
3143
3147
|
declare function updateClerkUserMetadataByEmail(secretKey: string, email: string, input: ClerkMetadataInput, fetchImpl?: typeof fetch): Promise<boolean>;
|
|
3144
|
-
/** Create
|
|
3145
|
-
*
|
|
3146
|
-
*
|
|
3147
|
-
* supplied public/private metadata on the existing account so a re-application
|
|
3148
|
-
* repairs a previously missed create (`refreshed: true`). */
|
|
3148
|
+
/** Create a new passwordless account. A provider collision never patches the
|
|
3149
|
+
* existing account. A retry may return its id only when backend-private metadata
|
|
3150
|
+
* already names the same original application, preserving all current claims. */
|
|
3149
3151
|
declare function createClerkUser(secretKey: string, input: ClerkUserInput, fetchImpl?: typeof fetch): Promise<ClerkResult>;
|
|
3150
3152
|
|
|
3151
3153
|
/** Backend metadata field selected for all role reads and writes. */
|
package/dist/index.d.ts
CHANGED
|
@@ -1230,7 +1230,9 @@ interface ChapterRunbookHints {
|
|
|
1230
1230
|
* Build the one CLI-consumable integration for a chapter/hub: the crm_*
|
|
1231
1231
|
* namespaces + crm_config seed + route probe, merged with the chapter's own
|
|
1232
1232
|
* namespaces and a guarded `groups`-row seed. Drop it in odla.config.mjs's
|
|
1233
|
-
* `integrations` array.
|
|
1233
|
+
* `integrations` array. Claim/private-Clerk policies also seed the exact role
|
|
1234
|
+
* ladder and metadata source for Studio. Seeds are insert-only: when changing
|
|
1235
|
+
* auth policy, reconcile that stored policy explicitly before enabling editing.
|
|
1234
1236
|
*/
|
|
1235
1237
|
declare function createChapterIntegration(chapter: Chapter, options?: ChapterIntegrationOptions): ChapterIntegrationDescriptor;
|
|
1236
1238
|
|
|
@@ -1248,7 +1250,7 @@ declare function createChapterIntegration(chapter: Chapter, options?: ChapterInt
|
|
|
1248
1250
|
* `superAdminSource: "odla"` uses reserved `$users` and adds no app namespace. A `"claim"`
|
|
1249
1251
|
* chapter therefore emits the reference namespace set — `applications`,
|
|
1250
1252
|
* `groups`, `meetings`, `emailLog`, `stripeEventReceipts`,
|
|
1251
|
-
* `subscriptionCheckoutIntents`, `superAdmins` — with
|
|
1253
|
+
* `subscriptionCheckoutIntents`, `chapterAccountPolicy`, `superAdmins` — with
|
|
1252
1254
|
* no `admins` table. */
|
|
1253
1255
|
declare function chapterDb(mode: ChapterMode, auth: ResolvedAuth, includeNetworkNotes?: boolean, application?: ResolvedApplication, includeSignupControl?: boolean, includeMemberContent?: boolean, includeBuilderLibrary?: boolean, includeLeaderAdmissions?: boolean, includeNetworkPersonRegistry?: boolean, includeNetworkCommercialReadModel?: boolean): {
|
|
1254
1256
|
schema: DbSchema;
|
|
@@ -2567,7 +2569,7 @@ declare function hasDisclaimerAck(fields: Record<string, unknown>): boolean;
|
|
|
2567
2569
|
* them. Pure; returns `undefined` when there is nothing to write.
|
|
2568
2570
|
*/
|
|
2569
2571
|
declare function applicantProfile(chapter: Chapter, fields: Record<string, unknown>): Record<string, unknown> | undefined;
|
|
2570
|
-
/** A validated submission, or a
|
|
2572
|
+
/** A validated submission, or a validation/duplicate-email error the route returns.
|
|
2571
2573
|
* `disclaimerAckAt` reports what THIS request recorded — a number when consent
|
|
2572
2574
|
* was stamped, `null` when none was supplied. It is always present so a missing
|
|
2573
2575
|
* consent record is visible in the response rather than silently absent from a
|
|
@@ -2581,6 +2583,8 @@ type SubmitResult = {
|
|
|
2581
2583
|
} | {
|
|
2582
2584
|
ok: false;
|
|
2583
2585
|
error: string;
|
|
2586
|
+
code?: string;
|
|
2587
|
+
status?: number;
|
|
2584
2588
|
};
|
|
2585
2589
|
/**
|
|
2586
2590
|
* Submit a membership application (B2 + B3). Validates the configured required
|
|
@@ -2590,6 +2594,9 @@ type SubmitResult = {
|
|
|
2590
2594
|
* create two applications. The application id is derived from that same stable
|
|
2591
2595
|
* input, so the duplicate response returns the first request's canonical id
|
|
2592
2596
|
* rather than a fresh, nonexistent one. Idempotency is package-enforced.
|
|
2597
|
+
* A unique normalized signup email key prevents concurrent submissions with
|
|
2598
|
+
* different ids from creating two applications; a conflict returns status 409.
|
|
2599
|
+
* Apply the current Chapter schema before deploying this writer.
|
|
2593
2600
|
* `now`/`newId` are injected (deterministic in tests).
|
|
2594
2601
|
*/
|
|
2595
2602
|
declare function submitApplication(db: ChapterDb, chapter: Chapter, fields: Record<string, unknown>, opts: {
|
|
@@ -3072,16 +3079,15 @@ type StripeResult = StripeRequestResult<Record<string, unknown>>;
|
|
|
3072
3079
|
* of each re-deriving the auth + encoding. */
|
|
3073
3080
|
declare function stripeCall(sk: string, method: "GET" | "POST" | "DELETE", path: string, params?: Record<string, unknown>, idempotencyKey?: string): Promise<StripeResult>;
|
|
3074
3081
|
|
|
3075
|
-
/** The outcome of
|
|
3076
|
-
*
|
|
3077
|
-
* state we wanted anyway. */
|
|
3082
|
+
/** The outcome of provisioning. An existing identifier is a conflict unless
|
|
3083
|
+
* the account proves it belongs to the original application being retried. */
|
|
3078
3084
|
interface ClerkResult {
|
|
3079
3085
|
ok: boolean;
|
|
3080
3086
|
status: number;
|
|
3081
3087
|
/** Stable Clerk user id returned by a successful fresh account create. */
|
|
3082
3088
|
userId?: string;
|
|
3083
3089
|
existed?: boolean;
|
|
3084
|
-
/**
|
|
3090
|
+
/** Legacy result field; signup never refreshes an existing account. */
|
|
3085
3091
|
refreshed?: boolean;
|
|
3086
3092
|
}
|
|
3087
3093
|
/** Inputs for a Clerk invitation. */
|
|
@@ -3100,9 +3106,8 @@ declare function clerkInviteRequest(input: ClerkInviteInput): {
|
|
|
3100
3106
|
path: string;
|
|
3101
3107
|
body: Record<string, unknown>;
|
|
3102
3108
|
};
|
|
3103
|
-
/** POST
|
|
3104
|
-
*
|
|
3105
|
-
* reporting a failure the caller would have to special-case. */
|
|
3109
|
+
/** POST a new invitation. Existing identifiers and all validation failures are
|
|
3110
|
+
* rejected; invitations never authorize changes to an existing account. */
|
|
3106
3111
|
declare function createClerkInvitation(secretKey: string, input: ClerkInviteInput, fetchImpl?: typeof fetch): Promise<ClerkResult>;
|
|
3107
3112
|
/** Inputs for a server-side Clerk user create. */
|
|
3108
3113
|
interface ClerkUserInput {
|
|
@@ -3113,9 +3118,8 @@ interface ClerkUserInput {
|
|
|
3113
3118
|
publicMetadata?: Record<string, unknown>;
|
|
3114
3119
|
/** Backend-only account signals and profile data. */
|
|
3115
3120
|
privateMetadata?: Record<string, unknown>;
|
|
3116
|
-
/**
|
|
3117
|
-
*
|
|
3118
|
-
* values on a newly-created user. Defaults to the create metadata. */
|
|
3121
|
+
/** @deprecated Ignored. Use an explicitly authorized metadata update for repairs;
|
|
3122
|
+
* signup must never modify an account found by email. */
|
|
3119
3123
|
repairMetadata?: ClerkMetadataInput;
|
|
3120
3124
|
}
|
|
3121
3125
|
/** Build the Clerk Backend API user-create request. The account is created
|
|
@@ -3137,15 +3141,13 @@ declare function updateClerkUserMetadata(secretKey: string, userId: string, inpu
|
|
|
3137
3141
|
/** Look a Clerk account up by email and merge its metadata.
|
|
3138
3142
|
*
|
|
3139
3143
|
* Returns `false` when no matching user can be resolved or Clerk rejects the
|
|
3140
|
-
* lookup or update.
|
|
3141
|
-
*
|
|
3144
|
+
* lookup or update. This is an explicit administrative repair primitive;
|
|
3145
|
+
* never call it from public signup or use email knowledge as authorization.
|
|
3142
3146
|
*/
|
|
3143
3147
|
declare function updateClerkUserMetadataByEmail(secretKey: string, email: string, input: ClerkMetadataInput, fetchImpl?: typeof fetch): Promise<boolean>;
|
|
3144
|
-
/** Create
|
|
3145
|
-
*
|
|
3146
|
-
*
|
|
3147
|
-
* supplied public/private metadata on the existing account so a re-application
|
|
3148
|
-
* repairs a previously missed create (`refreshed: true`). */
|
|
3148
|
+
/** Create a new passwordless account. A provider collision never patches the
|
|
3149
|
+
* existing account. A retry may return its id only when backend-private metadata
|
|
3150
|
+
* already names the same original application, preserving all current claims. */
|
|
3149
3151
|
declare function createClerkUser(secretKey: string, input: ClerkUserInput, fetchImpl?: typeof fetch): Promise<ClerkResult>;
|
|
3150
3152
|
|
|
3151
3153
|
/** Backend metadata field selected for all role reads and writes. */
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
// src/config.ts
|
|
2
2
|
import { defineCrm } from "@odla-ai/crm";
|
|
3
3
|
|
|
4
|
+
// src/schema-account-policy.ts
|
|
5
|
+
var chapterAccountPolicy = { attrs: {
|
|
6
|
+
id: { type: "string", unique: true, indexed: true, optional: false },
|
|
7
|
+
metadata: { type: "string", unique: false, indexed: false, optional: false },
|
|
8
|
+
roles: { type: "json", unique: false, indexed: false, optional: false }
|
|
9
|
+
} };
|
|
10
|
+
|
|
4
11
|
// src/member.ts
|
|
5
12
|
import { assertFieldCondition, resolveFieldStates } from "@odla-ai/crm";
|
|
6
13
|
|
|
@@ -124,8 +131,10 @@ async function submitApplication(db, chapter, fields, opts) {
|
|
|
124
131
|
if (fields.focus !== void 0) row2.focus = clampArray(fields.focus, app.maxArrayLen);
|
|
125
132
|
if (opts.groupId) row2.groupId = opts.groupId;
|
|
126
133
|
if (opts.runtime) row2.stripeRuntime = opts.runtime;
|
|
134
|
+
if (chapter.account !== "none") row2.clerkAccountPending = true;
|
|
127
135
|
if (typeof fields.email === "string" && isValidEmail(fields.email.trim())) {
|
|
128
136
|
row2.emailNormalized = normalizeChapterEmail(fields.email);
|
|
137
|
+
row2.signupEmailKey = row2.emailNormalized;
|
|
129
138
|
}
|
|
130
139
|
if (opts.admissionGrant?.decision === "waive_interview") {
|
|
131
140
|
row2.admissionGrantId = opts.admissionGrant.id;
|
|
@@ -149,11 +158,21 @@ async function submitApplication(db, chapter, fields, opts) {
|
|
|
149
158
|
consumedApplicationId: id10
|
|
150
159
|
} });
|
|
151
160
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
161
|
+
try {
|
|
162
|
+
const { duplicate } = await db.transact(
|
|
163
|
+
ops,
|
|
164
|
+
opts.submissionId ? { mutationId: `join:${opts.submissionId}` } : void 0
|
|
165
|
+
);
|
|
166
|
+
return { ok: true, id: id10, duplicate, status: chapter.pipeline.initial, disclaimerAckAt: acked ? opts.now : null };
|
|
167
|
+
} catch (error) {
|
|
168
|
+
if (error.code === "unique_violation") return {
|
|
169
|
+
ok: false,
|
|
170
|
+
code: "account_already_exists",
|
|
171
|
+
status: 409,
|
|
172
|
+
error: "An account or application already exists for this email. Please sign in to continue."
|
|
173
|
+
};
|
|
174
|
+
throw error;
|
|
175
|
+
}
|
|
157
176
|
}
|
|
158
177
|
function joinConfig(group, paymentsReady2, tiers2 = [], conditions = {}) {
|
|
159
178
|
return {
|
|
@@ -228,6 +247,9 @@ var applicationAttrs = {
|
|
|
228
247
|
refundPolicyAckAt: attr("number", { optional: true }),
|
|
229
248
|
prepEmailSentAt: attr("number", { optional: true }),
|
|
230
249
|
canceled: attr("boolean", { optional: true }),
|
|
250
|
+
signupEmailKey: attr("string", { unique: true, indexed: true, optional: true }),
|
|
251
|
+
clerkInvitationSentAt: attr("number", { optional: true }),
|
|
252
|
+
clerkAccountPending: attr("boolean", { optional: true }),
|
|
231
253
|
emailNormalized: attr("string", { indexed: true, optional: true }),
|
|
232
254
|
admissionGrantId: attr("string", { unique: true, indexed: true, optional: true }),
|
|
233
255
|
admissionSource: attr("string", { indexed: true, optional: true }),
|
|
@@ -900,6 +922,7 @@ function chapterDb(mode, auth, includeNetworkNotes = false, application = resolv
|
|
|
900
922
|
entities.memberContentLocal = memberContentLocal;
|
|
901
923
|
}
|
|
902
924
|
}
|
|
925
|
+
if (auth.source !== "table") entities.chapterAccountPolicy = chapterAccountPolicy;
|
|
903
926
|
if (auth.source === "table") entities.admins = admins;
|
|
904
927
|
if (auth.superAdminSource === "table") entities.superAdmins = superAdmins;
|
|
905
928
|
if (includeNetworkNotes) entities.networkNotes = networkNotes;
|
|
@@ -2979,6 +3002,12 @@ function createChapterIntegration(chapter, options = {}) {
|
|
|
2979
3002
|
...emails?.debugEmail ? { debugEmail: emails.debugEmail } : {}
|
|
2980
3003
|
});
|
|
2981
3004
|
const seeds = [...crmDesc.seeds ?? []];
|
|
3005
|
+
if (chapter.auth.source !== "table") seeds.push({
|
|
3006
|
+
id: "account-policy",
|
|
3007
|
+
ns: "chapterAccountPolicy",
|
|
3008
|
+
key: { attr: "id", value: chapter.id },
|
|
3009
|
+
attrs: { metadata: chapter.auth.source === "clerk" ? "private" : "public", roles: [...chapter.auth.ladder] }
|
|
3010
|
+
});
|
|
2982
3011
|
const group = chapter.groupSeed();
|
|
2983
3012
|
if (group) {
|
|
2984
3013
|
seeds.push({ id: "group", ns: "groups", key: { attr: "id", value: chapter.id }, attrs: { ...group, createdAt: now } });
|
|
@@ -7147,8 +7176,30 @@ async function stripeCall(sk, method, path, params, idempotencyKey) {
|
|
|
7147
7176
|
);
|
|
7148
7177
|
}
|
|
7149
7178
|
|
|
7179
|
+
// src/clerk-signup.ts
|
|
7180
|
+
async function findSignupAccount(secret, email, fetchImpl = fetch) {
|
|
7181
|
+
const response = await fetchImpl(`https://api.clerk.com/v1/users?email_address=${encodeURIComponent(normalizeChapterEmail(email))}&limit=2`, {
|
|
7182
|
+
headers: { authorization: `Bearer ${secret}` },
|
|
7183
|
+
redirect: "manual",
|
|
7184
|
+
signal: AbortSignal.timeout(5e3)
|
|
7185
|
+
});
|
|
7186
|
+
if (!response.ok) throw new Error("signup account lookup unavailable");
|
|
7187
|
+
const users = await response.json();
|
|
7188
|
+
if (!Array.isArray(users) || users.length > 1 || users.length === 1 && (typeof users[0]?.id !== "string" || !users[0].id)) {
|
|
7189
|
+
throw new Error("signup account lookup unavailable");
|
|
7190
|
+
}
|
|
7191
|
+
return users[0] ?? null;
|
|
7192
|
+
}
|
|
7193
|
+
function belongsToSignup(account, applicationId) {
|
|
7194
|
+
return typeof applicationId === "string" && applicationId.length > 0 && account.private_metadata?.applicationId === applicationId;
|
|
7195
|
+
}
|
|
7196
|
+
|
|
7150
7197
|
// src/clerk.ts
|
|
7151
|
-
|
|
7198
|
+
async function rejectedCreate(res) {
|
|
7199
|
+
const body = typeof res.json === "function" ? await res.json().catch(() => null) : null;
|
|
7200
|
+
const existed = Array.isArray(body?.errors) && body.errors.some((error) => error?.code === "form_identifier_exists" || error?.code === "duplicate_record");
|
|
7201
|
+
return { ok: false, status: res.status, ...existed ? { existed: true } : {} };
|
|
7202
|
+
}
|
|
7152
7203
|
function clerkInviteRequest(input) {
|
|
7153
7204
|
return {
|
|
7154
7205
|
path: "/v1/invitations",
|
|
@@ -7167,7 +7218,7 @@ async function createClerkInvitation(secretKey, input, fetchImpl = fetch) {
|
|
|
7167
7218
|
headers: { authorization: `Bearer ${secretKey}`, "content-type": "application/json" },
|
|
7168
7219
|
body: JSON.stringify(body)
|
|
7169
7220
|
});
|
|
7170
|
-
return res.ok ? { ok: true, status: res.status } :
|
|
7221
|
+
return res.ok ? { ok: true, status: res.status } : rejectedCreate(res);
|
|
7171
7222
|
}
|
|
7172
7223
|
function clerkUserRequest(input) {
|
|
7173
7224
|
return {
|
|
@@ -7219,20 +7270,10 @@ async function createClerkUser(secretKey, input, fetchImpl = fetch) {
|
|
|
7219
7270
|
...typeof body2?.id === "string" && body2.id ? { userId: body2.id } : {}
|
|
7220
7271
|
};
|
|
7221
7272
|
}
|
|
7222
|
-
const
|
|
7223
|
-
|
|
7224
|
-
const
|
|
7225
|
-
|
|
7226
|
-
...input.publicMetadata !== void 0 ? { publicMetadata: input.publicMetadata } : {},
|
|
7227
|
-
...input.privateMetadata !== void 0 ? { privateMetadata: input.privateMetadata } : {}
|
|
7228
|
-
};
|
|
7229
|
-
if (!healed.existed || repair.publicMetadata === void 0 && repair.privateMetadata === void 0) return healed;
|
|
7230
|
-
const userId = await existingClerkUserId(secretKey, input.email, fetchImpl).catch(() => null);
|
|
7231
|
-
const refreshed = userId ? await updateClerkUserMetadata(secretKey, userId, {
|
|
7232
|
-
...repair.publicMetadata !== void 0 ? { publicMetadata: repair.publicMetadata } : {},
|
|
7233
|
-
...repair.privateMetadata !== void 0 ? { privateMetadata: repair.privateMetadata } : {}
|
|
7234
|
-
}, fetchImpl).catch(() => false) : false;
|
|
7235
|
-
return { ...healed, refreshed, ...refreshed && userId ? { userId } : {} };
|
|
7273
|
+
const failure = await rejectedCreate(res);
|
|
7274
|
+
if (!failure.existed) return failure;
|
|
7275
|
+
const account = await findSignupAccount(secretKey, input.email, fetchImpl).catch(() => null);
|
|
7276
|
+
return account && belongsToSignup(account, input.privateMetadata?.applicationId) ? { ok: true, status: res.status, existed: true, userId: account.id } : failure;
|
|
7236
7277
|
}
|
|
7237
7278
|
|
|
7238
7279
|
// src/clerk-roles.ts
|