All files ajax.ts

100% Statements 16/16
100% Branches 6/6
100% Functions 4/4
100% Lines 16/16

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66                                7x 7x           7x 1x   6x 6x 1x   5x 5x 1x   4x                       1x   1x 1x                   1x     1x      
import type { Client, EditorData, SaveRequest, SaveResult } from './types';
 
declare global {
  // Moodle puts its config on window.M.
  // eslint-disable-next-line no-var
  var M: { cfg: { wwwroot: string; sesskey: string } };
}
 
interface ServiceReply {
  error: boolean;
  data?: unknown;
  exception?: { message: string };
}
 
/** Calls one web service function the way core/ajax does: a POST to lib/ajax/service.php. */
export async function callService<T>(methodname: string, args: Record<string, unknown>): Promise<T> {
  const { wwwroot, sesskey } = globalThis.M.cfg;
  const response = await fetch(`${wwwroot}/lib/ajax/service.php?sesskey=${sesskey}&info=${methodname}`, {
    method: 'POST',
    credentials: 'same-origin',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify([{ index: 0, methodname, args }]),
  });
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
  }
  const replies: unknown = await response.json();
  if (!Array.isArray(replies)) {
    throw new Error(`Unexpected reply from ${methodname}`);
  }
  const reply = replies[0] as ServiceReply;
  if (reply.error) {
    throw new Error(reply.exception?.message);
  }
  return reply.data as T;
}
 
interface RawEditorData extends Omit<EditorData, 'graph' | 'nodetypes' | 'events' | 'functions' | 'strings'> {
  graph: string;
  nodetypes: string;
  events: string;
  functions: string;
  strings: string;
}
 
/** The real client, talking to Moodle. */
export const moodleClient: Client = {
  async load(workflowid) {
    const raw = await callService<RawEditorData>('tool_autoflow_get_editor', { workflowid });
    return {
      ...raw,
      graph: JSON.parse(raw.graph),
      nodetypes: JSON.parse(raw.nodetypes),
      events: JSON.parse(raw.events),
      functions: JSON.parse(raw.functions),
      strings: JSON.parse(raw.strings),
    };
  },
  save(request: SaveRequest) {
    return callService<SaveResult>('tool_autoflow_save_workflow', { ...request, graph: JSON.stringify(request.graph) });
  },
  async run(workflowid) {
    return (await callService<{ queued: boolean }>('tool_autoflow_run_workflow', { id: workflowid })).queued;
  },
};