Skip to content

Commit

Permalink
refactor: SchemaView from typedef
Browse files Browse the repository at this point in the history
  • Loading branch information
morlay committed Apr 23, 2024
1 parent f74da0e commit a62eefd
Show file tree
Hide file tree
Showing 9 changed files with 251 additions and 232 deletions.
2 changes: 1 addition & 1 deletion nodepkg/jsoncue/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@innoai-tech/jsoncue",
"version": "0.1.4",
"version": "0.1.8",
"monobundle": {
"build": {
"clean": true
Expand Down
22 changes: 22 additions & 0 deletions nodepkg/jsoncue/src/__tests__/stringify.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { describe, expect, it } from "bun:test";
import { isValidIdentity } from "../astutil";

describe("#isValidIdentity", () => {
it("identity should true", () => {
for (const id of [
"job",
"job1"
]) {
expect(isValidIdentity(id)).toBeTrue();
}
});

it("invalid identity should false", () => {
for (const id of [
"job-1",
"1"
]) {
expect(isValidIdentity(id)).toBeFalsy();
}
});
});
4 changes: 2 additions & 2 deletions nodepkg/jsoncue/src/astutil/stringify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ function isValidJSONValue(v: any) {
return !(isUndefined(v) || isFunction(v));
}

function isValidIdentity(v: string) {
return /[_$A-Za-z0-9]+/.test(v);
export function isValidIdentity(v: string) {
return /^[A-Za-z$_]([$_A-Za-z0-9]+)?$/.test(v);
}

function isMultiline(v: string) {
Expand Down
39 changes: 35 additions & 4 deletions nodepkg/jsoncue/src/codemirror/completions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type AnyType, EmptyContext, t } from "@innoai-tech/typedef";
import { type AnyType, EmptyContext, SymbolRecordKey, t } from "@innoai-tech/typedef";
import { JSONCue } from "../JSONCue.ts";
import { isArray, isNumber, isObject, isUndefined } from "../astutil/typed.ts";
import type { EditorState } from "@codemirror/state";
Expand All @@ -12,7 +12,7 @@ import { selectionAt } from "./util.ts";
import type { SyntaxNode } from "@lezer/common";
import { NodeType } from "../astutil/index.ts";

function schemaAt(typ: AnyType, values: any, path: any[], ctx = EmptyContext) {
export function schemaAt(typ: AnyType, values: any, path: any[], ctx = EmptyContext) {
switch (typ.type) {
case "array":
if (path.length === 0) {
Expand Down Expand Up @@ -41,8 +41,38 @@ function schemaAt(typ: AnyType, values: any, path: any[], ctx = EmptyContext) {
}

break;
case "union":
case "record":
if (path.length === 0) {
return typ;
}

if (isUndefined(values)) {
values = {};
}

if (!isObject(values)) {
return;
}

if (Object.keys(values).length == 0 && path.length > 0) {
(values as any)[path[0]] = undefined;
}

for (const [key, _, propType] of typ.entries(values, ctx)) {
if (key == SymbolRecordKey) {
continue;
}

const childValue = (values as any)[key];

return schemaAt(propType, childValue, path.slice(1), {
path: [...ctx.path, String(key)],
branch: [...ctx.branch, childValue]
});
}

return typ;
case "union":
case "object":
if (isUndefined(values)) {
values = {};
Expand Down Expand Up @@ -127,8 +157,9 @@ function asCompletions(typ: AnyType, node: SyntaxNode): Completion[] {
);

break;
case "union":
case "record":
break;
case "union":
case "object":
for (const [key, _, propType] of typ.entries({}, EmptyContext)) {
const propName = String(key);
Expand Down
2 changes: 1 addition & 1 deletion nodepkg/typedef/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@innoai-tech/typedef",
"version": "0.2.26",
"version": "0.2.27",
"monobundle": {
"exports": {
".": "./src/index.ts"
Expand Down
2 changes: 1 addition & 1 deletion nodepkg/typedef/src/encoding/JSONSchemaDecoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ const isMetaType = (schema: any): any => {
return !hasProps(schema, ["type", "$ref", "$id", "oneOf", "anyOf", "allOf"]);
};

const normalizeSchema = (schema: any): any => {
const normalizeSchema = (schema: any = {}): any => {
if (isBoolean(schema)) {
return {};
}
Expand Down
27 changes: 6 additions & 21 deletions webapp/openapi-playground/mod/openapi/RequestBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ import {
rx, subscribeOnMountedUntilUnmount,
subscribeUntilUnmount,
t,
Type,
TypeWrapper, useRoute,
useRoute,
useRouter
} from "@innoai-tech/vuekit";
import type { JSONSchema, Operation } from "./models";
import type { Operation } from "./models";
import { FormData, f, type Field } from "@innoai-tech/vueformdata";
import { TextField } from "./components/TextField";
import { isUndefined } from "./util/typed.ts";
Expand All @@ -26,16 +25,6 @@ import { ResponsePreview } from "./ResponsePreview.tsx";
import { HttpRequest } from "./HTTPViews.tsx";
import { mdiUploadBox } from "@mdi/js";

export function rawSchema(rawSchema: JSONSchema) {
return <T, S>(t: Type<T, S>) => {
return TypeWrapper.of(t, {
$meta: {
rawSchema: rawSchema
}
});
};
}

export const RequestBuilder = component$({
operation: t.custom<Operation>(),
$default: t.custom<VNodeChild>()
Expand All @@ -48,8 +37,7 @@ export const RequestBuilder = component$({
let x: AnyType = JSONSchemaDecoder.decode(p.schema, (ref) => {
return [openapi$.schema(ref) ?? {}, refName(ref)];
}).use(
f.label(`${p.name}, in=${JSON.stringify(p.in)}`),
rawSchema(p.schema),
f.label(`${p.name}, in=${JSON.stringify(p.in)}`)
);

if (!p.required) {
Expand All @@ -72,8 +60,7 @@ export const RequestBuilder = component$({
const x = JSONSchemaDecoder.decode(content.schema ?? {}, (ref) => {
return [openapi$.schema(ref) ?? {}, refName(ref)];
}).use(
f.label(`body, content-type = ${JSON.stringify(contentType)}`),
rawSchema(content.schema),
f.label(`body, content-type = ${JSON.stringify(contentType)}`)
);

if (contentType.includes("json")) {
Expand Down Expand Up @@ -209,8 +196,6 @@ const ParameterInput = component$(
return rx(
combineLatest([field$, field$.input$]),
render(([s, value]) => {
let rawSchema = field$.meta?.["rawSchema"] as JSONSchema ?? {};

let Input: any = field$.meta?.input ?? TextInput;

const readOnly = (field$.meta?.readOnlyWhenInitialExist ?? false) && !!s.initial;
Expand All @@ -228,8 +213,8 @@ const ParameterInput = component$(
}
$supporting={
<Line>
<Description schema={rawSchema ?? {}} />
<SchemaView schema={rawSchema ?? {}} />
<Description schema={field$.typedef} />
<SchemaView schema={field$.typedef} />
</Line>
}
$trailing={(Input as any).$trailing}
Expand Down
15 changes: 13 additions & 2 deletions webapp/openapi-playground/mod/openapi/ResponseView.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { component$, t } from "@innoai-tech/vuekit";
import { component$, JSONSchemaDecoder, refName, t } from "@innoai-tech/vuekit";
import type { Response } from "./models";
import { Box, styled } from "@innoai-tech/vueuikit";
import { Line, PropName, SchemaView, Indent, Token } from "./SchemaView.tsx";
import { isUndefined } from "./util/typed.ts";
import { OpenAPIProvider } from "./OpenAPIProvider.tsx";

function isErrorCode(c: number | string) {
try {
Expand All @@ -16,6 +17,8 @@ export const ResponseView = component$({
code: t.custom<number | string>(),
response: t.custom<Response>()
}, (props) => {
const openapi$ = OpenAPIProvider.use();

return () => {
return (
<ResponseSection>
Expand Down Expand Up @@ -63,7 +66,15 @@ export const ResponseView = component$({
{Object.entries(props.response.content ?? {}).map(([contentType, { schema }]) => (
<ResponseSchema>
<Line spacing={0}>
<SchemaView schema={schema} />
<SchemaView
schema={JSONSchemaDecoder.decode(schema, (ref) => {
return [
openapi$.schema(ref) ?? {},
refName(ref)
];
})}
/>

</Line>
<div data-content-type>
{contentType}
Expand Down
Loading

0 comments on commit a62eefd

Please sign in to comment.