Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ jobs:
steps:
- uses: actions/checkout@v6
with:
token: ${{ secrets.RELEASE_PLEASE_TOKEN || github.token }}
ref: ${{ (github.event_name == 'pull_request' && startsWith(github.head_ref, 'release-please--')) && github.head_ref || github.sha }}
token: ${{ startsWith(github.head_ref, 'release-please--') && secrets.RELEASE_PLEASE_TOKEN || github.token }}
ref: ${{ startsWith(github.head_ref, 'release-please--') && github.head_ref || github.sha }}
fetch-depth: 0

- uses: ruby/setup-ruby@v1
Expand Down
1 change: 0 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,6 @@ CHECKSUMS
bigdecimal (4.1.2) sha256=53d217666027eab4280346fba98e7d5b66baaae1b9c3c1c0ffe89d48188a3fbd
brotli (0.8.0) sha256=0c5a42046b3b603fb109656881147fd76064c034b7d19c1b4fcc32a093a4d55d
builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f
bundler (4.0.12) sha256=7f8b757d28dfb636e7b24fba2344ac6dd13b5b24f4b46d62573d483f211825ac
climate_control (1.2.0) sha256=36b21896193fa8c8536fa1cd843a07cf8ddbd03aaba43665e26c53ec1bd70aa5
concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
Expand Down
14 changes: 7 additions & 7 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,24 @@
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@hey-api/openapi-ts": "^0.97.2",
"@hey-api/openapi-ts": "^0.98.1",
"@playwright/test": "^1.60.0",
"@preact/preset-vite": "^2.10.5",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/preact": "^3.2.4",
"baseline-browser-mapping": "^2.10.31",
"eslint": "^10.4.0",
"baseline-browser-mapping": "^2.10.33",
"eslint": "^10.4.1",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-unicorn": "^64.0.0",
"globals": "^17.6.0",
"jsdom": "^29.1.1",
"msw": "^2.14.6",
"prettier": "^3.8.3",
"stylelint": "^17.11.1",
"stylelint": "^17.12.0",
"stylelint-config-standard": "^40.0.0",
"typescript": "^6.0.3",
"typescript-eslint": "^8.59.4",
"vite": "^8.0.13",
"vitest": "^4.1.6"
"typescript-eslint": "^8.60.0",
"vite": "^8.0.16",
"vitest": "^4.1.8"
}
}
581 changes: 306 additions & 275 deletions frontend/pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions frontend/src/api/generated/client.gen.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// This file is auto-generated by @hey-api/openapi-ts

import { type ClientOptions, type Config, createClient, createConfig } from './client';
import { type Client, type ClientOptions, type Config, createClient, createConfig } from './client';
import type { ClientOptions as ClientOptions2 } from './types.gen';

/**
Expand All @@ -13,4 +13,4 @@ import type { ClientOptions as ClientOptions2 } from './types.gen';
*/
export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T>;

export const client = createClient(createConfig<ClientOptions2>({ baseUrl: 'https://api.html2rss.dev/api/v1' }));
export const client: Client = createClient(createConfig<ClientOptions2>({ baseUrl: 'https://api.html2rss.dev/api/v1' }));
1 change: 1 addition & 0 deletions frontend/src/api/generated/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export {
} from '../core/bodySerializer.gen';
export { buildClientParams } from '../core/params.gen';
export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen';
export type { ServerSentEventsResult } from '../core/serverSentEvents.gen';
export { createClient } from './client.gen';
export type {
Client,
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/api/generated/client/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,13 @@ type MethodFn = <

type SseFn = <
TData = unknown,
TError = unknown,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_TError = unknown,
ThrowOnError extends boolean = false,
TResponseStyle extends ResponseStyle = 'fields',
>(
options: Omit<RequestOptions<never, TResponseStyle, ThrowOnError>, 'method'>,
) => Promise<ServerSentEventsResult<TData, TError>>;
) => Promise<ServerSentEventsResult<TData>>;

