From fab6135ac5ab83451268364d8e810f1e5757b501 Mon Sep 17 00:00:00 2001 From: Cass Fridkin Date: Wed, 30 Mar 2022 06:44:42 -0500 Subject: [PATCH 1/5] ??? --- packages/core/src/plugins/bindings.ts | 30 +++++++++++++++++++++++---- packages/shared/src/wrangler.ts | 1 + 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/core/src/plugins/bindings.ts b/packages/core/src/plugins/bindings.ts index 7d1fc6ddf..998ae139a 100644 --- a/packages/core/src/plugins/bindings.ts +++ b/packages/core/src/plugins/bindings.ts @@ -45,6 +45,7 @@ export interface BindingsOptions { bindings?: Record; globals?: Record; wasmBindings?: Record; + textBlobs?: Record; serviceBindings?: ServiceBindingsOptions; } @@ -164,6 +165,16 @@ export class BindingsPlugin }) wasmBindings?: Record; + @Option({ + type: OptionType.OBJECT, + typeFormat: "NAME=PATH", + name: "text", + description: "Text blob to bind", + logName: "Text blobs", + fromWrangler: ({ text_blobs }) => text_blobs, + }) + textBlobs?: Record; + @Option({ type: OptionType.OBJECT, typeFormat: "NAME=MOUNT[@ENV]", @@ -246,8 +257,9 @@ export class BindingsPlugin // 1) Wrangler [vars] // 2) .env Variables // 3) WASM Module Bindings - // 4) Service Bindings - // 5) Custom Bindings + // 4) Text blobs + // 5) Service Bindings + // 6) Custom Bindings const bindings: Context = {}; const watch: string[] = []; @@ -281,12 +293,22 @@ export class BindingsPlugin } } - // 4) Load service bindings + // 4) Load text blobs from files + if (this.textBlobs) { + // eslint-disable-next-line prefer-const + for (let [name, textPath] of Object.entries(this.textBlobs)) { + textPath = path.resolve(this.ctx.rootPath, textPath); + bindings[name] = (await fs.readFile(textPath)).toString(); + watch.push(textPath); + } + } + + // 5) Load service bindings for (const { name, service } of this.#processedServiceBindings) { bindings[name] = new Fetcher(service, this.#getServiceFetch); } - // 5) Copy user's arbitrary bindings + // 6) Copy user's arbitrary bindings Object.assign(bindings, this.bindings); return { globals: this.globals, bindings, watch }; diff --git a/packages/shared/src/wrangler.ts b/packages/shared/src/wrangler.ts index c90afa459..8f2a97800 100644 --- a/packages/shared/src/wrangler.ts +++ b/packages/shared/src/wrangler.ts @@ -35,6 +35,7 @@ export interface WranglerEnvironmentConfig { }; // inherited usage_model?: "bundled" | "unbound"; // inherited wasm_modules?: Record; // (probably) inherited + text_blobs?: Record; experimental_services?: { name: string; service: string; From fb81001fce19c33b220c5c387a49e144905aff2b Mon Sep 17 00:00:00 2001 From: Cass Fridkin Date: Wed, 30 Mar 2022 08:20:46 -0500 Subject: [PATCH 2/5] code review + add tests --- packages/core/src/plugins/bindings.ts | 16 ++++---- packages/core/test/fixtures/lorem-ipsum.txt | 9 +++++ packages/core/test/plugins/bindings.spec.ts | 45 +++++++++++++++++++-- 3 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 packages/core/test/fixtures/lorem-ipsum.txt diff --git a/packages/core/src/plugins/bindings.ts b/packages/core/src/plugins/bindings.ts index 998ae139a..9b135088c 100644 --- a/packages/core/src/plugins/bindings.ts +++ b/packages/core/src/plugins/bindings.ts @@ -45,7 +45,7 @@ export interface BindingsOptions { bindings?: Record; globals?: Record; wasmBindings?: Record; - textBlobs?: Record; + textBlobBindings?: Record; serviceBindings?: ServiceBindingsOptions; } @@ -168,12 +168,12 @@ export class BindingsPlugin @Option({ type: OptionType.OBJECT, typeFormat: "NAME=PATH", - name: "text", + name: "text-blob", description: "Text blob to bind", - logName: "Text blobs", + logName: "Text Blob Bindings", fromWrangler: ({ text_blobs }) => text_blobs, }) - textBlobs?: Record; + textBlobBindings?: Record; @Option({ type: OptionType.OBJECT, @@ -257,7 +257,7 @@ export class BindingsPlugin // 1) Wrangler [vars] // 2) .env Variables // 3) WASM Module Bindings - // 4) Text blobs + // 4) Text blob Bindings // 5) Service Bindings // 6) Custom Bindings @@ -294,11 +294,11 @@ export class BindingsPlugin } // 4) Load text blobs from files - if (this.textBlobs) { + if (this.textBlobBindings) { // eslint-disable-next-line prefer-const - for (let [name, textPath] of Object.entries(this.textBlobs)) { + for (let [name, textPath] of Object.entries(this.textBlobBindings)) { textPath = path.resolve(this.ctx.rootPath, textPath); - bindings[name] = (await fs.readFile(textPath)).toString(); + bindings[name] = await fs.readFile(textPath, "utf-8"); watch.push(textPath); } } diff --git a/packages/core/test/fixtures/lorem-ipsum.txt b/packages/core/test/fixtures/lorem-ipsum.txt new file mode 100644 index 000000000..fbc74b53a --- /dev/null +++ b/packages/core/test/fixtures/lorem-ipsum.txt @@ -0,0 +1,9 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Amet consectetur adipiscing elit duis tristique sollicitudin nibh sit amet. Parturient montes nascetur ridiculus mus mauris vitae ultricies leo integer. Nisi porta lorem mollis aliquam ut porttitor. Placerat duis ultricies lacus sed. Amet nisl suscipit adipiscing bibendum est ultricies integer quis auctor. Hendrerit dolor magna eget est. Sed nisi lacus sed viverra. Id cursus metus aliquam eleifend mi in nulla posuere. Donec ultrices tincidunt arcu non sodales neque sodales ut etiam. Lectus proin nibh nisl condimentum id. Vitae tempus quam pellentesque nec nam aliquam sem. + +Ipsum dolor sit amet consectetur adipiscing elit pellentesque habitant. Pellentesque massa placerat duis ultricies. Ultrices gravida dictum fusce ut placerat orci nulla. Quam pellentesque nec nam aliquam sem et tortor consequat id. Laoreet sit amet cursus sit amet dictum sit amet justo. Cursus metus aliquam eleifend mi in nulla. Mattis molestie a iaculis at erat pellentesque adipiscing commodo. Nulla aliquet porttitor lacus luctus. Tristique senectus et netus et. Donec adipiscing tristique risus nec feugiat in fermentum posuere urna. + +Hac habitasse platea dictumst quisque sagittis purus sit. Adipiscing commodo elit at imperdiet dui accumsan sit. Etiam erat velit scelerisque in dictum non consectetur a. Cras pulvinar mattis nunc sed blandit libero volutpat sed cras. Est velit egestas dui id ornare. Orci dapibus ultrices in iaculis. Quis vel eros donec ac odio tempor orci dapibus ultrices. Lectus arcu bibendum at varius vel. Eget egestas purus viverra accumsan in nisl nisi scelerisque eu. Elementum eu facilisis sed odio morbi quis. Etiam tempor orci eu lobortis elementum nibh tellus molestie. Enim nulla aliquet porttitor lacus luctus accumsan tortor posuere ac. Nunc lobortis mattis aliquam faucibus purus in massa. Quam id leo in vitae turpis massa. Mus mauris vitae ultricies leo integer malesuada nunc vel. + +Et malesuada fames ac turpis egestas sed tempus urna et. Donec massa sapien faucibus et molestie ac feugiat. Amet cursus sit amet dictum sit amet justo donec enim. Ut etiam sit amet nisl purus. Risus in hendrerit gravida rutrum quisque non tellus. Nibh mauris cursus mattis molestie a. Elementum nisi quis eleifend quam adipiscing vitae proin. Mi quis hendrerit dolor magna eget est lorem ipsum. Ut morbi tincidunt augue interdum velit euismod in pellentesque massa. Proin sagittis nisl rhoncus mattis rhoncus urna neque. Ullamcorper sit amet risus nullam eget felis. Sit amet tellus cras adipiscing enim eu. Quis eleifend quam adipiscing vitae proin sagittis nisl rhoncus. Convallis posuere morbi leo urna molestie at elementum eu facilisis. Sed adipiscing diam donec adipiscing tristique risus nec. Rhoncus aenean vel elit scelerisque mauris pellentesque. Leo in vitae turpis massa sed elementum tempus egestas sed. In hac habitasse platea dictumst quisque sagittis purus sit amet. Eros donec ac odio tempor orci. Eleifend mi in nulla posuere sollicitudin aliquam ultrices. + +Amet facilisis magna etiam tempor orci eu lobortis. In ornare quam viverra orci. Convallis convallis tellus id interdum velit laoreet id. Rutrum tellus pellentesque eu tincidunt tortor aliquam. Tincidunt dui ut ornare lectus sit amet est placerat in. Nibh sed pulvinar proin gravida hendrerit lectus. Ornare aenean euismod elementum nisi quis eleifend quam adipiscing vitae. Amet luctus venenatis lectus magna fringilla urna. Nec ultrices dui sapien eget mi proin sed. Magna ac placerat vestibulum lectus. Risus nec feugiat in fermentum posuere urna. Cursus turpis massa tincidunt dui. Turpis egestas integer eget aliquet nibh praesent. Tincidunt vitae semper quis lectus. Massa id neque aliquam vestibulum morbi blandit cursus risus. Egestas fringilla phasellus faucibus scelerisque. In massa tempor nec feugiat nisl pretium fusce. A lacus vestibulum sed arcu non odio. Adipiscing elit duis tristique sollicitudin nibh sit amet commodo nulla. Quam id leo in vitae turpis massa sed elementum. diff --git a/packages/core/test/plugins/bindings.spec.ts b/packages/core/test/plugins/bindings.spec.ts index 48d04330a..a5c714863 100644 --- a/packages/core/test/plugins/bindings.spec.ts +++ b/packages/core/test/plugins/bindings.spec.ts @@ -1,4 +1,5 @@ import assert from "assert"; +import { readFileSync } from "fs"; import fs from "fs/promises"; import path from "path"; import { setImmediate } from "timers/promises"; @@ -37,6 +38,9 @@ const fixturesPath = path.join(__dirname, "..", "..", "..", "test", "fixtures"); // its 2 integer parameters together and returns the result, it is from: // https://webassembly.github.io/wabt/demo/wat2wasm/ const addModulePath = path.join(fixturesPath, "add.wasm"); +// lorem-ipsum.txt is five paragraphs of lorem ipsum nonsense text +const loremIpsumPath = path.join(fixturesPath, "lorem-ipsum.txt"); +const loremIpsum = readFileSync(loremIpsumPath, "utf-8"); test("BindingsPlugin: parses options from argv", (t) => { let options = parsePluginArgv(BindingsPlugin, [ @@ -54,6 +58,10 @@ test("BindingsPlugin: parses options from argv", (t) => { "MODULE1=module1.wasm", "--wasm", "MODULE2=module2.wasm", + "--text-blob", + "TEXT1=text-blob-1.txt", + "--text-blob", + "TEXT2=text-blob-2.txt", "--service", "SERVICE1=service1", "--service", @@ -64,6 +72,7 @@ test("BindingsPlugin: parses options from argv", (t) => { bindings: { KEY1: "value1", KEY2: "value2" }, globals: { KEY3: "value3", KEY4: "value4" }, wasmBindings: { MODULE1: "module1.wasm", MODULE2: "module2.wasm" }, + textBlobBindings: { TEXT1: "text-blob-1.txt", TEXT2: "text-blob-2.txt" }, serviceBindings: { SERVICE1: "service1", SERVICE2: { service: "service2", environment: "development" }, @@ -96,6 +105,10 @@ test("BindingsPlugin: parses options from wrangler config", async (t) => { MODULE1: "module1.wasm", MODULE2: "module2.wasm", }, + text_blobs: { + TEXT1: "text-blob-1.txt", + TEXT2: "text-blob-2.txt", + }, experimental_services: [ { name: "SERVICE1", service: "service1", environment: "development" }, { name: "SERVICE2", service: "service2", environment: "production" }, @@ -109,6 +122,7 @@ test("BindingsPlugin: parses options from wrangler config", async (t) => { envPath: ".env.test", globals: { KEY5: "value5", KEY6: false, KEY7: 10 }, wasmBindings: { MODULE1: "module1.wasm", MODULE2: "module2.wasm" }, + textBlobBindings: { TEXT1: "text-blob-1.txt", TEXT2: "text-blob-2.txt" }, serviceBindings: { SERVICE1: { service: "service1", environment: "development" }, SERVICE2: { service: "service2", environment: "production" }, @@ -141,6 +155,7 @@ test("BindingsPlugin: logs options", (t) => { bindings: { KEY3: "value3", KEY4: "value4" }, globals: { KEY5: "value5", KEY6: "value6" }, wasmBindings: { MODULE1: "module1.wasm", MODULE2: "module2.wasm" }, + textBlobBindings: { TEXT1: "text-blob-1.txt", TEXT2: "text-blob-2.txt" }, serviceBindings: { SERVICE1: "service1", SERVICE2: { service: "service2", environment: "development" }, @@ -152,6 +167,7 @@ test("BindingsPlugin: logs options", (t) => { "Custom Bindings: KEY3, KEY4", "Custom Globals: KEY5, KEY6", "WASM Bindings: MODULE1, MODULE2", + "Text Blob Bindings: TEXT1, TEXT2", "Service Bindings: SERVICE1, SERVICE2", ]); logs = logPluginOptions(BindingsPlugin, { envPath: true }); @@ -259,13 +275,33 @@ test("BindingsPlugin: setup: loads WebAssembly bindings", async (t) => { result = await plugin.setup(); t.not(result.bindings?.ADD, undefined); }); + +test("BindingsPlugin: setup: loads text blob bindings", async (t) => { + let plugin = new BindingsPlugin(ctx, { + textBlobBindings: { LOREM_IPSUM: loremIpsumPath }, + }); + let result = await plugin.setup(); + t.not(result.bindings?.LOREM_IPSUM, undefined); + t.is(result.bindings?.LOREM_IPSUM, loremIpsum); + + // Check resolves text blob bindings path relative to rootPath + plugin = new BindingsPlugin( + { log, compat, rootPath: path.dirname(loremIpsumPath) }, + { textBlobBindings: { LOREM_IPSUM: loremIpsumPath } } + ); + result = await plugin.setup(); + t.not(result.bindings?.LOREM_IPSUM, undefined); + t.is(result.bindings?.LOREM_IPSUM, loremIpsum); +}); + test("BindingsPlugin: setup: loads bindings from all sources", async (t) => { // Bindings should be loaded in this order, from lowest to highest priority: // 1) Wrangler [vars] // 2) .env Variables // 3) WASM Module Bindings - // 4) Service Bindings - // 5) Custom Bindings + // 4) Text Blob Bindings + // 5) Service Bindings + // 6) Custom Bindings // wranglerOptions should contain [kWranglerBindings] const wranglerOptions = parsePluginWranglerConfig(BindingsPlugin, { @@ -287,6 +323,9 @@ test("BindingsPlugin: setup: loads bindings from all sources", async (t) => { B: addModulePath, C: addModulePath, }, + textBlobBindings: { + D: loremIpsumPath, + }, serviceBindings: { A: throws, B: throws }, bindings: { A: obj }, envPath, @@ -295,7 +334,7 @@ test("BindingsPlugin: setup: loads bindings from all sources", async (t) => { assert(result.bindings); t.is(result.bindings.E, "w"); - t.is(result.bindings.D, "env"); + t.is(result.bindings.D, loremIpsum); t.true(result.bindings.C instanceof WebAssembly.Module); t.true(result.bindings.B instanceof Fetcher); t.is(result.bindings.A, obj); From a88f545ac42216929919d62587b425691275511b Mon Sep 17 00:00:00 2001 From: Cass Fridkin Date: Wed, 30 Mar 2022 08:34:13 -0500 Subject: [PATCH 3/5] nits from code review --- packages/core/test/plugins/bindings.spec.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/core/test/plugins/bindings.spec.ts b/packages/core/test/plugins/bindings.spec.ts index a5c714863..6af510159 100644 --- a/packages/core/test/plugins/bindings.spec.ts +++ b/packages/core/test/plugins/bindings.spec.ts @@ -281,16 +281,14 @@ test("BindingsPlugin: setup: loads text blob bindings", async (t) => { textBlobBindings: { LOREM_IPSUM: loremIpsumPath }, }); let result = await plugin.setup(); - t.not(result.bindings?.LOREM_IPSUM, undefined); t.is(result.bindings?.LOREM_IPSUM, loremIpsum); // Check resolves text blob bindings path relative to rootPath plugin = new BindingsPlugin( { log, compat, rootPath: path.dirname(loremIpsumPath) }, - { textBlobBindings: { LOREM_IPSUM: loremIpsumPath } } + { textBlobBindings: { LOREM_IPSUM: "lorem-ipsum.txt" } } ); result = await plugin.setup(); - t.not(result.bindings?.LOREM_IPSUM, undefined); t.is(result.bindings?.LOREM_IPSUM, loremIpsum); }); From cb7ede096b9979e5fbd7984abed82d20ddc8b08e Mon Sep 17 00:00:00 2001 From: Cass Fridkin Date: Wed, 30 Mar 2022 08:39:13 -0500 Subject: [PATCH 4/5] fix priority in test --- packages/core/test/plugins/bindings.spec.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/core/test/plugins/bindings.spec.ts b/packages/core/test/plugins/bindings.spec.ts index 6af510159..0a8ee63b3 100644 --- a/packages/core/test/plugins/bindings.spec.ts +++ b/packages/core/test/plugins/bindings.spec.ts @@ -320,9 +320,12 @@ test("BindingsPlugin: setup: loads bindings from all sources", async (t) => { A: addModulePath, B: addModulePath, C: addModulePath, + D: addModulePath, }, textBlobBindings: { - D: loremIpsumPath, + A: loremIpsumPath, + B: loremIpsumPath, + C: loremIpsumPath, }, serviceBindings: { A: throws, B: throws }, bindings: { A: obj }, @@ -332,8 +335,8 @@ test("BindingsPlugin: setup: loads bindings from all sources", async (t) => { assert(result.bindings); t.is(result.bindings.E, "w"); - t.is(result.bindings.D, loremIpsum); - t.true(result.bindings.C instanceof WebAssembly.Module); + t.true(result.bindings.D instanceof WebAssembly.Module); + t.is(result.bindings.C, loremIpsum); t.true(result.bindings.B instanceof Fetcher); t.is(result.bindings.A, obj); }); From a3043e1b528844aa2e46e4a67cd04ad05bf04e90 Mon Sep 17 00:00:00 2001 From: Cass Fridkin Date: Wed, 30 Mar 2022 08:42:05 -0500 Subject: [PATCH 5/5] F --- packages/core/test/plugins/bindings.spec.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/core/test/plugins/bindings.spec.ts b/packages/core/test/plugins/bindings.spec.ts index 0a8ee63b3..3b8ba0ee6 100644 --- a/packages/core/test/plugins/bindings.spec.ts +++ b/packages/core/test/plugins/bindings.spec.ts @@ -303,12 +303,12 @@ test("BindingsPlugin: setup: loads bindings from all sources", async (t) => { // wranglerOptions should contain [kWranglerBindings] const wranglerOptions = parsePluginWranglerConfig(BindingsPlugin, { - vars: { A: "w", B: "w", C: "w", D: "w", E: "w" }, + vars: { A: "w", B: "w", C: "w", D: "w", E: "w", F: "w" }, }); const tmp = await useTmp(t); const envPath = path.join(tmp, ".env"); - await fs.writeFile(envPath, "A=env\nB=env\nC=env\nD=env"); + await fs.writeFile(envPath, "A=env\nB=env\nC=env\nD=env\nE=env"); const obj = { ping: "pong" }; const throws = () => { @@ -334,7 +334,8 @@ test("BindingsPlugin: setup: loads bindings from all sources", async (t) => { const result = await plugin.setup(); assert(result.bindings); - t.is(result.bindings.E, "w"); + t.is(result.bindings.F, "w"); + t.is(result.bindings.E, "env"); t.true(result.bindings.D instanceof WebAssembly.Module); t.is(result.bindings.C, loremIpsum); t.true(result.bindings.B instanceof Fetcher);