@weborigami/language 0.5.8 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.ts +3 -4
- package/main.js +2 -4
- package/package.json +4 -5
- package/src/compiler/optimize.js +3 -1
- package/src/compiler/parserHelpers.js +1 -7
- package/src/handlers/csv_handler.js +13 -8
- package/src/handlers/getSource.js +36 -0
- package/src/handlers/ori_handler.js +5 -20
- package/src/handlers/oridocument_handler.js +5 -28
- package/src/handlers/tsv_handler.js +10 -1
- package/src/handlers/yaml_handler.js +75 -3
- package/src/project/jsGlobals.js +5 -1
- package/src/project/projectConfig.js +4 -4
- package/src/project/projectRoot.js +8 -9
- package/src/protocols/constructSiteTree.js +4 -4
- package/src/protocols/explore.js +2 -3
- package/src/protocols/fetchAndHandleExtension.js +0 -1
- package/src/protocols/files.js +2 -3
- package/src/protocols/http.js +0 -1
- package/src/protocols/https.js +0 -1
- package/src/protocols/httpstree.js +2 -3
- package/src/protocols/httptree.js +2 -3
- package/src/runtime/HandleExtensionsTransform.js +32 -8
- package/src/runtime/ImportModulesMixin.js +2 -2
- package/src/runtime/{OrigamiFiles.js → OrigamiFileMap.d.ts} +3 -3
- package/src/runtime/{OrigamiFiles.d.ts → OrigamiFileMap.js} +3 -5
- package/src/runtime/errors.js +9 -2
- package/src/runtime/evaluate.js +1 -1
- package/src/runtime/expressionFunction.js +3 -3
- package/src/runtime/expressionObject.js +19 -8
- package/src/runtime/handleExtension.js +2 -11
- package/src/runtime/mergeTrees.js +4 -7
- package/src/runtime/ops.js +13 -13
- package/test/cases/logicalAndExpression.yaml +7 -8
- package/test/compiler/compile.test.js +1 -1
- package/test/compiler/optimize.test.js +2 -2
- package/test/compiler/parse.test.js +13 -19
- package/test/generated/logicalAndExpression.test.js +4 -0
- package/test/handlers/csv_handler.test.js +5 -5
- package/test/handlers/js_handler.test.js +2 -2
- package/test/handlers/ori_handler.test.js +8 -8
- package/test/handlers/oridocument_handler.test.js +3 -3
- package/test/handlers/tsv_handler.test.js +5 -5
- package/test/handlers/wasm_handler.test.js +2 -2
- package/test/handlers/yaml_handler.test.js +31 -1
- package/test/runtime/OrigamiFileMap.test.js +40 -0
- package/test/runtime/evaluate.test.js +3 -3
- package/test/runtime/expressionObject.test.js +14 -6
- package/test/runtime/handleExtension.test.js +2 -9
- package/test/runtime/mergeTrees.test.js +2 -2
- package/test/runtime/ops.test.js +18 -12
- package/src/runtime/InvokeFunctionsTransform.d.ts +0 -5
- package/src/runtime/InvokeFunctionsTransform.js +0 -25
- package/src/runtime/functionResultsMap.js +0 -17
- package/test/runtime/OrigamiFiles.test.js +0 -35
- package/test/runtime/fixtures/subgraph = this.js +0 -5
- package/test/runtime/functionResultsMap.test.js +0 -20
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FileMap } from "@weborigami/async-tree";
|
|
2
2
|
import assert from "node:assert";
|
|
3
3
|
import { describe, test } from "node:test";
|
|
4
4
|
import wasm_handler from "../../src/handlers/wasm_handler.js";
|
|
5
5
|
import ImportModulesMixin from "../../src/runtime/ImportModulesMixin.js";
|
|
6
6
|
|
|
7
7
|
const fixturesUrl = new URL("fixtures", import.meta.url);
|
|
8
|
-
const fixturesTree = new (ImportModulesMixin(
|
|
8
|
+
const fixturesTree = new (ImportModulesMixin(FileMap))(fixturesUrl);
|
|
9
9
|
|
|
10
10
|
describe(".wasm handler", () => {
|
|
11
11
|
test("loads .wasm file that exports a function", async () => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Tree } from "@weborigami/async-tree";
|
|
1
2
|
import assert from "node:assert";
|
|
2
3
|
import { describe, test } from "node:test";
|
|
3
4
|
import yaml_handler from "../../src/handlers/yaml_handler.js";
|
|
@@ -8,10 +9,39 @@ describe(".yaml handler", () => {
|
|
|
8
9
|
a: 1
|
|
9
10
|
b: 2
|
|
10
11
|
`;
|
|
11
|
-
const data = yaml_handler.unpack(text);
|
|
12
|
+
const data = await yaml_handler.unpack(text);
|
|
12
13
|
assert.deepEqual(data, {
|
|
13
14
|
a: 1,
|
|
14
15
|
b: 2,
|
|
15
16
|
});
|
|
16
17
|
});
|
|
18
|
+
|
|
19
|
+
test("defines !ori tag for Origami expressions", async () => {
|
|
20
|
+
const text = `
|
|
21
|
+
message: Hello
|
|
22
|
+
answer: !ori 1 + 1
|
|
23
|
+
`;
|
|
24
|
+
const data = await yaml_handler.unpack(text);
|
|
25
|
+
const plain = await Tree.plain(data);
|
|
26
|
+
assert.deepEqual(plain, {
|
|
27
|
+
message: "Hello",
|
|
28
|
+
answer: 2,
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("defines !ori.call tag for Origami function invocation", async () => {
|
|
33
|
+
const text = `
|
|
34
|
+
message: Hello
|
|
35
|
+
answer: !ori.call
|
|
36
|
+
- (a, b) => a + b
|
|
37
|
+
- 2
|
|
38
|
+
- 3
|
|
39
|
+
`;
|
|
40
|
+
const data = await yaml_handler.unpack(text);
|
|
41
|
+
const plain = await Tree.plain(data);
|
|
42
|
+
assert.deepEqual(plain, {
|
|
43
|
+
message: "Hello",
|
|
44
|
+
answer: 5,
|
|
45
|
+
});
|
|
46
|
+
});
|
|
17
47
|
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { describe, test } from "node:test";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import OrigamiFileMap from "../../src/runtime/OrigamiFileMap.js";
|
|
7
|
+
|
|
8
|
+
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const tempDirectory = path.join(dirname, "fixtures/temp/OrigamiFileMap");
|
|
10
|
+
|
|
11
|
+
describe("OrigamiFileMap", () => {
|
|
12
|
+
test.skip("can watch its folder for changes", { timeout: 2000 }, async () => {
|
|
13
|
+
createTempDirectory();
|
|
14
|
+
|
|
15
|
+
const tempFiles = new OrigamiFileMap(tempDirectory);
|
|
16
|
+
const changedFileName = await new Promise(async (resolve) => {
|
|
17
|
+
tempFiles.addEventListener("change", (event) => {
|
|
18
|
+
resolve(/** @type {any} */ (event).options.key);
|
|
19
|
+
});
|
|
20
|
+
tempFiles.set(
|
|
21
|
+
"foo.txt",
|
|
22
|
+
"This file is left over from testing and can be removed."
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
removeTempDirectory();
|
|
26
|
+
assert.equal(changedFileName, "foo.txt");
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
function createTempDirectory() {
|
|
31
|
+
// Remove any existing files or directories inside the temp directory so
|
|
32
|
+
// tests start from a clean slate. Use force so this is safe if the
|
|
33
|
+
// directory doesn't exist.
|
|
34
|
+
fs.rmSync(tempDirectory, { force: true, recursive: true });
|
|
35
|
+
fs.mkdirSync(tempDirectory, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function removeTempDirectory() {
|
|
39
|
+
fs.rmSync(tempDirectory, { force: true, recursive: true });
|
|
40
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { SyncMap } from "@weborigami/async-tree";
|
|
5
5
|
import evaluate from "../../src/runtime/evaluate.js";
|
|
6
6
|
import { createCode } from "../compiler/codeHelpers.js";
|
|
7
7
|
|
|
@@ -27,12 +27,12 @@ describe("evaluate", () => {
|
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
test("if function has containerAsTarget, it gets bound to state.container", async () => {
|
|
30
|
-
/** @this {import("@weborigami/
|
|
30
|
+
/** @this {import("@weborigami/async-tree").SyncOrAsyncMap} */
|
|
31
31
|
const fn = function () {
|
|
32
32
|
return this;
|
|
33
33
|
};
|
|
34
34
|
fn.containerAsTarget = true;
|
|
35
|
-
const container = new
|
|
35
|
+
const container = new SyncMap();
|
|
36
36
|
const state = { container };
|
|
37
37
|
const code = createCode([fn]);
|
|
38
38
|
const result = await evaluate(code, state);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ObjectMap, symbols, SyncMap, Tree } from "@weborigami/async-tree";
|
|
2
2
|
import assert from "node:assert";
|
|
3
3
|
import { describe, test } from "node:test";
|
|
4
4
|
|
|
@@ -7,7 +7,7 @@ import { ops } from "../../src/runtime/internal.js";
|
|
|
7
7
|
|
|
8
8
|
describe("expressionObject", () => {
|
|
9
9
|
test("can instantiate an object", async () => {
|
|
10
|
-
const container = new
|
|
10
|
+
const container = new ObjectMap({
|
|
11
11
|
upper: (s) => s.toUpperCase(),
|
|
12
12
|
});
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ describe("expressionObject", () => {
|
|
|
15
15
|
["hello", [[[ops.scope, container], "upper"], "hello"]],
|
|
16
16
|
["world", [[[ops.scope, container], "upper"], "world"]],
|
|
17
17
|
];
|
|
18
|
-
const context = new
|
|
18
|
+
const context = new SyncMap();
|
|
19
19
|
|
|
20
20
|
const object = await expressionObject(entries, { object: context });
|
|
21
21
|
assert.equal(await object.hello, "HELLO");
|
|
@@ -43,7 +43,7 @@ describe("expressionObject", () => {
|
|
|
43
43
|
["name", "world"],
|
|
44
44
|
["message", [ops.concat, "Hello, ", [[ops.inherited, 0], "name"], "!"]],
|
|
45
45
|
];
|
|
46
|
-
const context = new
|
|
46
|
+
const context = new SyncMap();
|
|
47
47
|
const object = await expressionObject(entries, { object: context });
|
|
48
48
|
assert.deepEqual(await Tree.plain(object), {
|
|
49
49
|
name: "world",
|
|
@@ -54,7 +54,7 @@ describe("expressionObject", () => {
|
|
|
54
54
|
|
|
55
55
|
test("returned object values can be unpacked", async () => {
|
|
56
56
|
const entries = [["data.json", `{ "a": 1 }`]];
|
|
57
|
-
const context = new
|
|
57
|
+
const context = new SyncMap();
|
|
58
58
|
const result = await expressionObject(entries, { object: context });
|
|
59
59
|
const dataJson = await result["data.json"];
|
|
60
60
|
const json = await dataJson.unpack();
|
|
@@ -77,7 +77,7 @@ describe("expressionObject", () => {
|
|
|
77
77
|
["getter", [ops.getter, [ops.object, ["b", [ops.literal, 2]]]]],
|
|
78
78
|
["hasSlash/", "This isn't really a tree but says it is"],
|
|
79
79
|
["message", "Hello"],
|
|
80
|
-
// Immediate
|
|
80
|
+
// Immediate maplike value, should have a slash
|
|
81
81
|
["object", [ops.object, ["b", [ops.literal, 2]]]],
|
|
82
82
|
];
|
|
83
83
|
const object = await expressionObject(entries);
|
|
@@ -88,4 +88,12 @@ describe("expressionObject", () => {
|
|
|
88
88
|
"object/",
|
|
89
89
|
]);
|
|
90
90
|
});
|
|
91
|
+
|
|
92
|
+
test("sets symbols.async on objects with getters", async () => {
|
|
93
|
+
const noGetter = await expressionObject([["eager", 1]]);
|
|
94
|
+
assert.equal(noGetter[symbols.async], undefined);
|
|
95
|
+
|
|
96
|
+
const hasGetter = await expressionObject([["lazy", [ops.getter, [2]]]]);
|
|
97
|
+
assert.equal(hasGetter[symbols.async], true);
|
|
98
|
+
});
|
|
91
99
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ObjectMap } from "@weborigami/async-tree";
|
|
2
2
|
import assert from "node:assert";
|
|
3
3
|
import { describe, test } from "node:test";
|
|
4
4
|
import handleExtension from "../../src/runtime/handleExtension.js";
|
|
@@ -15,17 +15,10 @@ describe("handleExtension", () => {
|
|
|
15
15
|
const data = await withHandler.unpack();
|
|
16
16
|
assert.deepEqual(data, { bar: 2 });
|
|
17
17
|
});
|
|
18
|
-
|
|
19
|
-
test("immediately unpacks if key ends in slash", async () => {
|
|
20
|
-
const fixture = createFixture();
|
|
21
|
-
const jsonFile = await fixture.get("bar.json");
|
|
22
|
-
const data = await handleExtension(jsonFile, "bar.json/", fixture);
|
|
23
|
-
assert.deepEqual(data, { bar: 2 });
|
|
24
|
-
});
|
|
25
18
|
});
|
|
26
19
|
|
|
27
20
|
function createFixture() {
|
|
28
|
-
return new
|
|
21
|
+
return new ObjectMap({
|
|
29
22
|
foo: 1, // No extension, should be left alone
|
|
30
23
|
"bar.json": `{ "bar": 2 }`,
|
|
31
24
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ObjectMap, Tree } from "@weborigami/async-tree";
|
|
2
2
|
import assert from "node:assert";
|
|
3
3
|
import { describe, test } from "node:test";
|
|
4
4
|
import mergeTrees from "../../src/runtime/mergeTrees.js";
|
|
@@ -42,7 +42,7 @@ describe("mergeTrees", () => {
|
|
|
42
42
|
|
|
43
43
|
test("merges heterogenous arguments as trees", async () => {
|
|
44
44
|
const tree = await mergeTrees(
|
|
45
|
-
new
|
|
45
|
+
new ObjectMap({
|
|
46
46
|
a: 1,
|
|
47
47
|
b: 2,
|
|
48
48
|
}),
|
package/test/runtime/ops.test.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ObjectMap, Tree } from "@weborigami/async-tree";
|
|
2
2
|
import assert from "node:assert";
|
|
3
3
|
import { describe, test } from "node:test";
|
|
4
4
|
|
|
@@ -128,12 +128,12 @@ describe("ops", () => {
|
|
|
128
128
|
assert.deepEqual(await ops.flat(1, 2, [3]), [1, 2, 3]);
|
|
129
129
|
});
|
|
130
130
|
|
|
131
|
-
test("flattens
|
|
131
|
+
test("flattens maplike objects", async () => {
|
|
132
132
|
const object = {
|
|
133
133
|
a: 1,
|
|
134
134
|
b: 2,
|
|
135
135
|
};
|
|
136
|
-
const tree = new
|
|
136
|
+
const tree = new ObjectMap({
|
|
137
137
|
c: 3,
|
|
138
138
|
d: 4,
|
|
139
139
|
});
|
|
@@ -156,11 +156,14 @@ describe("ops", () => {
|
|
|
156
156
|
});
|
|
157
157
|
|
|
158
158
|
test("ops.inherited walks up the object parent chain", async () => {
|
|
159
|
-
const tree = new
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
const tree = new ObjectMap(
|
|
160
|
+
{
|
|
161
|
+
a: {
|
|
162
|
+
b: {},
|
|
163
|
+
},
|
|
162
164
|
},
|
|
163
|
-
|
|
165
|
+
{ deep: true }
|
|
166
|
+
);
|
|
164
167
|
const b = await Tree.traverse(tree, "a", "b");
|
|
165
168
|
assert.equal(await ops.inherited(2, { object: b }), tree);
|
|
166
169
|
});
|
|
@@ -368,12 +371,15 @@ describe("ops", () => {
|
|
|
368
371
|
|
|
369
372
|
describe("ops.scope", () => {
|
|
370
373
|
test("returns the scope of the given tree", async () => {
|
|
371
|
-
const tree = new
|
|
372
|
-
|
|
373
|
-
|
|
374
|
+
const tree = new ObjectMap(
|
|
375
|
+
{
|
|
376
|
+
a: {
|
|
377
|
+
b: {},
|
|
378
|
+
},
|
|
379
|
+
c: 1,
|
|
374
380
|
},
|
|
375
|
-
|
|
376
|
-
|
|
381
|
+
{ deep: true }
|
|
382
|
+
);
|
|
377
383
|
const a = await tree.get("a");
|
|
378
384
|
const b = await a.get("b");
|
|
379
385
|
const scope = await ops.scope(b);
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { Tree } from "@weborigami/async-tree";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* When using `get` to retrieve a value from a tree, if the value is a
|
|
5
|
-
* function, invoke it and return the result.
|
|
6
|
-
*
|
|
7
|
-
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
8
|
-
* @typedef {import("../../index.js").Constructor<AsyncTree>} AsyncTreeConstructor
|
|
9
|
-
* @param {AsyncTreeConstructor} Base
|
|
10
|
-
*/
|
|
11
|
-
export default function InvokeFunctionsTransform(Base) {
|
|
12
|
-
return class InvokeFunctions extends Base {
|
|
13
|
-
async get(key) {
|
|
14
|
-
let value = await super.get(key);
|
|
15
|
-
if (typeof value === "function") {
|
|
16
|
-
value = await value();
|
|
17
|
-
|
|
18
|
-
if (Tree.isAsyncTree(value) && !value.parent) {
|
|
19
|
-
value.parent = this;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return value;
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Tree } from "@weborigami/async-tree";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* When using `get` to retrieve a value from a tree, if the value is a
|
|
5
|
-
* function, invoke it and return the result.
|
|
6
|
-
*/
|
|
7
|
-
export default async function functionResultsMap(treelike) {
|
|
8
|
-
return Tree.map(treelike, {
|
|
9
|
-
description: "functionResultsMap",
|
|
10
|
-
|
|
11
|
-
value: async (sourceValue, sourceKey, tree) => {
|
|
12
|
-
const resultValue =
|
|
13
|
-
typeof sourceValue === "function" ? await sourceValue() : sourceValue;
|
|
14
|
-
return resultValue;
|
|
15
|
-
},
|
|
16
|
-
});
|
|
17
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert";
|
|
2
|
-
import * as fs from "node:fs/promises";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { describe, test } from "node:test";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
import OrigamiFiles from "../../src/runtime/OrigamiFiles.js";
|
|
7
|
-
|
|
8
|
-
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
-
const tempDirectory = path.join(dirname, "fixtures/temp");
|
|
10
|
-
|
|
11
|
-
describe("OrigamiFiles", () => {
|
|
12
|
-
test("can watch its folder for changes", { timeout: 2000 }, async () => {
|
|
13
|
-
await createTempDirectory();
|
|
14
|
-
const tempFiles = new OrigamiFiles(tempDirectory);
|
|
15
|
-
const changedFileName = await new Promise(async (resolve) => {
|
|
16
|
-
tempFiles.addEventListener("change", (event) => {
|
|
17
|
-
resolve(/** @type {any} */ (event).options.key);
|
|
18
|
-
});
|
|
19
|
-
await tempFiles.set(
|
|
20
|
-
"foo.txt",
|
|
21
|
-
"This file is left over from testing and can be removed."
|
|
22
|
-
);
|
|
23
|
-
});
|
|
24
|
-
await removeTempDirectory();
|
|
25
|
-
assert.equal(changedFileName, "foo.txt");
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
async function createTempDirectory() {
|
|
30
|
-
await fs.mkdir(tempDirectory, { recursive: true });
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function removeTempDirectory() {
|
|
34
|
-
await fs.rm(tempDirectory, { recursive: true });
|
|
35
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { ObjectTree, Tree } from "@weborigami/async-tree";
|
|
2
|
-
import assert from "node:assert";
|
|
3
|
-
import { describe, test } from "node:test";
|
|
4
|
-
import functionResultsMap from "../../src/runtime/functionResultsMap.js";
|
|
5
|
-
|
|
6
|
-
describe("functionResultsMap", () => {
|
|
7
|
-
test("get() invokes functions, returns other values as is", async () => {
|
|
8
|
-
const tree = new ObjectTree({
|
|
9
|
-
fn: function () {
|
|
10
|
-
return "Hello";
|
|
11
|
-
},
|
|
12
|
-
string: "string",
|
|
13
|
-
});
|
|
14
|
-
const fixture = await functionResultsMap(tree);
|
|
15
|
-
assert.deepEqual(await Tree.plain(fixture), {
|
|
16
|
-
fn: "Hello",
|
|
17
|
-
string: "string",
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
});
|