import {z} from 'zod' export type SyncsConnectionItem = {one_api?: (number | null) | undefined, connection_type?: (number | null) | undefined, display_order?: number | undefined, display_hidden?: boolean | undefined}; export type FieldItemType = 'fixed' | 'api'; export type FieldItemValue = {id: string, label: string}; export type FieldItem = {name: string, type: FieldItemType, display_condition?: ({[key: string]: unknown} | null) | undefined, values?: (Array | null) | undefined, api_route?: (string | null) | undefined, connection_type?: (number | null) | undefined}; export type CreateSyncMappingToFieldItemInput = {name: string, description?: (string | null) | undefined, display_order?: number | undefined, challenge_question?: (string | null) | undefined, conditions?: ({[key: string]: {[key: string]: unknown}} | null) | undefined, source_field: FieldItem, target_field: FieldItem, display_delete?: boolean | undefined, logic?: ({[key: string]: unknown} | null) | undefined, manual_mapping?: boolean | undefined}; export type CreateSyncMappingItemInput = {name: string, description?: (string | null) | undefined, display_order?: number | undefined, challenge_question?: (string | null) | undefined, conditions?: ({[key: string]: {[key: string]: unknown}} | null) | undefined, sub_mappings?: Array | undefined}; export type ExecutionType = 'code' | 'module'; export type FlowExecutionChain = {name: string}; export type FlowExecutionCode = {code: string}; export type FlowExecution = {type: ExecutionType, data: FlowExecutionChain | FlowExecutionCode | null}; export type DatastoreStatus = 'active' | 'inactive'; export type DatastoreColumn = {name: string, title: string, type: string, optional?: (boolean | null) | undefined}; export type DatastoreDef = {columns: Array, search_column?: (string | null) | undefined}; export type FlowDataStoreItemInput = {id?: (string | null) | undefined, name: string, status?: (DatastoreStatus | null) | undefined, definition: DatastoreDef}; export type FlowConfigInput = {definitionFields?: (Array<{[key: string]: unknown}> | null) | undefined, doorkeyFields?: (Array<{[key: string]: unknown}> | null) | undefined, customFields?: (Array<{[key: string]: unknown}> | null) | undefined, datastores?: (Array | null) | undefined}; export type TriggerType = 'timer' | 'event'; export type TriggerPriority = 'NORMAL' | 'MEDIUM' | 'HIGH'; export type FlowTrigger = {id: string, type: TriggerType, cronschedules?: (Array | null) | undefined, visible?: (boolean | null) | undefined, definitionFields?: (Array<{[key: string]: unknown}> | null) | undefined, options?: ({[key: string]: unknown} | null) | undefined, priority?: TriggerPriority | undefined}; export type CreateFlowItem = {name: string, description?: (string | null) | undefined, execution: FlowExecution, config?: (FlowConfigInput | null) | undefined, triggers: Array}; export type CreateSyncItem = {name: string, config?: ({[key: string]: unknown} | null) | undefined, connections: Array, mappings?: Array | undefined, flows?: Array | undefined}; export type CreateAgenticSyncItem = {module: string}; export type CreateApiSyncsArgs = {body: CreateSyncItem | CreateAgenticSyncItem}; export type CreateApiSyncsOptions = {baseUrl?: string | undefined, bearerAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const syncsConnectionItem = z.object({one_api: z.number().int().nullable().optional(), connection_type: z.number().int().nullable().optional(), display_order: z.number().int().optional(), display_hidden: z.boolean().optional()}); export const fieldItemType = z.enum(["fixed", "api"]); export const fieldItemValue = z.object({id: z.string(), label: z.string()}); export const fieldItem = z.object({name: z.string(), type: fieldItemType, display_condition: z.record(z.string(), z.unknown()).nullable().optional(), values: z.array(fieldItemValue).nullable().optional(), api_route: z.string().nullable().optional(), connection_type: z.number().int().nullable().optional()}); export const createSyncMappingToFieldItemOutput = z.object({name: z.string(), description: z.string().nullable().optional(), display_order: z.number().int().optional(), challenge_question: z.string().nullable().optional(), conditions: z.record(z.string(), z.record(z.string(), z.unknown())).nullable().optional(), source_field: fieldItem, target_field: fieldItem, display_delete: z.boolean().optional(), logic: z.record(z.string(), z.unknown()).nullable().optional(), manual_mapping: z.boolean().optional()}); export const createSyncMappingItemOutput = z.object({name: z.string(), description: z.string().nullable().optional(), display_order: z.number().int().optional(), challenge_question: z.string().nullable().optional(), conditions: z.record(z.string(), z.record(z.string(), z.unknown())).nullable().optional(), sub_mappings: z.array(createSyncMappingToFieldItemOutput).optional()}); export const executionType = z.enum(["code", "module"]); export const flowExecutionChain = z.object({name: z.string()}); export const flowExecutionCode = z.object({code: z.string()}); export const flowExecution = z.object({type: executionType, data: z.union([flowExecutionChain, flowExecutionCode]).nullable()}); export const datastoreStatus = z.enum(["active", "inactive"]); export const datastoreColumn = z.object({name: z.string(), title: z.string(), type: z.string(), optional: z.boolean().nullable().optional()}); export const datastoreDef = z.object({columns: z.array(datastoreColumn), search_column: z.string().nullable().optional()}); export const flowDataStoreItemOutput = z.object({id: z.string().nullable().optional(), name: z.string(), status: datastoreStatus.nullable().optional(), definition: datastoreDef}); export const flowConfigOutput = z.object({definitionFields: z.array(z.record(z.string(), z.unknown())).nullable().optional(), doorkeyFields: z.array(z.record(z.string(), z.unknown())).nullable().optional(), customFields: z.array(z.record(z.string(), z.unknown())).nullable().optional(), datastores: z.array(flowDataStoreItemOutput).nullable().optional()}); export const triggerType = z.enum(["timer", "event"]); export const triggerPriority = z.enum(["NORMAL", "MEDIUM", "HIGH"]); export const flowTrigger = z.object({id: z.string(), type: triggerType, cronschedules: z.array(z.string()).nullable().optional(), visible: z.boolean().nullable().optional(), definitionFields: z.array(z.record(z.string(), z.unknown())).nullable().optional(), options: z.record(z.string(), z.unknown()).nullable().optional(), priority: triggerPriority.optional()}); export const readFlowItem = z.object({name: z.string(), description: z.string().nullable().optional(), id: z.string(), execution: flowExecution.nullable().optional(), config: flowConfigOutput.nullable().optional(), triggers: z.array(flowTrigger).nullable().optional()}); export const objectKindItem = z.object({kind: z.string(), capability: z.string()}); export const readSyncItem = z.object({name: z.string().min(1), config: z.record(z.string(), z.unknown()).nullable().optional(), connections: z.array(syncsConnectionItem), mappings: z.array(createSyncMappingItemOutput).optional(), syncid: z.string(), consumers: z.array(z.string()), flows: z.array(readFlowItem), module: z.string().nullable().optional(), object_kinds: z.array(objectKindItem).nullable().optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Create sync * * POST /syncs */ export const createApiSyncs = async (args: CreateApiSyncsArgs, options?: CreateApiSyncsOptions) => { const {baseUrl = "https://api.chift.eu", fetch: fetchFn = fetch, bearerAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (bearerAuth !== undefined) headers.set('authorization', `Bearer ${bearerAuth}`) const url = `${baseUrl.replace(/\/+$/, '')}/syncs${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(readSyncItem, await res.json()) };