[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/feast-dev/feast/stable/ui/src/setupProxy.js [Back]  [Original]

const fs = require("fs");
const path = require("path");
const express = require("express");
const { feast } = require("./protos");

const registryBuf = fs.readFileSync(
  path.resolve(__dirname, "../public/registry.db"),
);
const parsedRegistry = feast.core.Registry.decode(registryBuf);
const projectsList = JSON.parse(
  fs.readFileSync(path.resolve(__dirname, "../public/projects-list.json")),
);

const toJSON = (obj) => (obj && obj.toJSON ? obj.toJSON() : obj);

const withType = (type) => (fv) => ({
  ...toJSON(fv),
  type,
});

const state = {
  entities: (parsedRegistry.entities || []).map(toJSON),
  featureViews: (parsedRegistry.featureViews || []).map(
    withType("featureView"),
  ),
  onDemandFeatureViews: (parsedRegistry.onDemandFeatureViews || []).map(
    withType("onDemandFeatureView"),
  ),
  streamFeatureViews: (parsedRegistry.streamFeatureViews || []).map(
    withType("streamFeatureView"),
  ),
  featureServices: (parsedRegistry.featureServices || []).map(toJSON),
  dataSources: (parsedRegistry.dataSources || []).map(toJSON),
  savedDatasets: (parsedRegistry.savedDatasets || []).map(toJSON),
  projects: (parsedRegistry.projects || []).map(toJSON),
};

const allFeatureViews = () => [
  ...state.featureViews,
  ...state.onDemandFeatureViews,
  ...state.streamFeatureViews,
];

const objectProject = (obj) => obj?.spec?.project || obj?.project;

const filterByProject = (items, project) => {
  if (!project || project === "all") return items;
  return items.filter((item) => objectProject(item) === project);
};

const allFeatures = (project) =>
  filterByProject(allFeatureViews(), project).flatMap((fv) =>
    (fv?.spec?.features || []).map((feature) => ({
      name: feature.name,
      featureViewName: fv.spec?.name,
      valueType: feature.valueType,
      project: fv.spec?.project,
    })),
  );

const responseList = (res, key, items) => {
  res.json({
    [key]: items,
    pagination: {},
    relationships: {},
  });
};

const findByName = (items, name) =>
  items.find((item) => item?.spec?.name === name || item?.name === name);

const entityPayloadToResource = (payload) => ({
  spec: {
    name: payload.name,
    joinKey: payload.join_key || payload.name,
    valueType: payload.value_type,
    description: payload.description || "",
    tags: payload.tags || {},
    owner: payload.owner || "",
    project: payload.project,
  },
  meta: {},
});

const dataSourcePayloadToResource = (payload) => ({
  name: payload.name,
  type: payload.type,
  timestampField: payload.timestamp_field,
  fieldMapping: payload.field_mapping || {},
  description: payload.description || "",
  tags: payload.tags || {},
  owner: payload.owner || "",
  project: payload.project,
  fileOptions: payload.file_options,
  bigqueryOptions: payload.bigquery_options,
  snowflakeOptions: payload.snowflake_options,
  redshiftOptions: payload.redshift_options,
  kafkaOptions: payload.kafka_options,
  sparkOptions: payload.spark_options,
});

const featureViewPayloadToResource = (payload) => ({
  spec: {
    name: payload.name,
    description: payload.description || "",
    owner: payload.owner || "",
    entities: payload.entities || [],
    features: payload.features || [],
    ttl: payload.ttl,
    online: payload.online,
    tags: payload.tags || {},
    project: payload.project,
    batchSource: payload.batch_source
      ? { name: payload.batch_source }
      : undefined,
  },
  meta: {},
  type: "featureView",
});

module.exports = function setupProxy(app) {
  app.use("/api/v1", express.json());

  app.get("/projects-list.json", (_req, res) => {
    res.json({
      ...projectsList,
      projects: projectsList.projects.map((project) =>
        project.id === "credit_scoring_aws"
          ? { ...project, registryPath: "/api/v1" }
          : project,
      ),
    });
  });

  app.get("/api/v1/entities/all", (_req, res) =>
    responseList(res, "entities", state.entities),
  );
  app.get("/api/v1/feature_views/all", (_req, res) =>
    responseList(res, "featureViews", allFeatureViews()),
  );
  app.get("/api/v1/feature_services/all", (_req, res) =>
    responseList(res, "featureServices", state.featureServices),
  );
  app.get("/api/v1/data_sources/all", (_req, res) =>
    responseList(res, "dataSources", state.dataSources),
  );
  app.get("/api/v1/saved_datasets/all", (_req, res) =>
    responseList(res, "savedDatasets", state.savedDatasets),
  );
  app.get("/api/v1/features/all", (_req, res) =>
    responseList(res, "features", allFeatures()),
  );
  app.get("/api/v1/label_views/all", (_req, res) =>
    responseList(res, "featureViews", []),
  );

  app.get("/api/v1/entities", (req, res) =>
    responseList(
      res,
      "entities",
      filterByProject(state.entities, req.query.project),
    ),
  );
  app.get("/api/v1/feature_views", (req, res) =>
    responseList(
      res,
      "featureViews",
      filterByProject(allFeatureViews(), req.query.project),
    ),
  );
  app.get("/api/v1/feature_services", (req, res) =>
    responseList(
      res,
      "featureServices",
      filterByProject(state.featureServices, req.query.project),
    ),
  );
  app.get("/api/v1/data_sources", (req, res) =>
    responseList(
      res,
      "dataSources",
      filterByProject(state.dataSources, req.query.project),
    ),
  );
  app.get("/api/v1/saved_datasets", (req, res) =>
    responseList(
      res,
      "savedDatasets",
      filterByProject(state.savedDatasets, req.query.project),
    ),
  );
  app.get("/api/v1/features", (req, res) =>
    responseList(res, "features", allFeatures(req.query.project)),
  );
  app.get("/api/v1/label_views", (_req, res) =>
    responseList(res, "featureViews", []),
  );
  app.get("/api/v1/labels", (_req, res) => responseList(res, "labels", []));
  app.get("/api/v1/projects", (_req, res) =>
    responseList(res, "projects", state.projects),
  );
  app.get("/api/v1/permissions", (_req, res) =>
    responseList(res, "permissions", []),
  );
  app.get("/api/v1/metrics/:type", (_req, res) => res.json({}));

  app.get("/api/v1/entities/:name", (req, res) => {
    const entity = findByName(state.entities, req.params.name);
    if (!entity) return res.status(404).json({ detail: "Not found" });
    return res.json(entity);
  });
  app.get("/api/v1/feature_views/:name", (req, res) => {
    const featureView = findByName(allFeatureViews(), req.params.name);
    if (!featureView) return res.status(404).json({ detail: "Not found" });
    return res.json(featureView);
  });
  app.get("/api/v1/feature_services/:name", (req, res) => {
    const featureService = findByName(state.featureServices, req.params.name);
    if (!featureService) return res.status(404).json({ detail: "Not found" });
    return res.json(featureService);
  });
  app.get("/api/v1/data_sources/:name", (req, res) => {
    const dataSource = findByName(state.dataSources, req.params.name);
    if (!dataSource) return res.status(404).json({ detail: "Not found" });
    return res.json(dataSource);
  });
  app.get("/api/v1/saved_datasets/:name", (req, res) => {
    const savedDataset = findByName(state.savedDatasets, req.params.name);
    if (!savedDataset) return res.status(404).json({ detail: "Not found" });
    return res.json(savedDataset);
  });
  app.get("/api/v1/features/:fvName/:featureName", (req, res) => {
    const featureView = findByName(allFeatureViews(), req.params.fvName);
    const feature = featureView?.spec?.features?.find(
      (f) => f.name === req.params.featureName,
    );
    if (!feature) return res.status(404).json({ detail: "Not found" });
    return res.json({
      featureViewName: req.params.fvName,
      featureName: req.params.featureName,
      feature,
      featureView,
    });
  });

  app.post("/api/v1/entities", (req, res) => {
    const body = req.body || {};
    const existingIndex = state.entities.findIndex(
      (entity) => entity?.spec?.name === body.name,
    );
    const entity = entityPayloadToResource(body);
    if (existingIndex >= 0) {
      state.entities[existingIndex] = entity;
    } else {
      state.entities.push(entity);
    }
    res.json({
      name: body.name,
      project: body.project,
      status: "applied",
    });
  });

  app.post("/api/v1/data_sources", (req, res) => {
    const body = req.body || {};
    const existingIndex = state.dataSources.findIndex(
      (dataSource) => dataSource?.name === body.name,
    );
    const dataSource = dataSourcePayloadToResource(body);
    if (existingIndex >= 0) {
      state.dataSources[existingIndex] = dataSource;
    } else {
      state.dataSources.push(dataSource);
    }
    res.json({
      name: body.name,
      project: body.project,
      status: "applied",
    });
  });

  app.post("/api/v1/feature_views", (req, res) => {
    const body = req.body || {};
    const existingIndex = state.featureViews.findIndex(
      (featureView) => featureView?.spec?.name === body.name,
    );
    const featureView = featureViewPayloadToResource(body);
    if (existingIndex >= 0) {
      state.featureViews[existingIndex] = featureView;
    } else {
      state.featureViews.push(featureView);
    }
    res.json({
      name: body.name,
      project: body.project,
      status: "applied",
    });
  });

  app.delete("/api/v1/entities/:name", (req, res) => {
    state.entities = state.entities.filter(
      (entity) => entity?.spec?.name !== req.params.name,
    );
    res.json({
      name: req.params.name,
      project: req.query.project,
      status: "deleted",
    });
  });

  app.delete("/api/v1/data_sources/:name", (req, res) => {
    state.dataSources = state.dataSources.filter(
      (dataSource) => dataSource?.name !== req.params.name,
    );
    res.json({
      name: req.params.name,
      project: req.query.project,
      status: "deleted",
    });
  });

  app.delete("/api/v1/feature_views/:name", (req, res) => {
    state.featureViews = state.featureViews.filter(
      (featureView) => featureView?.spec?.name !== req.params.name,
    );
    res.json({
      name: req.params.name,
      project: req.query.project,
      status: "deleted",
    });
  });
};

Web Proxy Viewer  |  New URL  |  Original Page