Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frontend-dev.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG NODE_TAG="18.20-alpine@sha256:b33d7471a6a5106cceb3b6e4368841e06338ff6e5e8b2ff345e2e17f15902d7d"
ARG NODE_TAG="18.20.8-alpine@sha256:929b04d7c782f04f615cf785488fed452b6569f87c73ff666ad553a7554f0006"

FROM node:${NODE_TAG}

Expand Down
2 changes: 1 addition & 1 deletion frontend-prod.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG NODE_TAG="18.20-alpine@sha256:b33d7471a6a5106cceb3b6e4368841e06338ff6e5e8b2ff345e2e17f15902d7d"
ARG NODE_TAG="18.20.8-alpine@sha256:929b04d7c782f04f615cf785488fed452b6569f87c73ff666ad553a7554f0006"
ARG NGINX_TAG="1.23-alpine@sha256:b5fe08305969d68f9d44309ea30f02a7dfbefe6e429f8c3f3f348fa45600f8b2"

###########################################
Expand Down
49 changes: 24 additions & 25 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import eslintCore from "@eslint/js";

import configPrettier from "eslint-config-prettier";
import * as importPlugin from "eslint-plugin-import";
import reactPlugin from "eslint-plugin-react";
Expand Down Expand Up @@ -43,7 +42,7 @@ export default eslintTypescript.config(
// ! Make sure prettier is *after* other plugins, so it can override
configPrettier,

{ ignores: ["scripts/", "playwright/", "coverage/", "dist/"] },
{ ignores: ["scripts/", "playwright/", "coverage/", "dist/", "src/api/autogen"] },

// Other configs -------------------------------------------------------------------
{
Expand All @@ -66,29 +65,29 @@ export default eslintTypescript.config(
"no-console": ["error", { allow: ["debug", "info", "warn", "error"] }],
"import/no-named-as-default-member": "off", // Conflicts with us requiring always using the react default
"import/order": [
"warn",
{
groups: [
"builtin", // Node.js builtins: fs, path, etc.
"external", // Packages from node_modules
"internal", // Aliased paths (e.g. @, @core)
"parent", // ../
"sibling", // ./file
"index", // ./index
],
pathGroups: [
{ pattern: "react", group: "external", position: "before" },
{ pattern: "@core/**", group: "internal", position: "before" },
{ pattern: "@components/**", group: "internal", position: "before" },
{ pattern: "@shared-types/**", group: "internal", position: "before" },
{ pattern: "@assets/**", group: "internal", position: "before" },
{ pattern: "@/**", group: "internal" }, // fallback for anything else under @
],
pathGroupsExcludedImportTypes: ["react"],
alphabetize: { order: "asc", caseInsensitive: true },
"newlines-between": "always",
},
],
"warn",
{
groups: [
"builtin", // Node.js builtins: fs, path, etc.
"external", // Packages from node_modules
"internal", // Aliased paths (e.g. @, @core)
"parent", // ../
"sibling", // ./file
"index", // ./index
],
pathGroups: [
{ pattern: "react", group: "external", position: "before" },
{ pattern: "@core/**", group: "internal", position: "before" },
{ pattern: "@components/**", group: "internal", position: "before" },
{ pattern: "@shared-types/**", group: "internal", position: "before" },
{ pattern: "@assets/**", group: "internal", position: "before" },
{ pattern: "@/**", group: "internal" }, // fallback for anything else under @
],
pathGroupsExcludedImportTypes: ["react"],
alphabetize: { order: "asc", caseInsensitive: true },
"newlines-between": "always",
},
],
},
},
);
21 changes: 9 additions & 12 deletions frontend/open-api/cachebusting-plugin/config.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import type { Plugin } from "@hey-api/openapi-ts";
import { definePluginConfig } from "@hey-api/openapi-ts";

import { handler } from "./plugin";
import type { Config } from "./types";
import type { CacheBustingPlugin } from "./types";

