impl spec types and basic runtime

This commit is contained in:
Yanzhen Yu 2021-07-02 16:55:22 +08:00
parent cd8014c4eb
commit 0a4199bde8
12 changed files with 414 additions and 0 deletions

View File

@ -0,0 +1,68 @@
import { createApplication } from "../src/application";
describe("application", () => {
it("can create runtime application", () => {
expect(
createApplication({
version: "demo/v1",
metadata: {
name: "test-app",
description: "first application",
},
spec: {
components: [
{
id: "input1",
type: "core/v1/test-component",
properties: {
x: "foo",
},
traits: [
{
type: "core/v1/test-trait",
properties: {
width: 2,
},
},
],
},
],
},
})
).toMatchInlineSnapshot(`
Object {
"kind": "Application",
"metadata": Object {
"description": "first application",
"name": "test-app",
},
"parsedVersion": Object {
"category": "demo",
"value": "v1",
},
"spec": Object {
"components": Array [
Object {
"id": "input1",
"properties": Object {
"x": "foo",
},
"traits": Array [
Object {
"properties": Object {
"width": 2,
},
"type": "core/v1/test-trait",
},
],
"type": "core/v1/test-component",
},
],
},
"version": "demo/v1",
}
`);
});
});

View File

@ -0,0 +1,84 @@
import { createComponent } from "../src/component";
describe("component", () => {
it("can create runtime component", () => {
expect(
createComponent({
version: "core/v1",
metadata: {
name: "test-component",
},
spec: {
properties: [
{
name: "x",
type: "string",
},
],
acceptTraits: [
{
name: "t1",
},
],
state: {
type: "string",
},
methods: [
{
name: "reset",
},
{
name: "add",
parameters: {
type: "number",
},
},
],
},
})
).toMatchInlineSnapshot(`
Object {
"kind": "Component",
"metadata": Object {
"name": "test-component",
},
"parsedVersion": Object {
"category": "core",
"value": "v1",
},
"spec": Object {
"acceptTraits": Array [
Object {
"name": "t1",
},
],
"methods": Array [
Object {
"name": "reset",
},
Object {
"name": "add",
"parameters": Object {
"type": "number",
},
},
],
"properties": Array [
Object {
"name": "x",
"type": "string",
},
],
"state": Object {
"type": "string",
},
},
"version": "core/v1",
}
`);
});
});

View File

@ -0,0 +1,26 @@
import { createScope } from "../src/scope";
describe("scope", () => {
it("can create runtime scope", () => {
expect(
createScope({
version: "core/v1",
metadata: {
name: "test-scope",
},
})
).toMatchInlineSnapshot(`
Object {
"kind": "Scope",
"metadata": Object {
"name": "test-scope",
},
"parsedVersion": Object {
"category": "core",
"value": "v1",
},
"version": "core/v1",
}
`);
});
});

View File

@ -0,0 +1,61 @@
import { createTrait } from "../src/trait";
describe("trait", () => {
it("can create runtime trait", () => {
expect(
createTrait({
version: "core/v1",
metadata: {
name: "test-trait",
},
spec: {
properties: [{ name: "width", type: "number" }],
state: {
type: "string",
},
methods: [
{
name: "times",
parameters: {
type: "number",
},
},
],
},
})
).toMatchInlineSnapshot(`
Object {
"kind": "Trait",
"metadata": Object {
"name": "test-trait",
},
"parsedVersion": Object {
"category": "core",
"value": "v1",
},
"spec": Object {
"methods": Array [
Object {
"name": "times",
"parameters": Object {
"type": "number",
},
},
],
"properties": Array [
Object {
"name": "width",
"type": "number",
},
],
"state": Object {
"type": "string",
},
},
"version": "core/v1",
}
`);
});
});

View File

@ -37,5 +37,8 @@
"prettier": "^2.3.2",
"ts-jest": "^27.0.3",
"typescript": "^4.3.5"
},
"dependencies": {
"@types/json-schema": "^7.0.7"
}
}

View File

@ -0,0 +1,45 @@
import { Metadata } from "./metadata";
import { parseVersion, Version } from "./version";
// spec
export type Application = {
version: string;
kind: "Application";
metadata: Metadata;
spec: ApplicationSpec;
};
type ApplicationSpec = {
components: ApplicationComponent[];
};
type ApplicationComponent = {
id: string;
type: string;
// do runtime type check
properties: object;
traits: ComponentTrait[];
// scopes TBD
};
type ComponentTrait = {
type: string;
// do runtime type check
properties: object;
};
// extended runtime
export type RuntimeApplication = Application & {
parsedVersion: Version;
};
export function createApplication(
options: Omit<Application, "kind">
): RuntimeApplication {
return {
...options,
kind: "Application",
parsedVersion: parseVersion(options.version),
};
}

View File

@ -0,0 +1,40 @@
import { JSONSchema4 } from "json-schema";
import { parseVersion } from "./version";
import { Metadata } from "./metadata";
import { MethodSchema } from "./method";
import { Version } from "./version";
// spec
export type Component = {
version: string;
kind: "Component";
metadata: Metadata;
spec: ComponentSpec;
};
type ComponentSpec = {
properties: Array<JSONSchema4 & { name: string }>;
acceptTraits: TraitSchema[];
state: JSONSchema4;
methods: MethodSchema[];
};
type TraitSchema = {
name: string;
};
// extended runtime
export type RuntimeComponent = Component & {
parsedVersion: Version;
};
export function createComponent(
options: Omit<Component, "kind">
): RuntimeComponent {
return {
...options,
kind: "Component",
parsedVersion: parseVersion(options.version),
};
}

View File

@ -0,0 +1,4 @@
export type Metadata = {
name: string;
description?: string;
};

View File

@ -0,0 +1,6 @@
import { JSONSchema4 } from "json-schema";
export type MethodSchema = {
name: string;
parameters?: JSONSchema4;
};

View File

@ -0,0 +1,23 @@
import { Metadata } from "./metadata";
import { parseVersion, Version } from "./version";
// spec
export type Scope = {
version: string;
kind: "Scope";
metadata: Metadata;
};
// extended runtime
export type RuntimeScope = Scope & {
parsedVersion: Version;
};
export function createScope(options: Omit<Scope, "kind">): RuntimeScope {
return {
...options,
kind: "Scope",
parsedVersion: parseVersion(options.version),
};
}

View File

@ -0,0 +1,32 @@
import { JSONSchema4 } from "json-schema";
import { Metadata } from "./metadata";
import { MethodSchema } from "./method";
import { parseVersion, Version } from "./version";
// spec
export type Trait = {
version: string;
kind: "Trait";
metadata: Metadata;
spec: TraitSpec;
};
type TraitSpec = {
properties: Array<JSONSchema4 & { name: string }>;
state: JSONSchema4;
methods: MethodSchema[];
};
// extended runtime
export type RuntimeTrait = Trait & {
parsedVersion: Version;
};
export function createTrait(options: Omit<Trait, "kind">): RuntimeTrait {
return {
...options,
kind: "Trait",
parsedVersion: parseVersion(options.version),
};
}

View File

@ -0,0 +1,22 @@
const VERSION_REG = /^([a-zA-Z-_\d]+)\/([a-zA-Z-_\d]+)$/;
export function isValidVersion(v: string): boolean {
return VERSION_REG.test(v);
}
export type Version = {
category: string;
value: string;
};
export function parseVersion(v: string): Version {
if (!isValidVersion(v)) {
throw new Error(`Invalid version string: "${v}"`);
}
const [, category, value] = v.match(VERSION_REG)!;
return {
category,
value,
};
}