@undefineds.co/xpod 0.3.71-rc.8 → 0.3.71

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 (48) hide show
  1. package/dist/api/ai-gateway/connect/index.d.ts +2 -0
  2. package/dist/api/ai-gateway/connect/index.js +87 -24
  3. package/dist/api/ai-gateway/connect/index.js.map +1 -1
  4. package/dist/api/ai-gateway/pod/HostedPodDataAccess.js +2 -2
  5. package/dist/api/ai-gateway/pod/HostedPodDataAccess.js.map +1 -1
  6. package/dist/api/container/common.js +1 -1
  7. package/dist/api/container/common.js.map +1 -1
  8. package/dist/api/container/routes.js +1 -1
  9. package/dist/api/container/routes.js.map +1 -1
  10. package/dist/api/handlers/AiGatewayManagementHandler.js +28 -12
  11. package/dist/api/handlers/AiGatewayManagementHandler.js.map +1 -1
  12. package/dist/api/handlers/PodSettingsHandler.d.ts +12 -19
  13. package/dist/api/handlers/PodSettingsHandler.js +12 -51
  14. package/dist/api/handlers/PodSettingsHandler.js.map +1 -1
  15. package/dist/http/InternalPodDataHttpHandler.d.ts +3 -1
  16. package/dist/http/InternalPodDataHttpHandler.js +48 -7
  17. package/dist/http/InternalPodDataHttpHandler.js.map +1 -1
  18. package/dist/http/InternalPodDataHttpHandler.jsonld +10 -2
  19. package/dist/runtime/GatewayAdminProxyAuth.d.ts +1 -1
  20. package/dist/runtime/GatewayAdminProxyAuth.js +1 -1
  21. package/dist/runtime/GatewayAdminProxyAuth.js.map +1 -1
  22. package/dist/runtime/Proxy.d.ts +1 -0
  23. package/dist/runtime/Proxy.js +22 -0
  24. package/dist/runtime/Proxy.js.map +1 -1
  25. package/package.json +1 -1
  26. package/static/dashboard/assets/{NetworkPage-CXjiUMR1.js → NetworkPage-CsERgA2D.js} +1 -1
  27. package/static/dashboard/assets/{PaneListHeader-BSipfl0W.js → PaneListHeader-WJWFvTKY.js} +1 -1
  28. package/static/dashboard/assets/{PodPage-Bd3Xhmp-.js → PodPage-Bo_NbnK1.js} +1 -1
  29. package/static/dashboard/assets/{ServicesPage-CI3jWZGe.js → ServicesPage-CrNDXQlg.js} +1 -1
  30. package/static/dashboard/assets/{card-z5BV5hTo.js → card-Cjax171A.js} +1 -1
  31. package/static/dashboard/assets/{dashboard-CSrqAv2L.js → dashboard-CaE1mRUL.js} +4 -4
  32. package/static/dashboard/assets/{database-Ct5ZPe6L.js → database-B0sGiSz2.js} +1 -1
  33. package/static/dashboard/assets/{external-link-B7wD1hkm.js → external-link-C_ANDdCY.js} +1 -1
  34. package/static/dashboard/assets/{index-tOBaUnM1.js → index-CDoxbvUP.js} +1 -1
  35. package/static/dashboard/assets/{refresh-cw-CFDZPaE8.js → refresh-cw-DHzHxCme.js} +1 -1
  36. package/static/dashboard/assets/{services-status-context-DN1Icg4A.js → services-status-context-ukghtkFD.js} +1 -1
  37. package/static/dashboard/dashboard.html +1 -1
  38. package/static/settings/assets/ModelsPage-ClTKzRGm.js +1 -0
  39. package/static/settings/assets/{PaneListHeader-BtON8Z5Q.js → PaneListHeader-DTVY4Ig2.js} +1 -1
  40. package/static/settings/assets/{PodPage-9LGuOloQ.js → PodPage-L_JAOD-r.js} +1 -1
  41. package/static/settings/assets/{ServicesPage-ZoT9-B_0.js → ServicesPage-BwLxrSWw.js} +1 -1
  42. package/static/settings/assets/{SettingsPage-Bj4lB3mq.js → SettingsPage-DUGHDPQx.js} +1 -1
  43. package/static/settings/assets/{card-CCGngjas.js → card-BZF0jSa_.js} +1 -1
  44. package/static/settings/assets/{services-status-context-CBfImxL_.js → services-status-context-BnbZHZnu.js} +1 -1
  45. package/static/settings/assets/{settings-yUyFIJxi.js → settings-BN7FyntE.js} +4 -4
  46. package/static/settings/assets/{workspace-layout-B0wJpPze.js → workspace-layout-jzYHoh3_.js} +1 -1
  47. package/static/settings/settings.html +1 -1
  48. package/static/settings/assets/ModelsPage-D87RrLB0.js +0 -1
