Skip to content
Draft
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
1 change: 1 addition & 0 deletions client/src/setupTests.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import '@testing-library/jest-dom/vitest';
import { vi } from 'vitest'

global.jest = vi as any;
2 changes: 1 addition & 1 deletion client/src/utils/collections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ export function filterNullOrUndefined<T>(
}

export function arrayFromArrayOrSingleItem<T>(array: readonly T[] | T): T[] {
return Array.isArray(array) ? [...array] : [array];
return Array.isArray(array) ? [...(array as readonly T[])] : [array as T];
}
2 changes: 1 addition & 1 deletion client/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"jsx": "react-jsx",
"target": "ESNext",
"types": ["vite/client", "vite-plugin-svgr/client"],
"types": ["vite/client", "vite-plugin-svgr/client", "jest", "google.maps"],
"module": "esnext",
"strict": true,
"esModuleInterop": true,
Expand Down
3 changes: 2 additions & 1 deletion server/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import cors from 'cors';
import express, { type ErrorRequestHandler } from 'express';
import session from 'express-session';
import { GraphQLError, type GraphQLFormattedError } from 'graphql';
import helmet from 'helmet';
import helmet_, { type HelmetOptions } from 'helmet';
const helmet = helmet_ as unknown as (options?: Readonly<HelmetOptions>) => (req: unknown, res: unknown, next: (err?: unknown) => void) => void;
Comment on lines +21 to +22
import passport from 'passport';

import { makeLoginUserDoesNotExistError } from './graphql/datasources/userApiErrors.js';
Expand Down
3 changes: 2 additions & 1 deletion server/condition_evaluator/getDerivedFieldValue.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import _ from 'lodash';
import stringify from 'safe-stable-stringify';
import stringify_ from 'safe-stable-stringify';
const stringify = stringify_ as unknown as (value: unknown) => string | undefined;