type RequestFn = <
TData = unknown,
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/api/generated/client/utils.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import type { Client, ClientOptions, Config, RequestOptions } from './types.gen'
export const createQuerySerializer = <T = unknown>({
parameters = {},
...args
}: QuerySerializerOptions = {}) => {
const querySerializer = (queryParams: T) => {
}: QuerySerializerOptions = {}): ((queryParams: T) => string) => {
const querySerializer = (queryParams: T): string => {
const search: string[] = [];
if (queryParams && typeof queryParams === 'object') {
for (const name in queryParams) {
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/api/generated/core/auth.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ export interface Auth {
* @default 'header'
*/
in?: 'header' | 'query' | 'cookie';
/**
* A unique identifier for the security scheme.
*
* Defined only when there are multiple security schemes whose `Auth`
* shape would otherwise be identical.
*/
key?: string;
/**
* Header or query parameter name.
*
Expand Down
26 changes: 14 additions & 12 deletions frontend/src/api/generated/core/params.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ type KeyMap = Map<
}
>;

const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => {
function buildKeyMap(fields: FieldsConfig, map?: KeyMap): KeyMap {
if (!map) {
map = new Map();
}
Expand All @@ -85,7 +85,7 @@ const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => {
}

return map;
};
}

interface Params {
body: unknown;
Expand All @@ -94,20 +94,22 @@ interface Params {
query: Record<string, unknown>;
}

const stripEmptySlots = (params: Params) => {
type ParamsSlotMap = Record<Slot, unknown>;

function stripEmptySlots(params: ParamsSlotMap): void {
for (const [slot, value] of Object.entries(params)) {
if (value && typeof value === 'object' && !Array.isArray(value) && !Object.keys(value).length) {
delete params[slot as Slot];
}
}
};
}

export const buildClientParams = (args: ReadonlyArray<unknown>, fields: FieldsConfig) => {
const params: Params = {
body: {},
headers: {},
path: {},
query: {},
export function buildClientParams(args: ReadonlyArray<unknown>, fields: FieldsConfig): Params {
const params: ParamsSlotMap = {
body: Object.create(null),
headers: Object.create(null),
path: Object.create(null),
query: Object.create(null),
};

const map = buildKeyMap(fields);
Expand Down Expand Up @@ -165,5 +167,5 @@ export const buildClientParams = (args: ReadonlyArray<unknown>, fields: FieldsCo

stripEmptySlots(params);

return params;
};
return params as Params;
}
12 changes: 6 additions & 6 deletions frontend/src/api/generated/core/pathSerializer.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ interface SerializePrimitiveParam extends SerializePrimitiveOptions {
value: string;
}

export const separatorArrayExplode = (style: ArraySeparatorStyle) => {
export const separatorArrayExplode = (style: ArraySeparatorStyle): '.' | ';' | ',' | '&' => {
switch (style) {
case 'label':
return '.';
Expand All @@ -38,7 +38,7 @@ export const separatorArrayExplode = (style: ArraySeparatorStyle) => {
}
};

export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => {
export const separatorArrayNoExplode = (style: ArraySeparatorStyle): ',' | '|' | '%20' => {
switch (style) {
case 'form':
return ',';
Expand All @@ -51,7 +51,7 @@ export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => {
}
};

export const separatorObjectExplode = (style: ObjectSeparatorStyle) => {
export const separatorObjectExplode = (style: ObjectSeparatorStyle): '.' | ';' | ',' | '&' => {
switch (style) {
case 'label':
return '.';
Expand All @@ -72,7 +72,7 @@ export const serializeArrayParam = ({
value,
}: SerializeOptions<ArraySeparatorStyle> & {
value: unknown[];
}) => {
}): string => {
if (!explode) {
const joinedValues = (
allowReserved ? value : value.map((v) => encodeURIComponent(v as string))
Expand Down Expand Up @@ -110,7 +110,7 @@ export const serializePrimitiveParam = ({
allowReserved,
name,
value,
}: SerializePrimitiveParam) => {
}: SerializePrimitiveParam): string => {
if (value === undefined || value === null) {
return '';
}
Expand All @@ -134,7 +134,7 @@ export const serializeObjectParam = ({
}: SerializeOptions<ObjectSeparatorStyle> & {
value: Record<string, unknown> | Date;
valueOnly?: boolean;
}) => {
}): string => {
if (value instanceof Date) {
return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/api/generated/core/queryKeySerializer.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export type JsonValue =
/**
* Replacer that converts non-JSON values (bigint, Date, etc.) to safe substitutes.
*/
export const queryKeyJsonReplacer = (_key: string, value: unknown) => {
export const queryKeyJsonReplacer = (_key: string, value: unknown): unknown | undefined => {
if (value === undefined || typeof value === 'function' || typeof value === 'symbol') {
return undefined;
}
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/api/generated/core/utils.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ export interface PathSerializer {
url: string;
}

export const PATH_PARAM_RE = /\{[^{}]+\}/g;
export const PATH_PARAM_RE: RegExp = /\{[^{}]+\}/g;

export const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {
export const defaultPathSerializer = ({ path, url: _url }: PathSerializer): string => {
let url = _url;
const matches = _url.match(PATH_PARAM_RE);
if (matches) {
Expand Down Expand Up @@ -94,7 +94,7 @@ export const getUrl = ({
query?: Record<string, unknown>;
querySerializer: QuerySerializer;
url: string;
}) => {
}): string => {
const pathUrl = _url.startsWith('/') ? _url : `/${_url}`;
let url = (baseUrl ?? '') + pathUrl;
if (path) {
Expand All @@ -114,7 +114,7 @@ export function getValidRequestBody(options: {
body?: unknown;
bodySerializer?: BodySerializer | null;
serializedBody?: unknown;
}) {
}): unknown {
const hasBody = options.body !== undefined;
const isSerializedBody = hasBody && options.bodySerializer;

Expand Down
16 changes: 8 additions & 8 deletions frontend/src/api/generated/sdk.gen.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// This file is auto-generated by @hey-api/openapi-ts

import type { Client, Options as Options2, TDataShape } from './client';
import type { Client, Options as Options2, RequestResult, TDataShape } from './client';
import { client } from './client.gen';
import type { CreateFeedData, CreateFeedErrors, CreateFeedResponses, GetApiMetadataData, GetApiMetadataResponses, GetHealthStatusData, GetHealthStatusErrors, GetHealthStatusResponses, GetLivenessProbeData, GetLivenessProbeResponses, GetReadinessProbeData, GetReadinessProbeResponses, ListStrategiesData, ListStrategiesResponses, RenderFeedByTokenData, RenderFeedByTokenErrors, RenderFeedByTokenResponses } from './types.gen';

Expand All @@ -23,14 +23,14 @@ export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends
*
* API metadata
*/
export const getApiMetadata = <ThrowOnError extends boolean = false>(options?: Options<GetApiMetadataData, ThrowOnError>) => (options?.client ?? client).get<GetApiMetadataResponses, unknown, ThrowOnError>({ url: '/', ...options });
export const getApiMetadata = <ThrowOnError extends boolean = false>(options?: Options<GetApiMetadataData, ThrowOnError>): RequestResult<GetApiMetadataResponses, unknown, ThrowOnError> => (options?.client ?? client).get<GetApiMetadataResponses, unknown, ThrowOnError>({ url: '/', ...options });

/**
* Create a feed
*
* Create a feed
*/
export const createFeed = <ThrowOnError extends boolean = false>(options: Options<CreateFeedData, ThrowOnError>) => (options.client ?? client).post<CreateFeedResponses, CreateFeedErrors, ThrowOnError>({
export const createFeed = <ThrowOnError extends boolean = false>(options: Options<CreateFeedData, ThrowOnError>): RequestResult<CreateFeedResponses, CreateFeedErrors, ThrowOnError> => (options.client ?? client).post<CreateFeedResponses, CreateFeedErrors, ThrowOnError>({
security: [{ scheme: 'bearer', type: 'http' }],
url: '/feeds',
...options,
Expand All @@ -45,14 +45,14 @@ export const createFeed = <ThrowOnError extends boolean = false>(options: Option
*
* Render feed by token
*/
export const renderFeedByToken = <ThrowOnError extends boolean = false>(options: Options<RenderFeedByTokenData, ThrowOnError>) => (options.client ?? client).get<RenderFeedByTokenResponses, RenderFeedByTokenErrors, ThrowOnError>({ url: '/feeds/{token}', ...options });
export const renderFeedByToken = <ThrowOnError extends boolean = false>(options: Options<RenderFeedByTokenData, ThrowOnError>): RequestResult<RenderFeedByTokenResponses, RenderFeedByTokenErrors, ThrowOnError> => (options.client ?? client).get<RenderFeedByTokenResponses, RenderFeedByTokenErrors, ThrowOnError>({ url: '/feeds/{token}', ...options });

/**
* Authenticated health check
*
* Authenticated health check
*/
export const getHealthStatus = <ThrowOnError extends boolean = false>(options: Options<GetHealthStatusData, ThrowOnError>) => (options.client ?? client).get<GetHealthStatusResponses, GetHealthStatusErrors, ThrowOnError>({
export const getHealthStatus = <ThrowOnError extends boolean = false>(options: Options<GetHealthStatusData, ThrowOnError>): RequestResult<GetHealthStatusResponses, GetHealthStatusErrors, ThrowOnError> => (options.client ?? client).get<GetHealthStatusResponses, GetHealthStatusErrors, ThrowOnError>({
security: [{ scheme: 'bearer', type: 'http' }],
url: '/health',
...options
Expand All @@ -63,18 +63,18 @@ export const getHealthStatus = <ThrowOnError extends boolean = false>(options: O
*
* Liveness probe
*/
export const getLivenessProbe = <ThrowOnError extends boolean = false>(options?: Options<GetLivenessProbeData, ThrowOnError>) => (options?.client ?? client).get<GetLivenessProbeResponses, unknown, ThrowOnError>({ url: '/health/live', ...options });
export const getLivenessProbe = <ThrowOnError extends boolean = false>(options?: Options<GetLivenessProbeData, ThrowOnError>): RequestResult<GetLivenessProbeResponses, unknown, ThrowOnError> => (options?.client ?? client).get<GetLivenessProbeResponses, unknown, ThrowOnError>({ url: '/health/live', ...options });

/**
* Readiness probe
*
* Readiness probe
*/
export const getReadinessProbe = <ThrowOnError extends boolean = false>(options?: Options<GetReadinessProbeData, ThrowOnError>) => (options?.client ?? client).get<GetReadinessProbeResponses, unknown, ThrowOnError>({ url: '/health/ready', ...options });
export const getReadinessProbe = <ThrowOnError extends boolean = false>(options?: Options<GetReadinessProbeData, ThrowOnError>): RequestResult<GetReadinessProbeResponses, unknown, ThrowOnError> => (options?.client ?? client).get<GetReadinessProbeResponses, unknown, ThrowOnError>({ url: '/health/ready', ...options });

/**
* List extraction strategies
*
* List extraction strategies
*/
export const listStrategies = <ThrowOnError extends boolean = false>(options?: Options<ListStrategiesData, ThrowOnError>) => (options?.client ?? client).get<ListStrategiesResponses, unknown, ThrowOnError>({ url: '/strategies', ...options });
export const listStrategies = <ThrowOnError extends boolean = false>(options?: Options<ListStrategiesData, ThrowOnError>): RequestResult<ListStrategiesResponses, unknown, ThrowOnError> => (options?.client ?? client).get<ListStrategiesResponses, unknown, ThrowOnError>({ url: '/strategies', ...options });