mirror of
https://github.com/fluencelabs/fluence-js.git
synced 2024-12-11 13:10:18 +00:00
feat(npm-aqua-compiler): create package (#401)
* Add npm-aqua-compiler package * Release new package * Remove noUncheckedIndexedAccess from tsconfig.json * Fix a test script * Fix length checks * Fix * Update error description * Try to choose a nicer err message * New import format and API * Fix error message * Improve test * Don't add empty string key when globalImports prop is empty * Fix exports
This commit is contained in:
parent
ac407c204d
commit
d6008110cf
@ -20,13 +20,7 @@
|
|||||||
],
|
],
|
||||||
"ignorePatterns": ["**/node_modules/", "**/dist/", "**/build/", "**/public/"],
|
"ignorePatterns": ["**/node_modules/", "**/dist/", "**/build/", "**/public/"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"eqeqeq": [
|
"eqeqeq": ["error", "always"],
|
||||||
"error",
|
|
||||||
"always",
|
|
||||||
{
|
|
||||||
"null": "ignore"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"no-console": ["error"],
|
"no-console": ["error"],
|
||||||
"arrow-body-style": ["error", "always"],
|
"arrow-body-style": ["error", "always"],
|
||||||
"no-empty": [
|
"no-empty": [
|
||||||
|
3
.github/release-please/config.json
vendored
3
.github/release-please/config.json
vendored
@ -12,6 +12,7 @@
|
|||||||
"packages/core/js-client-isomorphic": {},
|
"packages/core/js-client-isomorphic": {},
|
||||||
"packages/core/marine-worker": {},
|
"packages/core/marine-worker": {},
|
||||||
"packages/core/aqua-to-js": {},
|
"packages/core/aqua-to-js": {},
|
||||||
"packages/core/interfaces": {}
|
"packages/core/interfaces": {},
|
||||||
|
"packages/core/npm-aqua-compiler": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3
.github/release-please/manifest.json
vendored
3
.github/release-please/manifest.json
vendored
@ -3,5 +3,6 @@
|
|||||||
"packages/core/marine-worker": "0.5.0",
|
"packages/core/marine-worker": "0.5.0",
|
||||||
"packages/core/aqua-to-js": "0.3.4",
|
"packages/core/aqua-to-js": "0.3.4",
|
||||||
"packages/core/js-client-isomorphic": "0.3.0",
|
"packages/core/js-client-isomorphic": "0.3.0",
|
||||||
"packages/core/interfaces": "0.9.0"
|
"packages/core/interfaces": "0.9.0",
|
||||||
|
"packages/core/npm-aqua-compiler": "0.0.0"
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import assert from "node:assert";
|
||||||
import { dirname, join } from "path";
|
import { dirname, join } from "path";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
|
|
||||||
@ -45,6 +46,8 @@ const test = async () => {
|
|||||||
const browser = await puppeteer.launch();
|
const browser = await puppeteer.launch();
|
||||||
const page = (await browser.pages())[0];
|
const page = (await browser.pages())[0];
|
||||||
|
|
||||||
|
assert(page);
|
||||||
|
|
||||||
page.on("console", (message) => {
|
page.on("console", (message) => {
|
||||||
console.log(`${message.type().toUpperCase()}: ${message.text()}`);
|
console.log(`${message.type().toUpperCase()}: ${message.text()}`);
|
||||||
});
|
});
|
||||||
@ -77,7 +80,7 @@ const test = async () => {
|
|||||||
await browser.close();
|
await browser.close();
|
||||||
await stopServer(localServer);
|
await stopServer(localServer);
|
||||||
|
|
||||||
if (content == null) {
|
if (content === null || content === undefined) {
|
||||||
throw new Error("smoke test failed!");
|
throw new Error("smoke test failed!");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -35,7 +35,7 @@ export function genTypeName(
|
|||||||
const args =
|
const args =
|
||||||
item.tag === "labeledProduct" ? Object.values(item.fields) : item.items;
|
item.tag === "labeledProduct" ? Object.values(item.fields) : item.items;
|
||||||
|
|
||||||
if (args.length === 1) {
|
if (args.length === 1 && "0" in args) {
|
||||||
return genTypeName(args[0], name);
|
return genTypeName(args[0], name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ export function typeToTs(t: NonArrowType | ArrowType): string {
|
|||||||
const retType =
|
const retType =
|
||||||
codomain.tag === "nil"
|
codomain.tag === "nil"
|
||||||
? "void"
|
? "void"
|
||||||
: codomain.items.length === 1
|
: codomain.items.length === 1 && "0" in codomain.items
|
||||||
? typeToTs(codomain.items[0])
|
? typeToTs(codomain.items[0])
|
||||||
: typeToTs(codomain);
|
: typeToTs(codomain);
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ export class TSTypeGenerator implements TypeGenerator {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const registerServiceArgs =
|
const registerServiceArgs =
|
||||||
srvDef.defaultServiceId == null
|
srvDef.defaultServiceId === undefined
|
||||||
? functionOverloadsWithoutDefaultServiceId
|
? functionOverloadsWithoutDefaultServiceId
|
||||||
: functionOverloadsWithDefaultServiceId;
|
: functionOverloadsWithDefaultServiceId;
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import assert from "assert";
|
|
||||||
import { readFile } from "fs/promises";
|
import { readFile } from "fs/promises";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
|
|
||||||
@ -86,7 +85,7 @@ export function recursiveRenameLaquaProps(obj: JSONValue): unknown {
|
|||||||
// Last part of the property separated by "_" is a correct name
|
// Last part of the property separated by "_" is a correct name
|
||||||
const refinedProperty = prop.split("_").pop();
|
const refinedProperty = prop.split("_").pop();
|
||||||
|
|
||||||
if (refinedProperty == null) {
|
if (refinedProperty === undefined) {
|
||||||
throw new Error(`Bad property name: ${prop}.`);
|
throw new Error(`Bad property name: ${prop}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,11 +94,15 @@ export function recursiveRenameLaquaProps(obj: JSONValue): unknown {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(accessProp in obj);
|
const laquaProp = obj[accessProp];
|
||||||
|
|
||||||
|
if (laquaProp === undefined) {
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...acc,
|
...acc,
|
||||||
[accessProp]: recursiveRenameLaquaProps(obj[accessProp]),
|
[accessProp]: recursiveRenameLaquaProps(laquaProp),
|
||||||
};
|
};
|
||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../../tsconfig.json",
|
"extends": "../../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"esModuleInterop": true,
|
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"outDir": "./dist"
|
"outDir": "./dist"
|
||||||
},
|
},
|
||||||
|
@ -36,7 +36,7 @@ export const fetchResource: FetchResourceFn = async (pkg, assetPath) => {
|
|||||||
|
|
||||||
const packagePath = matches?.[0];
|
const packagePath = matches?.[0];
|
||||||
|
|
||||||
if (packagePath == null) {
|
if (packagePath === undefined) {
|
||||||
throw new Error(`Cannot find dependency ${name} in path ${posixPath}`);
|
throw new Error(`Cannot find dependency ${name} in path ${posixPath}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ import { fileURLToPath } from "url";
|
|||||||
|
|
||||||
import { compileFromPath } from "@fluencelabs/aqua-api";
|
import { compileFromPath } from "@fluencelabs/aqua-api";
|
||||||
import { ServiceDef } from "@fluencelabs/interfaces";
|
import { ServiceDef } from "@fluencelabs/interfaces";
|
||||||
import { describe, expect, it } from "vitest";
|
import { assert, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
import { v5_registerService } from "./api.js";
|
import { v5_registerService } from "./api.js";
|
||||||
import { callAquaFunction } from "./compilerSupport/callFunction.js";
|
import { callAquaFunction } from "./compilerSupport/callFunction.js";
|
||||||
@ -65,8 +65,12 @@ describe("User API methods", () => {
|
|||||||
|
|
||||||
const typedServices: Record<string, ServiceDef> = services;
|
const typedServices: Record<string, ServiceDef> = services;
|
||||||
|
|
||||||
|
assert("demoCalc" in functions);
|
||||||
|
|
||||||
const { script } = functions["demoCalc"];
|
const { script } = functions["demoCalc"];
|
||||||
|
|
||||||
|
assert("Calc" in typedServices);
|
||||||
|
|
||||||
v5_registerService([peer, "calc", calcService], {
|
v5_registerService([peer, "calc", calcService], {
|
||||||
defaultServiceId: "calc",
|
defaultServiceId: "calc",
|
||||||
functions: typedServices["Calc"].functions,
|
functions: typedServices["Calc"].functions,
|
||||||
|
@ -26,12 +26,13 @@ import { z } from "zod";
|
|||||||
import { CallAquaFunctionConfig } from "./compilerSupport/callFunction.js";
|
import { CallAquaFunctionConfig } from "./compilerSupport/callFunction.js";
|
||||||
import {
|
import {
|
||||||
aqua2js,
|
aqua2js,
|
||||||
SchemaValidationError,
|
|
||||||
js2aqua,
|
js2aqua,
|
||||||
|
SchemaValidationError,
|
||||||
wrapJsFunction,
|
wrapJsFunction,
|
||||||
} from "./compilerSupport/conversions.js";
|
} from "./compilerSupport/conversions.js";
|
||||||
import { ServiceImpl, UserServiceImpl } from "./compilerSupport/types.js";
|
import { ServiceImpl, UserServiceImpl } from "./compilerSupport/types.js";
|
||||||
import { FluencePeer } from "./jsPeer/FluencePeer.js";
|
import { FluencePeer } from "./jsPeer/FluencePeer.js";
|
||||||
|
import { zip } from "./util/utils.js";
|
||||||
|
|
||||||
import { callAquaFunction, Fluence, registerService } from "./index.js";
|
import { callAquaFunction, Fluence, registerService } from "./index.js";
|
||||||
|
|
||||||
@ -74,51 +75,48 @@ export const v5_callFunction = async (
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const argNames = Object.keys(
|
|
||||||
def.arrow.domain.tag === "nil" ? [] : def.arrow.domain.fields,
|
|
||||||
);
|
|
||||||
|
|
||||||
const schemaArgCount = argNames.length;
|
|
||||||
|
|
||||||
type FunctionArg = SimpleTypes | ArrowWithoutCallbacks;
|
|
||||||
|
|
||||||
const schemaFunctionArgs: Record<string, FunctionArg> =
|
const schemaFunctionArgs: Record<string, FunctionArg> =
|
||||||
def.arrow.domain.tag === "nil" ? {} : def.arrow.domain.fields;
|
def.arrow.domain.tag === "nil" ? {} : def.arrow.domain.fields;
|
||||||
|
|
||||||
|
const schemaFunctionArgEntries = Object.entries(schemaFunctionArgs);
|
||||||
|
|
||||||
|
const schemaArgCount = schemaFunctionArgEntries.length;
|
||||||
|
|
||||||
|
type FunctionArg = SimpleTypes | ArrowWithoutCallbacks;
|
||||||
|
|
||||||
// if there are more args than expected in schema (schemaArgCount) then last arg is config
|
// if there are more args than expected in schema (schemaArgCount) then last arg is config
|
||||||
const config = schemaArgCount < rest.length ? rest.pop() : undefined;
|
const config = schemaArgCount < rest.length ? rest.pop() : undefined;
|
||||||
|
|
||||||
validateAquaConfig(config);
|
validateAquaConfig(config);
|
||||||
|
|
||||||
const callArgs = Object.fromEntries<JSONValue | ServiceImpl[string]>(
|
const callArgs = Object.fromEntries<JSONValue | ServiceImpl[string]>(
|
||||||
rest.slice(0, schemaArgCount).map((arg, i) => {
|
zip(rest.slice(0, schemaArgCount), schemaFunctionArgEntries).map(
|
||||||
const argName = argNames[i];
|
([arg, [argName, argType]]) => {
|
||||||
const argSchema = schemaFunctionArgs[argName];
|
if (argType.tag === "arrow") {
|
||||||
|
|
||||||
if (argSchema.tag === "arrow") {
|
|
||||||
if (typeof arg !== "function") {
|
if (typeof arg !== "function") {
|
||||||
throw new SchemaValidationError(
|
throw new SchemaValidationError(
|
||||||
[argName],
|
[argName],
|
||||||
argSchema,
|
argType,
|
||||||
"function",
|
"function",
|
||||||
arg,
|
arg,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [argName, wrapJsFunction(arg, argSchema)];
|
return [argName, wrapJsFunction(arg, argType)];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof arg === "function") {
|
if (typeof arg === "function") {
|
||||||
throw new SchemaValidationError(
|
throw new SchemaValidationError(
|
||||||
[argName],
|
[argName],
|
||||||
argSchema,
|
argType,
|
||||||
"non-function value",
|
"non-function value",
|
||||||
arg,
|
arg,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [argName, js2aqua(arg, argSchema, { path: [def.functionName] })];
|
return [argName, js2aqua(arg, argType, { path: [def.functionName] })];
|
||||||
}),
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const returnTypeVoid =
|
const returnTypeVoid =
|
||||||
@ -126,7 +124,8 @@ export const v5_callFunction = async (
|
|||||||
|
|
||||||
const returnSchema =
|
const returnSchema =
|
||||||
def.arrow.codomain.tag === "unlabeledProduct" &&
|
def.arrow.codomain.tag === "unlabeledProduct" &&
|
||||||
def.arrow.codomain.items.length === 1
|
def.arrow.codomain.items.length === 1 &&
|
||||||
|
"0" in def.arrow.codomain.items
|
||||||
? def.arrow.codomain.items[0]
|
? def.arrow.codomain.items[0]
|
||||||
: def.arrow.codomain;
|
: def.arrow.codomain;
|
||||||
|
|
||||||
@ -145,7 +144,7 @@ export const v5_callFunction = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getDefaultPeer = (): FluencePeer => {
|
const getDefaultPeer = (): FluencePeer => {
|
||||||
if (Fluence.defaultClient == null) {
|
if (Fluence.defaultClient === undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Could not register Aqua service because the client is not initialized. Did you forget to call Fluence.connect()?",
|
"Could not register Aqua service because the client is not initialized. Did you forget to call Fluence.connect()?",
|
||||||
);
|
);
|
||||||
@ -155,7 +154,7 @@ const getDefaultPeer = (): FluencePeer => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getDefaultServiceId = (def: ServiceDef) => {
|
const getDefaultServiceId = (def: ServiceDef) => {
|
||||||
if (def.defaultServiceId == null) {
|
if (def.defaultServiceId === undefined) {
|
||||||
throw new Error("Service ID is not provided");
|
throw new Error("Service ID is not provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,13 +203,18 @@ export const v5_registerService = (
|
|||||||
|
|
||||||
// Wrapping service functions, selecting only those listed in schema, to convert their args js -> aqua and backwards
|
// Wrapping service functions, selecting only those listed in schema, to convert their args js -> aqua and backwards
|
||||||
const wrappedServiceImpl = Object.fromEntries(
|
const wrappedServiceImpl = Object.fromEntries(
|
||||||
Object.keys(serviceSchema).map((schemaKey) => {
|
Object.entries(serviceSchema).map(([schemaKey, schemaValue]) => {
|
||||||
|
const serviceImplValue = serviceImpl[schemaKey];
|
||||||
|
|
||||||
|
if (serviceImplValue === undefined) {
|
||||||
|
throw new Error(
|
||||||
|
`Service function ${schemaKey} listed in Aqua schema but wasn't provided in schema implementation object or class instance. Check that your Aqua service definition matches passed service implementation`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
schemaKey,
|
schemaKey,
|
||||||
wrapJsFunction(
|
wrapJsFunction(serviceImplValue.bind(serviceImpl), schemaValue),
|
||||||
serviceImpl[schemaKey].bind(serviceImpl),
|
|
||||||
serviceSchema[schemaKey],
|
|
||||||
),
|
|
||||||
] as const;
|
] as const;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -60,7 +60,7 @@ export const makeClientPeerConfig = async (
|
|||||||
relayConfig: {
|
relayConfig: {
|
||||||
peerId: keyPair.getLibp2pPeerId(),
|
peerId: keyPair.getLibp2pPeerId(),
|
||||||
relayAddress: relayAddress,
|
relayAddress: relayAddress,
|
||||||
...(config.connectionOptions?.dialTimeoutMs != null
|
...(config.connectionOptions?.dialTimeoutMs !== undefined
|
||||||
? {
|
? {
|
||||||
dialTimeout: config.connectionOptions.dialTimeoutMs,
|
dialTimeout: config.connectionOptions.dialTimeoutMs,
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { JSONValue } from "@fluencelabs/interfaces";
|
import { JSONValue } from "@fluencelabs/interfaces";
|
||||||
import { it, describe, expect } from "vitest";
|
import { it, describe, expect, assert } from "vitest";
|
||||||
|
|
||||||
import { ExpirationError } from "../../jsPeer/errors.js";
|
import { ExpirationError } from "../../jsPeer/errors.js";
|
||||||
import { CallServiceData } from "../../jsServiceHost/interfaces.js";
|
import { CallServiceData } from "../../jsServiceHost/interfaces.js";
|
||||||
@ -103,6 +103,7 @@ describe("FluenceClient usage test suite", () => {
|
|||||||
callback: {
|
callback: {
|
||||||
callback: (args): undefined => {
|
callback: (args): undefined => {
|
||||||
const [val] = args;
|
const [val] = args;
|
||||||
|
assert(val);
|
||||||
resolve(val);
|
resolve(val);
|
||||||
},
|
},
|
||||||
error: (args): undefined => {
|
error: (args): undefined => {
|
||||||
|
@ -20,6 +20,6 @@ export const nodes = [
|
|||||||
"/ip4/127.0.0.1/tcp/9991/ws/p2p/12D3KooWBM3SdXWqGaawQDGQ6JprtwswEg3FWGvGhmgmMez1vRbR",
|
"/ip4/127.0.0.1/tcp/9991/ws/p2p/12D3KooWBM3SdXWqGaawQDGQ6JprtwswEg3FWGvGhmgmMez1vRbR",
|
||||||
peerId: "12D3KooWBM3SdXWqGaawQDGQ6JprtwswEg3FWGvGhmgmMez1vRbR",
|
peerId: "12D3KooWBM3SdXWqGaawQDGQ6JprtwswEg3FWGvGhmgmMez1vRbR",
|
||||||
},
|
},
|
||||||
];
|
] as const;
|
||||||
|
|
||||||
export const RELAY = nodes[0].multiaddr;
|
export const RELAY = nodes[0].multiaddr;
|
||||||
|
@ -86,7 +86,7 @@ export const checkConnection = async (
|
|||||||
const [val] = args;
|
const [val] = args;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
resolve(val);
|
resolve(val ?? null);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -76,7 +76,7 @@ const structs = [
|
|||||||
c: [null, 2],
|
c: [null, 2],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
] as const;
|
||||||
|
|
||||||
const labeledProduct2 = {
|
const labeledProduct2 = {
|
||||||
tag: "labeledProduct",
|
tag: "labeledProduct",
|
||||||
@ -167,7 +167,7 @@ const nestedStructs = [
|
|||||||
c: [],
|
c: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
] as const;
|
||||||
|
|
||||||
interface ConversionTestArgs {
|
interface ConversionTestArgs {
|
||||||
aqua: JSONValue;
|
aqua: JSONValue;
|
||||||
|
@ -25,6 +25,8 @@ import {
|
|||||||
UnlabeledProductType,
|
UnlabeledProductType,
|
||||||
} from "@fluencelabs/interfaces";
|
} from "@fluencelabs/interfaces";
|
||||||
|
|
||||||
|
import { zip } from "../util/utils.js";
|
||||||
|
|
||||||
import { ServiceImpl, UserServiceImpl } from "./types.js";
|
import { ServiceImpl, UserServiceImpl } from "./types.js";
|
||||||
|
|
||||||
export class SchemaValidationError extends Error {
|
export class SchemaValidationError extends Error {
|
||||||
@ -103,10 +105,10 @@ export function aqua2js(
|
|||||||
throw new SchemaValidationError([], schema, "array", value);
|
throw new SchemaValidationError([], schema, "array", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.length === 0) {
|
if ("0" in value) {
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return aqua2js(value[0], schema.type);
|
return aqua2js(value[0], schema.type);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
schema.tag === "scalar" ||
|
schema.tag === "scalar" ||
|
||||||
@ -127,17 +129,23 @@ export function aqua2js(
|
|||||||
throw new SchemaValidationError([], schema, "array", value);
|
throw new SchemaValidationError([], schema, "array", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value.map((y, i) => {
|
return zip(value, schema.items).map(([v, s]) => {
|
||||||
return aqua2js(y, schema.items[i]);
|
return aqua2js(v, s);
|
||||||
});
|
});
|
||||||
} else if (["labeledProduct", "struct"].includes(schema.tag)) {
|
} else if (["labeledProduct", "struct"].includes(schema.tag)) {
|
||||||
if (typeof value !== "object" || value == null || Array.isArray(value)) {
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
||||||
throw new SchemaValidationError([], schema, "object", value);
|
throw new SchemaValidationError([], schema, "object", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(schema.fields).map(([key, type]) => {
|
Object.entries(schema.fields).map(([key, type]) => {
|
||||||
const val = aqua2js(value[key], type);
|
let v = value[key];
|
||||||
|
|
||||||
|
if (v === undefined) {
|
||||||
|
v = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const val = aqua2js(v, type);
|
||||||
return [key, val];
|
return [key, val];
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@ -159,7 +167,7 @@ export function js2aqua(
|
|||||||
return value;
|
return value;
|
||||||
} else if (schema.tag === "option") {
|
} else if (schema.tag === "option") {
|
||||||
// option means 'type | null'
|
// option means 'type | null'
|
||||||
return value == null ? [] : [js2aqua(value, schema.type, { path })];
|
return value === null ? [] : [js2aqua(value, schema.type, { path })];
|
||||||
} else if (schema.tag === "topType") {
|
} else if (schema.tag === "topType") {
|
||||||
// topType equals to 'any'
|
// topType equals to 'any'
|
||||||
return value;
|
return value;
|
||||||
@ -181,8 +189,8 @@ export function js2aqua(
|
|||||||
throw new SchemaValidationError(path, schema, "array", value);
|
throw new SchemaValidationError(path, schema, "array", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value.map((y, i) => {
|
return zip(value, schema.items).map(([v, s], i) => {
|
||||||
return js2aqua(y, schema.items[i], { path: [...path, `[${i}]`] });
|
return js2aqua(v, s, { path: [...path, `[${i}]`] });
|
||||||
});
|
});
|
||||||
} else if (["labeledProduct", "struct"].includes(schema.tag)) {
|
} else if (["labeledProduct", "struct"].includes(schema.tag)) {
|
||||||
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
||||||
@ -191,7 +199,13 @@ export function js2aqua(
|
|||||||
|
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(schema.fields).map(([key, type]) => {
|
Object.entries(schema.fields).map(([key, type]) => {
|
||||||
const val = js2aqua(value[key], type, { path: [...path, key] });
|
let v = value[key];
|
||||||
|
|
||||||
|
if (v === undefined) {
|
||||||
|
v = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const val = js2aqua(v, type, { path: [...path, key] });
|
||||||
return [key, val];
|
return [key, val];
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@ -222,8 +236,8 @@ export const wrapJsFunction = (
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const jsArgs = args.map((arg, i) => {
|
const jsArgs = zip(args, schemaArgs).map(([arg, schemaArg]) => {
|
||||||
return aqua2js(arg, schemaArgs[i]);
|
return aqua2js(arg, schemaArg);
|
||||||
});
|
});
|
||||||
|
|
||||||
const returnTypeVoid =
|
const returnTypeVoid =
|
||||||
@ -231,7 +245,8 @@ export const wrapJsFunction = (
|
|||||||
|
|
||||||
const resultSchema =
|
const resultSchema =
|
||||||
schema.codomain.tag === "unlabeledProduct" &&
|
schema.codomain.tag === "unlabeledProduct" &&
|
||||||
schema.codomain.items.length === 1
|
schema.codomain.items.length === 1 &&
|
||||||
|
"0" in schema.codomain.items
|
||||||
? schema.codomain.items[0]
|
? schema.codomain.items[0]
|
||||||
: schema.codomain;
|
: schema.codomain;
|
||||||
|
|
||||||
|
@ -28,10 +28,12 @@ interface RegisterServiceArgs {
|
|||||||
service: ServiceImpl;
|
service: ServiceImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ServiceFunctionPair = [key: string, value: ServiceImpl[string]];
|
||||||
|
|
||||||
// This function iterates on plain object or class instance functions ignoring inherited functions and prototype chain.
|
// This function iterates on plain object or class instance functions ignoring inherited functions and prototype chain.
|
||||||
const findAllPossibleRegisteredServiceFunctions = (
|
const findAllPossibleRegisteredServiceFunctions = (
|
||||||
service: ServiceImpl,
|
service: ServiceImpl,
|
||||||
): Array<string> => {
|
): Array<ServiceFunctionPair> => {
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||||
const prototype = Object.getPrototypeOf(service) as ServiceImpl;
|
const prototype = Object.getPrototypeOf(service) as ServiceImpl;
|
||||||
|
|
||||||
@ -41,8 +43,13 @@ const findAllPossibleRegisteredServiceFunctions = (
|
|||||||
service = prototype;
|
service = prototype;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.getOwnPropertyNames(service).filter((prop) => {
|
return Object.getOwnPropertyNames(service)
|
||||||
return typeof service[prop] === "function" && prop !== "constructor";
|
.map((prop) => {
|
||||||
|
return [prop, service[prop]];
|
||||||
|
})
|
||||||
|
.filter((entry): entry is ServiceFunctionPair => {
|
||||||
|
const [prop, value] = entry;
|
||||||
|
return typeof value === "function" && prop !== "constructor";
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -55,8 +62,7 @@ export const registerService = ({
|
|||||||
|
|
||||||
const serviceFunctions = findAllPossibleRegisteredServiceFunctions(service);
|
const serviceFunctions = findAllPossibleRegisteredServiceFunctions(service);
|
||||||
|
|
||||||
for (const serviceFunction of serviceFunctions) {
|
for (const [serviceFunction, handler] of serviceFunctions) {
|
||||||
const handler = service[serviceFunction];
|
|
||||||
const userDefinedHandler = handler.bind(service);
|
const userDefinedHandler = handler.bind(service);
|
||||||
|
|
||||||
const serviceDescription = userHandlerService(
|
const serviceDescription = userHandlerService(
|
||||||
|
@ -79,7 +79,7 @@ export const responseService = (resolveCallback: (val: JSONValue) => void) => {
|
|||||||
const userFunctionReturn =
|
const userFunctionReturn =
|
||||||
req.args.length === 0
|
req.args.length === 0
|
||||||
? null
|
? null
|
||||||
: req.args.length === 1
|
: req.args.length === 1 && "0" in req.args
|
||||||
? req.args[0]
|
? req.args[0]
|
||||||
: req.args;
|
: req.args;
|
||||||
|
|
||||||
@ -108,7 +108,10 @@ export const errorHandlingService = (
|
|||||||
const [err] = req.args;
|
const [err] = req.args;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
rejectCallback(err);
|
rejectCallback(
|
||||||
|
err ??
|
||||||
|
"Unknown error happened when executing aqua code. No error text was passed to 'errorHandlingSrv.error' function, probably because AIR code was modified or aqua compiler didn't produce the correct call",
|
||||||
|
);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -92,7 +92,7 @@ export class RelayConnection implements IConnection {
|
|||||||
this.relayAddress = multiaddr(this.config.relayAddress);
|
this.relayAddress = multiaddr(this.config.relayAddress);
|
||||||
const peerId = this.relayAddress.getPeerId();
|
const peerId = this.relayAddress.getPeerId();
|
||||||
|
|
||||||
if (peerId == null) {
|
if (peerId === null) {
|
||||||
throwHasNoPeerId(this.relayAddress);
|
throwHasNoPeerId(this.relayAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ export class RelayConnection implements IConnection {
|
|||||||
streamMuxers: [yamux()],
|
streamMuxers: [yamux()],
|
||||||
connectionEncryption: [noise()],
|
connectionEncryption: [noise()],
|
||||||
connectionManager: {
|
connectionManager: {
|
||||||
...(this.config.dialTimeoutMs != null
|
...(this.config.dialTimeoutMs !== undefined
|
||||||
? {
|
? {
|
||||||
dialTimeout: this.config.dialTimeoutMs,
|
dialTimeout: this.config.dialTimeoutMs,
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,12 @@ import { logger } from "../util/logger.js";
|
|||||||
const log = logger("ephemeral");
|
const log = logger("ephemeral");
|
||||||
|
|
||||||
interface EphemeralConfig {
|
interface EphemeralConfig {
|
||||||
peers: Array<{
|
peers: Readonly<
|
||||||
|
Array<{
|
||||||
peerId: PeerIdB58;
|
peerId: PeerIdB58;
|
||||||
sk: string;
|
sk: string;
|
||||||
}>;
|
}>
|
||||||
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultConfig = {
|
export const defaultConfig = {
|
||||||
@ -119,7 +121,7 @@ export const defaultConfig = {
|
|||||||
sk: "RbgKmG6soWW9uOi7yRedm+0Qck3f3rw6MSnDP7AcBQs=",
|
sk: "RbgKmG6soWW9uOi7yRedm+0Qck3f3rw6MSnDP7AcBQs=",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
} as const;
|
||||||
|
|
||||||
export interface IEphemeralConnection extends IConnection {
|
export interface IEphemeralConnection extends IConnection {
|
||||||
readonly selfPeerId: PeerIdB58;
|
readonly selfPeerId: PeerIdB58;
|
||||||
@ -248,17 +250,17 @@ export class EphemeralNetwork {
|
|||||||
|
|
||||||
const peers = await Promise.all(promises);
|
const peers = await Promise.all(promises);
|
||||||
|
|
||||||
for (let i = 0; i < peers.length; i++) {
|
peers.forEach((peer, i) => {
|
||||||
for (let j = 0; j < i; j++) {
|
const otherPeers = peers.slice(0, i);
|
||||||
|
|
||||||
|
otherPeers.forEach((otherPeer, j) => {
|
||||||
if (i === j) {
|
if (i === j) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
peers[i].ephemeralConnection.connectToOther(
|
peer.ephemeralConnection.connectToOther(otherPeer.ephemeralConnection);
|
||||||
peers[j].ephemeralConnection,
|
});
|
||||||
);
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const startPromises = peers.map((x) => {
|
const startPromises = peers.map((x) => {
|
||||||
return x.start();
|
return x.start();
|
||||||
|
@ -111,7 +111,7 @@ export const Fluence: FluencePublicApi = {
|
|||||||
* @returns IFluenceClient instance
|
* @returns IFluenceClient instance
|
||||||
*/
|
*/
|
||||||
getClient: function () {
|
getClient: function () {
|
||||||
if (this.defaultClient == null) {
|
if (this.defaultClient === undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Fluence client is not initialized. Call Fluence.connect() first",
|
"Fluence client is not initialized. Call Fluence.connect() first",
|
||||||
);
|
);
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { JSONValue } from "@fluencelabs/interfaces";
|
import { JSONValue } from "@fluencelabs/interfaces";
|
||||||
import { it, describe, expect } from "vitest";
|
import { it, describe, expect, assert } from "vitest";
|
||||||
|
|
||||||
import { handleTimeout } from "../../particle/Particle.js";
|
import { handleTimeout } from "../../particle/Particle.js";
|
||||||
import { registerHandlersHelper, withPeer } from "../../util/testUtils.js";
|
import { registerHandlersHelper, withPeer } from "../../util/testUtils.js";
|
||||||
@ -39,6 +39,7 @@ describe("Basic AVM functionality in Fluence Peer tests", () => {
|
|||||||
print: {
|
print: {
|
||||||
print: (args): undefined => {
|
print: (args): undefined => {
|
||||||
const [res] = args;
|
const [res] = args;
|
||||||
|
assert(res);
|
||||||
resolve(res);
|
resolve(res);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -80,6 +81,7 @@ describe("Basic AVM functionality in Fluence Peer tests", () => {
|
|||||||
registerHandlersHelper(peer, particle, {
|
registerHandlersHelper(peer, particle, {
|
||||||
print: {
|
print: {
|
||||||
print: (args): undefined => {
|
print: (args): undefined => {
|
||||||
|
assert(args[0]);
|
||||||
res.push(args[0]);
|
res.push(args[0]);
|
||||||
|
|
||||||
if (res.length === 2) {
|
if (res.length === 2) {
|
||||||
|
@ -14,10 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import assert from "assert";
|
|
||||||
|
|
||||||
import { JSONValue } from "@fluencelabs/interfaces";
|
import { JSONValue } from "@fluencelabs/interfaces";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it, assert } from "vitest";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CallServiceData,
|
CallServiceData,
|
||||||
@ -52,6 +50,7 @@ describe("FluencePeer flow tests", () => {
|
|||||||
(req: CallServiceData) => {
|
(req: CallServiceData) => {
|
||||||
const [timeout, message] = req.args;
|
const [timeout, message] = req.args;
|
||||||
assert(typeof timeout === "number");
|
assert(typeof timeout === "number");
|
||||||
|
assert(message);
|
||||||
|
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -77,6 +76,7 @@ describe("FluencePeer flow tests", () => {
|
|||||||
callback: {
|
callback: {
|
||||||
callback1: (args): undefined => {
|
callback1: (args): undefined => {
|
||||||
const [val] = args;
|
const [val] = args;
|
||||||
|
assert(val);
|
||||||
values.push(val);
|
values.push(val);
|
||||||
|
|
||||||
if (values.length === 2) {
|
if (values.length === 2) {
|
||||||
@ -85,6 +85,7 @@ describe("FluencePeer flow tests", () => {
|
|||||||
},
|
},
|
||||||
callback2: (args): undefined => {
|
callback2: (args): undefined => {
|
||||||
const [val] = args;
|
const [val] = args;
|
||||||
|
assert(val);
|
||||||
values.push(val);
|
values.push(val);
|
||||||
|
|
||||||
if (values.length === 2) {
|
if (values.length === 2) {
|
||||||
|
@ -18,7 +18,7 @@ import * as fs from "fs";
|
|||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import * as url from "url";
|
import * as url from "url";
|
||||||
|
|
||||||
import { it, describe, expect, beforeAll } from "vitest";
|
import { it, describe, expect, beforeAll, assert } from "vitest";
|
||||||
|
|
||||||
import { compileAqua, CompiledFnCall, withPeer } from "../../util/testUtils.js";
|
import { compileAqua, CompiledFnCall, withPeer } from "../../util/testUtils.js";
|
||||||
|
|
||||||
@ -46,6 +46,7 @@ describe("Marine js tests", () => {
|
|||||||
await peer.registerMarineService(wasm, "greeting");
|
await peer.registerMarineService(wasm, "greeting");
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
assert(aqua["call"]);
|
||||||
const res = await aqua["call"](peer, { arg: "test" });
|
const res = await aqua["call"](peer, { arg: "test" });
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
|
@ -43,7 +43,7 @@ export class MarineBackgroundRunner implements IMarineHost {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async hasService(serviceId: string) {
|
async hasService(serviceId: string) {
|
||||||
if (this.workerThread == null) {
|
if (this.workerThread === undefined) {
|
||||||
throw new Error("Worker is not initialized");
|
throw new Error("Worker is not initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ export class MarineBackgroundRunner implements IMarineHost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async removeService(serviceId: string) {
|
async removeService(serviceId: string) {
|
||||||
if (this.workerThread == null) {
|
if (this.workerThread === undefined) {
|
||||||
throw new Error("Worker is not initialized");
|
throw new Error("Worker is not initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ export class MarineBackgroundRunner implements IMarineHost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async start(): Promise<void> {
|
async start(): Promise<void> {
|
||||||
if (this.workerThread != null) {
|
if (this.workerThread !== undefined) {
|
||||||
throw new Error("Worker thread already initialized");
|
throw new Error("Worker thread already initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ export class MarineBackgroundRunner implements IMarineHost {
|
|||||||
const logfn: LogFunction = (message) => {
|
const logfn: LogFunction = (message) => {
|
||||||
const serviceLogger = this.loggers.get(message.service);
|
const serviceLogger = this.loggers.get(message.service);
|
||||||
|
|
||||||
if (serviceLogger == null) {
|
if (serviceLogger === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ export class MarineBackgroundRunner implements IMarineHost {
|
|||||||
serviceModule: ArrayBuffer | SharedArrayBuffer,
|
serviceModule: ArrayBuffer | SharedArrayBuffer,
|
||||||
serviceId: string,
|
serviceId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (this.workerThread == null) {
|
if (this.workerThread === undefined) {
|
||||||
throw new Error("Worker is not initialized");
|
throw new Error("Worker is not initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ export class MarineBackgroundRunner implements IMarineHost {
|
|||||||
args: Array<JSONValueNonNullable> | Record<string, JSONValueNonNullable>,
|
args: Array<JSONValueNonNullable> | Record<string, JSONValueNonNullable>,
|
||||||
callParams?: CallParameters,
|
callParams?: CallParameters,
|
||||||
): Promise<JSONValue> {
|
): Promise<JSONValue> {
|
||||||
if (this.workerThread == null) {
|
if (this.workerThread === undefined) {
|
||||||
throw new Error("Worker is not initialized");
|
throw new Error("Worker is not initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ export class MarineBackgroundRunner implements IMarineHost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async stop(): Promise<void> {
|
async stop(): Promise<void> {
|
||||||
if (this.workerThread == null) {
|
if (this.workerThread === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,11 +14,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import assert from "assert";
|
|
||||||
|
|
||||||
import { JSONArray } from "@fluencelabs/interfaces";
|
import { JSONArray } from "@fluencelabs/interfaces";
|
||||||
import { toUint8Array } from "js-base64";
|
import { toUint8Array } from "js-base64";
|
||||||
import { describe, expect, it, test } from "vitest";
|
import { describe, expect, it, test, assert } from "vitest";
|
||||||
|
|
||||||
import { CallServiceData } from "../../jsServiceHost/interfaces.js";
|
import { CallServiceData } from "../../jsServiceHost/interfaces.js";
|
||||||
import { KeyPair } from "../../keypair/index.js";
|
import { KeyPair } from "../../keypair/index.js";
|
||||||
@ -155,7 +153,8 @@ describe("Tests for default handler", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// act
|
// act
|
||||||
const fn = builtInServices[req.serviceId][req.fnName];
|
const fn = builtInServices[req.serviceId]?.[req.fnName];
|
||||||
|
assert(fn);
|
||||||
const res = await fn(req);
|
const res = await fn(req);
|
||||||
|
|
||||||
// Our test cases above depend on node error message. In node 20 error message for JSON.parse has changed.
|
// Our test cases above depend on node error message. In node 20 error message for JSON.parse has changed.
|
||||||
@ -192,7 +191,8 @@ describe("Tests for default handler", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// act
|
// act
|
||||||
const fn = builtInServices[req.serviceId][req.fnName];
|
const fn = builtInServices[req.serviceId]?.[req.fnName];
|
||||||
|
assert(fn);
|
||||||
const res = await fn(req);
|
const res = await fn(req);
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import * as url from "url";
|
import * as url from "url";
|
||||||
|
|
||||||
import { it, describe, expect, beforeAll } from "vitest";
|
import { it, describe, expect, beforeAll, assert } from "vitest";
|
||||||
|
|
||||||
import { registerService } from "../../compilerSupport/registerService.js";
|
import { registerService } from "../../compilerSupport/registerService.js";
|
||||||
import { KeyPair } from "../../keypair/index.js";
|
import { KeyPair } from "../../keypair/index.js";
|
||||||
@ -72,6 +72,7 @@ describe("Sig service test suite", () => {
|
|||||||
|
|
||||||
customSig.securityGuard = allowServiceFn("data", "provide_data");
|
customSig.securityGuard = allowServiceFn("data", "provide_data");
|
||||||
|
|
||||||
|
assert(aqua["callSig"]);
|
||||||
const result = await aqua["callSig"](peer, { sigId: "CustomSig" });
|
const result = await aqua["callSig"](peer, { sigId: "CustomSig" });
|
||||||
|
|
||||||
expect(result).toHaveProperty("success", true);
|
expect(result).toHaveProperty("success", true);
|
||||||
@ -116,6 +117,7 @@ describe("Sig service test suite", () => {
|
|||||||
|
|
||||||
customSig.securityGuard = allowServiceFn("wrong", "wrong");
|
customSig.securityGuard = allowServiceFn("wrong", "wrong");
|
||||||
|
|
||||||
|
assert(aqua["callSig"]);
|
||||||
const result = await aqua["callSig"](peer, { sigId: "CustomSig" });
|
const result = await aqua["callSig"](peer, { sigId: "CustomSig" });
|
||||||
expect(result).toHaveProperty("success", false);
|
expect(result).toHaveProperty("success", false);
|
||||||
});
|
});
|
||||||
@ -137,6 +139,7 @@ describe("Sig service test suite", () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
assert(aqua["callSig"]);
|
||||||
const callAsSigRes = await aqua["callSig"](peer, { sigId: "sig" });
|
const callAsSigRes = await aqua["callSig"](peer, { sigId: "sig" });
|
||||||
|
|
||||||
const callAsPeerIdRes = await aqua["callSig"](peer, {
|
const callAsPeerIdRes = await aqua["callSig"](peer, {
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import * as url from "url";
|
import * as url from "url";
|
||||||
|
|
||||||
import { it, describe, expect, beforeAll } from "vitest";
|
import { it, describe, expect, beforeAll, assert } from "vitest";
|
||||||
|
|
||||||
import { compileAqua, CompiledFnCall, withPeer } from "../../util/testUtils.js";
|
import { compileAqua, CompiledFnCall, withPeer } from "../../util/testUtils.js";
|
||||||
import { registerNodeUtils } from "../_aqua/node-utils.js";
|
import { registerNodeUtils } from "../_aqua/node-utils.js";
|
||||||
@ -42,6 +42,7 @@ describe("Srv service test suite", () => {
|
|||||||
const wasm = path.join(__dirname, "../../../data_for_test/greeting.wasm");
|
const wasm = path.join(__dirname, "../../../data_for_test/greeting.wasm");
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
assert(aqua["happy_path"]);
|
||||||
const res = await aqua["happy_path"](peer, { file_path: wasm });
|
const res = await aqua["happy_path"](peer, { file_path: wasm });
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
@ -57,6 +58,7 @@ describe("Srv service test suite", () => {
|
|||||||
const wasm = path.join(__dirname, "../../../data_for_test/greeting.wasm");
|
const wasm = path.join(__dirname, "../../../data_for_test/greeting.wasm");
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
assert(aqua["list_services"]);
|
||||||
const res = await aqua["list_services"](peer, { file_path: wasm });
|
const res = await aqua["list_services"](peer, { file_path: wasm });
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
@ -72,6 +74,8 @@ describe("Srv service test suite", () => {
|
|||||||
const wasm = path.join(__dirname, "../../../data_for_test/greeting.wasm");
|
const wasm = path.join(__dirname, "../../../data_for_test/greeting.wasm");
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
assert(aqua["service_removed"]);
|
||||||
|
|
||||||
const res = await aqua["service_removed"](peer, {
|
const res = await aqua["service_removed"](peer, {
|
||||||
file_path: wasm,
|
file_path: wasm,
|
||||||
});
|
});
|
||||||
@ -87,6 +91,7 @@ describe("Srv service test suite", () => {
|
|||||||
registerNodeUtils(peer, "node_utils", new NodeUtils(peer));
|
registerNodeUtils(peer, "node_utils", new NodeUtils(peer));
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
assert(aqua["file_not_found"]);
|
||||||
const res = await aqua["file_not_found"](peer, {});
|
const res = await aqua["file_not_found"](peer, {});
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
@ -102,6 +107,7 @@ describe("Srv service test suite", () => {
|
|||||||
registerNodeUtils(peer, "node_utils", new NodeUtils(peer));
|
registerNodeUtils(peer, "node_utils", new NodeUtils(peer));
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
assert(aqua["removing_non_exiting"]);
|
||||||
const res = await aqua["removing_non_exiting"](peer, {});
|
const res = await aqua["removing_non_exiting"](peer, {});
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
|
@ -109,7 +109,7 @@ const parseWithSchema = <T extends z.ZodTypeAny>(
|
|||||||
if (result.success) {
|
if (result.success) {
|
||||||
return [result.data, null];
|
return [result.data, null];
|
||||||
} else {
|
} else {
|
||||||
return [null, result.error.errors[0].message];
|
return [null, result.error.errors[0]?.message ?? "Unknown error"];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ const withSchema: withSchema = <T extends z.ZodTypeAny>(schema: T) => {
|
|||||||
return (req) => {
|
return (req) => {
|
||||||
const [value, message] = parseWithSchema(schema, req);
|
const [value, message] = parseWithSchema(schema, req);
|
||||||
|
|
||||||
if (message != null) {
|
if (message !== null) {
|
||||||
return error(message);
|
return error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +306,7 @@ export const builtInServices: Record<
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
identity: withSchema(z.array(jsonSchema).max(1))((args) => {
|
identity: withSchema(z.array(jsonSchema).max(1))((args) => {
|
||||||
return success(args.length === 0 ? {} : args[0]);
|
return success("0" in args ? args[0] : {});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
concat: withSchema(z.array(z.array(z.any())))((args) => {
|
concat: withSchema(z.array(z.array(z.any())))((args) => {
|
||||||
|
@ -33,8 +33,8 @@ export const allowTetraplet = (
|
|||||||
pred: (tetraplet: SecurityTetraplet) => boolean,
|
pred: (tetraplet: SecurityTetraplet) => boolean,
|
||||||
): SecurityGuard => {
|
): SecurityGuard => {
|
||||||
return (params) => {
|
return (params) => {
|
||||||
const t = params.tetraplets[0][0];
|
const t = params.tetraplets[0]?.[0];
|
||||||
return pred(t);
|
return t !== undefined && pred(t);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ export function relayOptionToMultiaddr(relay: RelayOptions): Multiaddr {
|
|||||||
|
|
||||||
const peerId = ma.getPeerId();
|
const peerId = ma.getPeerId();
|
||||||
|
|
||||||
if (peerId == null) {
|
if (peerId === null) {
|
||||||
throwHasNoPeerId(ma);
|
throwHasNoPeerId(ma);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,3 +33,19 @@ export const getErrorMessage = (error: unknown) => {
|
|||||||
|
|
||||||
return String(error);
|
return String(error);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function zip<A, B>(arr1: Array<A>, arr2: Array<B>): Array<[A, B]> {
|
||||||
|
if (arr1.length !== arr2.length) {
|
||||||
|
throw new Error(`Array length doesn't match`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const arr = new Array<[A, B]>(arr1.length);
|
||||||
|
|
||||||
|
for (let i = 0; i < arr1.length; i++) {
|
||||||
|
// Length has been checked above
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
arr[i] = [arr1[i]!, arr2[i]!];
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
@ -74,7 +74,7 @@ const toExpose = {
|
|||||||
serviceId: string,
|
serviceId: string,
|
||||||
envs?: Env,
|
envs?: Env,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
if (controlModule == null) {
|
if (controlModule === undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"MarineJS is not initialized. To initialize call `init` function",
|
"MarineJS is not initialized. To initialize call `init` function",
|
||||||
);
|
);
|
||||||
@ -135,7 +135,7 @@ const toExpose = {
|
|||||||
) => {
|
) => {
|
||||||
const srv = marineServices.get(serviceId);
|
const srv = marineServices.get(serviceId);
|
||||||
|
|
||||||
if (srv == null) {
|
if (srv === undefined) {
|
||||||
throw new Error(`service with id=${serviceId} not found`);
|
throw new Error(`service with id=${serviceId} not found`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
packages/core/npm-aqua-compiler/package.json
Normal file
29
packages/core/npm-aqua-compiler/package.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"type": "module",
|
||||||
|
"name": "@fluencelabs/npm-aqua-compiler",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "Tool for converting npm imports to aqua compiler input",
|
||||||
|
"types": "./dist/imports.d.ts",
|
||||||
|
"exports": {
|
||||||
|
".": "./dist/imports.js"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "npm i --prefix ./test/transitive-deps/project && vitest run",
|
||||||
|
"build": "tsc"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"keywords": [],
|
||||||
|
"author": "Fluence Labs",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@npmcli/arborist": "^7.2.1",
|
||||||
|
"treeverse": "3.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/npmcli__arborist": "5.6.5",
|
||||||
|
"@types/treeverse": "3.0.4",
|
||||||
|
"vitest": "0.34.6"
|
||||||
|
}
|
||||||
|
}
|
115
packages/core/npm-aqua-compiler/src/imports.spec.ts
Normal file
115
packages/core/npm-aqua-compiler/src/imports.spec.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/**
|
||||||
|
* 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 { join } from "path";
|
||||||
|
import { fileURLToPath } from "url";
|
||||||
|
|
||||||
|
import { assert, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { gatherImportsFromNpm } from "./imports.js";
|
||||||
|
|
||||||
|
describe("imports", () => {
|
||||||
|
/**
|
||||||
|
* NOTE: This test expects that `npm i` is run
|
||||||
|
* inside `./__test__/data/transitive-deps/project` folder
|
||||||
|
*/
|
||||||
|
it("should resolve transitive dependencies", async () => {
|
||||||
|
const npmProjectDirPath = "./test/transitive-deps/project";
|
||||||
|
const aquaToCompileDirPath = "./test/transitive-deps/aqua-project";
|
||||||
|
const globalImports = ["./.fluence/aqua"];
|
||||||
|
|
||||||
|
const expectedResolution: Record<
|
||||||
|
string,
|
||||||
|
Record<string, string[] | string>
|
||||||
|
> = {
|
||||||
|
[aquaToCompileDirPath]: {
|
||||||
|
"": globalImports,
|
||||||
|
A: "./A",
|
||||||
|
B: "./B",
|
||||||
|
},
|
||||||
|
"./A": {
|
||||||
|
C: "./C",
|
||||||
|
D: "./D",
|
||||||
|
},
|
||||||
|
"./B": {
|
||||||
|
C: "./B/C",
|
||||||
|
D: "./B/D",
|
||||||
|
},
|
||||||
|
"./C": {
|
||||||
|
D: "./C/D",
|
||||||
|
},
|
||||||
|
"./B/C": {
|
||||||
|
D: "./B/C/D",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const prefix = join(
|
||||||
|
fileURLToPath(new URL("./", import.meta.url)),
|
||||||
|
"..",
|
||||||
|
"test",
|
||||||
|
"transitive-deps",
|
||||||
|
"project",
|
||||||
|
);
|
||||||
|
|
||||||
|
const buildResolutionKey = (str: string) => {
|
||||||
|
return (
|
||||||
|
"./" +
|
||||||
|
str
|
||||||
|
.slice(prefix.length)
|
||||||
|
.split("/node_modules/")
|
||||||
|
.filter(Boolean)
|
||||||
|
.join("/")
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const imports = await gatherImportsFromNpm({
|
||||||
|
npmProjectDirPath,
|
||||||
|
aquaToCompileDirPath,
|
||||||
|
globalImports,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(Object.keys(imports).length).toBe(
|
||||||
|
Object.keys(expectedResolution).length,
|
||||||
|
);
|
||||||
|
|
||||||
|
Object.entries(imports).forEach(([key, value]) => {
|
||||||
|
const resolutionKey =
|
||||||
|
key === aquaToCompileDirPath ? key : buildResolutionKey(key);
|
||||||
|
|
||||||
|
const resolutionValues = expectedResolution[resolutionKey];
|
||||||
|
|
||||||
|
assert(resolutionValues);
|
||||||
|
|
||||||
|
expect(Object.keys(value).length).toBe(
|
||||||
|
Object.keys(resolutionValues).length,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const [dep, path] of Object.entries(value)) {
|
||||||
|
if (Array.isArray(path)) {
|
||||||
|
expect(dep).toBe("");
|
||||||
|
expect(expectedResolution[resolutionKey]).toHaveProperty(dep, path);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(expectedResolution[resolutionKey]).toHaveProperty(
|
||||||
|
dep,
|
||||||
|
buildResolutionKey(path),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
92
packages/core/npm-aqua-compiler/src/imports.ts
Normal file
92
packages/core/npm-aqua-compiler/src/imports.ts
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/**
|
||||||
|
* 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 Arborist from "@npmcli/arborist";
|
||||||
|
import { breadth } from "treeverse";
|
||||||
|
|
||||||
|
export interface GatherImportsArg {
|
||||||
|
npmProjectDirPath: string;
|
||||||
|
aquaToCompileDirPath?: string; // Default: npmProjectDirPath
|
||||||
|
globalImports?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GatherImportsResult = Record<
|
||||||
|
string,
|
||||||
|
Record<string, string[] | string>
|
||||||
|
>;
|
||||||
|
|
||||||
|
export async function gatherImportsFromNpm({
|
||||||
|
npmProjectDirPath,
|
||||||
|
aquaToCompileDirPath,
|
||||||
|
globalImports = [],
|
||||||
|
}: GatherImportsArg): Promise<GatherImportsResult> {
|
||||||
|
const arborist = new Arborist({ path: npmProjectDirPath });
|
||||||
|
const tree = await arborist.loadActual();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Traverse dependency tree to construct map
|
||||||
|
* (real path of a package) -> (real paths of its immediate dependencies)
|
||||||
|
*/
|
||||||
|
const result: GatherImportsResult = {};
|
||||||
|
|
||||||
|
breadth({
|
||||||
|
tree,
|
||||||
|
getChildren(node) {
|
||||||
|
const deps: Arborist.Node[] = [];
|
||||||
|
|
||||||
|
for (const edge of node.edgesOut.values()) {
|
||||||
|
// Skip dependencies that are not installed.
|
||||||
|
|
||||||
|
// Looks like Arborist type is incorrect here, so it's possible to have null here
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
|
if (edge.to === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Any errors in edge are ignored.
|
||||||
|
const dep = edge.to;
|
||||||
|
|
||||||
|
// Gather dependencies to traverse them.
|
||||||
|
deps.push(dep);
|
||||||
|
|
||||||
|
// Root node should have top-level property pointed to aqua dependency folder
|
||||||
|
if (node.isRoot) {
|
||||||
|
const aquaDepPath = aquaToCompileDirPath ?? npmProjectDirPath;
|
||||||
|
|
||||||
|
result[aquaDepPath] = {
|
||||||
|
...(result[aquaDepPath] ??
|
||||||
|
(globalImports.length > 0
|
||||||
|
? {
|
||||||
|
"": globalImports,
|
||||||
|
}
|
||||||
|
: {})),
|
||||||
|
[dep.name]: dep.realpath,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Gather dependencies real paths.
|
||||||
|
result[node.realpath] = {
|
||||||
|
...(result[node.realpath] ?? {}),
|
||||||
|
[dep.name]: dep.realpath,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return deps;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
BIN
packages/core/npm-aqua-compiler/test/transitive-deps/A-0.1.0.tgz
Normal file
BIN
packages/core/npm-aqua-compiler/test/transitive-deps/A-0.1.0.tgz
Normal file
Binary file not shown.
BIN
packages/core/npm-aqua-compiler/test/transitive-deps/B-0.1.0.tgz
Normal file
BIN
packages/core/npm-aqua-compiler/test/transitive-deps/B-0.1.0.tgz
Normal file
Binary file not shown.
BIN
packages/core/npm-aqua-compiler/test/transitive-deps/C-0.1.0.tgz
Normal file
BIN
packages/core/npm-aqua-compiler/test/transitive-deps/C-0.1.0.tgz
Normal file
Binary file not shown.
BIN
packages/core/npm-aqua-compiler/test/transitive-deps/C-0.2.0.tgz
Normal file
BIN
packages/core/npm-aqua-compiler/test/transitive-deps/C-0.2.0.tgz
Normal file
Binary file not shown.
BIN
packages/core/npm-aqua-compiler/test/transitive-deps/D-0.1.0.tgz
Normal file
BIN
packages/core/npm-aqua-compiler/test/transitive-deps/D-0.1.0.tgz
Normal file
Binary file not shown.
BIN
packages/core/npm-aqua-compiler/test/transitive-deps/D-0.2.0.tgz
Normal file
BIN
packages/core/npm-aqua-compiler/test/transitive-deps/D-0.2.0.tgz
Normal file
Binary file not shown.
@ -0,0 +1,8 @@
|
|||||||
|
use "B.aqua"
|
||||||
|
|
||||||
|
func versionAC() -> string:
|
||||||
|
<- A.versionC()
|
||||||
|
|
||||||
|
func versionBC() -> string:
|
||||||
|
<- B.versionC()
|
||||||
|
|
70
packages/core/npm-aqua-compiler/test/transitive-deps/project/package-lock.json
generated
Normal file
70
packages/core/npm-aqua-compiler/test/transitive-deps/project/package-lock.json
generated
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"name": "project",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "project",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"dependencies": {
|
||||||
|
"A": "file:../A-0.1.0.tgz",
|
||||||
|
"B": "file:../B-0.1.0.tgz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/A": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "file:../A-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-H0nhbQVQxPm3VwXYiePLJ0oyHa2FxPNNPjOcTdz3YWvIoE0/dZFJ1yrqig7fkrETYEYfLuVJaN0yg1BX/HAScg==",
|
||||||
|
"dependencies": {
|
||||||
|
"C": "file:./C-0.2.0.tgz",
|
||||||
|
"D": "file:./D-0.1.0.tgz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/B": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "file:../B-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-u6n6V5KlxIN/GwRQt82gZQAPwYi0OzqQ2wr8ufmygreLK3fPIfO49f13qagbGXaYiRxN9effXaPqZlMIyTygng==",
|
||||||
|
"dependencies": {
|
||||||
|
"C": "file:./C-0.1.0.tgz",
|
||||||
|
"D": "file:./D-0.2.0.tgz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/B/node_modules/C": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "file:../C-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-zvzWgHLm+ptWwysP+dJItnogVSca/jvHegWmwi6NmmHFO/wTqlGrMPnC2dEkpXDJBU4X1bUjevFh0q3Xe9e0MA==",
|
||||||
|
"dependencies": {
|
||||||
|
"D": "file:./D-0.1.0.tgz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/B/node_modules/C/node_modules/D": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "file:../D-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-1rlKmuyzHSGTt9tBhEBY3j7gZvMBg0LnZMogZSucmX4gww4l0+HPQwBIPjJpqOspE2ND8PcLymQoiw06xWXn0g=="
|
||||||
|
},
|
||||||
|
"node_modules/B/node_modules/D": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "file:../D-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-7h1TUU8j60q6BZ0Wq/xDZOUf6iS0S4SgL/lgXOaiyxN76q7ld8Rx/qIxtGKmrWh65v5cjvAG5asbMEkXb6DuYQ=="
|
||||||
|
},
|
||||||
|
"node_modules/C": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "file:../C-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-uNqb8p69kuombZsb3xI/ygeL94WHpwkGR9/GRWgdg+01iKGsRMaZgL5up0UG7D/9DW7NQBozZG8ITPQ8DLgwSQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"D": "file:./D-0.2.0.tgz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/C/node_modules/D": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "file:../D-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-7h1TUU8j60q6BZ0Wq/xDZOUf6iS0S4SgL/lgXOaiyxN76q7ld8Rx/qIxtGKmrWh65v5cjvAG5asbMEkXb6DuYQ=="
|
||||||
|
},
|
||||||
|
"node_modules/D": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "file:../D-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-1rlKmuyzHSGTt9tBhEBY3j7gZvMBg0LnZMogZSucmX4gww4l0+HPQwBIPjJpqOspE2ND8PcLymQoiw06xWXn0g=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "project",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"dependencies": {
|
||||||
|
"A": "file:../A-0.1.0.tgz",
|
||||||
|
"B": "file:../B-0.1.0.tgz"
|
||||||
|
}
|
||||||
|
}
|
9
packages/core/npm-aqua-compiler/tsconfig.json
Normal file
9
packages/core/npm-aqua-compiler/tsconfig.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"outDir": "./dist"
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["node_modules", "dist", "src/**/__test__"]
|
||||||
|
}
|
1150
pnpm-lock.yaml
generated
1150
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -7,8 +7,7 @@
|
|||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"moduleResolution": "nodenext",
|
"moduleResolution": "nodenext"
|
||||||
"noUncheckedIndexedAccess": false
|
|
||||||
},
|
},
|
||||||
"files": ["reset.d.ts"]
|
"files": ["reset.d.ts"]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user