Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: more permission ts client parsing #71

Merged
merged 18 commits into from
Jul 23, 2024
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ node_modules
/.sass-cache
/connect.lock
/coverage
**/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
Expand Down
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"middlewares",
"modii",
"nitropack",
"nocheck",
"ofetch",
"pathe",
"postversion",
Expand Down
5 changes: 4 additions & 1 deletion languages/ts/ts-client/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ test("error messages", async () => {
const request = await arriSafeRequest({
url: "http://thisurldoesntexist.blah",
method: "get",
parser() {},
responseFromJson() {},
responseFromString() {},
serializer() {
return undefined;
},
headers: undefined,
clientVersion: "",
});
expect(!request.success);
if (!request.success) {
Expand Down
62 changes: 52 additions & 10 deletions languages/ts/ts-client/src/request.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { serializeSmallString } from "@arrirpc/schema";
import { EventSourcePlusOptions, type HttpMethod } from "event-source-plus";
import { FetchError, ofetch } from "ofetch";

Expand All @@ -10,13 +11,14 @@ export interface ArriRequestOpts<
> {
url: string;
method: HttpMethod;
headers?: EventSourcePlusOptions["headers"];
headers: EventSourcePlusOptions["headers"];
params?: TParams;
parser: (input: unknown) => TType;
responseFromJson: (input: Record<string, unknown>) => TType;
responseFromString: (input: string) => TType;
serializer: (
input: TParams,
) => TParams extends undefined ? undefined : string;
clientVersion?: string;
clientVersion: string;
}

export async function arriRequest<
Expand All @@ -30,12 +32,7 @@ export async function arriRequest<
case "get":
case "head":
if (opts.params && typeof opts.params === "object") {
const urlParts: string[] = [];
Object.keys(opts.params).forEach((key) => {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
urlParts.push(`${key}=${(opts.params as any)[key]}`);
});
url = `${opts.url}?${urlParts.join("&")}`;
url = `${opts.url}?${opts.serializer(opts.params)}`;
}
break;
default:
Expand All @@ -54,7 +51,7 @@ export async function arriRequest<
body,
headers,
});
return opts.parser(result);
return opts.responseFromJson(result);
} catch (err) {
const error = err as any as FetchError;
if (isArriError(error.data)) {
Expand Down Expand Up @@ -118,3 +115,48 @@ export type SafeResponse<T> =
value: T;
}
| { success: false; error: ArriErrorInstance };

export interface ArriModelValidator<T> {
new: () => T;
validate: (input: unknown) => input is T;
fromJson: (input: Record<string, unknown>) => T;
fromJsonString: (input: string) => T;
toJsonString: (input: T) => string;
toUrlQueryString: (input: T) => string;
}
export interface ArriEnumValidator<T> {
new: () => T;
values: readonly T[];
validate: (input: unknown) => input is T;
fromSerialValue: (input: string) => T;
}
const STR_ESCAPE =
// eslint-disable-next-line no-control-regex
/[\u0000-\u001f\u0022\u005c\ud800-\udfff]|[\ud800-\udbff](?![\udc00-\udfff])|(?:[^\ud800-\udbff]|^)[\udc00-\udfff]/;

export function serializeString(input: string): string {
if (input.length < 42) {
return serializeSmallString(input);
}
if (input.length < 5000 && !STR_ESCAPE.test(input)) {
return `"${input}"`;
}
return JSON.stringify(input);
}

export const INT8_MIN = -128;
export const INT8_MAX = 127;
export const UINT8_MAX = 255;
export const INT16_MIN = -32768;
export const INT16_MAX = 32767;
export const UINT16_MAX = 65535;
export const INT32_MIN = -2147483648;
export const INT32_MAX = 2147483647;
export const UINT32_MAX = 4294967295;
export const INT64_MIN = BigInt("9223372036854775808");
export const INT64_MAX = BigInt("9223372036854775807");
export const UINT64_MAX = BigInt("18446744073709551615");

export function isObject(input: unknown): input is Record<string, unknown> {
return typeof input === "object" && input !== null;
}
8 changes: 2 additions & 6 deletions languages/ts/ts-client/src/sse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,7 @@ export function arriSseRequest<
typeof opts.params === "object" &&
opts.params !== null
) {
const urlParts: string[] = [];
Object.keys(opts.params).forEach((key) => {
urlParts.push(`${key}=${(opts.params as any)[key]}`);
});
url = `${opts.url}?${urlParts.join("&")}`;
url = `${opts.url}?${opts.serializer(opts.params)}`;
}
break;
default:
Expand Down Expand Up @@ -88,7 +84,7 @@ export function arriSseRequest<
message.event === undefined ||
message.event === ""
) {
options.onMessage?.(opts.parser(message.data));
options.onMessage?.(opts.responseFromString(message.data));
return;
}
if (message.event === "done") {
Expand Down
8 changes: 4 additions & 4 deletions languages/ts/ts-client/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { EventSourcePlusOptions } from "event-source-plus";

export async function getHeaders(
input: EventSourcePlusOptions["headers"],
): Promise<Record<string, string> | undefined> {
): Promise<Record<string, string>> {
if (typeof input === "function") {
const result = input();
if ("then" in result && typeof result.then === "function") {
return result.then((data) => data);
return result.then((data) => data as Record<string, string>);
}
return result;
return result as Record<string, string>;
}
return input;
return (input ?? {}) as Record<string, string>;
}
15 changes: 9 additions & 6 deletions languages/ts/ts-client/src/ws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ function isBrowser() {
interface WsControllerOptions<TParams, TResponse> {
url: string;
serializer: (input: TParams) => string;
parser: (input: unknown) => TResponse;
responseFromJson: (input: Record<string, unknown>) => TResponse;
responseFromString: (input: string) => TResponse;
onMessage?: WsMessageHook<TResponse>;
onErrorMessage?: WsErrorHook;
onConnectionError?: WsErrorHook;
Expand All @@ -31,7 +32,8 @@ interface ArriWsRequestOptions<TParams = any, TResponse = any> {
url: string;
headers?: EventSourcePlusOptions["headers"];
params?: TParams;
parser: (input: unknown) => TResponse;
responseFromJson: (input: Record<string, unknown>) => TResponse;
responseFromString: (input: string) => TResponse;
serializer: (input: TParams) => string;
onMessage?: WsMessageHook<TResponse>;
onError?: WsErrorHook;
Expand Down Expand Up @@ -72,7 +74,8 @@ export async function arriWsRequest<
try {
const controller = new WsController<TParams, TResponse>({
url,
parser: opts.parser,
responseFromJson: opts.responseFromJson,
responseFromString: opts.responseFromString,
serializer: opts.serializer ?? ((_) => ""),
onOpen: opts.onOpen,
onClose: opts.onClose,
Expand All @@ -94,11 +97,11 @@ export async function arriWsRequest<
type WsErrorHook = (err: ArriErrorInstance) => void;
type WsMessageHook<TResponse> = (msg: TResponse) => any;

class WsController<TParams, TResponse> {
export class WsController<TParams, TResponse> {
url: string;
private _ws?: NodeWebsocket | WebSocket;
private readonly _serializer: (input: TParams) => string;
private readonly _parser: (input: unknown) => TResponse;
private readonly _parser: (input: string) => TResponse;
onMessage?: WsMessageHook<TResponse>;
onErrorMessage?: WsErrorHook;
onConnectionError?: WsErrorHook;
Expand All @@ -107,7 +110,7 @@ class WsController<TParams, TResponse> {
constructor(opts: WsControllerOptions<TParams, TResponse>) {
this.url = opts.url;
this._serializer = opts.serializer;
this._parser = opts.parser;
this._parser = opts.responseFromString;
this.onOpen = opts.onOpen;
this.onClose = opts.onClose;
this.onErrorMessage = opts.onErrorMessage;
Expand Down
18 changes: 18 additions & 0 deletions languages/ts/ts-codegen-reference/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"extends": ["../../.eslintrc.js"],
"ignorePatterns": [],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
11 changes: 11 additions & 0 deletions languages/ts/ts-codegen-reference/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# ts-codegen-reference

This library was generated with [Nx](https://nx.dev).

## Building

Run `nx build ts-codegen-reference` to build the library.

## Running unit tests

Run `nx test ts-codegen-reference` to execute the unit tests via [Vitest](https://vitest.dev).
28 changes: 28 additions & 0 deletions languages/ts/ts-codegen-reference/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "ts-codegen-reference",
"version": "0.56.0",
"type": "module",
"license": "MIT",
"author": {
"name": "joshmossas",
"url": "https://github.com/joshmossas"
},
"bugs": {
"url": "https://github.com/modiimedia/arri/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/modiimedia/arri.git",
"directory": "tooling/ts-codegen-reference"
},
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"dependencies": {
"@arrirpc/client": "workspace:*"
},
"devDependencies": {}
}
29 changes: 29 additions & 0 deletions languages/ts/ts-codegen-reference/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "ts-codegen-reference",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "languages/ts/ts-codegen-reference/src",
"projectType": "application",
"targets": {
"lint": {
"executor": "nx:run-commands",
"options": {
"command": "pnpm eslint languages/ts/ts-codegen-reference"
}
},
"test": {
"executor": "@nx/vite:test",
"outputs": ["{workspaceRoot}/coverage/languages/ts/ts-codegen-reference"],
"options": {
"passWithNoTests": true,
"reportsDirectory": "../../coverage/languages/ts/ts-codegen-reference",
"watch": false
},
"configurations": {
"watch": {
"command": "vitest watch --passWithNoTests --globals"
}
}
}
},
"tags": []
}
Loading
Loading