@odla-ai/chapter 0.26.0 → 0.26.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/README.md +32 -4
- package/dist/{copy-context-CLvhJhrF.d.ts → copy-context-Vof2eTMt.d.ts} +5 -0
- package/dist/index.cjs +8 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/ui/admin/index.d.ts +2 -2
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/member/index.d.ts +2 -2
- package/dist/worker/index.cjs +123 -78
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +5 -0
- package/dist/worker/index.d.ts +5 -0
- package/dist/worker/index.js +120 -75
- package/dist/worker/index.js.map +1 -1
- package/package.json +1 -1
package/dist/ui/admin/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as preact from 'preact';
|
|
2
2
|
import { ComponentChildren, JSX } from 'preact';
|
|
3
3
|
import { CrmClient, Crm, CrmRecord } from '@odla-ai/crm';
|
|
4
|
-
import { a as Chapter, b as ChapterCopy } from '../../copy-context-
|
|
5
|
-
export { C as ChapterCopyProvider, u as useChapterCopy } from '../../copy-context-
|
|
4
|
+
import { a as Chapter, b as ChapterCopy } from '../../copy-context-Vof2eTMt.js';
|
|
5
|
+
export { C as ChapterCopyProvider, u as useChapterCopy } from '../../copy-context-Vof2eTMt.js';
|
|
6
6
|
import { CrmLifecycleAdapter, CrmWorkspaceMasterContext, CrmWorkspaceRecordContext, RecordPanelTab } from '@odla-ai/crm/ui';
|
|
7
7
|
|
|
8
8
|
/** Normalized public auth configuration consumed by the Clerk gate. */
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { AdminAccountMenuProps, AdminChrome, AdminNote, AdminPage, AdminResource, AdminRouteState, AdminRouteTarget, AdminRouting, AdminSection, AdminSectionContext, AdminWorkspace, AdminWorkspaceNavProps, AvailabilitySectionOptions, BillingSectionOptions, ChapterAdmin, ChapterAdminAuthAdapter, ChapterAdminAuthConfig, ChapterAdminAuthLoadContext, ChapterAdminProps, ChapterAdminUser, CollectionSectionOptions, DashboardSectionOptions, EmailSectionOptions, LeaderNetworkOverview, MeetingsSectionOptions, NetworkShareActions, NetworkShareActionsProps, Panel, PeopleSectionOptions, RecordActions, RecordActionsProps, ThemeWarning, adminFetch, adminRouteFromUrl, adminRouteHref, adminSectionFromUrl, adminSectionHref, applicationLifecycleAdapter, availabilitySection, billingSection, collectionSection, dashboardSection, defaultAdminSections, defaultAdminWorkspaces, emailSection, loadChapterAdminConfig, loadChapterAdminUser, meetingsSection, peopleSection, useAdminResource } from './admin/index.js';
|
|
2
|
-
export { C as ChapterCopyProvider, u as useChapterCopy } from '../copy-context-
|
|
2
|
+
export { C as ChapterCopyProvider, u as useChapterCopy } from '../copy-context-Vof2eTMt.js';
|
|
3
3
|
export { ApiFn, BrandStyle, BrandStyleProps, JoinConfig, JoinFlowState, JoinIsland, JoinIslandProps, JoinStepRenderContext, JoinSubmitRenderContext, MemberProvisionalRenderContext, MembersArea, MembersAreaProps, PaymentPriceLines, PaymentStep, PaymentStepProps, RescheduleProps, Rescheduler, Slot, SlotPicker, SlotPickerClasses, SlotPickerProps, dayKey, dayLabel, fmtDate, fmtMoney, fullLabel, groupSlotsByDay, loadJoinResume, timeLabel, tzShort } from './member/index.js';
|
|
4
4
|
import 'preact';
|
|
5
5
|
import '@odla-ai/crm';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as preact from 'preact';
|
|
2
2
|
import { ComponentChildren, JSX } from 'preact';
|
|
3
|
-
import { b as ChapterCopy, c as ChapterBrand } from '../../copy-context-
|
|
4
|
-
export { C as ChapterCopyProvider, u as useChapterCopy } from '../../copy-context-
|
|
3
|
+
import { b as ChapterCopy, c as ChapterBrand } from '../../copy-context-Vof2eTMt.js';
|
|
4
|
+
export { C as ChapterCopyProvider, u as useChapterCopy } from '../../copy-context-Vof2eTMt.js';
|
|
5
5
|
import '@odla-ai/crm';
|
|
6
6
|
|
|
7
7
|
/** A bookable slot: a start instant in epoch milliseconds. */
|
package/dist/worker/index.cjs
CHANGED
|
@@ -2637,8 +2637,118 @@ var handleAdminComms = async (req, url, env, ctx) => {
|
|
|
2637
2637
|
};
|
|
2638
2638
|
|
|
2639
2639
|
// src/worker-routes-network.ts
|
|
2640
|
+
var import_crm5 = require("@odla-ai/crm");
|
|
2641
|
+
var import_db4 = require("@odla-ai/db");
|
|
2642
|
+
|
|
2643
|
+
// src/worker-network-fetch.ts
|
|
2644
|
+
function targetFetcher(env, target) {
|
|
2645
|
+
if (!target.binding) return null;
|
|
2646
|
+
const candidate = env[target.binding];
|
|
2647
|
+
if (typeof candidate !== "object" || candidate === null || !("fetch" in candidate) || typeof candidate.fetch !== "function") {
|
|
2648
|
+
throw new Error(`service binding "${target.binding}" is unavailable`);
|
|
2649
|
+
}
|
|
2650
|
+
return candidate;
|
|
2651
|
+
}
|
|
2652
|
+
function fetchNetworkTarget(env, target, destination, init) {
|
|
2653
|
+
const binding = targetFetcher(env, target);
|
|
2654
|
+
return binding ? binding.fetch(new Request(destination, init)) : globalThis.fetch(destination, init);
|
|
2655
|
+
}
|
|
2656
|
+
|
|
2657
|
+
// src/worker-network-push.ts
|
|
2640
2658
|
var import_crm4 = require("@odla-ai/crm");
|
|
2641
2659
|
var import_db3 = require("@odla-ai/db");
|
|
2660
|
+
async function pushNetworkRecord(db, env, ctx, target, record) {
|
|
2661
|
+
const secret = await getVaultSecret(db, target.secretName);
|
|
2662
|
+
const crmDeps3 = {
|
|
2663
|
+
crm: ctx.chapter.crm,
|
|
2664
|
+
db,
|
|
2665
|
+
now: () => Date.now(),
|
|
2666
|
+
newId: () => crypto.randomUUID()
|
|
2667
|
+
};
|
|
2668
|
+
if (!secret) {
|
|
2669
|
+
const error = `vault secret "${target.secretName}" is missing`;
|
|
2670
|
+
await (0, import_crm4.recordDeliveryAttempt)(crmDeps3, {
|
|
2671
|
+
recordId: record.id,
|
|
2672
|
+
targetId: target.id,
|
|
2673
|
+
status: "failed",
|
|
2674
|
+
payloadVersion: 2,
|
|
2675
|
+
error
|
|
2676
|
+
});
|
|
2677
|
+
return { id: target.id, name: target.name, ok: false, error };
|
|
2678
|
+
}
|
|
2679
|
+
let payload;
|
|
2680
|
+
try {
|
|
2681
|
+
payload = sharedRecordFromCrm(ctx.chapter.crm, record, target, ctx.chapter.id);
|
|
2682
|
+
} catch (err) {
|
|
2683
|
+
return {
|
|
2684
|
+
id: target.id,
|
|
2685
|
+
name: target.name,
|
|
2686
|
+
ok: false,
|
|
2687
|
+
error: err instanceof Error ? err.message : "record is not shareable"
|
|
2688
|
+
};
|
|
2689
|
+
}
|
|
2690
|
+
const payloadBody = JSON.stringify(payload);
|
|
2691
|
+
const destination = new URL("/api/network/shared", target.url);
|
|
2692
|
+
try {
|
|
2693
|
+
const signed = await (0, import_db3.signFederatedRequest)({
|
|
2694
|
+
secret,
|
|
2695
|
+
sender: ctx.chapter.id,
|
|
2696
|
+
method: "POST",
|
|
2697
|
+
url: destination,
|
|
2698
|
+
body: payloadBody
|
|
2699
|
+
});
|
|
2700
|
+
const res = await fetchNetworkTarget(env, target, destination, {
|
|
2701
|
+
method: "POST",
|
|
2702
|
+
headers: { ...signed, "content-type": "application/json" },
|
|
2703
|
+
body: payloadBody,
|
|
2704
|
+
signal: AbortSignal.timeout(1e4)
|
|
2705
|
+
});
|
|
2706
|
+
const responseBody = await res.json().catch(() => ({}));
|
|
2707
|
+
if (!res.ok) {
|
|
2708
|
+
const error = responseBody.error ?? "follower rejected the record";
|
|
2709
|
+
await (0, import_crm4.recordDeliveryAttempt)(crmDeps3, {
|
|
2710
|
+
recordId: record.id,
|
|
2711
|
+
targetId: target.id,
|
|
2712
|
+
status: "failed",
|
|
2713
|
+
payloadVersion: 2,
|
|
2714
|
+
error
|
|
2715
|
+
});
|
|
2716
|
+
return {
|
|
2717
|
+
id: target.id,
|
|
2718
|
+
name: target.name,
|
|
2719
|
+
ok: false,
|
|
2720
|
+
status: res.status,
|
|
2721
|
+
error
|
|
2722
|
+
};
|
|
2723
|
+
}
|
|
2724
|
+
await (0, import_crm4.recordDeliveryAttempt)(crmDeps3, {
|
|
2725
|
+
recordId: record.id,
|
|
2726
|
+
targetId: target.id,
|
|
2727
|
+
status: "delivered",
|
|
2728
|
+
payloadVersion: 2,
|
|
2729
|
+
...responseBody.recordId ? { remoteRecordId: responseBody.recordId } : {}
|
|
2730
|
+
});
|
|
2731
|
+
return {
|
|
2732
|
+
id: target.id,
|
|
2733
|
+
name: target.name,
|
|
2734
|
+
ok: true,
|
|
2735
|
+
status: res.status,
|
|
2736
|
+
recordId: responseBody.recordId
|
|
2737
|
+
};
|
|
2738
|
+
} catch (err) {
|
|
2739
|
+
const error = err instanceof Error ? err.message : "delivery failed";
|
|
2740
|
+
await (0, import_crm4.recordDeliveryAttempt)(crmDeps3, {
|
|
2741
|
+
recordId: record.id,
|
|
2742
|
+
targetId: target.id,
|
|
2743
|
+
status: "failed",
|
|
2744
|
+
payloadVersion: 2,
|
|
2745
|
+
error
|
|
2746
|
+
});
|
|
2747
|
+
return { id: target.id, name: target.name, ok: false, error };
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
|
|
2751
|
+
// src/worker-routes-network.ts
|
|
2642
2752
|
async function gate4(req, env, ctx) {
|
|
2643
2753
|
const db = ctx.makeDb(env);
|
|
2644
2754
|
const user = await ctx.verifyUser(req, env);
|
|
@@ -2664,10 +2774,10 @@ var handleNetworkSnapshot = async (req, url, env, ctx) => {
|
|
|
2664
2774
|
const db = ctx.makeDb(env);
|
|
2665
2775
|
const secret = await getVaultSecret(db, "network_share_secret");
|
|
2666
2776
|
if (!secret) return json({ error: "unauthorized" }, 401);
|
|
2667
|
-
const verified = await (0,
|
|
2777
|
+
const verified = await (0, import_db4.verifyFederatedRequest)(req, { secret });
|
|
2668
2778
|
if (!verified.ok) return json({ error: "unauthorized", reason: verified.reason }, 401);
|
|
2669
2779
|
const types = await Promise.all(
|
|
2670
|
-
Object.keys(ctx.chapter.crm.config.types).map((type) => (0,
|
|
2780
|
+
Object.keys(ctx.chapter.crm.config.types).map((type) => (0, import_crm5.typeSummary)({ crm: ctx.chapter.crm, db }, type))
|
|
2671
2781
|
);
|
|
2672
2782
|
const snapshot = {
|
|
2673
2783
|
version: 1,
|
|
@@ -2677,18 +2787,21 @@ var handleNetworkSnapshot = async (req, url, env, ctx) => {
|
|
|
2677
2787
|
};
|
|
2678
2788
|
return json(snapshot);
|
|
2679
2789
|
};
|
|
2680
|
-
async function snapshotOne(db, ctx, target) {
|
|
2790
|
+
async function snapshotOne(db, env, ctx, target) {
|
|
2681
2791
|
const secret = await getVaultSecret(db, target.secretName);
|
|
2682
2792
|
if (!secret) return { id: target.id, name: target.name, url: target.url, available: false, error: "edge secret is missing" };
|
|
2683
2793
|
const destination = new URL("/api/network/snapshot", target.url);
|
|
2684
2794
|
try {
|
|
2685
|
-
const headers = await (0,
|
|
2795
|
+
const headers = await (0, import_db4.signFederatedRequest)({
|
|
2686
2796
|
secret,
|
|
2687
2797
|
sender: ctx.chapter.id,
|
|
2688
2798
|
method: "GET",
|
|
2689
2799
|
url: destination
|
|
2690
2800
|
});
|
|
2691
|
-
const response = await
|
|
2801
|
+
const response = await fetchNetworkTarget(env, target, destination, {
|
|
2802
|
+
headers,
|
|
2803
|
+
signal: AbortSignal.timeout(1e4)
|
|
2804
|
+
});
|
|
2692
2805
|
const body = await response.json().catch(() => null);
|
|
2693
2806
|
if (!response.ok || !body || !("version" in body) || body.version !== 1 || !("site" in body) || body.site.id !== target.id || !Array.isArray(body.types)) {
|
|
2694
2807
|
const upstream = body && "error" in body && typeof body.error === "string" ? body.error : void 0;
|
|
@@ -2723,7 +2836,7 @@ var handleAdminNetworkRollup = async (req, url, env, ctx) => {
|
|
|
2723
2836
|
const got = await gate4(req, env, ctx);
|
|
2724
2837
|
if ("response" in got) return got.response;
|
|
2725
2838
|
const targets = await Promise.all(
|
|
2726
|
-
ctx.chapter.network.targets.map((target) => snapshotOne(got.db, ctx, target))
|
|
2839
|
+
ctx.chapter.network.targets.map((target) => snapshotOne(got.db, env, ctx, target))
|
|
2727
2840
|
);
|
|
2728
2841
|
const byType = /* @__PURE__ */ new Map();
|
|
2729
2842
|
for (const target of targets) {
|
|
@@ -2745,74 +2858,6 @@ var handleAdminNetworkRollup = async (req, url, env, ctx) => {
|
|
|
2745
2858
|
};
|
|
2746
2859
|
return json(rollup);
|
|
2747
2860
|
};
|
|
2748
|
-
async function pushOne(db, ctx, target, record) {
|
|
2749
|
-
const secret = await getVaultSecret(db, target.secretName);
|
|
2750
|
-
const crmDeps3 = { crm: ctx.chapter.crm, db, now: () => Date.now(), newId: () => crypto.randomUUID() };
|
|
2751
|
-
if (!secret) {
|
|
2752
|
-
const error = `vault secret "${target.secretName}" is missing`;
|
|
2753
|
-
await (0, import_crm4.recordDeliveryAttempt)(crmDeps3, {
|
|
2754
|
-
recordId: record.id,
|
|
2755
|
-
targetId: target.id,
|
|
2756
|
-
status: "failed",
|
|
2757
|
-
payloadVersion: 2,
|
|
2758
|
-
error
|
|
2759
|
-
});
|
|
2760
|
-
return { id: target.id, name: target.name, ok: false, error };
|
|
2761
|
-
}
|
|
2762
|
-
let payload;
|
|
2763
|
-
try {
|
|
2764
|
-
payload = sharedRecordFromCrm(ctx.chapter.crm, record, target, ctx.chapter.id);
|
|
2765
|
-
} catch (err) {
|
|
2766
|
-
return { id: target.id, name: target.name, ok: false, error: err instanceof Error ? err.message : "record is not shareable" };
|
|
2767
|
-
}
|
|
2768
|
-
const payloadBody = JSON.stringify(payload);
|
|
2769
|
-
const destination = new URL("/api/network/shared", target.url);
|
|
2770
|
-
try {
|
|
2771
|
-
const signed = await (0, import_db3.signFederatedRequest)({
|
|
2772
|
-
secret,
|
|
2773
|
-
sender: ctx.chapter.id,
|
|
2774
|
-
method: "POST",
|
|
2775
|
-
url: destination,
|
|
2776
|
-
body: payloadBody
|
|
2777
|
-
});
|
|
2778
|
-
const res = await fetch(destination, {
|
|
2779
|
-
method: "POST",
|
|
2780
|
-
headers: { ...signed, "content-type": "application/json" },
|
|
2781
|
-
body: payloadBody,
|
|
2782
|
-
signal: AbortSignal.timeout(1e4)
|
|
2783
|
-
});
|
|
2784
|
-
const responseBody = await res.json().catch(() => ({}));
|
|
2785
|
-
if (!res.ok) {
|
|
2786
|
-
const error = responseBody.error ?? "follower rejected the record";
|
|
2787
|
-
await (0, import_crm4.recordDeliveryAttempt)(crmDeps3, {
|
|
2788
|
-
recordId: record.id,
|
|
2789
|
-
targetId: target.id,
|
|
2790
|
-
status: "failed",
|
|
2791
|
-
payloadVersion: 2,
|
|
2792
|
-
error
|
|
2793
|
-
});
|
|
2794
|
-
return { id: target.id, name: target.name, ok: false, status: res.status, error };
|
|
2795
|
-
}
|
|
2796
|
-
await (0, import_crm4.recordDeliveryAttempt)(crmDeps3, {
|
|
2797
|
-
recordId: record.id,
|
|
2798
|
-
targetId: target.id,
|
|
2799
|
-
status: "delivered",
|
|
2800
|
-
payloadVersion: 2,
|
|
2801
|
-
...responseBody.recordId ? { remoteRecordId: responseBody.recordId } : {}
|
|
2802
|
-
});
|
|
2803
|
-
return { id: target.id, name: target.name, ok: true, status: res.status, recordId: responseBody.recordId };
|
|
2804
|
-
} catch (err) {
|
|
2805
|
-
const error = err instanceof Error ? err.message : "delivery failed";
|
|
2806
|
-
await (0, import_crm4.recordDeliveryAttempt)(crmDeps3, {
|
|
2807
|
-
recordId: record.id,
|
|
2808
|
-
targetId: target.id,
|
|
2809
|
-
status: "failed",
|
|
2810
|
-
payloadVersion: 2,
|
|
2811
|
-
error
|
|
2812
|
-
});
|
|
2813
|
-
return { id: target.id, name: target.name, ok: false, error };
|
|
2814
|
-
}
|
|
2815
|
-
}
|
|
2816
2861
|
var handleAdminNetworkPush = async (req, url, env, ctx) => {
|
|
2817
2862
|
if (req.method !== "POST" || url.pathname !== "/api/admin/network/push") return null;
|
|
2818
2863
|
const got = await gate4(req, env, ctx);
|
|
@@ -2830,16 +2875,16 @@ var handleAdminNetworkPush = async (req, url, env, ctx) => {
|
|
|
2830
2875
|
if (requested.size !== body.targetIds.length) return json({ error: "targetIds must contain unique strings" }, 400);
|
|
2831
2876
|
const targets = ctx.chapter.network.targets.filter((target) => requested.has(target.id));
|
|
2832
2877
|
if (targets.length !== requested.size) return json({ error: "one or more targetIds are not configured" }, 400);
|
|
2833
|
-
const record = await (0,
|
|
2878
|
+
const record = await (0, import_crm5.getRecord)({ crm: ctx.chapter.crm, db: got.db }, body.recordId);
|
|
2834
2879
|
if (!record) return json({ error: "record not found" }, 404);
|
|
2835
2880
|
const results = await Promise.all(
|
|
2836
|
-
targets.map((target) =>
|
|
2881
|
+
targets.map((target) => pushNetworkRecord(got.db, env, ctx, target, record))
|
|
2837
2882
|
);
|
|
2838
2883
|
return json({ ok: results.every((result) => result.ok), results });
|
|
2839
2884
|
};
|
|
2840
2885
|
|
|
2841
2886
|
// src/worker-routes-formation.ts
|
|
2842
|
-
var
|
|
2887
|
+
var import_crm6 = require("@odla-ai/crm");
|
|
2843
2888
|
|
|
2844
2889
|
// src/formation.ts
|
|
2845
2890
|
function formationFields(crm, formation) {
|
|
@@ -2905,7 +2950,7 @@ var handleFormation = async (req, url, env, ctx) => {
|
|
|
2905
2950
|
const db = ctx.makeDb(env);
|
|
2906
2951
|
const id = submissionId ? await applicationIdForSubmission(`formation:${ctx.chapter.id}:${submissionId}`) : crypto.randomUUID();
|
|
2907
2952
|
try {
|
|
2908
|
-
const created = await (0,
|
|
2953
|
+
const created = await (0, import_crm6.createRecord)(
|
|
2909
2954
|
{
|
|
2910
2955
|
crm: ctx.chapter.crm,
|
|
2911
2956
|
db,
|