go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/nodes/static/_nextjs/src/api/nodes.ts (about)

     1  /**
     2   * Copyright (c) 2024 - Present. Will Charczuk. All rights reserved.
     3   * Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     4   */
     5  export interface Node {
     6    id: string;
     7    label: string;
     8    metadata: NodeMetadata;
     9  }
    10  
    11  export interface NodeMetadata {
    12    collapsed?: boolean;
    13    expression?: string;
    14    input_type?: string;
    15    node_type: string;
    16    output_type?: string;
    17    parent_node_id?: string;
    18    position_x: number;
    19    position_y: number;
    20    height?: number;
    21    width?: number;
    22    watched?: boolean;
    23    watched_collapsed?: boolean;
    24  }
    25  
    26  export const defaultNodeType = 'var';
    27  
    28  export const emptyNode: Node = {
    29    id: '',
    30    label: '',
    31    metadata: {
    32      node_type: defaultNodeType,
    33      position_x: 0,
    34      position_y: 0,
    35    }
    36  }
    37  
    38  export interface Edge {
    39    parent_id: string;
    40    child_id: string;
    41    child_input_name: string | null;
    42  }
    43  
    44  export interface Table {
    45    columns: TableColumn[];
    46  }
    47  
    48  export interface TableColumn {
    49    name?: string;
    50    value_type?: string;
    51    values: any[];
    52  }
    53  
    54  export interface TableRange {
    55    top: number;
    56    left: number;
    57    bottom: number;
    58    right: number;
    59  }
    60  
    61  export interface TableInfo {
    62    rows: number;
    63    columns: string[];
    64  }
    65  
    66  export function tableColumnNames(table: Table): Array<string> {
    67    if (!table.columns || table.columns.length === 0) {
    68      return []
    69    }
    70    return table.columns.map(c => c.name || '')
    71  }
    72  
    73  export function tableMaxRows(table: Table): number {
    74    const columnRowCounts = table && table.columns ? (table.columns.map(c => c.values ? c.values.length : 0)) : [];
    75    let maxRowCount = 0;
    76    for (const count of columnRowCounts) {
    77      if (count > maxRowCount) {
    78        maxRowCount = count
    79      }
    80    }
    81    return maxRowCount
    82  }
    83  
    84  export function tableRowCol(table: Table, row: number, col: number): any {
    85    if (!table.columns) {
    86      return ''
    87    }
    88    if (col < 0 || col >= table.columns.length) {
    89      return ''
    90    }
    91    if (!table.columns[col].values) {
    92      return ''
    93    }
    94    if (row < 0 || row >= table.columns[col].values.length) {
    95      return ''
    96    }
    97    return table.columns[col].values[row]
    98  }
    99  
   100  export interface NodeValue {
   101    id: string;
   102    value: any;
   103  }
   104  
   105  export function nodeLabelOrID(n: Node): string {
   106    if (n.label !== undefined && n.label !== null && n.label !== "") {
   107      return n.label
   108    }
   109    return n.id
   110  }
   111  
   112  export const sortNodesByLabelAsc = (a: Node, b: Node) => {
   113    if (a.label < b.label) {
   114      return -1;
   115    }
   116    if (a.label > b.label) {
   117      return 1
   118    }
   119    return 0
   120  }
   121  export const sortNodesByLabelDesc = (a: Node, b: Node) => {
   122    if (a.label < b.label) {
   123      return 1;
   124    }
   125    if (a.label > b.label) {
   126      return -1
   127    }
   128    return 0
   129  }
   130  
   131  export type NativeValueScalarType = boolean | string | number | Date;
   132  export type NativeValueArrayType = Array<NativeValueScalarType>;
   133  export type NativeValueType = NativeValueScalarType | NativeValueArrayType | Table;
   134  
   135  export async function getNode(graphId: string, node_id: string): Promise<Node> {
   136    const res = await fetch(`/api/v1/graph/${graphId}/node/${node_id}`);
   137    if (!res?.ok) {
   138      const message = (await res.json()) as string;
   139      throw new Error(message)
   140    }
   141    const data = await res.json();
   142    return data as Node;
   143  };
   144  
   145  export async function getNodes(graphId: string): Promise<Node[]> {
   146    const res = await fetch(`/api/v1/graph/${graphId}/nodes`);
   147    if (!res?.ok) {
   148      const message = (await res.json()) as string;
   149      throw new Error(message)
   150    }
   151    const data = await res.json();
   152    return data as Node[];
   153  };
   154  
   155  
   156  export async function getEdges(graphId: string): Promise<Edge[]> {
   157    const res = await fetch(`/api/v1/graph/${graphId}/edges`);
   158    if (!res?.ok) {
   159      const message = (await res.json()) as string;
   160      throw new Error(message)
   161    }
   162    const data = await res.json();
   163    return data as Edge[];
   164  };
   165  
   166  export async function getNodeValue(graphId: string, id: string): Promise<any> {
   167    const res = await fetch(`/api/v1/graph/${graphId}/node.value/${id}`);
   168    if (res.status == 404) {
   169      return undefined
   170    }
   171    if (!res?.ok) {
   172      const message = (await res.json()) as string;
   173      throw new Error(message)
   174    }
   175    const data = await res.json();
   176    return data as any;
   177  };
   178  
   179  export async function getNodeValues(graphId: string, ids: string[]): Promise<NodeValue[]> {
   180    const res = await fetch(`/api/v1/graph/${graphId}/node.values?ids=${ids.join(',')}`);
   181    const data = await res.json();
   182    return data as NodeValue[];
   183  };
   184  
   185  export async function getNodeValueTableInfo(graphId: string, id: string): Promise<TableInfo> {
   186    const res = await fetch(`/api/v1/graph/${graphId}/node.value.table/${id}/info`)
   187    if (res.status == 404) {
   188      return { rows: 0, columns: [] }
   189    }
   190    if (!res?.ok) {
   191      const message = (await res.json()) as string;
   192      throw new Error(message)
   193    }
   194    const data = await res.json();
   195    return data as TableInfo;
   196  };
   197  
   198  export async function getNodeValueTableRange(graphId: string, id: string, range: { top: number, left: number, bottom: number, right: number }): Promise<any[][]> {
   199    const res = await fetch(`/api/v1/graph/${graphId}/node.value.table/${id}/range?range=${range.top},${range.left},${range.bottom},${range.right}`);
   200    if (res.status == 404) {
   201      return []
   202    }
   203    if (!res?.ok) {
   204      const message = (await res.json()) as string;
   205      throw new Error(message)
   206    }
   207    const data = await res.json();
   208    return data as any[][];
   209  };
   210  
   211  export async function putNodeValueTable(graphId: string, id: string, ops: Array<any>): Promise<void> {
   212    const res = await fetch(`/api/v1/graph/${graphId}/node.value.table/${id}`, {
   213      method: "PUT",
   214      body: JSON.stringify(ops),
   215    });
   216    if (!res?.ok) {
   217      const message = (await res.json()) as string;
   218      throw new Error(message)
   219    }
   220  }
   221  
   222  type PostedNode = Omit<Node, 'id'> & { id?: string };
   223  
   224  export async function postNode(graphId: string, node: PostedNode): Promise<string> {
   225    // rip id off the payload (we can't use interfaces
   226    // because types in typescript are an illusion).
   227    const { id, ...body }: PostedNode = node;
   228    const res = await fetch(`/api/v1/graph/${graphId}/node`, {
   229      method: "POST",
   230      body: JSON.stringify(body),
   231    });
   232    if (!res?.ok) {
   233      const message = (await res.json()) as string;
   234      throw new Error(message)
   235    }
   236    const data = await res.json()
   237    return data as string;
   238  };
   239  
   240  export async function patchNodes(graphId: string, patchData: { [key: string]: any }): Promise<void> {
   241    const res = await fetch(`/api/v1/graph/${graphId}/nodes`, {
   242      method: "PATCH",
   243      body: JSON.stringify(patchData),
   244    });
   245    if (!res?.ok) {
   246      const message = (await res.json()) as string;
   247      throw new Error(message)
   248    }
   249  };
   250  
   251  export async function patchNode(graphId: string, id: string, patchData: { [key: string]: any }): Promise<void> {
   252    const res = await fetch(`/api/v1/graph/${graphId}/node/${id}`, {
   253      method: "PATCH",
   254      body: JSON.stringify(patchData),
   255    });
   256    if (!res?.ok) {
   257      const message = (await res.json()) as string;
   258      throw new Error(message)
   259    }
   260  };
   261  
   262  export async function postNodeStale(graphId: string, id: string): Promise<void> {
   263    const res = await fetch(`/api/v1/graph/${graphId}/node.stale/${id}`, {
   264      method: "POST",
   265    });
   266    if (!res?.ok) {
   267      const message = (await res.json()) as string;
   268      throw new Error(message)
   269    }
   270  };
   271  
   272  export async function putNodeValue(graphId: string, id: string, value: any): Promise<void> {
   273    const res = await fetch(`/api/v1/graph/${graphId}/node.value/${id}`, {
   274      method: "PUT",
   275      body: JSON.stringify(value),
   276    });
   277    if (!res?.ok) {
   278      const message = (await res.json()) as string;
   279      throw new Error(message)
   280    }
   281  };
   282  
   283  export async function postEdge(graphId: string, e: Edge): Promise<void> {
   284    let url = `/api/v1/graph/${graphId}/edge`
   285    const res = await fetch(url, {
   286      method: "POST",
   287      body: JSON.stringify(e)
   288    });
   289    if (!res?.ok) {
   290      const message = (await res.json()) as string;
   291      throw new Error(message)
   292    }
   293  };
   294  
   295  export async function deleteEdge(graphId: string, e: Edge): Promise<void> {
   296    let url = `/api/v1/graph/${graphId}/edge`
   297    const res = await fetch(url, {
   298      method: "DELETE",
   299      body: JSON.stringify(e)
   300    });
   301    if (!res?.ok) {
   302      const message = (await res.json()) as string;
   303      throw new Error(message)
   304    }
   305  };
   306  
   307  export async function deleteNode(graphId: string, nodeID: string): Promise<void> {
   308    const res = await fetch(`/api/v1/graph/${graphId}/node/${nodeID}`, {
   309      method: "DELETE",
   310    });
   311    if (!res?.ok) {
   312      const message = (await res.json()) as string;
   313      throw new Error(message)
   314    }
   315  };
   316  
   317  export async function postNodeTableImportCsv(graphId: string, nodeId: string, file: FileList): Promise<void> {
   318    const formData = new FormData();
   319    formData.append('file', file[0]);
   320  
   321    // Make a POST request to the server
   322    const res = await fetch(`/api/v1/graph/${graphId}/node.value.table/${nodeId}/csv`, {
   323      method: 'POST',
   324      body: formData,
   325    });
   326    if (!res?.ok) {
   327      const message = (await res.json()) as string;
   328      throw new Error(message)
   329    }
   330  }