mirror of
https://github.com/fluencelabs/fluence-js.git
synced 2025-06-29 07:41:35 +00:00
feat(js-client)!: Adding strictes eslint and ts config to all packages [fixes DXJ-464] (#355)
* introduce eslint * Fix all eslint errors * Eslint fix and some touches * Fix tests * Fix misc errors * change semver * change semver #2 * Fix path * Fix path #2 * freeze lock file in CI * fix package install * Fix formatting of surrounding files * Add empty prettier config * Fix formatting * Fix build errors * Remove unused deps * remove changelog from formatting * deps cleanup * make resource importers async * Refactor * Fix error message * remove comment * more refactoring * Update packages/core/js-client/src/compilerSupport/registerService.ts Co-authored-by: shamsartem <shamsartem@gmail.com> * refactoring * refactoring fix * optimize import * Update packages/@tests/smoke/node/src/index.ts Co-authored-by: shamsartem <shamsartem@gmail.com> * Revert package * Fix pnpm lock * Lint-fix * Fix CI * Update tests * Fix build * Fix import * Use forked threads dep * Use fixed version * Update threads * Fix lint * Fix test * Fix test * Add polyfill for assert * Add subpath import * Fix tests * Fix deps --------- Co-authored-by: shamsartem <shamsartem@gmail.com>
This commit is contained in:
3
packages/core/aqua-to-js/.eslintrc.json
Normal file
3
packages/core/aqua-to-js/.eslintrc.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"ignorePatterns": ["src/**/__snapshots__/**/*"]
|
||||
}
|
@ -2,9 +2,9 @@
|
||||
|
||||
### Dependencies
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* devDependencies
|
||||
* @fluencelabs/js-client bumped to 0.1.7
|
||||
- The following workspace dependencies were updated
|
||||
- devDependencies
|
||||
- @fluencelabs/js-client bumped to 0.1.7
|
||||
|
||||
### Dependencies
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
|
||||
## 0.0.1 (2023-09-22)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **aqua-compiler:** JS-client aqua wrapper [fixes DXJ-461] ([#347](https://github.com/fluencelabs/js-client/issues/347)) ([7fff3b1](https://github.com/fluencelabs/js-client/commit/7fff3b1c0374eef76ab4e665b13cf97b5c50ff70))
|
||||
- **aqua-compiler:** JS-client aqua wrapper [fixes DXJ-461] ([#347](https://github.com/fluencelabs/js-client/issues/347)) ([7fff3b1](https://github.com/fluencelabs/js-client/commit/7fff3b1c0374eef76ab4e665b13cf97b5c50ff70))
|
||||
|
@ -1,31 +1,30 @@
|
||||
{
|
||||
"name": "@fluencelabs/aqua-to-js",
|
||||
"type": "module",
|
||||
"version": "0.0.4",
|
||||
"description": "Tool for generating aqua wrapper",
|
||||
"main": "dist/index.js",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
"build": "tsc"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Fluence Labs",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"ts-pattern": "5.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fluencelabs/aqua-api": "0.12.0",
|
||||
"@fluencelabs/aqua-lib": "0.7.3",
|
||||
"@fluencelabs/interfaces": "workspace:*",
|
||||
"@fluencelabs/js-client": "workspace:*",
|
||||
"@fluencelabs/registry": "0.8.7",
|
||||
"@fluencelabs/spell": "0.5.20",
|
||||
"@fluencelabs/trust-graph": "0.4.7",
|
||||
"typescript": "5.1.6",
|
||||
"vitest": "0.29.7"
|
||||
}
|
||||
"name": "@fluencelabs/aqua-to-js",
|
||||
"type": "module",
|
||||
"version": "0.0.4",
|
||||
"description": "Tool for generating aqua wrapper",
|
||||
"main": "dist/index.js",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
"build": "tsc"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Fluence Labs",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"ts-pattern": "5.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fluencelabs/aqua-api": "0.12.0",
|
||||
"@fluencelabs/aqua-lib": "0.7.3",
|
||||
"@fluencelabs/interfaces": "workspace:*",
|
||||
"@fluencelabs/js-client": "workspace:*",
|
||||
"@fluencelabs/registry": "0.8.7",
|
||||
"@fluencelabs/spell": "0.5.20",
|
||||
"@fluencelabs/trust-graph": "0.4.7",
|
||||
"vitest": "0.34.6"
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -14,85 +14,136 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ArrowType, ArrowWithoutCallbacks, NonArrowType, ProductType } from '@fluencelabs/interfaces';
|
||||
import { match, P } from 'ts-pattern';
|
||||
import { getFuncArgs } from './utils.js';
|
||||
import { ArrowWithoutCallbacks, NonArrowType } from "@fluencelabs/interfaces";
|
||||
import { match, P } from "ts-pattern";
|
||||
|
||||
export function genTypeName(t: NonArrowType | ProductType<NonArrowType> | ArrowWithoutCallbacks, name: string): readonly [string | undefined, string] {
|
||||
const genType = typeToTs(t);
|
||||
return match(t)
|
||||
.with(
|
||||
{ tag: 'nil' },
|
||||
() => [undefined, 'void'] as const
|
||||
).with(
|
||||
{ tag: 'struct' },
|
||||
() => [`export type ${name} = ${genType}`, name] as const
|
||||
).with(
|
||||
{ tag: P.union('labeledProduct', 'unlabeledProduct') },
|
||||
(item) => {
|
||||
const args = item.tag === 'labeledProduct'
|
||||
? Object.values(item.fields)
|
||||
: item.items;
|
||||
|
||||
if (args.length === 1) {
|
||||
return genTypeName(args[0], name);
|
||||
}
|
||||
import { getFuncArgs } from "./utils.js";
|
||||
|
||||
return [`export type ${name} = ${genType}`, name] as const;
|
||||
},
|
||||
).otherwise(() => [undefined, genType] as const);
|
||||
export function genTypeName(
|
||||
t: NonArrowType | ArrowWithoutCallbacks,
|
||||
name: string,
|
||||
): readonly [string | undefined, string] {
|
||||
const genType = typeToTs(t);
|
||||
return match(t)
|
||||
.with({ tag: "nil" }, () => {
|
||||
return [undefined, "void"] as const;
|
||||
})
|
||||
.with({ tag: "struct" }, () => {
|
||||
return [`export type ${name} = ${genType}`, name] as const;
|
||||
})
|
||||
.with({ tag: P.union("labeledProduct", "unlabeledProduct") }, (item) => {
|
||||
const args =
|
||||
item.tag === "labeledProduct" ? Object.values(item.fields) : item.items;
|
||||
|
||||
if (args.length === 1) {
|
||||
return genTypeName(args[0], name);
|
||||
}
|
||||
|
||||
return [`export type ${name} = ${genType}`, name] as const;
|
||||
})
|
||||
.otherwise(() => {
|
||||
return [undefined, genType] as const;
|
||||
});
|
||||
}
|
||||
|
||||
export function typeToTs(t: NonArrowType | ArrowWithoutCallbacks | ProductType<NonArrowType>): string {
|
||||
return match(t)
|
||||
export function typeToTs(t: NonArrowType | ArrowWithoutCallbacks): string {
|
||||
return match(t)
|
||||
.with({ tag: "nil" }, () => {
|
||||
return "null";
|
||||
})
|
||||
.with({ tag: "option" }, ({ type }) => {
|
||||
return typeToTs(type) + " | null";
|
||||
})
|
||||
.with({ tag: "scalar" }, ({ name }) => {
|
||||
return match(name)
|
||||
.with(
|
||||
{ tag: 'nil' },
|
||||
() => 'null'
|
||||
).with(
|
||||
{ tag: 'option' },
|
||||
({ type }) => typeToTs(type) + ' | null'
|
||||
).with(
|
||||
{ tag: 'scalar' },
|
||||
({ name }) => match(name)
|
||||
.with(P.union('u8', 'u16', 'u32', 'u64', 'i8', 'i16', 'i32', 'i64', 'f32', 'f64'), () => 'number')
|
||||
.with('bool', () => 'boolean')
|
||||
.with('string', () => 'string')
|
||||
.with(P._, () => 'any').exhaustive()
|
||||
).with(
|
||||
{ tag: 'array' },
|
||||
({ type }) => typeToTs(type) + '[]'
|
||||
).with(
|
||||
{ tag: 'struct' },
|
||||
({ fields }) => `{ ${Object.entries(fields).map(([field, type]) => `${field}: ${typeToTs(type)};`).join(' ')} }`
|
||||
).with(
|
||||
{ tag: 'labeledProduct' },
|
||||
({ fields }) => `{ ${Object.entries(fields).map(([field, type]) => `${field}: ${typeToTs(type)};`).join(' ')} }`
|
||||
).with(
|
||||
{ tag: 'unlabeledProduct' },
|
||||
({ items }) => `[${items.map(item => typeToTs(item)).join(', ')}]`
|
||||
).with(
|
||||
{ tag: 'arrow' },
|
||||
({ tag, domain, codomain }) => {
|
||||
const retType = codomain.tag === 'nil'
|
||||
? 'void'
|
||||
: codomain.items.length === 1
|
||||
? typeToTs(codomain.items[0])
|
||||
: typeToTs(codomain);
|
||||
|
||||
const args = getFuncArgs(domain).map(([name, type]) => ([name, typeToTs(type)]));
|
||||
P.union(
|
||||
"u8",
|
||||
"u16",
|
||||
"u32",
|
||||
"u64",
|
||||
"i8",
|
||||
"i16",
|
||||
"i32",
|
||||
"i64",
|
||||
"f32",
|
||||
"f64",
|
||||
),
|
||||
() => {
|
||||
return "number";
|
||||
},
|
||||
)
|
||||
.with("bool", () => {
|
||||
return "boolean";
|
||||
})
|
||||
.with("string", () => {
|
||||
return "string";
|
||||
})
|
||||
.with(P._, () => {
|
||||
return "any";
|
||||
})
|
||||
.exhaustive();
|
||||
})
|
||||
.with({ tag: "array" }, ({ type }) => {
|
||||
return typeToTs(type) + "[]";
|
||||
})
|
||||
.with({ tag: "struct" }, ({ fields }) => {
|
||||
return `{ ${Object.entries(fields)
|
||||
.map(([field, type]) => {
|
||||
return `${field}: ${typeToTs(type)};`;
|
||||
})
|
||||
.join(" ")} }`;
|
||||
})
|
||||
.with({ tag: "labeledProduct" }, ({ fields }) => {
|
||||
return `{ ${Object.entries(fields)
|
||||
.map(([field, type]) => {
|
||||
return `${field}: ${typeToTs(type)};`;
|
||||
})
|
||||
.join(" ")} }`;
|
||||
})
|
||||
.with({ tag: "unlabeledProduct" }, ({ items }) => {
|
||||
return `[${items
|
||||
.map((item) => {
|
||||
return typeToTs(item);
|
||||
})
|
||||
.join(", ")}]`;
|
||||
})
|
||||
.with({ tag: "arrow" }, ({ domain, codomain }) => {
|
||||
const retType =
|
||||
codomain.tag === "nil"
|
||||
? "void"
|
||||
: codomain.items.length === 1
|
||||
? typeToTs(codomain.items[0])
|
||||
: typeToTs(codomain);
|
||||
|
||||
const generic = args.length === 0 ? 'null' : args.map(([name]) => `'${name}'`).join(' | ');
|
||||
args.push(['callParams', `CallParams$$<${generic}>`]);
|
||||
const args = getFuncArgs(domain).map(([name, type]) => {
|
||||
return [name, typeToTs(type)];
|
||||
});
|
||||
|
||||
const funcArgs = args.map(([name, type]) => `${name}: ${type}`).join(', ');
|
||||
const generic =
|
||||
args.length === 0
|
||||
? "null"
|
||||
: args
|
||||
.map(([name]) => {
|
||||
return `'${name}'`;
|
||||
})
|
||||
.join(" | ");
|
||||
|
||||
return `(${funcArgs}) => ${retType} | Promise<${retType}>`;
|
||||
}
|
||||
).with(
|
||||
{ tag: 'topType' },
|
||||
() => 'unknown'
|
||||
).with(
|
||||
{ tag: 'bottomType' },
|
||||
() => 'never'
|
||||
).exhaustive();
|
||||
}
|
||||
args.push(["callParams", `CallParams$$<${generic}>`]);
|
||||
|
||||
const funcArgs = args
|
||||
.map(([name, type]) => {
|
||||
return `${name}: ${type}`;
|
||||
})
|
||||
.join(", ");
|
||||
|
||||
return `(${funcArgs}) => ${retType} | Promise<${retType}>`;
|
||||
})
|
||||
.with({ tag: "topType" }, () => {
|
||||
return "unknown";
|
||||
})
|
||||
.with({ tag: "bottomType" }, () => {
|
||||
return "never";
|
||||
})
|
||||
.exhaustive();
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -14,4 +14,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export const CLIENT = 'IFluenceClient$$';
|
||||
export const CLIENT = "IFluenceClient$$";
|
||||
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ArrayType,
|
||||
BottomType, LabeledProductType,
|
||||
NilType,
|
||||
NonArrowType,
|
||||
OptionType,
|
||||
ScalarType,
|
||||
StructType,
|
||||
TopType, UnlabeledProductType
|
||||
} from '@fluencelabs/interfaces';
|
||||
|
||||
// Type definitions for inferring ts types from air json definition
|
||||
// In the future we may remove string type declaration and move to type inference.
|
||||
|
||||
type GetTsTypeFromScalar<T extends ScalarType> = T['name'] extends 'u8' | 'u16' | 'u32' | 'u64' | 'i8' | 'i16' | 'i32' | 'i64' | 'f32' | 'f64'
|
||||
? number
|
||||
: T['name'] extends 'bool'
|
||||
? boolean
|
||||
: T['name'] extends 'string'
|
||||
? string
|
||||
: never;
|
||||
|
||||
type MapTuple<T> = { [K in keyof T]: T[K] extends NonArrowType ? GetTsType<T[K]> : never }
|
||||
|
||||
type GetTsType<T extends NonArrowType> = T extends NilType
|
||||
? null
|
||||
: T extends ArrayType
|
||||
? GetTsType<T['type']>[]
|
||||
: T extends StructType
|
||||
? { [K in keyof T]: GetTsType<T> }
|
||||
: T extends OptionType
|
||||
? GetTsType<T['type']> | null
|
||||
: T extends ScalarType
|
||||
? GetTsTypeFromScalar<T>
|
||||
: T extends TopType
|
||||
? unknown
|
||||
: T extends BottomType
|
||||
? never
|
||||
: T extends Exclude<UnlabeledProductType<infer H>, NilType>
|
||||
? MapTuple<H>
|
||||
: T extends Exclude<LabeledProductType<infer H>, NilType>
|
||||
? H extends NonArrowType
|
||||
? { [K in keyof T['fields']]: GetTsType<H> }
|
||||
: never
|
||||
: never;
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -14,36 +14,40 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { generateTypes, generateSources } from '../index.js';
|
||||
import { compileFromPath } from '@fluencelabs/aqua-api';
|
||||
import url from 'url';
|
||||
import { getPackageJsonContent, PackageJson } from '../../utils.js';
|
||||
import url from "url";
|
||||
|
||||
describe('Aqua to js/ts compiler', () => {
|
||||
it('compiles smoke tests successfully', async () => {
|
||||
const res = await compileFromPath({
|
||||
filePath: url.fileURLToPath(new URL('./sources/smoke_test.aqua', import.meta.url)),
|
||||
imports: ['./node_modules'],
|
||||
targetType: 'air'
|
||||
});
|
||||
|
||||
const pkg: PackageJson = {
|
||||
...(await getPackageJsonContent()),
|
||||
version: '0.0.0',
|
||||
devDependencies: {
|
||||
'@fluencelabs/aqua-api': '0.0.0'
|
||||
},
|
||||
};
|
||||
|
||||
const jsResult = await generateSources(res, 'js', pkg);
|
||||
const jsTypes = await generateTypes(res, pkg);
|
||||
|
||||
expect(jsResult).toMatchSnapshot();
|
||||
expect(jsTypes).toMatchSnapshot();
|
||||
import { compileFromPath } from "@fluencelabs/aqua-api";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
const tsResult = await generateSources(res, 'ts', pkg);
|
||||
import { getPackageJsonContent, PackageJson } from "../../utils.js";
|
||||
import { generateTypes, generateSources } from "../index.js";
|
||||
|
||||
expect(tsResult).toMatchSnapshot();
|
||||
describe("Aqua to js/ts compiler", () => {
|
||||
it("compiles smoke tests successfully", async () => {
|
||||
const res = await compileFromPath({
|
||||
filePath: url.fileURLToPath(
|
||||
new URL("./sources/smoke_test.aqua", import.meta.url),
|
||||
),
|
||||
imports: ["./node_modules"],
|
||||
targetType: "air",
|
||||
});
|
||||
});
|
||||
|
||||
const pkg: PackageJson = {
|
||||
...(await getPackageJsonContent()),
|
||||
version: "0.0.0",
|
||||
devDependencies: {
|
||||
"@fluencelabs/aqua-api": "0.0.0",
|
||||
},
|
||||
};
|
||||
|
||||
const jsResult = generateSources(res, "js", pkg);
|
||||
const jsTypes = generateTypes(res, pkg);
|
||||
|
||||
expect(jsResult).toMatchSnapshot();
|
||||
expect(jsTypes).toMatchSnapshot();
|
||||
|
||||
const tsResult = generateSources(res, "ts", pkg);
|
||||
|
||||
expect(tsResult).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -14,24 +14,38 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { recursiveRenameLaquaProps } from '../utils.js';
|
||||
import { AquaFunction, TypeGenerator } from './interfaces.js';
|
||||
import { recursiveRenameLaquaProps } from "../utils.js";
|
||||
|
||||
export function generateFunctions(typeGenerator: TypeGenerator, functions: Record<string, AquaFunction>) {
|
||||
return Object.values(functions).map(func => generateFunction(typeGenerator, func)).join('\n\n');
|
||||
import { AquaFunction, TypeGenerator } from "./interfaces.js";
|
||||
|
||||
export function generateFunctions(
|
||||
typeGenerator: TypeGenerator,
|
||||
functions: Record<string, AquaFunction>,
|
||||
) {
|
||||
return Object.values(functions)
|
||||
.map((func) => {
|
||||
return generateFunction(typeGenerator, func);
|
||||
})
|
||||
.join("\n\n");
|
||||
}
|
||||
|
||||
type DeepToType<T> = { [K in keyof T]: DeepToType<T[K]> };
|
||||
|
||||
function generateFunction(typeGenerator: TypeGenerator, func: AquaFunction) {
|
||||
const scriptConstName = func.funcDef.functionName + '_script';
|
||||
return `export const ${scriptConstName} = \`
|
||||
const funcDef: DeepToType<typeof func.funcDef> = func.funcDef;
|
||||
const scriptConstName = func.funcDef.functionName + "_script";
|
||||
return `export const ${scriptConstName} = \`
|
||||
${func.script}\`;
|
||||
|
||||
${typeGenerator.funcType(func)}
|
||||
export function ${func.funcDef.functionName}(${typeGenerator.type('...args', 'any[]')}) {
|
||||
export function ${func.funcDef.functionName}(${typeGenerator.type(
|
||||
"...args",
|
||||
"any[]",
|
||||
)}) {
|
||||
return callFunction$$(
|
||||
args,
|
||||
${JSON.stringify(recursiveRenameLaquaProps(func.funcDef), null, 4)},
|
||||
${JSON.stringify(recursiveRenameLaquaProps(funcDef), null, 4)},
|
||||
${scriptConstName}
|
||||
);
|
||||
}`
|
||||
}
|
||||
}`;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -14,25 +14,33 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { OutputType } from './interfaces.js';
|
||||
import { PackageJson } from '../utils.js';
|
||||
import { PackageJson } from "../utils.js";
|
||||
|
||||
export default function generateHeader({ version, devDependencies }: PackageJson, outputType: OutputType) {
|
||||
return `/* eslint-disable */
|
||||
import { OutputType } from "./interfaces.js";
|
||||
|
||||
export default function generateHeader(
|
||||
{ version, devDependencies }: PackageJson,
|
||||
outputType: OutputType,
|
||||
) {
|
||||
return `/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
/**
|
||||
*
|
||||
* This file is generated using:
|
||||
* @fluencelabs/aqua-api version: ${devDependencies['@fluencelabs/aqua-api']}
|
||||
* @fluencelabs/aqua-api version: ${devDependencies["@fluencelabs/aqua-api"]}
|
||||
* @fluencelabs/aqua-to-js version: ${version}
|
||||
* If you find any bugs in generated AIR, please write an issue on GitHub: https://github.com/fluencelabs/aqua/issues
|
||||
* If you find any bugs in generated JS/TS, please write an issue on GitHub: https://github.com/fluencelabs/js-client/issues
|
||||
*
|
||||
*/
|
||||
${outputType === 'ts' ? 'import type { IFluenceClient as IFluenceClient$$, CallParams as CallParams$$ } from \'@fluencelabs/js-client\';' : ''}
|
||||
${
|
||||
outputType === "ts"
|
||||
? "import type { IFluenceClient as IFluenceClient$$, CallParams as CallParams$$ } from '@fluencelabs/js-client';"
|
||||
: ""
|
||||
}
|
||||
|
||||
import {
|
||||
v5_callFunction as callFunction$$,
|
||||
v5_registerService as registerService$$,
|
||||
} from '@fluencelabs/js-client';`;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -14,46 +14,80 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { CompilationResult, JSTypeGenerator, OutputType, TSTypeGenerator, TypeGenerator } from './interfaces.js';
|
||||
import { PackageJson } from '../utils.js';
|
||||
import { generateServices } from './service.js';
|
||||
import { generateFunctions } from './function.js';
|
||||
import header from './header.js';
|
||||
import { PackageJson } from "../utils.js";
|
||||
|
||||
const typeGenerators: Record<OutputType, TypeGenerator> = {
|
||||
'js': new JSTypeGenerator(),
|
||||
'ts': new TSTypeGenerator()
|
||||
import { generateFunctions } from "./function.js";
|
||||
import header from "./header.js";
|
||||
import {
|
||||
CompilationResult,
|
||||
JSTypeGenerator,
|
||||
OutputType,
|
||||
TSTypeGenerator,
|
||||
TypeGenerator,
|
||||
} from "./interfaces.js";
|
||||
import { generateServices } from "./service.js";
|
||||
|
||||
const typeGenerators: Record<OutputType, TypeGenerator> = {
|
||||
js: new JSTypeGenerator(),
|
||||
ts: new TSTypeGenerator(),
|
||||
};
|
||||
|
||||
export async function generateSources({ services, functions }: CompilationResult, outputType: OutputType, packageJson: PackageJson) {
|
||||
const typeGenerator = typeGenerators[outputType];
|
||||
return `${header(packageJson, outputType)}
|
||||
export function generateSources(
|
||||
{ services, functions }: CompilationResult,
|
||||
outputType: OutputType,
|
||||
packageJson: PackageJson,
|
||||
) {
|
||||
const typeGenerator = typeGenerators[outputType];
|
||||
return `${header(packageJson, outputType)}
|
||||
|
||||
${Object.entries(services).length > 0 ? `// Services
|
||||
${
|
||||
Object.entries(services).length > 0
|
||||
? `// Services
|
||||
${generateServices(typeGenerator, services)}
|
||||
` : ''}
|
||||
${Object.entries(functions).length > 0 ? `// Functions
|
||||
`
|
||||
: ""
|
||||
}
|
||||
${
|
||||
Object.entries(functions).length > 0
|
||||
? `// Functions
|
||||
${generateFunctions(typeGenerator, functions)}
|
||||
`: ''}`
|
||||
`
|
||||
: ""
|
||||
}`;
|
||||
}
|
||||
|
||||
export async function generateTypes({ services, functions }: CompilationResult, packageJson: PackageJson) {
|
||||
const typeGenerator = typeGenerators['ts'];
|
||||
|
||||
const generatedServices = Object.entries(services)
|
||||
.map(([srvName, srvDef]) => typeGenerator.serviceType(srvName, srvDef))
|
||||
.join('\n');
|
||||
|
||||
const generatedFunctions = Object.entries(functions)
|
||||
.map(([funcName, funcDef]) => typeGenerator.funcType(funcDef))
|
||||
.join('\n');
|
||||
|
||||
return `${header(packageJson, 'ts')}
|
||||
export function generateTypes(
|
||||
{ services, functions }: CompilationResult,
|
||||
packageJson: PackageJson,
|
||||
) {
|
||||
const typeGenerator = typeGenerators["ts"];
|
||||
|
||||
${Object.entries(services).length > 0 ? `// Services
|
||||
const generatedServices = Object.entries(services)
|
||||
.map(([srvName, srvDef]) => {
|
||||
return typeGenerator.serviceType(srvName, srvDef);
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
const generatedFunctions = Object.entries(functions)
|
||||
.map(([, funcDef]) => {
|
||||
return typeGenerator.funcType(funcDef);
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
return `${header(packageJson, "ts")}
|
||||
|
||||
${
|
||||
Object.entries(services).length > 0
|
||||
? `// Services
|
||||
${generatedServices}
|
||||
` : ''}
|
||||
${Object.entries(functions).length > 0 ? `// Functions
|
||||
`
|
||||
: ""
|
||||
}
|
||||
${
|
||||
Object.entries(functions).length > 0
|
||||
? `// Functions
|
||||
${generatedFunctions}
|
||||
`: ''}`
|
||||
}
|
||||
`
|
||||
: ""
|
||||
}`;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -14,123 +14,160 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { CLIENT } from '../constants.js';
|
||||
import { FunctionCallDef, ServiceDef } from '@fluencelabs/interfaces';
|
||||
import { genTypeName, typeToTs } from '../common.js';
|
||||
import { capitalize, getFuncArgs } from '../utils.js';
|
||||
import { FunctionCallDef, ServiceDef } from "@fluencelabs/interfaces";
|
||||
|
||||
import { genTypeName, typeToTs } from "../common.js";
|
||||
import { CLIENT } from "../constants.js";
|
||||
import { capitalize, getFuncArgs } from "../utils.js";
|
||||
|
||||
export interface TypeGenerator {
|
||||
type(field: string, type: string): string;
|
||||
generic(field: string, type: string): string;
|
||||
bang(field: string): string;
|
||||
funcType(funcDef: AquaFunction): string;
|
||||
serviceType(srvName: string, srvDef: ServiceDef): string;
|
||||
type(field: string, type: string): string;
|
||||
generic(field: string, type: string): string;
|
||||
bang(field: string): string;
|
||||
funcType(funcDef: AquaFunction): string;
|
||||
serviceType(srvName: string, srvDef: ServiceDef): string;
|
||||
}
|
||||
|
||||
export class TSTypeGenerator implements TypeGenerator {
|
||||
bang(field: string): string {
|
||||
return `${field}!`;
|
||||
}
|
||||
bang(field: string): string {
|
||||
return `${field}!`;
|
||||
}
|
||||
|
||||
generic(field: string, type: string): string {
|
||||
return `${field}<${type}>`;
|
||||
}
|
||||
generic(field: string, type: string): string {
|
||||
return `${field}<${type}>`;
|
||||
}
|
||||
|
||||
type(field: string, type: string): string {
|
||||
return `${field}: ${type}`;
|
||||
}
|
||||
type(field: string, type: string): string {
|
||||
return `${field}: ${type}`;
|
||||
}
|
||||
|
||||
funcType({ funcDef }: AquaFunction): string {
|
||||
const args = getFuncArgs(funcDef.arrow.domain).map(([name, type]) => {
|
||||
const [typeDesc, t] = genTypeName(type, capitalize(funcDef.functionName) + 'Arg' + capitalize(name));
|
||||
return [typeDesc, `${name}: ${t}`] as const;
|
||||
});
|
||||
args.push([undefined, `config?: {ttl?: number}`]);
|
||||
funcType({ funcDef }: AquaFunction): string {
|
||||
const args = getFuncArgs(funcDef.arrow.domain).map(([name, type]) => {
|
||||
const [typeDesc, t] = genTypeName(
|
||||
type,
|
||||
capitalize(funcDef.functionName) + "Arg" + capitalize(name),
|
||||
);
|
||||
|
||||
const argsDefs = args.map(([, def]) => " " + def);
|
||||
const argsDesc = args.filter(([desc]) => desc !== undefined).map(([desc]) => desc);
|
||||
return [typeDesc, `${name}: ${t}`] as const;
|
||||
});
|
||||
|
||||
const functionOverloads = [
|
||||
argsDefs.join(',\n'),
|
||||
[` peer: ${CLIENT}`, ...argsDefs].join(',\n')
|
||||
];
|
||||
|
||||
const [resTypeDesc, resType] = genTypeName(funcDef.arrow.codomain, capitalize(funcDef.functionName) + "Result");
|
||||
args.push([undefined, `config?: {ttl?: number}`]);
|
||||
|
||||
return [
|
||||
argsDesc.join('\n'),
|
||||
resTypeDesc || "",
|
||||
functionOverloads.flatMap(fo => [
|
||||
`export function ${funcDef.functionName}(`,
|
||||
fo,
|
||||
`): Promise<${resType}>;`,
|
||||
''
|
||||
]).join('\n')
|
||||
].filter(s => s !== '').join('\n\n');
|
||||
}
|
||||
const argsDefs = args.map(([, def]) => {
|
||||
return " " + def;
|
||||
});
|
||||
|
||||
serviceType(srvName: string, srvDef: ServiceDef): string {
|
||||
const members = srvDef.functions.tag === 'nil' ? [] : Object.entries(srvDef.functions.fields);
|
||||
const argsDesc = args
|
||||
.filter(([desc]) => {
|
||||
return desc !== undefined;
|
||||
})
|
||||
.map(([desc]) => {
|
||||
return desc;
|
||||
});
|
||||
|
||||
const interfaceDefs = members
|
||||
.map(([name, arrow]) => {
|
||||
return ` ${name}: ${typeToTs(arrow)};`;
|
||||
})
|
||||
.join('\n');
|
||||
const functionOverloads = [
|
||||
argsDefs.join(",\n"),
|
||||
[` peer: ${CLIENT}`, ...argsDefs].join(",\n"),
|
||||
];
|
||||
|
||||
const interfaces = [`export interface ${srvName}Def {`, interfaceDefs, '}'].join('\n');
|
||||
|
||||
const peerDecl = `peer: ${CLIENT}`;
|
||||
const serviceDecl = `service: ${srvName}Def`;
|
||||
const serviceIdDecl = `serviceId: string`;
|
||||
const registerServiceArgs = [
|
||||
[serviceDecl],
|
||||
[serviceIdDecl, serviceDecl],
|
||||
[peerDecl, serviceDecl],
|
||||
[peerDecl, serviceIdDecl, serviceDecl]
|
||||
];
|
||||
const [resTypeDesc, resType] = genTypeName(
|
||||
funcDef.arrow.codomain,
|
||||
capitalize(funcDef.functionName) + "Result",
|
||||
);
|
||||
|
||||
return [interfaces, ...registerServiceArgs.map(registerServiceArg => {
|
||||
const args = registerServiceArg.join(', ');
|
||||
return `export function register${srvName}(${args}): void;`
|
||||
})].join('\n');
|
||||
}
|
||||
return [
|
||||
argsDesc.join("\n"),
|
||||
resTypeDesc ?? "",
|
||||
functionOverloads
|
||||
.flatMap((fo) => {
|
||||
return [
|
||||
`export function ${funcDef.functionName}(`,
|
||||
fo,
|
||||
`): Promise<${resType}>;`,
|
||||
"",
|
||||
];
|
||||
})
|
||||
.join("\n"),
|
||||
]
|
||||
.filter((s) => {
|
||||
return s !== "";
|
||||
})
|
||||
.join("\n\n");
|
||||
}
|
||||
|
||||
serviceType(srvName: string, srvDef: ServiceDef): string {
|
||||
const members =
|
||||
srvDef.functions.tag === "nil"
|
||||
? []
|
||||
: Object.entries(srvDef.functions.fields);
|
||||
|
||||
const interfaceDefs = members
|
||||
.map(([name, arrow]) => {
|
||||
return ` ${name}: ${typeToTs(arrow)};`;
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
const interfaces = [
|
||||
`export interface ${srvName}Def {`,
|
||||
interfaceDefs,
|
||||
"}",
|
||||
].join("\n");
|
||||
|
||||
const peerDecl = `peer: ${CLIENT}`;
|
||||
const serviceDecl = `service: ${srvName}Def`;
|
||||
const serviceIdDecl = `serviceId: string`;
|
||||
|
||||
const registerServiceArgs = [
|
||||
[serviceDecl],
|
||||
[serviceIdDecl, serviceDecl],
|
||||
[peerDecl, serviceDecl],
|
||||
[peerDecl, serviceIdDecl, serviceDecl],
|
||||
];
|
||||
|
||||
return [
|
||||
interfaces,
|
||||
...registerServiceArgs.map((registerServiceArg) => {
|
||||
const args = registerServiceArg.join(", ");
|
||||
return `export function register${srvName}(${args}): void;`;
|
||||
}),
|
||||
].join("\n");
|
||||
}
|
||||
}
|
||||
|
||||
export class JSTypeGenerator implements TypeGenerator {
|
||||
bang(field: string): string {
|
||||
return field;
|
||||
}
|
||||
bang(field: string): string {
|
||||
return field;
|
||||
}
|
||||
|
||||
generic(field: string, type: string): string {
|
||||
return field;
|
||||
}
|
||||
generic(field: string): string {
|
||||
return field;
|
||||
}
|
||||
|
||||
type(field: string, type: string): string {
|
||||
return field;
|
||||
}
|
||||
type(field: string): string {
|
||||
return field;
|
||||
}
|
||||
|
||||
funcType(): string {
|
||||
return '';
|
||||
}
|
||||
funcType(): string {
|
||||
return "";
|
||||
}
|
||||
|
||||
serviceType(): string {
|
||||
return '';
|
||||
}
|
||||
serviceType(): string {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
export interface AquaFunction {
|
||||
funcDef: FunctionCallDef;
|
||||
script: string;
|
||||
funcDef: FunctionCallDef;
|
||||
script: string;
|
||||
}
|
||||
|
||||
export interface CompilationResult {
|
||||
services: Record<string, ServiceDef>;
|
||||
functions: Record<string, AquaFunction>;
|
||||
services: Record<string, ServiceDef>;
|
||||
functions: Record<string, AquaFunction>;
|
||||
}
|
||||
|
||||
export interface EntityGenerator {
|
||||
generate(compilationResult: CompilationResult): string;
|
||||
generate(compilationResult: CompilationResult): string;
|
||||
}
|
||||
|
||||
export type OutputType = 'js' | 'ts';
|
||||
export type OutputType = "js" | "ts";
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -14,45 +14,74 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ServiceDef } from '@fluencelabs/interfaces';
|
||||
import { recursiveRenameLaquaProps } from '../utils.js';
|
||||
import { TypeGenerator } from './interfaces.js';
|
||||
import { ServiceDef } from "@fluencelabs/interfaces";
|
||||
|
||||
import { recursiveRenameLaquaProps } from "../utils.js";
|
||||
|
||||
import { TypeGenerator } from "./interfaces.js";
|
||||
|
||||
interface DefaultServiceId {
|
||||
s_Some__f_value?: string
|
||||
s_Some__f_value?: string;
|
||||
}
|
||||
|
||||
export function generateServices(typeGenerator: TypeGenerator, services: Record<string, ServiceDef>) {
|
||||
const generated = Object.entries(services).map(([srvName, srvDef]) => generateService(typeGenerator, srvName, srvDef)).join('\n\n');
|
||||
export function generateServices(
|
||||
typeGenerator: TypeGenerator,
|
||||
services: Record<string, ServiceDef>,
|
||||
) {
|
||||
const generated = Object.entries(services)
|
||||
.map(([srvName, srvDef]) => {
|
||||
return generateService(typeGenerator, srvName, srvDef);
|
||||
})
|
||||
.join("\n\n");
|
||||
|
||||
return generated + '\n';
|
||||
return generated + "\n";
|
||||
}
|
||||
|
||||
function generateService(typeGenerator: TypeGenerator, srvName: string, srvDef: ServiceDef) {
|
||||
return [
|
||||
typeGenerator.serviceType(srvName, srvDef),
|
||||
generateRegisterServiceOverload(typeGenerator, srvName, srvDef)
|
||||
].join('\n');
|
||||
function generateService(
|
||||
typeGenerator: TypeGenerator,
|
||||
srvName: string,
|
||||
srvDef: ServiceDef,
|
||||
) {
|
||||
return [
|
||||
typeGenerator.serviceType(srvName, srvDef),
|
||||
generateRegisterServiceOverload(typeGenerator, srvName, srvDef),
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
function generateRegisterServiceOverload(typeGenerator: TypeGenerator, srvName: string, srvDef: ServiceDef) {
|
||||
return [
|
||||
`export function register${srvName}(${typeGenerator.type('...args', 'any[]')}) {`,
|
||||
' registerService$$(',
|
||||
' args,',
|
||||
` ${serviceToJson(srvDef)}`,
|
||||
' );',
|
||||
'}'
|
||||
].join('\n');
|
||||
function generateRegisterServiceOverload(
|
||||
typeGenerator: TypeGenerator,
|
||||
srvName: string,
|
||||
srvDef: ServiceDef,
|
||||
) {
|
||||
return [
|
||||
`export function register${srvName}(${typeGenerator.type(
|
||||
"...args",
|
||||
"any[]",
|
||||
)}) {`,
|
||||
" registerService$$(",
|
||||
" args,",
|
||||
` ${serviceToJson(srvDef)}`,
|
||||
" );",
|
||||
"}",
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
function serviceToJson(service: ServiceDef): string {
|
||||
return JSON.stringify({
|
||||
...(
|
||||
(service.defaultServiceId as DefaultServiceId)?.s_Some__f_value
|
||||
? { defaultServiceId: (service.defaultServiceId as DefaultServiceId).s_Some__f_value }
|
||||
: {}
|
||||
),
|
||||
functions: recursiveRenameLaquaProps(service.functions)
|
||||
}, null, 4);
|
||||
}
|
||||
return JSON.stringify(
|
||||
{
|
||||
// This assertion is required because aqua-api gives bad types
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
...((service.defaultServiceId as DefaultServiceId).s_Some__f_value != null
|
||||
? {
|
||||
defaultServiceId:
|
||||
// This assertion is required because aqua-api gives bad types
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
(service.defaultServiceId as DefaultServiceId).s_Some__f_value,
|
||||
}
|
||||
: {}),
|
||||
functions: recursiveRenameLaquaProps(service.functions),
|
||||
},
|
||||
null,
|
||||
4,
|
||||
);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -14,34 +14,47 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
generateSources,
|
||||
generateTypes,
|
||||
} from './generate/index.js';
|
||||
import { CompilationResult, OutputType } from './generate/interfaces.js';
|
||||
import { getPackageJsonContent } from './utils.js';
|
||||
import { generateSources, generateTypes } from "./generate/index.js";
|
||||
import { CompilationResult, OutputType } from "./generate/interfaces.js";
|
||||
import { getPackageJsonContent } from "./utils.js";
|
||||
|
||||
interface JsOutput {
|
||||
sources: string;
|
||||
types: string;
|
||||
sources: string;
|
||||
types: string;
|
||||
}
|
||||
|
||||
interface TsOutput {
|
||||
sources: string;
|
||||
sources: string;
|
||||
}
|
||||
|
||||
type LanguageOutput = {
|
||||
"js": JsOutput,
|
||||
"ts": TsOutput
|
||||
js: JsOutput;
|
||||
ts: TsOutput;
|
||||
};
|
||||
|
||||
export default async function aquaToJs<T extends OutputType>(res: CompilationResult, outputType: T): Promise<LanguageOutput[T]> {
|
||||
const packageJson = await getPackageJsonContent();
|
||||
|
||||
return outputType === 'js' ? {
|
||||
sources: await generateSources(res, 'js', packageJson),
|
||||
types: await generateTypes(res, packageJson)
|
||||
} : {
|
||||
sources: await generateSources(res, 'ts', packageJson),
|
||||
} as LanguageOutput[T];
|
||||
};
|
||||
type NothingToGenerate = null;
|
||||
|
||||
export default async function aquaToJs<T extends OutputType>(
|
||||
res: CompilationResult,
|
||||
outputType: T,
|
||||
): Promise<LanguageOutput[T] | NothingToGenerate> {
|
||||
if (
|
||||
Object.keys(res.services).length === 0 &&
|
||||
Object.keys(res.functions).length === 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const packageJson = await getPackageJsonContent();
|
||||
|
||||
return outputType === "js"
|
||||
? {
|
||||
sources: generateSources(res, "js", packageJson),
|
||||
types: generateTypes(res, packageJson),
|
||||
}
|
||||
: // TODO: probably there is a way to remove this type assert
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
({
|
||||
sources: generateSources(res, "ts", packageJson),
|
||||
} as LanguageOutput[T]);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -14,57 +14,94 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ArrowWithoutCallbacks, NonArrowType, ProductType } from '@fluencelabs/interfaces';
|
||||
import { readFile } from 'fs/promises';
|
||||
import path from 'path';
|
||||
import assert from "assert";
|
||||
import { readFile } from "fs/promises";
|
||||
import path from "path";
|
||||
|
||||
import {
|
||||
ArrowType,
|
||||
ArrowWithoutCallbacks,
|
||||
JSONValue,
|
||||
LabeledProductType,
|
||||
NilType,
|
||||
SimpleTypes,
|
||||
UnlabeledProductType,
|
||||
} from "@fluencelabs/interfaces";
|
||||
|
||||
export interface PackageJson {
|
||||
name: string;
|
||||
version: string;
|
||||
devDependencies: {
|
||||
['@fluencelabs/aqua-api']: string
|
||||
}
|
||||
name: string;
|
||||
version: string;
|
||||
devDependencies: {
|
||||
["@fluencelabs/aqua-api"]: string;
|
||||
};
|
||||
}
|
||||
|
||||
export async function getPackageJsonContent(): Promise<PackageJson> {
|
||||
const content = await readFile(new URL(path.join('..', 'package.json'), import.meta.url), 'utf-8');
|
||||
return JSON.parse(content);
|
||||
const content = await readFile(
|
||||
new URL(path.join("..", "package.json"), import.meta.url),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
// TODO: Add validation here
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
return JSON.parse(content) as PackageJson;
|
||||
}
|
||||
|
||||
export function getFuncArgs(domain: ProductType<NonArrowType | ArrowWithoutCallbacks>): [string, NonArrowType | ArrowWithoutCallbacks][] {
|
||||
if (domain.tag === 'labeledProduct') {
|
||||
return Object.entries(domain.fields).map(([label, type]) => [label, type]);
|
||||
} else if (domain.tag === 'unlabeledProduct') {
|
||||
return domain.items.map((type, index) => ['arg' + index, type]);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
export function getFuncArgs(
|
||||
domain:
|
||||
| LabeledProductType<SimpleTypes | ArrowType<UnlabeledProductType>>
|
||||
| UnlabeledProductType
|
||||
| NilType,
|
||||
): [string, SimpleTypes | ArrowWithoutCallbacks][] {
|
||||
if (domain.tag === "labeledProduct") {
|
||||
return Object.entries(domain.fields).map(([label, type]) => {
|
||||
return [label, type];
|
||||
});
|
||||
} else if (domain.tag === "unlabeledProduct") {
|
||||
return domain.items.map((type, index) => {
|
||||
return ["arg" + index, type];
|
||||
});
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export function recursiveRenameLaquaProps(obj: unknown): unknown {
|
||||
if (typeof obj !== 'object' || obj === null) return obj;
|
||||
export function recursiveRenameLaquaProps(obj: JSONValue): unknown {
|
||||
if (typeof obj !== "object" || obj === null) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map(item => recursiveRenameLaquaProps(item));
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map((item) => {
|
||||
return recursiveRenameLaquaProps(item);
|
||||
});
|
||||
}
|
||||
|
||||
return Object.getOwnPropertyNames(obj).reduce((acc, prop) => {
|
||||
let accessProp = prop;
|
||||
|
||||
if (prop.includes("Laqua_js")) {
|
||||
// Last part of the property separated by "_" is a correct name
|
||||
const refinedProperty = prop.split("_").pop();
|
||||
|
||||
if (refinedProperty == null) {
|
||||
throw new Error(`Bad property name: ${prop}.`);
|
||||
}
|
||||
|
||||
if (refinedProperty in obj) {
|
||||
accessProp = refinedProperty;
|
||||
}
|
||||
}
|
||||
|
||||
return Object.getOwnPropertyNames(obj).reduce((acc, prop) => {
|
||||
let accessProp = prop;
|
||||
if (prop.includes('Laqua_js')) {
|
||||
// Last part of the property separated by "_" is a correct name
|
||||
const refinedProperty = prop.split('_').pop()!;
|
||||
if (refinedProperty in obj) {
|
||||
accessProp = refinedProperty;
|
||||
}
|
||||
}
|
||||
assert(accessProp in obj);
|
||||
|
||||
return {
|
||||
...acc,
|
||||
[accessProp]: recursiveRenameLaquaProps(obj[accessProp as keyof typeof obj])
|
||||
};
|
||||
}, {});
|
||||
return {
|
||||
...acc,
|
||||
[accessProp]: recursiveRenameLaquaProps(obj[accessProp]),
|
||||
};
|
||||
}, {});
|
||||
}
|
||||
|
||||
export function capitalize(str: string) {
|
||||
return str.slice(0, 1).toUpperCase() + str.slice(1);
|
||||
}
|
||||
return str.slice(0, 1).toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "src/**/__test__"],
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "src/**/__test__"]
|
||||
}
|
||||
|
Reference in New Issue
Block a user