@salsita-ai/contracts 0.0.0-stage → 0.49.0-develop.2a2e8d75e7
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/CHANGELOG.md +419 -0
- package/LICENSE +61 -0
- package/README.md +28 -2
- package/dist/api/access-level.d.ts +7 -0
- package/dist/api/access-level.js +1 -0
- package/dist/api/access-token.d.ts +6 -0
- package/dist/api/access-token.js +1 -0
- package/dist/api/index.d.ts +4 -0
- package/dist/api/index.js +1 -0
- package/dist/api/session-role.d.ts +8 -0
- package/dist/api/session-role.js +1 -0
- package/dist/api/session-token.d.ts +22 -0
- package/dist/api/session-token.js +1 -0
- package/dist/assistant/browser-details-tool.d.ts +16 -0
- package/dist/assistant/browser-details-tool.js +1 -0
- package/dist/assistant/deployment-assistant.d.ts +84 -0
- package/dist/assistant/deployment-assistant.js +1 -0
- package/dist/assistant/graphql-tools.d.ts +120 -0
- package/dist/assistant/graphql-tools.js +1 -0
- package/dist/assistant/index.d.ts +6 -0
- package/dist/assistant/index.js +1 -0
- package/dist/assistant/message-metadata.d.ts +17 -0
- package/dist/assistant/message-metadata.js +1 -0
- package/dist/chat/api.d.ts +52 -0
- package/dist/chat/api.js +1 -0
- package/dist/chat/completions/messages.d.ts +3 -0
- package/dist/chat/completions/messages.js +1 -0
- package/dist/chat/completions/types.d.ts +28 -0
- package/dist/chat/completions/types.js +1 -0
- package/dist/chat/functions/augmentations.d.ts +3 -0
- package/dist/chat/functions/augmentations.js +1 -0
- package/dist/chat/functions/create.d.ts +5 -0
- package/dist/chat/functions/create.js +1 -0
- package/dist/chat/functions/process.d.ts +14 -0
- package/dist/chat/functions/process.js +1 -0
- package/dist/chat/functions/types.d.ts +21 -0
- package/dist/chat/functions/types.js +1 -0
- package/dist/chat/functions/validate.d.ts +1 -0
- package/dist/chat/functions/validate.js +2 -0
- package/dist/chat/index.d.ts +10 -0
- package/dist/chat/index.js +1 -0
- package/dist/chat/utils/types.d.ts +1 -0
- package/dist/chat/utils/types.js +1 -0
- package/dist/clerk/clerk-backend-api-client.d.ts +129 -0
- package/dist/clerk/clerk-backend-api-client.js +1 -0
- package/dist/clerk/clerk-backend-api-types.d.ts +740 -0
- package/dist/clerk/clerk-backend-api-types.js +1 -0
- package/dist/clerk/clerk-session-token.d.ts +28 -0
- package/dist/clerk/clerk-session-token.js +1 -0
- package/dist/clerk/clerk-token-service.d.ts +15 -0
- package/dist/clerk/clerk-token-service.js +1 -0
- package/dist/clerk/index.d.ts +4 -0
- package/dist/clerk/index.js +1 -0
- package/dist/domain/deployments/ai-image-domain.d.ts +10 -0
- package/dist/domain/deployments/ai-image-domain.js +1 -0
- package/dist/domain/deployments/api-token-domain.d.ts +8 -0
- package/dist/domain/deployments/api-token-domain.js +1 -0
- package/dist/domain/deployments/configuration-schema-domain.d.ts +22 -0
- package/dist/domain/deployments/configuration-schema-domain.js +1 -0
- package/dist/domain/deployments/customer-domain.d.ts +69 -0
- package/dist/domain/deployments/customer-domain.js +1 -0
- package/dist/domain/deployments/deployment-build-domain.d.ts +78 -0
- package/dist/domain/deployments/deployment-build-domain.js +1 -0
- package/dist/domain/deployments/deployment-domain.d.ts +126 -0
- package/dist/domain/deployments/deployment-domain.js +1 -0
- package/dist/domain/deployments/embedding-domain.d.ts +9 -0
- package/dist/domain/deployments/embedding-domain.js +1 -0
- package/dist/domain/deployments/environment-domain.d.ts +107 -0
- package/dist/domain/deployments/environment-domain.js +1 -0
- package/dist/domain/deployments/image-render-domain.d.ts +22 -0
- package/dist/domain/deployments/image-render-domain.js +1 -0
- package/dist/domain/deployments/index.d.ts +14 -0
- package/dist/domain/deployments/index.js +1 -0
- package/dist/domain/deployments/oauth-connection-domain.d.ts +62 -0
- package/dist/domain/deployments/oauth-connection-domain.js +1 -0
- package/dist/domain/deployments/oauth-provider-domain.d.ts +23 -0
- package/dist/domain/deployments/oauth-provider-domain.js +1 -0
- package/dist/domain/deployments/project-domain.d.ts +26 -0
- package/dist/domain/deployments/project-domain.js +1 -0
- package/dist/domain/deployments/sdk-builder-setup-domain.d.ts +13 -0
- package/dist/domain/deployments/sdk-builder-setup-domain.js +1 -0
- package/dist/domain/deployments/session-domain.d.ts +20 -0
- package/dist/domain/deployments/session-domain.js +1 -0
- package/dist/domain/feedback/feedback-domain.d.ts +55 -0
- package/dist/domain/feedback/feedback-domain.js +1 -0
- package/dist/domain/feedback/index.d.ts +1 -0
- package/dist/domain/feedback/index.js +1 -0
- package/dist/domain/index.d.ts +3 -0
- package/dist/domain/index.js +1 -0
- package/dist/domain/product-configurations/configurations-domain.d.ts +113 -0
- package/dist/domain/product-configurations/configurations-domain.js +1 -0
- package/dist/domain/product-configurations/index.d.ts +1 -0
- package/dist/domain/product-configurations/index.js +1 -0
- package/dist/webhook/core/index.d.ts +3 -0
- package/dist/webhook/core/index.js +1 -0
- package/dist/webhook/core/task-resource.d.ts +80 -0
- package/dist/webhook/core/task-resource.js +1 -0
- package/dist/webhook/core/task-type.d.ts +18 -0
- package/dist/webhook/core/task-type.js +1 -0
- package/dist/webhook/core/template.d.ts +65 -0
- package/dist/webhook/core/template.js +1 -0
- package/dist/webhook/empty-xlsx.d.ts +10 -0
- package/dist/webhook/empty-xlsx.js +1 -0
- package/dist/webhook/excel-workbook-client.d.ts +78 -0
- package/dist/webhook/excel-workbook-client.js +1 -0
- package/dist/webhook/google-sheets-client.d.ts +23 -0
- package/dist/webhook/google-sheets-client.js +1 -0
- package/dist/webhook/implementation/index.d.ts +4 -0
- package/dist/webhook/implementation/index.js +1 -0
- package/dist/webhook/implementation/webhook-api-types.d.ts +302 -0
- package/dist/webhook/implementation/webhook-api-types.js +1 -0
- package/dist/webhook/implementation/webhook-client.d.ts +85 -0
- package/dist/webhook/implementation/webhook-client.js +1 -0
- package/dist/webhook/implementation/webhook-routing.d.ts +30 -0
- package/dist/webhook/implementation/webhook-routing.js +1 -0
- package/dist/webhook/implementation/webhook-tunnel-types.d.ts +114 -0
- package/dist/webhook/implementation/webhook-tunnel-types.js +1 -0
- package/dist/webhook/index.d.ts +7 -0
- package/dist/webhook/index.js +1 -0
- package/dist/webhook/spreadsheet-adapter-factory.d.ts +10 -0
- package/dist/webhook/spreadsheet-adapter-factory.js +1 -0
- package/dist/webhook/spreadsheet-adapter.d.ts +94 -0
- package/dist/webhook/spreadsheet-adapter.js +1 -0
- package/dist/webhook/tasks/call-lambda-back-task.d.ts +22 -0
- package/dist/webhook/tasks/call-lambda-back-task.js +1 -0
- package/dist/webhook/tasks/edit-google-spreadsheet-task.d.ts +48 -0
- package/dist/webhook/tasks/edit-google-spreadsheet-task.js +1 -0
- package/dist/webhook/tasks/finalize-task.d.ts +184 -0
- package/dist/webhook/tasks/finalize-task.js +1 -0
- package/dist/webhook/tasks/generate-configuration-link-task.d.ts +56 -0
- package/dist/webhook/tasks/generate-configuration-link-task.js +1 -0
- package/dist/webhook/tasks/generate-csv-task.d.ts +30 -0
- package/dist/webhook/tasks/generate-csv-task.js +1 -0
- package/dist/webhook/tasks/generate-images-task.d.ts +404 -0
- package/dist/webhook/tasks/generate-images-task.js +1 -0
- package/dist/webhook/tasks/generate-pdf-task.d.ts +188 -0
- package/dist/webhook/tasks/generate-pdf-task.js +1 -0
- package/dist/webhook/tasks/index.d.ts +13 -0
- package/dist/webhook/tasks/index.js +1 -0
- package/dist/webhook/tasks/publish-revision-chunks-staged-task.d.ts +73 -0
- package/dist/webhook/tasks/publish-revision-chunks-staged-task.js +1 -0
- package/dist/webhook/tasks/publish-revision-chunks-task.d.ts +76 -0
- package/dist/webhook/tasks/publish-revision-chunks-task.js +1 -0
- package/dist/webhook/tasks/publish-revision-task.d.ts +38 -0
- package/dist/webhook/tasks/publish-revision-task.js +1 -0
- package/dist/webhook/tasks/send-email-task.d.ts +129 -0
- package/dist/webhook/tasks/send-email-task.js +1 -0
- package/dist/webhook/tasks/send-http-task.d.ts +27 -0
- package/dist/webhook/tasks/send-http-task.js +1 -0
- package/dist/webhook/tasks/woocommerce-add-to-cart-task.d.ts +91 -0
- package/dist/webhook/tasks/woocommerce-add-to-cart-task.js +1 -0
- package/dist/webhook/webhook-payload.d.ts +56 -0
- package/dist/webhook/webhook-payload.js +1 -0
- package/package.json +84 -3
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type CellValue, type ColumnMeta, type CreateSpreadsheetResult, type CreateWorkbookLocation, type LegendTabData, type SheetTabData, type SpreadsheetAdapter, type SpreadsheetFileRef, type SpreadsheetMeta } from './spreadsheet-adapter.js';
|
|
2
|
+
/** Folder visible in the picker — only relevant when browsing (not searching). */
|
|
3
|
+
export interface ExcelFolderRef {
|
|
4
|
+
readonly itemId: string;
|
|
5
|
+
readonly name: string;
|
|
6
|
+
}
|
|
7
|
+
/** Workbook the picker can select. */
|
|
8
|
+
export interface ExcelWorkbookRef {
|
|
9
|
+
readonly itemId: string;
|
|
10
|
+
readonly driveId: string;
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly webUrl: string | null;
|
|
13
|
+
readonly lastModified: string | null;
|
|
14
|
+
}
|
|
15
|
+
export interface ExcelListFilesResult {
|
|
16
|
+
readonly folders: readonly ExcelFolderRef[];
|
|
17
|
+
readonly files: readonly ExcelWorkbookRef[];
|
|
18
|
+
}
|
|
19
|
+
export interface ExcelSpreadsheetAdapterOptions {
|
|
20
|
+
/** Override for staging/test environments. Defaults to the production Microsoft Graph endpoint. */
|
|
21
|
+
readonly apiBaseUrl?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare class ExcelSpreadsheetAdapter implements SpreadsheetAdapter {
|
|
24
|
+
private readonly _apiBaseUrl;
|
|
25
|
+
constructor(options?: ExcelSpreadsheetAdapterOptions);
|
|
26
|
+
fetchMeta: (accessToken: string, ref: SpreadsheetFileRef) => Promise<SpreadsheetMeta>;
|
|
27
|
+
/**
|
|
28
|
+
* Resolves the SharePoint `webUrl` for a workbook so the studio can render
|
|
29
|
+
* a deep link to it. Microsoft Graph returns whatever URL is appropriate
|
|
30
|
+
* for the drive the item lives in — for SharePoint drives that's the
|
|
31
|
+
* Office Online "open in browser" link (or the plain file path), not a
|
|
32
|
+
* OneDrive URL. Returns `null` when the lookup fails so the UI can fall
|
|
33
|
+
* back to the site root link.
|
|
34
|
+
*/
|
|
35
|
+
fetchWebUrl: (accessToken: string, ref: SpreadsheetFileRef) => Promise<string | null>;
|
|
36
|
+
fetchTabHeaders: (accessToken: string, ref: SpreadsheetFileRef, tabName: string) => Promise<readonly string[]>;
|
|
37
|
+
fetchData: (accessToken: string, ref: SpreadsheetFileRef, tabNames: readonly string[], headerRowIndex?: number | null) => Promise<readonly SheetTabData[]>;
|
|
38
|
+
createWorkbook: (accessToken: string, title: string, headers: readonly string[], values?: ReadonlyArray<readonly CellValue[]>, columns?: readonly ColumnMeta[], dataTabName?: string, legendTab?: LegendTabData, location?: CreateWorkbookLocation) => Promise<CreateSpreadsheetResult>;
|
|
39
|
+
/**
|
|
40
|
+
* Lists folders and `.xlsx` workbooks in the SharePoint site's default
|
|
41
|
+
* document library. When `query` is non-empty, fetches root children and
|
|
42
|
+
* filters client-side — the Graph `search(q='...')` function endpoint
|
|
43
|
+
* returns 500 with `Sites.Selected` app-only auth because the SharePoint
|
|
44
|
+
* Search Service can't resolve scope without a user context (known
|
|
45
|
+
* limitation, not fixable client-side). When `parentItemId` is set (and
|
|
46
|
+
* `query` is empty), lists the children of that folder; otherwise lists
|
|
47
|
+
* the drive root.
|
|
48
|
+
*
|
|
49
|
+
* No pagination — Graph returns its first page (default 200 items).
|
|
50
|
+
* Client-side filter operates over that page, so deeply-buried files in
|
|
51
|
+
* very large libraries may not show up; admins should navigate by folder
|
|
52
|
+
* in that case.
|
|
53
|
+
*/
|
|
54
|
+
listFiles: (accessToken: string, siteId: string, params?: {
|
|
55
|
+
readonly parentItemId?: string;
|
|
56
|
+
readonly query?: string;
|
|
57
|
+
}) => Promise<ExcelListFilesResult>;
|
|
58
|
+
resetData: (accessToken: string, ref: SpreadsheetFileRef, tabNames: readonly string[], headers: readonly string[], values: ReadonlyArray<readonly CellValue[]>, columns?: readonly ColumnMeta[], legendTab?: LegendTabData) => Promise<void>;
|
|
59
|
+
private readonly _requireDriveId;
|
|
60
|
+
private readonly _workbookUrl;
|
|
61
|
+
private readonly _authHeaders;
|
|
62
|
+
private readonly _parseJsonResponse;
|
|
63
|
+
private readonly _parseGraphError;
|
|
64
|
+
private readonly _createWorkbookSession;
|
|
65
|
+
private readonly _closeWorkbookSession;
|
|
66
|
+
private readonly _escapeWorksheetName;
|
|
67
|
+
private readonly _fetchWorksheetNames;
|
|
68
|
+
private readonly _fetchWorksheetUsedRangeValues;
|
|
69
|
+
private readonly _columnIndexToLetter;
|
|
70
|
+
private readonly _buildRangeAddress;
|
|
71
|
+
private readonly _writeRowsToWorksheet;
|
|
72
|
+
private readonly _clearWorksheet;
|
|
73
|
+
private readonly _renameFirstWorksheet;
|
|
74
|
+
private readonly _ensureWorksheetExists;
|
|
75
|
+
private readonly _writeLegendWorksheet;
|
|
76
|
+
private readonly _writeWorksheetWithDefaults;
|
|
77
|
+
}
|
|
78
|
+
export declare const excelSpreadsheetAdapter: ExcelSpreadsheetAdapter;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{z as e}from"zod";import{EMPTY_XLSX_BYTES as t}from"./empty-xlsx.js";import{SpreadsheetAdapterError as r,normalizeCellOnWrite as s}from"./spreadsheet-adapter.js";let a=e.object({id:e.string(),name:e.string(),webUrl:e.string().optional(),lastModifiedDateTime:e.string().optional(),folder:e.object({childCount:e.number().optional()}).optional(),file:e.object({mimeType:e.string().optional()}).optional(),parentReference:e.object({driveId:e.string().optional()}).optional()}),o=e.object({webUrl:e.string().optional()}),i=e.object({value:e.array(a)}),n=e.object({id:e.string()}),h=e.object({value:e.array(e.object({name:e.string()}))}),d=e.object({values:e.array(e.array(e.unknown())).optional()});export class ExcelSpreadsheetAdapter{_apiBaseUrl;constructor(e={}){this._apiBaseUrl=e.apiBaseUrl??"https://graph.microsoft.com/v1.0"}fetchMeta=async(e,t)=>({tabs:await this._fetchWorksheetNames(e,this._requireDriveId(t))});fetchWebUrl=async(e,t)=>{let r=this._requireDriveId(t),s=await fetch(`${this._apiBaseUrl}/drives/${encodeURIComponent(r.driveId)}/items/${encodeURIComponent(r.itemId)}?$select=webUrl`,{headers:{Authorization:`Bearer ${e}`}});return s.ok?(await this._parseJsonResponse(s,o,"fetch workbook webUrl")).webUrl??null:null};fetchTabHeaders=async(e,t,r)=>(await this._fetchWorksheetUsedRangeValues(e,this._requireDriveId(t),r))[0]??[];fetchData=async(e,t,r,s)=>{let a=s??0,o=this._requireDriveId(t),i=await this._createWorkbookSession(e,o);try{let t=[];for(let s of r){let r=await this._fetchWorksheetUsedRangeValues(e,o,s,i),n=r[a]??[],h=r.slice(a+1);t.push({headers:n,rows:h})}return t}finally{await this._closeWorkbookSession(e,o,i)}};createWorkbook=async(e,r,s,o,i,n,h,d)=>{if(!d?.siteId)throw Error("Excel workbook creation requires a SharePoint site context (location.siteId). The studio's CreateSheetButton must pass the configured site's id when called for the Microsoft provider.");let l=r.endsWith(".xlsx")?r:`${r}.xlsx`,c=`${this._apiBaseUrl}/sites/${encodeURIComponent(d.siteId)}/drive/root:/${encodeURIComponent(l)}:/content`,p=await fetch(c,{method:"PUT",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},body:t});p.ok||await this._parseGraphError(p,`create workbook '${l}' in site`);let w=await this._parseJsonResponse(p,a,`create workbook '${l}'`);if(!w.parentReference?.driveId)throw Error("Created Excel workbook but Graph response did not include parentReference.driveId — this is unexpected. The workbook was created but cannot be addressed for follow-up writes.");let u={driveId:w.parentReference.driveId,itemId:w.id},k=n??"Sheet1",f=await this._createWorkbookSession(e,u);try{await this._renameFirstWorksheet(e,u,f,k),await this._writeWorksheetWithDefaults(e,u,f,k,s,o??[],i),h&&await this._writeLegendWorksheet(e,u,f,h)}finally{await this._closeWorkbookSession(e,u,f)}return{fileId:w.id,driveId:w.parentReference.driveId,title:w.name}};listFiles=async(e,t,r={})=>{let s=r.query?.trim().toLowerCase()??"",a=r.parentItemId?`/sites/${encodeURIComponent(t)}/drive/items/${encodeURIComponent(r.parentItemId)}/children`:`/sites/${encodeURIComponent(t)}/drive/root/children`,o=await fetch(`${this._apiBaseUrl}${a}`,{headers:{Authorization:`Bearer ${e}`}});o.ok||await this._parseGraphError(o,"list drive items");let n=await this._parseJsonResponse(o,i,"list drive items"),h=[],d=[];for(let e of n.value){if(""===s||e.name.toLowerCase().includes(s)){if(e.folder){""===s&&h.push({itemId:e.id,name:e.name});continue}e.file&&e.name.toLowerCase().endsWith(".xlsx")&&e.parentReference?.driveId&&d.push({itemId:e.id,driveId:e.parentReference.driveId,name:e.name,webUrl:e.webUrl??null,lastModified:e.lastModifiedDateTime??null})}}return{folders:h,files:d}};resetData=async(e,t,r,s,a,o,i)=>{let n=this._requireDriveId(t),h=await this._createWorkbookSession(e,n);try{for(let t of r)await this._ensureWorksheetExists(e,n,h,t),await this._clearWorksheet(e,n,h,t),await this._writeWorksheetWithDefaults(e,n,h,t,s,a,o);i&&await this._writeLegendWorksheet(e,n,h,i)}finally{await this._closeWorkbookSession(e,n,h)}};_requireDriveId=e=>{if(!e.driveId)throw Error("Excel workbook reference is missing driveId. Microsoft Graph requires both driveId and itemId. Make sure ConnectedDataConfig.driveId is set when provider is 'microsoft'.");return{driveId:e.driveId,itemId:e.fileId}};_workbookUrl=({driveId:e,itemId:t},r)=>`${this._apiBaseUrl}/drives/${encodeURIComponent(e)}/items/${encodeURIComponent(t)}/workbook${r}`;_authHeaders=(e,t)=>{let r={Authorization:`Bearer ${e}`,"Content-Type":"application/json"};return t&&(r["workbook-session-id"]=t),r};_parseJsonResponse=async(e,t,s)=>{let a=await e.json().catch(()=>null),o=t.safeParse(a);if(!o.success)throw new r({kind:"unknown",provider:"microsoft",status:e.status,action:s,bodyExcerpt:JSON.stringify(a).slice(0,500),message:`Microsoft Graph ${s} returned a response that does not match the expected shape — this likely means the Graph API contract has changed. Validation issues: ${o.error.issues.map(e=>`${e.path.join(".")}: ${e.message}`).join("; ")}`});return o.data};_parseGraphError=async(e,t)=>{let s=(await e.text().catch(()=>"")).slice(0,500),a=e.status,o=(e,o)=>{throw new r({kind:e,provider:"microsoft",status:a,action:t,bodyExcerpt:s,message:o})};return 401===a?o("auth",`Microsoft Graph ${t} failed with status 401. The Graph app token was rejected — it may have expired or been revoked. The server should refresh the app token; if this persists, re-check the customer's app client id/secret in the SharePoint wizard. Body: ${s}`):403===a?o("forbidden",`Microsoft Graph ${t} failed with status 403 (accessDenied). The app reached the SharePoint site but does not have the required role. Most common cause: the per-site Sites.Selected grant was issued with roles: ["read"] only — writes require ["read", "write"]. A tenant admin must re-run POST /sites/{hostname}:{path}:/permissions with both roles in the body, or PATCH the existing permission to add "write". See docs/how-to-setup-microsoft-oauth-app.md \xa75. Body: ${s}`):400===a&&s.includes("Resource not found for the segment")?o("unknown",`Microsoft Graph ${t} failed with status 400. The request path uses a Graph API segment that is not supported by the Excel workbook API. Check the Microsoft spreadsheet adapter for an unsupported endpoint before changing SharePoint grants. Body: ${s}`):404===a?o("not-found",`Microsoft Graph ${t} failed with status 404. The site, drive, or workbook item was not found, or the app has no access to it. If the workbook was moved or deleted, re-pick it via the in-house picker. Body: ${s}`):423===a?o("locked",`Microsoft Graph ${t} failed with status 423 (locked). The workbook is open in desktop Excel — close it and retry. Body: ${s}`):429===a?o("rate-limit",`Microsoft Graph ${t} failed with status 429 (throttled). Wait a moment and retry. Body: ${s}`):o("unknown",`Microsoft Graph ${t} failed with status ${a}. Verify the app token has Sites.Selected (Application) admin-consented, and that the configured site has a per-site grant with roles: ["read", "write"]. Body: ${s}`)};_createWorkbookSession=async(e,t)=>{let r=await fetch(this._workbookUrl(t,"/createSession"),{method:"POST",headers:this._authHeaders(e),body:JSON.stringify({persistChanges:!0})});return r.ok||await this._parseGraphError(r,"createSession"),(await this._parseJsonResponse(r,n,"createSession")).id};_closeWorkbookSession=async(e,t,r)=>{await fetch(this._workbookUrl(t,"/closeSession"),{method:"POST",headers:this._authHeaders(e,r)})};_escapeWorksheetName=e=>`'${e.replace(/'/g,"''")}'`;_fetchWorksheetNames=async(e,t,r)=>{let s=await fetch(this._workbookUrl(t,"/worksheets?$select=name"),{headers:this._authHeaders(e,r)});return s.ok||await this._parseGraphError(s,"list worksheets"),(await this._parseJsonResponse(s,h,"list worksheets")).value.map(e=>e.name)};_fetchWorksheetUsedRangeValues=async(e,t,r,s)=>{let a=`/worksheets(${this._escapeWorksheetName(r)})/usedRange?$select=values`,o=await fetch(this._workbookUrl(t,a),{headers:this._authHeaders(e,s)});if(!o.ok){if(404===o.status)return[];await this._parseGraphError(o,`read worksheet "${r}"`)}return((await this._parseJsonResponse(o,d,`read worksheet "${r}"`)).values??[]).map(e=>e.map(e=>null==e?"":String(e)))};_columnIndexToLetter=e=>{let t="",r=e;for(;r>=0;)t=String.fromCharCode(65+r%26)+t,r=Math.floor(r/26)-1;return t};_buildRangeAddress=(e,t,r)=>{let s=this._columnIndexToLetter(r-1);return`A${e}:${s}${t}`};_writeRowsToWorksheet=async(e,t,r,s,a)=>{if(0===a.length)return;let o=Math.max(...a.map(e=>e.length)),i=this._buildRangeAddress(1,a.length,o),n=`/worksheets(${this._escapeWorksheetName(s)})/range(address='${i}')`,h=a.map(e=>{let t=[...e];for(;t.length<o;)t.push("");return t}),d=await fetch(this._workbookUrl(t,n),{method:"PATCH",headers:this._authHeaders(e,r),body:JSON.stringify({values:h})});d.ok||await this._parseGraphError(d,`write range to "${s}"`)};_clearWorksheet=async(e,t,r,s)=>{let a=`/worksheets(${this._escapeWorksheetName(s)})/usedRange/clear`,o=await fetch(this._workbookUrl(t,a),{method:"POST",headers:this._authHeaders(e,r),body:JSON.stringify({applyTo:"All"})});o.ok||404===o.status||await this._parseGraphError(o,`clear worksheet "${s}"`)};_renameFirstWorksheet=async(e,t,r,s)=>{let a=(await this._fetchWorksheetNames(e,t,r))[0];if(!a||a===s)return;let o=`/worksheets(${this._escapeWorksheetName(a)})`,i=await fetch(this._workbookUrl(t,o),{method:"PATCH",headers:this._authHeaders(e,r),body:JSON.stringify({name:s})});i.ok||await this._parseGraphError(i,`rename worksheet '${a}' to '${s}'`)};_ensureWorksheetExists=async(e,t,r,s)=>{if((await this._fetchWorksheetNames(e,t,r)).includes(s))return;let a=await fetch(this._workbookUrl(t,"/worksheets/add"),{method:"POST",headers:this._authHeaders(e,r),body:JSON.stringify({name:s})});a.ok||await this._parseGraphError(a,`add worksheet "${s}"`)};_writeLegendWorksheet=async(e,t,r,s)=>{await this._ensureWorksheetExists(e,t,r,s.tabName),await this._clearWorksheet(e,t,r,s.tabName);let a=s.rows.map(e=>[...e]);await this._writeRowsToWorksheet(e,t,r,s.tabName,[["Field","Type","Description","Possible Values"],...a])};_writeWorksheetWithDefaults=async(e,t,r,a,o,i,n)=>{let h=[...o],d=i.map(e=>e.map((e,t)=>s(e,n?.[t])));await this._writeRowsToWorksheet(e,t,r,a,[h,...d])}}export const excelSpreadsheetAdapter=new ExcelSpreadsheetAdapter;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type CellValue, type ColumnMeta, type CreateSpreadsheetResult, type LegendTabData, type SheetTabData, type SpreadsheetAdapter, type SpreadsheetFileRef, type SpreadsheetMeta } from './spreadsheet-adapter.js';
|
|
2
|
+
export interface GoogleSpreadsheetAdapterOptions {
|
|
3
|
+
/** Override for staging/test environments. Defaults to the production Google Sheets API endpoint. */
|
|
4
|
+
readonly apiBaseUrl?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class GoogleSpreadsheetAdapter implements SpreadsheetAdapter {
|
|
7
|
+
private readonly _apiBaseUrl;
|
|
8
|
+
constructor(options?: GoogleSpreadsheetAdapterOptions);
|
|
9
|
+
private readonly _parseJsonResponse;
|
|
10
|
+
private readonly _parseSheetsError;
|
|
11
|
+
fetchMeta: (accessToken: string, ref: SpreadsheetFileRef) => Promise<SpreadsheetMeta>;
|
|
12
|
+
fetchTabHeaders: (accessToken: string, ref: SpreadsheetFileRef, tabName: string) => Promise<readonly string[]>;
|
|
13
|
+
fetchData: (accessToken: string, ref: SpreadsheetFileRef, tabNames: readonly string[], headerRowIndex?: number | null) => Promise<readonly SheetTabData[]>;
|
|
14
|
+
createWorkbook: (accessToken: string, title: string, headers: readonly string[], values?: ReadonlyArray<readonly CellValue[]>, columns?: readonly ColumnMeta[], dataTabName?: string, legendTab?: LegendTabData) => Promise<CreateSpreadsheetResult>;
|
|
15
|
+
resetData: (accessToken: string, ref: SpreadsheetFileRef, tabNames: readonly string[], headers: readonly string[], values: ReadonlyArray<readonly CellValue[]>, columns?: readonly ColumnMeta[], legendTab?: LegendTabData) => Promise<void>;
|
|
16
|
+
private readonly _toCellValue;
|
|
17
|
+
private readonly _toDataCellFormat;
|
|
18
|
+
private readonly _buildHeaderValidationRequests;
|
|
19
|
+
private readonly _buildDataValidationRequests;
|
|
20
|
+
private readonly _fetchSheetIdMap;
|
|
21
|
+
private readonly _writeLegendTab;
|
|
22
|
+
}
|
|
23
|
+
export declare const googleSpreadsheetAdapter: GoogleSpreadsheetAdapter;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{z as e}from"zod";import{SpreadsheetAdapterError as t,normalizeCellOnWrite as a}from"./spreadsheet-adapter.js";let s=e.object({sheets:e.array(e.object({properties:e.object({title:e.string()})}))}),r=e.object({sheets:e.array(e.object({properties:e.object({title:e.string(),sheetId:e.number()})}))}),o=e.object({spreadsheetId:e.string(),properties:e.object({title:e.string()}),sheets:e.array(e.object({properties:e.object({sheetId:e.number()})})).min(1)}),i=e.object({values:e.array(e.array(e.unknown())).optional()});export class GoogleSpreadsheetAdapter{_apiBaseUrl;constructor(e={}){this._apiBaseUrl=e.apiBaseUrl??"https://sheets.googleapis.com/v4/spreadsheets"}_parseJsonResponse=async(e,a,s)=>{let r=await e.json().catch(()=>null),o=a.safeParse(r);if(!o.success)throw new t({kind:"unknown",provider:"google",status:e.status,action:s,bodyExcerpt:JSON.stringify(r).slice(0,500),message:`Google Sheets ${s} returned a response that does not match the expected shape — this likely means the Sheets API contract has changed. Validation issues: ${o.error.issues.map(e=>`${e.path.join(".")}: ${e.message}`).join("; ")}`});return o.data};_parseSheetsError=async(e,a)=>{let s=(await e.text().catch(()=>"")).slice(0,500),r=e.status,o=(e,o)=>{throw new t({kind:e,provider:"google",status:r,action:a,bodyExcerpt:s,message:o})};return 401===r?o("auth",`Google Sheets ${a} failed with status 401. The OAuth access token was rejected — most likely the connected Google account's token has been revoked or expired. Reconnect Google in the SuperAdmin panel and retry. Body: ${s}`):403===r?o("forbidden",`Google Sheets ${a} failed with status 403. The token is valid but the API rejected the request. Common causes: (1) the file was not picked via Google Picker — the configurator uses the 'drive.file' scope, which only grants access to files the user explicitly selected through Picker; (2) the Google Sheets API is not enabled on the OAuth app's GCP project; (3) the daily quota has been exceeded. Body: ${s}`):404===r?o("not-found",`Google Sheets ${a} failed with status 404. The spreadsheet was not found or the OAuth token has no access to it. Re-pick the file via the Google Picker. Body: ${s}`):429===r?o("rate-limit",`Google Sheets ${a} failed with status 429 (rate-limited). Wait a moment and retry. Body: ${s}`):o("unknown",`Google Sheets ${a} failed with status ${r}. Verify the OAuth connection is still active and that the Sheets API is reachable. Body: ${s}`)};fetchMeta=async(e,t)=>{let a=await fetch(`${this._apiBaseUrl}/${t.fileId}?fields=sheets.properties`,{headers:{Authorization:`Bearer ${e}`}});return a.ok||await this._parseSheetsError(a,"fetch spreadsheet metadata"),{tabs:(await this._parseJsonResponse(a,s,"fetch spreadsheet metadata")).sheets.map(e=>e.properties.title)}};fetchTabHeaders=async(e,t,a)=>{let s=encodeURIComponent(`'${a}'!1:1`),r=await fetch(`${this._apiBaseUrl}/${t.fileId}/values/${s}`,{headers:{Authorization:`Bearer ${e}`}});r.ok||await this._parseSheetsError(r,`fetch tab headers for "${a}"`);let o=await this._parseJsonResponse(r,i,`fetch tab headers for "${a}"`);return(o.values?.[0]??[]).map(e=>null==e?"":String(e))};fetchData=async(e,t,a,s)=>{let r=s??0,o=[];for(let s of a){let a=encodeURIComponent(`'${s}'`),n=await fetch(`${this._apiBaseUrl}/${t.fileId}/values/${a}`,{headers:{Authorization:`Bearer ${e}`}});n.ok||await this._parseSheetsError(n,`fetch sheet data for tab "${s}"`);let l=((await this._parseJsonResponse(n,i,`fetch sheet data for tab "${s}"`)).values??[]).map(e=>e.map(e=>null==e?"":String(e))),h=l[r]??[],d=l.slice(r+1);o.push({headers:h,rows:d})}return o};createWorkbook=async(e,t,s,r,i,n,l)=>{let h=[{properties:{title:n??"Sheet1"},data:[{startRow:0,startColumn:0,rowData:[{values:s.map(e=>({userEnteredValue:{stringValue:e},userEnteredFormat:{textFormat:{bold:!0},numberFormat:{type:"TEXT"}}}))},...(r??[]).map(e=>({values:e.map((e,t)=>{let s=this._toCellValue(a(e,i?.[t])),r=this._toDataCellFormat(i?.[t]);return r?{...s,userEnteredFormat:r}:s})}))]}]}];if(l){let e={values:["Field","Type","Description","Possible Values"].map(e=>({userEnteredValue:{stringValue:e},userEnteredFormat:{textFormat:{bold:!0}}}))},t=l.rows.map(e=>({values:e.map(e=>({userEnteredValue:{stringValue:e}}))}));h.push({properties:{title:l.tabName},data:[{startRow:0,startColumn:0,rowData:[e,...t]}]})}let d=await fetch(this._apiBaseUrl,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({properties:{title:t},sheets:h})});d.ok||await this._parseSheetsError(d,`create spreadsheet '${t}'`);let p=await this._parseJsonResponse(d,o,`create spreadsheet '${t}'`),u=p.sheets[0].properties.sheetId,c=[...this._buildHeaderValidationRequests(u,s),...this._buildDataValidationRequests(u,i)];return c.length>0&&await fetch(`${this._apiBaseUrl}/${p.spreadsheetId}:batchUpdate`,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({requests:c})}),{fileId:p.spreadsheetId,driveId:null,title:p.properties.title}};resetData=async(e,t,s,r,o,i,n)=>{let l=t.fileId,h=await this._fetchSheetIdMap(e,l);for(let t of s){let s=h.get(t);if(void 0===s)continue;let n=encodeURIComponent(`'${t}'`);await fetch(`${this._apiBaseUrl}/${l}/values/${n}:clear`,{method:"POST",headers:{Authorization:`Bearer ${e}`}});let d=[{updateCells:{rows:[{values:r.map(e=>({userEnteredValue:{stringValue:e},userEnteredFormat:{textFormat:{bold:!0},numberFormat:{type:"TEXT"}}}))},...o.map(e=>e.map((e,t)=>{let s=this._toCellValue(a(e,i?.[t])),r=this._toDataCellFormat(i?.[t]);return r?{...s,userEnteredFormat:r}:s})).map(e=>({values:e}))],fields:"userEnteredValue,userEnteredFormat",start:{sheetId:s,rowIndex:0,columnIndex:0}}},...this._buildHeaderValidationRequests(s,r),...this._buildDataValidationRequests(s,i)],p=await fetch(`${this._apiBaseUrl}/${l}:batchUpdate`,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({requests:d})});p.ok||await this._parseSheetsError(p,`reset sheet data for tab "${t}"`)}n&&await this._writeLegendTab(e,l,n,h)};_toCellValue=e=>"boolean"==typeof e?{userEnteredValue:{boolValue:e}}:"number"==typeof e?{userEnteredValue:{numberValue:e}}:{userEnteredValue:{stringValue:e}};_toDataCellFormat=e=>{if(e&&("number"===e.type||"integer"===e.type))return{numberFormat:{type:"NUMBER"}}};_buildHeaderValidationRequests=(e,t)=>t.map((t,a)=>({setDataValidation:{range:{sheetId:e,startRowIndex:0,endRowIndex:1,startColumnIndex:a,endColumnIndex:a+1},rule:{condition:{type:"ONE_OF_LIST",values:[{userEnteredValue:t}]},strict:!0,showCustomUi:!1}}}));_buildDataValidationRequests=(e,t)=>t?t.flatMap((t,a)=>"boolean"===t.type?[{setDataValidation:{range:{sheetId:e,startRowIndex:1,startColumnIndex:a,endColumnIndex:a+1},rule:{condition:{type:"BOOLEAN"},showCustomUi:!0}}}]:t.enum&&0!==t.enum.length?[{setDataValidation:{range:{sheetId:e,startRowIndex:1,startColumnIndex:a,endColumnIndex:a+1},rule:{condition:{type:"ONE_OF_LIST",values:t.enum.map(e=>({userEnteredValue:String(e)}))},strict:!0,showCustomUi:!0}}}]:[]):[];_fetchSheetIdMap=async(e,t)=>{let a=await fetch(`${this._apiBaseUrl}/${t}?fields=sheets.properties`,{headers:{Authorization:`Bearer ${e}`}});return a.ok||await this._parseSheetsError(a,"fetch sheet id map"),new Map((await this._parseJsonResponse(a,r,"fetch sheet id map")).sheets.map(e=>[e.properties.title,e.properties.sheetId]))};_writeLegendTab=async(e,t,a,s)=>{if(void 0!==s.get(a.tabName)){let s=encodeURIComponent(`'${a.tabName}'`);await fetch(`${this._apiBaseUrl}/${t}/values/${s}:clear`,{method:"POST",headers:{Authorization:`Bearer ${e}`}})}else{let s=await fetch(`${this._apiBaseUrl}/${t}:batchUpdate`,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({requests:[{addSheet:{properties:{title:a.tabName}}}]})});s.ok||await this._parseSheetsError(s,"add legend tab")}let r=["Field","Type","Description","Possible Values"].map(e=>({userEnteredValue:{stringValue:e},userEnteredFormat:{textFormat:{bold:!0}}})),o=a.rows.map(e=>e.map(e=>({userEnteredValue:{stringValue:e}}))),i=(await this._fetchSheetIdMap(e,t)).get(a.tabName);if(void 0===i)return;let n=await fetch(`${this._apiBaseUrl}/${t}:batchUpdate`,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({requests:[{updateCells:{rows:[{values:r},...o.map(e=>({values:e}))],fields:"userEnteredValue,userEnteredFormat",start:{sheetId:i,rowIndex:0,columnIndex:0}}}]})});n.ok||await this._parseSheetsError(n,"update legend tab")}}export const googleSpreadsheetAdapter=new GoogleSpreadsheetAdapter;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { routeWebhookRequests } from './webhook-routing.js';
|
|
2
|
+
export { TunneledWebhookRequest, TunneledWebhookResponse, WebhookTunnelPollRequest, WebhookTunnelPollResponse, WebhookTunnelRespondRequest, } from './webhook-tunnel-types.js';
|
|
3
|
+
export { WebhookClient, createUrlWebhookHttpClient, fetchWebhookHttpClient, type WebhookHttpClient, } from './webhook-client.js';
|
|
4
|
+
export { AuthHandlerResponse, AuthUserIdSource, RefreshPayload, CodePayload, AuthPayload, AnonymousPayload, FinalizeWebhookPayload, CallbackPayload, CallbackResponse, FetchBackendDataPayload, FetchBackendDataHandlerResponse, } from './webhook-api-types.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{routeWebhookRequests}from"./webhook-routing.js";export{TunneledWebhookRequest,TunneledWebhookResponse,WebhookTunnelPollRequest,WebhookTunnelPollResponse,WebhookTunnelRespondRequest}from"./webhook-tunnel-types.js";export{WebhookClient,createUrlWebhookHttpClient,fetchWebhookHttpClient}from"./webhook-client.js";export{AuthHandlerResponse,AuthUserIdSource,RefreshPayload,CodePayload,AuthPayload,AnonymousPayload,FinalizeWebhookPayload,CallbackPayload,CallbackResponse,FetchBackendDataPayload,FetchBackendDataHandlerResponse}from"./webhook-api-types.js";
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SessionRole } from '../../api/index.js';
|
|
3
|
+
import type { Entity } from '../../domain/index.js';
|
|
4
|
+
import { ConfigurationId, DeploymentId, FrontendUrl, RevisionId } from '../../domain/index.js';
|
|
5
|
+
import { CallLambdaBackResourceType } from '../tasks/index.js';
|
|
6
|
+
export interface CallbackPayload<REPLAY_DATA extends Record<string, unknown>, RESOURCE extends string> {
|
|
7
|
+
replayData: REPLAY_DATA;
|
|
8
|
+
resources: Partial<Record<RESOURCE, {
|
|
9
|
+
type: CallLambdaBackResourceType;
|
|
10
|
+
link: string;
|
|
11
|
+
}>> & Record<string, {
|
|
12
|
+
type: CallLambdaBackResourceType;
|
|
13
|
+
link: string;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
export declare const CallbackPayload: z.ZodType<CallbackPayload<Record<string, unknown>, string>>;
|
|
17
|
+
export interface CallbackResponse<RESULT extends Record<string, unknown>> {
|
|
18
|
+
result?: RESULT;
|
|
19
|
+
}
|
|
20
|
+
export declare const CallbackResponse: z.ZodType<CallbackResponse<Record<string, unknown>>>;
|
|
21
|
+
/** The identity provider of a user id an auth handler returns; it becomes the prefix of the session `sub`. */
|
|
22
|
+
export declare const AuthUserIdSource: z.ZodEnum<["clerk", "custom"]>;
|
|
23
|
+
export type AuthUserIdSource = z.infer<typeof AuthUserIdSource>;
|
|
24
|
+
export declare const AuthHandlerResponse: z.ZodDiscriminatedUnion<"success", [z.ZodObject<{
|
|
25
|
+
success: z.ZodLiteral<true>;
|
|
26
|
+
data: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
27
|
+
role: z.ZodNativeEnum<{
|
|
28
|
+
readonly Anonymous: 'anonymous';
|
|
29
|
+
readonly User: 'user';
|
|
30
|
+
readonly Admin: 'admin';
|
|
31
|
+
readonly SuperAdmin: 'superadmin';
|
|
32
|
+
}>;
|
|
33
|
+
refreshToken: z.ZodOptional<z.ZodString>;
|
|
34
|
+
expirationTime: z.ZodOptional<z.ZodNumber>;
|
|
35
|
+
scopes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
36
|
+
userId: z.ZodOptional<z.ZodString>;
|
|
37
|
+
userIdSource: z.ZodOptional<z.ZodEnum<["clerk", "custom"]>>;
|
|
38
|
+
}, "strip", z.ZodTypeAny, {
|
|
39
|
+
success: true;
|
|
40
|
+
data: Record<string, unknown>;
|
|
41
|
+
role: "admin" | "anonymous" | "superadmin" | "user";
|
|
42
|
+
refreshToken?: string | undefined;
|
|
43
|
+
expirationTime?: number | undefined;
|
|
44
|
+
scopes?: string[] | undefined;
|
|
45
|
+
userId?: string | undefined;
|
|
46
|
+
userIdSource?: "clerk" | "custom" | undefined;
|
|
47
|
+
}, {
|
|
48
|
+
success: true;
|
|
49
|
+
data: Record<string, unknown>;
|
|
50
|
+
role: "admin" | "anonymous" | "superadmin" | "user";
|
|
51
|
+
refreshToken?: string | undefined;
|
|
52
|
+
expirationTime?: number | undefined;
|
|
53
|
+
scopes?: string[] | undefined;
|
|
54
|
+
userId?: string | undefined;
|
|
55
|
+
userIdSource?: "clerk" | "custom" | undefined;
|
|
56
|
+
}>, z.ZodObject<{
|
|
57
|
+
success: z.ZodLiteral<false>;
|
|
58
|
+
}, "strip", z.ZodTypeAny, {
|
|
59
|
+
success: false;
|
|
60
|
+
}, {
|
|
61
|
+
success: false;
|
|
62
|
+
}>]>;
|
|
63
|
+
export interface AuthHandlerSuccessResponse<SESSION_DATA extends Record<string, unknown>> {
|
|
64
|
+
success: true;
|
|
65
|
+
data: SESSION_DATA;
|
|
66
|
+
role: SessionRole;
|
|
67
|
+
refreshToken?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Defaults to 3h, it should not be overridden if not 100% needed. It is used to calculate session tracking and changing this time
|
|
70
|
+
* will make sessions longer.
|
|
71
|
+
*/
|
|
72
|
+
expirationTime?: number;
|
|
73
|
+
scopes?: readonly string[];
|
|
74
|
+
/**
|
|
75
|
+
* The id of the signed-in user, unprefixed. The server namespaces it with {@link userIdSource} into the
|
|
76
|
+
* session token's `sub`. When omitted, the session falls back to the browser's anonymous id.
|
|
77
|
+
*/
|
|
78
|
+
userId?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Which identity provider {@link userId} comes from. Defaults to `custom`. The SDK's auth handler builder
|
|
81
|
+
* sets it: `clerk` for its Clerk handlers, `custom` for every other handler.
|
|
82
|
+
*/
|
|
83
|
+
userIdSource?: AuthUserIdSource;
|
|
84
|
+
}
|
|
85
|
+
export interface AuthHandlerErrorResponse {
|
|
86
|
+
success: false;
|
|
87
|
+
}
|
|
88
|
+
export type AuthHandlerResponse<SESSION_DATA extends Record<string, unknown>> = AuthHandlerSuccessResponse<SESSION_DATA> | AuthHandlerErrorResponse;
|
|
89
|
+
export declare const RefreshPayload: z.ZodObject<{
|
|
90
|
+
type: z.ZodLiteral<"refresh">;
|
|
91
|
+
refreshToken: z.ZodString;
|
|
92
|
+
}, "strip", z.ZodTypeAny, {
|
|
93
|
+
type: "refresh";
|
|
94
|
+
refreshToken: string;
|
|
95
|
+
}, {
|
|
96
|
+
type: "refresh";
|
|
97
|
+
refreshToken: string;
|
|
98
|
+
}>;
|
|
99
|
+
export type RefreshPayload = z.infer<typeof RefreshPayload>;
|
|
100
|
+
export declare const CodePayload: z.ZodObject<{
|
|
101
|
+
type: z.ZodLiteral<"code">;
|
|
102
|
+
accessToken: z.ZodString;
|
|
103
|
+
refreshToken: z.ZodOptional<z.ZodString>;
|
|
104
|
+
idToken: z.ZodOptional<z.ZodString>;
|
|
105
|
+
}, "strip", z.ZodTypeAny, {
|
|
106
|
+
type: "code";
|
|
107
|
+
accessToken: string;
|
|
108
|
+
refreshToken?: string | undefined;
|
|
109
|
+
idToken?: string | undefined;
|
|
110
|
+
}, {
|
|
111
|
+
type: "code";
|
|
112
|
+
accessToken: string;
|
|
113
|
+
refreshToken?: string | undefined;
|
|
114
|
+
idToken?: string | undefined;
|
|
115
|
+
}>;
|
|
116
|
+
export type CodePayload = z.infer<typeof CodePayload>;
|
|
117
|
+
export declare const AnonymousPayload: z.ZodObject<{
|
|
118
|
+
type: z.ZodLiteral<"anonymous">;
|
|
119
|
+
}, "strip", z.ZodTypeAny, {
|
|
120
|
+
type: "anonymous";
|
|
121
|
+
}, {
|
|
122
|
+
type: "anonymous";
|
|
123
|
+
}>;
|
|
124
|
+
export type AnonymousPayload = z.infer<typeof AnonymousPayload>;
|
|
125
|
+
export declare const AuthPayload: z.ZodUnion<[z.ZodObject<{
|
|
126
|
+
type: z.ZodLiteral<"refresh">;
|
|
127
|
+
refreshToken: z.ZodString;
|
|
128
|
+
}, "strip", z.ZodTypeAny, {
|
|
129
|
+
type: "refresh";
|
|
130
|
+
refreshToken: string;
|
|
131
|
+
}, {
|
|
132
|
+
type: "refresh";
|
|
133
|
+
refreshToken: string;
|
|
134
|
+
}>, z.ZodObject<{
|
|
135
|
+
type: z.ZodLiteral<"code">;
|
|
136
|
+
accessToken: z.ZodString;
|
|
137
|
+
refreshToken: z.ZodOptional<z.ZodString>;
|
|
138
|
+
idToken: z.ZodOptional<z.ZodString>;
|
|
139
|
+
}, "strip", z.ZodTypeAny, {
|
|
140
|
+
type: "code";
|
|
141
|
+
accessToken: string;
|
|
142
|
+
refreshToken?: string | undefined;
|
|
143
|
+
idToken?: string | undefined;
|
|
144
|
+
}, {
|
|
145
|
+
type: "code";
|
|
146
|
+
accessToken: string;
|
|
147
|
+
refreshToken?: string | undefined;
|
|
148
|
+
idToken?: string | undefined;
|
|
149
|
+
}>, z.ZodObject<{
|
|
150
|
+
type: z.ZodLiteral<"anonymous">;
|
|
151
|
+
}, "strip", z.ZodTypeAny, {
|
|
152
|
+
type: "anonymous";
|
|
153
|
+
}, {
|
|
154
|
+
type: "anonymous";
|
|
155
|
+
}>]>;
|
|
156
|
+
export type AuthPayload = z.infer<typeof AuthPayload>;
|
|
157
|
+
export interface FinalizeWebhookPayload<FINALIZE_DATA extends Record<string, unknown>, ENTITIES extends {
|
|
158
|
+
id: string;
|
|
159
|
+
type: string;
|
|
160
|
+
}, SESSION_DATA extends Record<string, unknown>, FRONTEND_DATA extends Record<string, unknown>> {
|
|
161
|
+
configurationId: ConfigurationId;
|
|
162
|
+
revisionId: RevisionId;
|
|
163
|
+
deploymentId: DeploymentId;
|
|
164
|
+
frontendUrl: FrontendUrl;
|
|
165
|
+
rootEntityType: Entity['type'];
|
|
166
|
+
entities: ENTITIES[];
|
|
167
|
+
modelVersion: number;
|
|
168
|
+
data: FINALIZE_DATA;
|
|
169
|
+
frontendData?: FRONTEND_DATA;
|
|
170
|
+
locale: string;
|
|
171
|
+
sessionRole: SessionRole;
|
|
172
|
+
sessionPayload: SESSION_DATA;
|
|
173
|
+
publishedAdminRevisionPath?: string;
|
|
174
|
+
publishedChunkUrls?: Record<string, string>;
|
|
175
|
+
/**
|
|
176
|
+
* Pre-signed PUT URL for staging connected-data chunks outside the webhook response. Optional on purpose: older
|
|
177
|
+
* servers never send it and older SDKs ignore it, so the SDK feature-detects staging by its presence.
|
|
178
|
+
*/
|
|
179
|
+
chunksUploadUrl?: string;
|
|
180
|
+
connectedProviderAccessTokens?: Record<string, string>;
|
|
181
|
+
}
|
|
182
|
+
export declare const FinalizeWebhookPayload: z.ZodObject<{
|
|
183
|
+
configurationId: z.ZodEffects<z.ZodString, ConfigurationId, string>;
|
|
184
|
+
revisionId: z.ZodEffects<z.ZodString, RevisionId, string>;
|
|
185
|
+
deploymentId: z.ZodEffects<z.ZodString, DeploymentId, string>;
|
|
186
|
+
frontendUrl: z.ZodEffects<z.ZodString, FrontendUrl, string>;
|
|
187
|
+
rootEntityType: z.ZodString;
|
|
188
|
+
entities: z.ZodArray<z.ZodIntersection<z.ZodObject<{
|
|
189
|
+
type: z.ZodString;
|
|
190
|
+
id: z.ZodString;
|
|
191
|
+
}, "strip", z.ZodTypeAny, {
|
|
192
|
+
type: string;
|
|
193
|
+
id: string;
|
|
194
|
+
}, {
|
|
195
|
+
type: string;
|
|
196
|
+
id: string;
|
|
197
|
+
}>, z.ZodRecord<z.ZodString, z.ZodUnknown>>, "many">;
|
|
198
|
+
modelVersion: z.ZodNumber;
|
|
199
|
+
data: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
200
|
+
frontendData: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
201
|
+
locale: z.ZodString;
|
|
202
|
+
sessionRole: z.ZodNativeEnum<{
|
|
203
|
+
readonly Anonymous: 'anonymous';
|
|
204
|
+
readonly User: 'user';
|
|
205
|
+
readonly Admin: 'admin';
|
|
206
|
+
readonly SuperAdmin: 'superadmin';
|
|
207
|
+
}>;
|
|
208
|
+
sessionPayload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
209
|
+
publishedAdminRevisionPath: z.ZodOptional<z.ZodString>;
|
|
210
|
+
publishedChunkUrls: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
211
|
+
chunksUploadUrl: z.ZodOptional<z.ZodString>;
|
|
212
|
+
connectedProviderAccessTokens: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
213
|
+
}, "strip", z.ZodTypeAny, {
|
|
214
|
+
configurationId: string & import("@salsita-ai/common/utils").Brand<"ConfigurationId">;
|
|
215
|
+
revisionId: string & import("@salsita-ai/common/utils").Brand<"RevisionId">;
|
|
216
|
+
deploymentId: string & import("@salsita-ai/common/utils").Brand<"DeploymentId">;
|
|
217
|
+
frontendUrl: string & import("@salsita-ai/common/utils").Brand<"FrontendUrl">;
|
|
218
|
+
rootEntityType: string;
|
|
219
|
+
entities: ({
|
|
220
|
+
type: string;
|
|
221
|
+
id: string;
|
|
222
|
+
} & Record<string, unknown>)[];
|
|
223
|
+
modelVersion: number;
|
|
224
|
+
data: Record<string, unknown>;
|
|
225
|
+
frontendData?: Record<string, unknown> | undefined;
|
|
226
|
+
locale: string;
|
|
227
|
+
sessionRole: "admin" | "anonymous" | "superadmin" | "user";
|
|
228
|
+
sessionPayload: Record<string, unknown>;
|
|
229
|
+
publishedAdminRevisionPath?: string | undefined;
|
|
230
|
+
publishedChunkUrls?: Record<string, string> | undefined;
|
|
231
|
+
chunksUploadUrl?: string | undefined;
|
|
232
|
+
connectedProviderAccessTokens?: Record<string, string> | undefined;
|
|
233
|
+
}, {
|
|
234
|
+
configurationId: string;
|
|
235
|
+
revisionId: string;
|
|
236
|
+
deploymentId: string;
|
|
237
|
+
frontendUrl: string;
|
|
238
|
+
rootEntityType: string;
|
|
239
|
+
entities: ({
|
|
240
|
+
type: string;
|
|
241
|
+
id: string;
|
|
242
|
+
} & Record<string, unknown>)[];
|
|
243
|
+
modelVersion: number;
|
|
244
|
+
data: Record<string, unknown>;
|
|
245
|
+
frontendData?: Record<string, unknown> | undefined;
|
|
246
|
+
locale: string;
|
|
247
|
+
sessionRole: "admin" | "anonymous" | "superadmin" | "user";
|
|
248
|
+
sessionPayload: Record<string, unknown>;
|
|
249
|
+
publishedAdminRevisionPath?: string | undefined;
|
|
250
|
+
publishedChunkUrls?: Record<string, string> | undefined;
|
|
251
|
+
chunksUploadUrl?: string | undefined;
|
|
252
|
+
connectedProviderAccessTokens?: Record<string, string> | undefined;
|
|
253
|
+
}>;
|
|
254
|
+
export interface FetchBackendDataPayload<SESSION_DATA extends Record<string, unknown>, FRONTEND_DATA extends Record<string, unknown>> {
|
|
255
|
+
deploymentId: DeploymentId;
|
|
256
|
+
frontendUrl: FrontendUrl;
|
|
257
|
+
frontendData?: FRONTEND_DATA;
|
|
258
|
+
sessionRole: SessionRole;
|
|
259
|
+
sessionPayload: SESSION_DATA;
|
|
260
|
+
publishedAdminRevisionPath?: string;
|
|
261
|
+
publishedChunkUrls?: Record<string, string>;
|
|
262
|
+
}
|
|
263
|
+
export declare const FetchBackendDataPayload: z.ZodObject<{
|
|
264
|
+
deploymentId: z.ZodEffects<z.ZodString, DeploymentId, string>;
|
|
265
|
+
frontendUrl: z.ZodEffects<z.ZodString, FrontendUrl, string>;
|
|
266
|
+
frontendData: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
267
|
+
sessionRole: z.ZodNativeEnum<{
|
|
268
|
+
readonly Anonymous: 'anonymous';
|
|
269
|
+
readonly User: 'user';
|
|
270
|
+
readonly Admin: 'admin';
|
|
271
|
+
readonly SuperAdmin: 'superadmin';
|
|
272
|
+
}>;
|
|
273
|
+
sessionPayload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
274
|
+
publishedAdminRevisionPath: z.ZodOptional<z.ZodString>;
|
|
275
|
+
publishedChunkUrls: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
276
|
+
}, "strip", z.ZodTypeAny, {
|
|
277
|
+
deploymentId: string & import("@salsita-ai/common/utils").Brand<"DeploymentId">;
|
|
278
|
+
frontendUrl: string & import("@salsita-ai/common/utils").Brand<"FrontendUrl">;
|
|
279
|
+
frontendData?: Record<string, unknown> | undefined;
|
|
280
|
+
sessionRole: "admin" | "anonymous" | "superadmin" | "user";
|
|
281
|
+
sessionPayload: Record<string, unknown>;
|
|
282
|
+
publishedAdminRevisionPath?: string | undefined;
|
|
283
|
+
publishedChunkUrls?: Record<string, string> | undefined;
|
|
284
|
+
}, {
|
|
285
|
+
deploymentId: string;
|
|
286
|
+
frontendUrl: string;
|
|
287
|
+
frontendData?: Record<string, unknown> | undefined;
|
|
288
|
+
sessionRole: "admin" | "anonymous" | "superadmin" | "user";
|
|
289
|
+
sessionPayload: Record<string, unknown>;
|
|
290
|
+
publishedAdminRevisionPath?: string | undefined;
|
|
291
|
+
publishedChunkUrls?: Record<string, string> | undefined;
|
|
292
|
+
}>;
|
|
293
|
+
export interface FetchBackendDataHandlerResponse {
|
|
294
|
+
backendData: Record<string, unknown>;
|
|
295
|
+
}
|
|
296
|
+
export declare const FetchBackendDataHandlerResponse: z.ZodObject<{
|
|
297
|
+
backendData: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
298
|
+
}, "strip", z.ZodTypeAny, {
|
|
299
|
+
backendData: Record<string, unknown>;
|
|
300
|
+
}, {
|
|
301
|
+
backendData: Record<string, unknown>;
|
|
302
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{z as o}from"zod";import{usingType as n}from"@salsita-ai/common/utils";import{SessionRole as e}from"../../api/index.js";import{ConfigurationId as r,DeploymentId as t,FrontendUrl as s,RevisionId as a}from"../../domain/index.js";import{CallLambdaBackResourceType as i}from"../tasks/index.js";export const CallbackPayload=o.object({replayData:o.record(o.unknown()),resources:o.record(o.object({type:o.literal(i.Link),link:o.string()}))});export const CallbackResponse=o.object({result:o.record(o.unknown()).optional()});export const AuthUserIdSource=o.enum(["clerk","custom"]);export const AuthHandlerResponse=o.discriminatedUnion("success",[o.object({success:o.literal(!0),data:o.record(o.unknown()),role:o.nativeEnum(e),refreshToken:o.string().optional(),expirationTime:o.number().optional(),scopes:o.array(o.string()).optional(),userId:o.string().optional(),userIdSource:AuthUserIdSource.optional()}),o.object({success:o.literal(!1)})]);export const RefreshPayload=o.object({type:o.literal("refresh"),refreshToken:o.string()});export const CodePayload=o.object({type:o.literal("code"),accessToken:o.string(),refreshToken:o.string().optional(),idToken:o.string().optional()});export const AnonymousPayload=o.object({type:o.literal("anonymous")});export const AuthPayload=o.union([RefreshPayload,CodePayload,AnonymousPayload]);export const FinalizeWebhookPayload=o.object({configurationId:o.string().transform(n(r)),revisionId:o.string().transform(n(a)),deploymentId:o.string().transform(n(t)),frontendUrl:o.string().transform(n(s)),rootEntityType:o.string(),entities:o.array(o.object({type:o.string(),id:o.string()}).and(o.record(o.unknown()))),modelVersion:o.number().positive(),data:o.record(o.unknown()),frontendData:o.record(o.unknown()).optional(),locale:o.string(),sessionRole:o.nativeEnum(e),sessionPayload:o.record(o.unknown()),publishedAdminRevisionPath:o.string().optional(),publishedChunkUrls:o.record(o.string()).optional(),chunksUploadUrl:o.string().optional(),connectedProviderAccessTokens:o.record(o.string()).optional()});export const FetchBackendDataPayload=o.object({deploymentId:o.string().transform(n(t)),frontendUrl:o.string().transform(n(s)),frontendData:o.record(o.unknown()).optional(),sessionRole:o.nativeEnum(e),sessionPayload:o.record(o.unknown()),publishedAdminRevisionPath:o.string().optional(),publishedChunkUrls:o.record(o.string()).optional()});export const FetchBackendDataHandlerResponse=o.object({backendData:o.record(o.unknown())});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { ApplicationType } from '../../domain/index.js';
|
|
2
|
+
import { type CallbackPayload, CallbackResponse, type FetchBackendDataPayload, type FinalizeWebhookPayload } from './webhook-api-types.js';
|
|
3
|
+
export type WebhookHttpClient = (url: string, init: RequestInit) => Promise<Response>;
|
|
4
|
+
export declare const fetchWebhookHttpClient: WebhookHttpClient;
|
|
5
|
+
export declare const createUrlWebhookHttpClient: (baseUrl: string, httpClient?: WebhookHttpClient) => WebhookHttpClient;
|
|
6
|
+
export declare class WebhookClient {
|
|
7
|
+
private readonly _httpClient;
|
|
8
|
+
constructor(httpClient: WebhookHttpClient);
|
|
9
|
+
/** @deprecated Pass createUrlWebhookHttpClient(baseUrl, httpClient) instead. This overload will be removed in a future version. */
|
|
10
|
+
constructor(baseUrl: string, httpClient?: WebhookHttpClient);
|
|
11
|
+
handleRefreshFlow: (refreshToken: string) => Promise<{
|
|
12
|
+
success: true;
|
|
13
|
+
data: Record<string, unknown>;
|
|
14
|
+
role: "admin" | "anonymous" | "superadmin" | "user";
|
|
15
|
+
refreshToken?: string | undefined;
|
|
16
|
+
expirationTime?: number | undefined;
|
|
17
|
+
scopes?: string[] | undefined;
|
|
18
|
+
userId?: string | undefined;
|
|
19
|
+
userIdSource?: "clerk" | "custom" | undefined;
|
|
20
|
+
} | {
|
|
21
|
+
success: false;
|
|
22
|
+
}>;
|
|
23
|
+
handleCodeFlow: (accessToken: string, refreshToken: string | undefined, idToken: string | undefined) => Promise<{
|
|
24
|
+
success: true;
|
|
25
|
+
data: Record<string, unknown>;
|
|
26
|
+
role: "admin" | "anonymous" | "superadmin" | "user";
|
|
27
|
+
refreshToken?: string | undefined;
|
|
28
|
+
expirationTime?: number | undefined;
|
|
29
|
+
scopes?: string[] | undefined;
|
|
30
|
+
userId?: string | undefined;
|
|
31
|
+
userIdSource?: "clerk" | "custom" | undefined;
|
|
32
|
+
} | {
|
|
33
|
+
success: false;
|
|
34
|
+
}>;
|
|
35
|
+
handleAnonymousFlow: () => Promise<{
|
|
36
|
+
success: true;
|
|
37
|
+
data: Record<string, unknown>;
|
|
38
|
+
role: "admin" | "anonymous" | "superadmin" | "user";
|
|
39
|
+
refreshToken?: string | undefined;
|
|
40
|
+
expirationTime?: number | undefined;
|
|
41
|
+
scopes?: string[] | undefined;
|
|
42
|
+
userId?: string | undefined;
|
|
43
|
+
userIdSource?: "clerk" | "custom" | undefined;
|
|
44
|
+
} | {
|
|
45
|
+
success: false;
|
|
46
|
+
}>;
|
|
47
|
+
finalize: (data: FinalizeWebhookPayload<Record<string, unknown>, {
|
|
48
|
+
id: string;
|
|
49
|
+
type: string;
|
|
50
|
+
}, Record<string, unknown>, Record<string, unknown>>, applicationType: ApplicationType) => Promise<{
|
|
51
|
+
dataVersion: 1;
|
|
52
|
+
tasks: (import("../tasks/call-lambda-back-task.js").CallLambdaBackTask<Record<string, unknown>, string> | import("../tasks/edit-google-spreadsheet-task.js").EditGoogleSpreadsheetTask | import("../tasks/generate-csv-task.js").GenerateCsvTask | import("../tasks/generate-images-task.js").GenerateImagesTask | import("../tasks/generate-pdf-task.js").GeneratePdfTask | import("../tasks/generate-pdf-task.js").GenerateStaticPdfTask | import("../tasks/send-email-task.js").SendEmailTask | import("../tasks/send-http-task.js").SendHttpRequestTask | import("../tasks/send-email-task.js").SendStaticEmailTask | import("../tasks/woocommerce-add-to-cart-task.js").WooCommerceAddToCartTask | {
|
|
53
|
+
type: "GenerateConfigurationLink";
|
|
54
|
+
name: string;
|
|
55
|
+
frontendUrl: string & import("@salsita-ai/common/utils").Brand<"FrontendUrl">;
|
|
56
|
+
expiration?: number | undefined;
|
|
57
|
+
access: "o" | "r" | "rr";
|
|
58
|
+
configurationId: string & import("@salsita-ai/common/utils").Brand<"ConfigurationId">;
|
|
59
|
+
revisionId?: import("../../domain/index.js").RevisionId | undefined;
|
|
60
|
+
} | {
|
|
61
|
+
type: "PublishRevision";
|
|
62
|
+
version: number & import("@salsita-ai/common/utils").Brand<"PublishedDataRevisionVersion">;
|
|
63
|
+
revisionId: string & import("@salsita-ai/common/utils").Brand<"RevisionId">;
|
|
64
|
+
data: Record<string, unknown>;
|
|
65
|
+
} | {
|
|
66
|
+
type: "PublishRevisionChunks";
|
|
67
|
+
revisionId: string & import("@salsita-ai/common/utils").Brand<"RevisionId">;
|
|
68
|
+
chunks: {
|
|
69
|
+
key: string & import("@salsita-ai/common/utils").Brand<"ChunkKey">;
|
|
70
|
+
scope: string & import("@salsita-ai/common/utils").Brand<"ChunkScope">;
|
|
71
|
+
data: Record<string, unknown>;
|
|
72
|
+
}[];
|
|
73
|
+
publishedDataHash: string;
|
|
74
|
+
} | {
|
|
75
|
+
type: "PublishRevisionChunksStaged";
|
|
76
|
+
revisionId: string & import("@salsita-ai/common/utils").Brand<"RevisionId">;
|
|
77
|
+
publishedDataHash: string;
|
|
78
|
+
})[];
|
|
79
|
+
resources: import("../index.js").FinalizeTaskResource<string>[];
|
|
80
|
+
}>;
|
|
81
|
+
callback: (payload: CallbackPayload<Record<string, unknown>, string>) => Promise<CallbackResponse<Record<string, unknown>>>;
|
|
82
|
+
fetchBackendData: (payload: FetchBackendDataPayload<Record<string, unknown>, Record<string, unknown>>) => Promise<{
|
|
83
|
+
backendData: Record<string, unknown>;
|
|
84
|
+
}>;
|
|
85
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{WebhookFinalizeTaskConfiguration as t}from"../tasks/index.js";import{AuthHandlerResponse as e,CallbackResponse as o,FetchBackendDataHandlerResponse as a}from"./webhook-api-types.js";import{getAuthRoute as i,getCallbackRoute as n,getFetchBackendDataRoute as r,getFinalizeRoute as s}from"./webhook-routing.js";export const fetchWebhookHttpClient=(t,e)=>fetch(t,e);export const createUrlWebhookHttpClient=(t,e=fetchWebhookHttpClient)=>(o,a)=>e(`${t}${o}`,a);export class WebhookClient{_httpClient;constructor(t,e=fetchWebhookHttpClient){this._httpClient="string"==typeof t?createUrlWebhookHttpClient(t,e):t}handleRefreshFlow=async t=>{let o=await this._httpClient(i(),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"refresh",refreshToken:t})});if(!o.ok)throw Error(`Refresh webhook call failed: ${await o.text()}`);return e.parse(await o.json())};handleCodeFlow=async(t,o,a)=>{let n=await this._httpClient(i(),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"code",accessToken:t,refreshToken:o,idToken:a})});if(!n.ok)throw Error(`Refresh webhook call failed: ${await n.text()}`);return e.parse(await n.json())};handleAnonymousFlow=async()=>{let t=await this._httpClient(i(),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"anonymous"})});if(!t.ok)throw Error(`Refresh webhook call failed: ${await t.text()}`);return e.parse(await t.json())};finalize=async(e,o)=>{let a=await this._httpClient(s(o),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!a.ok)throw Error("Lambda call failed: "+await a.text());let i=await a.json();return t.parse(i)};callback=async t=>{let e=await this._httpClient(n(),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!e.ok)throw Error("Lambda call failed: "+await e.text());let a=await e.json();return o.parse(a)};fetchBackendData=async t=>{let e=await this._httpClient(r(),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!e.ok)throw Error("Lambda call failed: "+await e.text());return a.parse(await e.json())}}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { APIGatewayProxyEventV2, LambdaFunctionURLResult } from 'aws-lambda';
|
|
2
|
+
import type { Logger } from '@salsita-ai/common/utils';
|
|
3
|
+
import { ApplicationType } from '../../domain/index.js';
|
|
4
|
+
import { type WebhookFinalizeTaskConfiguration } from '../tasks/index.js';
|
|
5
|
+
import type { AuthHandlerResponse, CallbackResponse, FetchBackendDataHandlerResponse } from './webhook-api-types.js';
|
|
6
|
+
import { AuthPayload, CallbackPayload, FetchBackendDataPayload, FinalizeWebhookPayload } from './webhook-api-types.js';
|
|
7
|
+
export declare const getAuthRoute: () => string;
|
|
8
|
+
export declare const getFinalizeRoute: (applicationType: ApplicationType) => string;
|
|
9
|
+
export declare const getCallbackRoute: () => string;
|
|
10
|
+
export declare const getFetchBackendDataRoute: () => string;
|
|
11
|
+
export declare const handleWebhookSafely: (handler: (e: APIGatewayProxyEventV2) => Promise<LambdaFunctionURLResult>, logger: Logger) => (event: APIGatewayProxyEventV2) => Promise<LambdaFunctionURLResult>;
|
|
12
|
+
type CallbackHandler = (body: CallbackPayload<Record<string, unknown>, string>, e: APIGatewayProxyEventV2) => Promise<CallbackResponse<Record<string, unknown>>>;
|
|
13
|
+
type FinalizeHandler = (body: FinalizeWebhookPayload<Record<string, unknown>, {
|
|
14
|
+
id: string;
|
|
15
|
+
type: string;
|
|
16
|
+
}, Record<string, unknown>, Record<string, unknown>>, e: APIGatewayProxyEventV2) => Promise<WebhookFinalizeTaskConfiguration>;
|
|
17
|
+
type AuthHandler = (body: AuthPayload, e: APIGatewayProxyEventV2) => Promise<AuthHandlerResponse<Record<string, unknown>>>;
|
|
18
|
+
type FetchBackendDataHandler = (body: FetchBackendDataPayload<Record<string, unknown>, Record<string, unknown>>, e: APIGatewayProxyEventV2) => Promise<FetchBackendDataHandlerResponse>;
|
|
19
|
+
export declare const routeWebhookRequests: (handlers: {
|
|
20
|
+
configurator?: {
|
|
21
|
+
onFetchBackendData?: FetchBackendDataHandler;
|
|
22
|
+
onCallback?: CallbackHandler;
|
|
23
|
+
onFinalize?: FinalizeHandler;
|
|
24
|
+
};
|
|
25
|
+
admin?: {
|
|
26
|
+
onFinalize?: FinalizeHandler;
|
|
27
|
+
};
|
|
28
|
+
onAuth?: AuthHandler;
|
|
29
|
+
}, logger: Logger) => (event: APIGatewayProxyEventV2) => Promise<LambdaFunctionURLResult>;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{P as o,match as t}from"ts-pattern";import{ApplicationType as r}from"../../domain/index.js";import{validateTaskConfiguration as n}from"../tasks/index.js";import{AuthPayload as e,CallbackPayload as a,FetchBackendDataPayload as i,FinalizeWebhookPayload as s}from"./webhook-api-types.js";let f="auth",c="finalize",d="callback",h="fetchBackendData";export const getAuthRoute=()=>`?o=${f}`;export const getFinalizeRoute=o=>`?o=${c}&t=${o}`;export const getCallbackRoute=()=>`?o=${d}`;export const getFetchBackendDataRoute=()=>`?o=${h}`;export const handleWebhookSafely=(o,t)=>async r=>{try{return await o(r)}catch(n){let o=`Webhook failed: ${n instanceof Error?n.message:"Unknown error"}`,r="object"==typeof n&&n instanceof Error?n:Error(o);return t.error(o,{},r),{statusCode:500,body:JSON.stringify({message:o})}}};export const routeWebhookRequests=(u,l)=>handleWebhookSafely(async p=>{if(!p.body)throw Error("No body found in the webhook event!");let g=JSON.parse(p.isBase64Encoded?Buffer.from(p.body,"base64").toString():p.body);return t(p.queryStringParameters?.o).with(f,async()=>{if(l.info("Handling auth operation."),!u.onAuth)throw Error("Auth operation is not configured for this webhook!");let o=e.parse(g);return{statusCode:200,body:JSON.stringify(await u.onAuth(o,p))}}).with(d,async()=>{if(l.info("Handling configurator callback operation."),!u.configurator?.onCallback)throw Error("Auth operation is not configured for this webhook!");let o=a.parse(g);return{statusCode:200,body:JSON.stringify(await u.configurator.onCallback(o,p))}}).with(o.union(void 0,c),()=>t(p.queryStringParameters?.t).with(r.Admin,async()=>{if(l.info("Handling admin finalize operation."),!u.admin?.onFinalize)throw Error("Admin finalize operation is not configured for this webhook!");let o=s.parse(g),t=await u.admin.onFinalize(o,p);return n(t),{statusCode:200,body:JSON.stringify(t)}}).with(o.union(void 0,r.Configurator),async()=>{if(l.info("Handling configurator finalize operation."),!u.configurator?.onFinalize)throw Error("Configurator finalize operation is not configured for this webhook!");let o=s.parse(g),t=await u.configurator.onFinalize(o,p);return n(t),{statusCode:200,body:JSON.stringify(t)}}).otherwise(o=>{throw Error(`Can not parse application type - unknown type: ${o}!`)})).with(h,async()=>{if(l.info("Handling fetch backend data operation."),!u.configurator?.onFetchBackendData)throw Error("Fetch backend data operation is not configured for this webhook!");let o=i.parse(g);return{statusCode:200,body:JSON.stringify(await u.configurator.onFetchBackendData(o,p))}}).otherwise(o=>{throw Error(`Can not parse webhook operation - unknown operation: ${o}!`)})},l);
|