@@ -125,6 +125,7 @@ type ConnectedCredentialDb = {
125
125
  };
126
126
  };
127
127
  findById<TRow>(resource: typeof credentialResource, id: string): Promise<TRow | null>;
128
+ deleteById(resource: typeof credentialResource, id: string): Promise<boolean>;
128
129
  updateById<TRow>(resource: typeof credentialResource, id: string, patch: unknown): Promise<TRow | null>;
129
130
  update(resource: typeof credentialResource): {
130
131
  set(patch: unknown): {
@@ -141,6 +142,7 @@ export interface PodConnectedCredentialRepositoryOptions {
141
142
  providerIds?: string[];
142
143
  dbFactory?: (input: {
143
144
  owner: string;
145
+ podUrl: string;
144
146
  auth?: AuthContext;
145
147
  fetch: typeof fetch;
146
148
  credential?: typeof credentialResource;
@@ -43,7 +43,17 @@ class PodConnectedCredentialRepository {
43
43
  }
44
44
  }))).filter((row) => row !== null);
45
45
  return rows
46
- .map((row) => recordFromCredentialRow(row, input.webId))
46
+ .flatMap((row) => {
47
+ try {
48
+ return [recordFromCredentialRow(row, input.webId)];
49
+ }
50
+ catch (error) {
51
+ if (error instanceof PlaintextCredentialPayload_1.UnsupportedCredentialStorageModeError) {
52
+ return [];
53
+ }
54
+ throw error;
55
+ }
56
+ })
47
57
  .filter((record) => record.webId === input.webId)
48
58
  .filter((record) => record.deployment === input.deployment)
49
59
  .filter((record) => record.status === 'active')
@@ -69,7 +79,11 @@ class PodConnectedCredentialRepository {
69
79
  const { db, credential } = await this.dbForOwner(record.webId, context?.auth);
70
80
  const existing = await db.findById(credential, record.id);
71
81
  const existingVersion = existing ? versionFromRow(existing) : 0;
72
- if (record.expectedVersion !== undefined && record.expectedVersion !== existingVersion) {
82
+ const replacesUnsupportedRecord = Boolean(existing)
83
+ && stringFrom(existing?.storageMode) !== PlaintextCredentialPayload_1.PLAINTEXT_CREDENTIAL_STORAGE_MODE;
84
+ if (!replacesUnsupportedRecord
85
+ && record.expectedVersion !== undefined
86
+ && record.expectedVersion !== existingVersion) {
73
87
  throw new Error('credential_version_conflict');
74
88
  }
75
89
  const nextVersion = existingVersion + 1;
@@ -78,10 +92,35 @@ class PodConnectedCredentialRepository {
78
92
  version: nextVersion,
79
93
  });
80
94
  if (existing) {
81
- const updated = await db.updateById(credential, record.id, row);
82
- return recordFromCredentialRow(updated ?? row, record.webId);
95
+ try {
96
+ const deleted = await db.deleteById(credential, record.id);
97
+ if (!deleted) {
98
+ throw new Error('exact credential resource was not deleted');
99
+ }
100
+ }
101
+ catch (error) {
102
+ throw credentialPersistenceError('replace-delete', error);
103
+ }
104
+ try {
105
+ await db.insert(credential).values(row).execute();
106
+ }
107
+ catch (error) {
108
+ try {
109
+ await db.insert(credential).values(existing).execute();
110
+ }
111
+ catch (rollbackError) {
112
+ throw credentialPersistenceError('replace-insert-rollback', rollbackError);
113
+ }
114
+ throw credentialPersistenceError('replace-insert', error);
115
+ }
116
+ return recordFromCredentialRow(row, record.webId);
117
+ }
118
+ try {
119
+ await db.insert(credential).values(row).execute();
120
+ }
121
+ catch (error) {
122
+ throw credentialPersistenceError('insert', error);
83
123
  }
84
- await db.insert(credential).values(row).execute();
85
124
  return recordFromCredentialRow(row, record.webId);
86
125
  }
87
126
  async markReauthRequired(input) {
@@ -119,7 +158,8 @@ class PodConnectedCredentialRepository {
119
158
  const trustedFetch = await this.resolveTrustedFetch(owner, auth);
120
159
  const credential = (0, drizzle_solid_1.alias)(this.credentialTemplate, 'credential');
121
160
  const aiProvider = (0, drizzle_solid_1.alias)(this.aiProviderTemplate, 'aiProvider');
122
- const db = await this.dbFactory({ owner, auth, fetch: trustedFetch, credential, aiProvider });
161
+ const podUrl = podUrlFromHostedWebId(owner);
162
+ const db = await this.dbFactory({ owner, podUrl, auth, fetch: trustedFetch, credential, aiProvider });
123
163
  await db.init?.(credential, aiProvider);
124
164
  return { db, credential };
125
165
  }
@@ -643,17 +683,25 @@ class ProviderConnectService {
643
683
  }
644
684
  async listProviders(input) {
645
685
  return Promise.all(this.registry.listProviders().map(async (descriptor) => {
646
- const credential = this.credentialRepository?.getCredential
647
- ? await this.credentialRepository.getCredential({
648
- ...input,
649
- provider: descriptor.id,
650
- })
651
- : await this.credentialRepository?.getActiveCredential({
652
- ...input,
653
- provider: descriptor.id,
654
- });
655
- const active = credential?.status === 'active';
656
- const reauthRequired = active && credential.reauthRequired === true;
686
+ let credential;
687
+ try {
688
+ credential = this.credentialRepository?.getCredential
689
+ ? await this.credentialRepository.getCredential({
690
+ ...input,
691
+ provider: descriptor.id,
692
+ })
693
+ : await this.credentialRepository?.getActiveCredential({
694
+ ...input,
695
+ provider: descriptor.id,
696
+ });
697
+ }
698
+ catch (error) {
699
+ if (!(error instanceof PlaintextCredentialPayload_1.UnsupportedCredentialStorageModeError)) {
700
+ throw error;
701
+ }
702
+ }
703
+ const activeCredential = credential?.status === 'active' ? credential : undefined;
704
+ const reauthRequired = activeCredential?.reauthRequired === true;
657
705
  const modes = Array.from(new Set([
658
706
  ...descriptor.authModes.filter((mode) => mode !== 'connectUnsupported'),
659
707
  ...(descriptor.connect?.apiKeyManagementSupported ? ['apiKey'] : []),
@@ -662,15 +710,15 @@ class ProviderConnectService {
662
710
  provider: descriptor.id,
663
711
  status: reauthRequired
664
712
  ? 'reauthRequired'
665
- : active
713
+ : activeCredential
666
714
  ? 'connected'
667
715
  : 'disconnected',
668
- authMode: active ? credential.authMode : undefined,
669
- accountLabel: active ? credential.accountLabel : undefined,
670
- expiresAt: active ? credential.expiresAt?.toISOString() : undefined,
716
+ authMode: activeCredential?.authMode,
717
+ accountLabel: activeCredential?.accountLabel,
718
+ expiresAt: activeCredential?.expiresAt?.toISOString(),
671
719
  reauthRequired: reauthRequired || undefined,
672
- credentialIri: active ? credential.credentialIri : undefined,
673
- version: active ? credential.version : undefined,
720
+ credentialIri: activeCredential?.credentialIri,
721
+ version: activeCredential?.version,
674
722
  connect: {
675
723
  modes,
676
724
  configured: descriptor.connect?.configured !== false,
@@ -754,14 +802,26 @@ function createDefaultConnectedCredentialDb(input) {
754
802
  const aiProvider = input.aiProvider ?? models_1.aiProviderResource;
755
803
  return Promise.resolve((0, drizzle_solid_1.drizzle)({
756
804
  fetch: input.fetch,
757
- info: { webId: input.owner, isLoggedIn: true },
805
+ info: { webId: input.owner, podUrl: input.podUrl, isLoggedIn: true },
758
806
  }, {
759
807
  schema: {
760
808
  credential,
761
809
  aiProvider,
762
810
  },
811
+ podUrl: input.podUrl,
763
812
  }));
764
813
  }
814
+ function podUrlFromHostedWebId(webId) {
815
+ const ownerUrl = new URL(webId);
816
+ if (ownerUrl.hash !== '#me' || !ownerUrl.pathname.endsWith('/profile/card')) {
817
+ throw new Error('hosted_pod_owner_url_invalid');
818
+ }
819
+ const podPath = ownerUrl.pathname.slice(0, -'profile/card'.length);
820
+ if (!podPath || !podPath.endsWith('/')) {
821
+ throw new Error('hosted_pod_owner_url_invalid');
822
+ }
823
+ return new URL(podPath, ownerUrl.origin).href;
824
+ }
765
825
  function credentialRowFromRecord(record) {
766
826
  return {
767
827
  id: record.id,
@@ -825,6 +885,9 @@ function providerFromRelation(value) {
825
885
  const provider = fileName.replace(/\.ttl$/u, '');
826
886
  return provider ? normalizeProvider(provider) : undefined;
827
887
  }
888
+ function credentialPersistenceError(stage, cause) {
889
+ return new Error(`credential_persistence_failed:${stage}`, { cause });
890
+ }
828
891
  function isPodResourceNotFound(error) {
829
892
  if (!(error instanceof Error)) {
830
893
  return false;