export const defaultConfig: Plugin.Config<Config> = {
export const defaultConfig: CacheBustingPlugin["Config"] = {
name: "cache-busting",
output: "types",
cacheKey: "t",
// No need to define this
_handlerLegacy: () => {},
_handler: handler,
handler: handler,
output: {},
config: {
cacheKey: "t",
},
};

export const makePlugin: Plugin.DefineConfig<Config> = (config) => ({
...defaultConfig,
...config,
});
export const makePlugin = definePluginConfig(defaultConfig);
2 changes: 1 addition & 1 deletion frontend/open-api/cachebusting-plugin/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { defaultConfig, makePlugin } from "./config";
export type { Config } from "./types";
export type { CacheBustingPlugin } from "./types";
25 changes: 12 additions & 13 deletions frontend/open-api/cachebusting-plugin/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { IR, Plugin } from "@hey-api/openapi-ts";
import type { IR } from "@hey-api/openapi-ts";
import { set } from "lodash";

import type { Config } from "./types";
import type { CacheBustingPlugin } from "./types";

export const handler: Plugin.Handler<Config> = ({ context, plugin }) => {
const cacheKeyCfg = plugin.cacheKey;
export const handler: CacheBustingPlugin["Handler"] = ({ plugin }) => {
const cacheKeyCfg = plugin.config.cacheKey;

let cacheKey: string;
let cacheParmObj: IR.ParameterObject;
Expand All @@ -22,15 +23,13 @@ export const handler: Plugin.Handler<Config> = ({ context, plugin }) => {
};
}

context.subscribe("operation", (ctx) => {
const existingParams = ctx.operation.parameters;
plugin.forEach("operation", (event) => {
if (event.operation.parameters?.query?.[cacheKey]) {
throw Error(
`Cannot add cache busting parameter. Operation ${event.operation.id} already has already defined ${cacheKey} as a query field!`,
);
}

ctx.operation.parameters = {
...existingParams,
query: {
...existingParams?.query,
[cacheKey]: cacheParmObj,
},
};
set(event, `operation.parameters.query.${cacheKey}`, cacheParmObj);
});
};
12 changes: 7 additions & 5 deletions frontend/open-api/cachebusting-plugin/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import type { IR } from "@hey-api/openapi-ts";
import type { DefinePlugin, IR } from "@hey-api/openapi-ts";

export interface Config {
/**
* The name of the plugin.
*/
name: "cache-busting";
/**
* Name of the generated file.
*/
output: "types";
// /**
// * Name of the generated file.
// */
// output: "";

/**
* The query parameter to use for caching
* @default "t"
*/
cacheKey?: string | IR.ParameterObject;
}

export type CacheBustingPlugin = DefinePlugin<Config>;
53 changes: 47 additions & 6 deletions frontend/openapi-ts.config.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,64 @@
import { defaultPlugins, defineConfig } from "@hey-api/openapi-ts";
import { defineConfig } from "@hey-api/openapi-ts";
import { startCase } from "lodash";

import { makePlugin as cacheBustingPlugin } from "./open-api/cachebusting-plugin";

function addSuffix(name: string, categoricalSuffix = "", coreSuffix = "_api"): string {
const pascalCasedName = startCase(name).replaceAll(" ", "");
const suffixedName = pascalCasedName + categoricalSuffix + coreSuffix;

return suffixedName;
}

export default defineConfig({
client: "@hey-api/client-axios",
input: "http://localhost:5000/openapi.json",
output: {
format: "prettier",
lint: "eslint",
path: "./src/api/autogen/",
// (Revert v0.67) Don't append js to relative paths
tsConfigPath: "off",
},
parser: {
hooks: {
operations: {
// (Revert v0.82) Generate tanstack query for post methods
isQuery: (op) => (op.method === "post" ? true : undefined),
},
},
transforms: {
// (Revert v0.66) Only generate a single payload type
readWrite: false,
enums: { mode: "root" },
},
},
experimentalParser: true,
plugins: [
cacheBustingPlugin(),
...defaultPlugins,
"@tanstack/react-query",
"@hey-api/sdk",
{ name: "@hey-api/client-axios", exportFromIndex: true },
{
name: "@tanstack/react-query",
exportFromIndex: true,
"~hooks": {
operations: {
// (Revert v0.82) Generate tanstack query for post methods
isQuery: (op) => (op.method === "post" ? true : undefined),
},
},
},
{
enums: "typescript+namespace",
name: "@hey-api/typescript",
enums: "typescript",

// Add `_api` suffix to generated types
// Because our suffix doesn't follow PascalCasing, we need to manually handle the generated names.
case: "preserve",
// ? It might be possible to handle this via a plugin, but I could not figure out how. This works for now...
definitions: { name: (name) => addSuffix(name) },
responses: { name: (name) => addSuffix(name, "Response") },
requests: { name: (name) => addSuffix(name, "Data") },
errors: { name: (name) => addSuffix(name, "Error") },
webhooks: { name: (name) => addSuffix(name, "Hook") },
},
],
});
Loading
Loading