import {
getDerivedFieldValue,
Expand Down
1 change: 1 addition & 0 deletions server/graphql/customScalars/OpaqueScalarMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export default <T extends object>(
'serialize' | 'parseValue' | 'parseLiteral'
> => ({
serialize(value) {
// @ts-expect-error -- @types/jsonwebtoken@9 brands expiresIn as StringValue from ms; plain string is valid at runtime
return jwt.sign(value as T, jwtSigningKey, {
expiresIn: jwtExpiresIn,
});
Comment on lines 45 to 49
Expand Down
14 changes: 12 additions & 2 deletions server/lib/cache/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import { setTimeout } from "timers/promises";
import debug from "debug";
import stringify from "safe-stable-stringify";
import stringify_ from "safe-stable-stringify";

// Minimal debug-compatible logger — avoids phantom dep under pnpm strict mode.
// Behaviour is identical when DEBUG is unset (the common case in tests/prod).
const debug = (namespace: string) => {
const patterns = (process.env.DEBUG ?? '').split(',').map((p) => p.trim());
const enabled = patterns.some(
(p) => p === '*' || p === namespace || (p.endsWith('*') && namespace.startsWith(p.slice(0, -1))),
);
return (...args: unknown[]) => { if (enabled) console.debug(` ${namespace}`, ...args); };
};
Comment on lines +4 to +12
const stringify = stringify_ as unknown as (value: unknown) => string | undefined;
import { type JsonValue, type Tagged } from "type-fest";

import { components, type Logger } from "../types/index.js";
Expand Down
3 changes: 2 additions & 1 deletion server/lib/cache/utils/wrapProducer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import stableStringify from "safe-stable-stringify";
import stableStringify_ from "safe-stable-stringify";
const stableStringify = stableStringify_ as unknown as (value: unknown) => string | undefined;

import type Cache from "../Cache.js";
import { type NormalizedProducerResult } from "../types/06_Normalization.js";
Expand Down
5 changes: 3 additions & 2 deletions server/plugins/warehouse/utils/clickhouseSql.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import safeStableStringify from 'safe-stable-stringify';
import safeStableStringify_ from 'safe-stable-stringify';
const safeStableStringify = safeStableStringify_ as unknown as (value: unknown) => string | undefined;

function escapeString(value: string): string {
return value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
Expand Down Expand Up @@ -37,7 +38,7 @@ function formatValue(value: unknown): string {
}

if (typeof value === 'object') {
const json = safeStableStringify(value);
const json = safeStableStringify(value) ?? 'null';
return `'${escapeString(json)}'`;
}

Expand Down
2 changes: 1 addition & 1 deletion server/rule_engine/RuleEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ type RuleEvaluationContextImpl = Readonly<{

export type RuleEvaluationContext = Opaque<
RuleEvaluationContextImpl,
RuleEvaluationContextImpl
'RuleEvaluationContext'
>;

export type RuleExecutionResult = {
Expand Down
3 changes: 2 additions & 1 deletion server/services/itemInvestigationService/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ItemIdentifier } from '@roostorg/coop-types';
import _ from 'lodash';
import stringify from 'safe-stable-stringify';
import stringify_ from 'safe-stable-stringify';
const stringify = stringify_ as unknown as (value: unknown) => string | undefined;
import _S2A from 'stream-to-async-iterator';

import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,9 @@ export default class JobDecisioning {
.with(['ALREADY_LOGGED', 'SUCCESS'], () => jobAlreadySubmittedError)
// Case 4, client retrying after failed job deletion; deletion failed again.
.with(['ALREADY_LOGGED', 'FAILED'], () => decisioningFailedError)
.exhaustive(),
// ts-pattern v5.9 + TS 5.9: .exhaustive() triggers NonExhaustiveError<[any]>;
// all four cases above are covered so this branch is dead code.
.otherwise(() => undefined),
Comment on lines 324 to +329
};
})();

Expand Down
4 changes: 2 additions & 2 deletions server/services/networkingService/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,15 +213,15 @@ export async function fetchHTTP<T extends HandleResponseBody>(
// If the body isn't already an ArrayBuffer, we need to encode the body
// as an ArrayBuffer, so we first coerce it to a string from a `string |
// URLSearchParams` type, and then encode it with TextEncoder
const bodyBuffer =
const bodyBuffer: ArrayBuffer =
castBody instanceof ArrayBuffer
? castBody
: new TextEncoder().encode(
// `satisfies` ensures that new body types, on which we can't
// necessarily just call toString, won't get accidentally
// handled incorrectly
(castBody satisfies string | URLSearchParams).toString(),
);
).buffer as ArrayBuffer;

const { signature } = await query.signWith(bodyBuffer);
return b64EncodeArrayBuffer(signature);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { SpanStatusCode } from '@opentelemetry/api';
import _ from 'lodash';
import stringify from 'safe-stable-stringify';
import stringify_ from 'safe-stable-stringify';
const stringify = stringify_ as unknown as (value: unknown) => string | undefined;
import { type ReadonlyDeep } from 'type-fest';

import { inject } from '../../iocContainer/utils.js';
Expand Down
2 changes: 1 addition & 1 deletion server/test/arbitraries/ContentType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const GeohashArbitrary = fc
});

export const DateStringArbitrary = fc
.date()
.date({ noInvalidDate: true })
.map((date) => makeDateString(date.toISOString())!);

// Id-like fields allow numbers and strings as inputs, but the normalized
Expand Down
6 changes: 5 additions & 1 deletion server/test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,11 @@ export function makeTestWithFixture<T extends Record<string, unknown>>(

function _makeTestWithFixture<T extends Record<string, unknown>>(
makeSetupTeardown: () => Promise<Fixture<T>> | Fixture<T>,
jestFn = it,
jestFn: (
name: string,
fn?: jest.ProvidesCallback,
timeout?: number,
) => void = it,
) {
return (
name: string,
Expand Down
3 changes: 2 additions & 1 deletion server/utils/encoding.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import stringify from 'safe-stable-stringify';
import stringify_ from 'safe-stable-stringify';
const stringify = stringify_ as unknown as (value: unknown) => string | undefined;
Comment on lines +1 to +2
import { type Opaque } from 'type-fest';

import { JSON } from './json-schema-types.js';
Expand Down
Loading