Skip to content
Merged

Next #125

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 30 additions & 14 deletions client/invoke.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,54 @@
import deserialize from '../shared/deserialize';
import worker from './worker';
import prefix from '../shared/prefix';
import page from './page';
import worker from './worker';

export default function invoke(name, hash) {
return async function _invoke(params = {}) {
let payload;
worker.fetching = true;
if(Object.isFrozen(worker.queues[name])) {
if (Object.isFrozen(worker.queues[name])) {
worker.queues[name] = [params];
} else {
worker.queues[name] = [...worker.queues[name], params];
}
const finalHash = hash === this.constructor.hash ? hash : `${hash}-${this.constructor.hash}`;
let url = `${worker.api}/${prefix}/${finalHash}/${name}.json`;
let body = JSON.stringify(params || {});

const options = {
headers: worker.headers,
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
redirect: 'follow',
referrerPolicy: 'no-referrer',
}
if (/get[A-Z]([*]*)/.test(name)) {
options.method = 'GET';
url += `?payload=${body}`;
} else {
options.body = body;
if (/patch[A-Z]([*]*)/.test(name)) {
options.method = 'PATCH';
} else if (/put[A-Z]([*]*)/.test(name)) {
options.method = 'PUT';
} else if (/delete[A-Z]([*]*)/.test(name)) {
options.method = 'DELETE';
} else {
options.method = 'POST';
}
}
try {
const response = await fetch(url, {
method: 'POST',
headers: worker.headers,
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
redirect: 'follow',
referrerPolicy: 'no-referrer',
body: JSON.stringify(params || {})
});
const response = await fetch(url, options);
page.status = response.status;
const text = await response.text();
payload = deserialize(text).result;
worker.responsive = true;
} catch(e) {
} catch (e) {
worker.responsive = false;
}
if(worker.queues[name]?.length === 1) {
if (worker.queues[name]?.length === 1) {
delete worker.queues[name];
} else {
worker.queues[name] = worker.queues[name].filter((task) => task !== params);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nullstack",
"version": "0.12.1",
"version": "0.12.2",
"description": "Full-stack Javascript Components for one-dev armies",
"main": "nullstack.js",
"author": "Mortaro",
Expand Down
5 changes: 3 additions & 2 deletions server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,9 @@ server.start = function () {
response.send(generateRobots());
});

app.post(`/${prefix}/:hash/:methodName.json`, async (request, response) => {
const args = deserialize(request.body);
app.all(`/${prefix}/:hash/:methodName.json`, async (request, response) => {
const payload = request.method === 'GET' ? request.query.payload : request.body;
const args = deserialize(payload);
const { hash, methodName } = request.params;
const [invokerHash, boundHash] = hash.split('-');
const key = `${invokerHash}.${methodName}`;
Expand Down
2 changes: 2 additions & 0 deletions tests/src/Application.njs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import TwoWayBindings from './TwoWayBindings';
import UnderscoredAttributes from './UnderscoredAttributes';
import Vunerability from './Vunerability';
import WindowDependency from './WindowDependency';
import WorkerVerbs from './WorkerVerbs';

class Application extends Nullstack {

Expand Down Expand Up @@ -89,6 +90,7 @@ class Application extends Nullstack {
<PersistentComponent route="/persistent-component/:id" persistent />
<UnderscoredAttributes route="/underscored-attributes" />
<IsomorphicStartup route="/isomorphic-startup" />
<WorkerVerbs route="/worker-verbs" />
<ErrorPage route="*" />
</main>
)
Expand Down
59 changes: 59 additions & 0 deletions tests/src/WorkerVerbs.njs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import Nullstack from 'nullstack';

class WorkerVerbs extends Nullstack {

static async getter({ request }) {
return request.method;
}

static async getSomething({ request }) {
return request.method;
}

static async putSomething({ request }) {
return request.method;
}

static async patchSomething({ request }) {
return request.method;
}

static async deleteSomething({ request }) {
return request.method;
}

static async postSomething({ request }) {
return request.method;
}

static async regularSomething({ request }) {
return request.method;
}

async hydrate() {
this.getter = await this.getter()
this.get = await this.getSomething()
this.put = await this.putSomething()
this.patch = await this.patchSomething()
this.delete = await this.deleteSomething()
this.post = await this.postSomething()
this.regular = await this.regularSomething()
}

render() {
return (
<div
data-getter={this.getter}
data-get={this.get}
data-put={this.put}
data-patch={this.patch}
data-delete={this.delete}
data-post={this.post}
data-regular={this.regular}
/>
)
}

}

export default WorkerVerbs;
60 changes: 60 additions & 0 deletions tests/src/WorkerVerbs.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const puppeteer = require('puppeteer');

let browser;
let page;

beforeAll(async () => {
browser = await puppeteer.launch();
page = await browser.newPage();
await page.goto('http://localhost:6969/worker-verbs');
});

describe('WorkerVerbs', () => {

test('server functions with name starting with get followed by uppercase letter use GET', async () => {
await page.waitForSelector('[data-get="GET"]');
const element = await page.$('[data-get="GET"]');
expect(element).toBeTruthy();
});

test('server functions with name starting with put followed by uppercase letter use PUT', async () => {
await page.waitForSelector('[data-put="PUT"]');
const element = await page.$('[data-put="PUT"]');
expect(element).toBeTruthy();
});

test('server functions with name starting with patch followed by uppercase letter use PATCH', async () => {
await page.waitForSelector('[data-patch="PATCH"]');
const element = await page.$('[data-patch="PATCH"]');
expect(element).toBeTruthy();
});

test('server functions with name starting with delete followed by uppercase letter use DELETE', async () => {
await page.waitForSelector('[data-delete="DELETE"]');
const element = await page.$('[data-delete="DELETE"]');
expect(element).toBeTruthy();
});

test('server functions with name starting with post followed by uppercase letter use POST', async () => {
await page.waitForSelector('[data-post="POST"]');
const element = await page.$('[data-post="POST"]');
expect(element).toBeTruthy();
});

test('server functions with name starting with get but not followed by uppercase letter use POST', async () => {
await page.waitForSelector('[data-getter="POST"]');
const element = await page.$('[data-getter="POST"]');
expect(element).toBeTruthy();
});

test('server functions with name not starting with a verb use POST', async () => {
await page.waitForSelector('[data-regular="POST"]');
const element = await page.$('[data-regular="POST"]');
expect(element).toBeTruthy();
});

});

afterAll(async () => {
browser.close();
});
3 changes: 3 additions & 0 deletions workers/dynamicFetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ function dynamicStrategy(event) {
const url = new URL(event.request.url);
if (url.origin !== location.origin) return;
if (event.request.method !== 'GET') return;
if (url.pathname.indexOf('/nullstack/') > -1) {
return event.respondWith(networkFirst(event));
}
if (url.pathname.indexOf(self.context.environment.key) > -1) {
return event.respondWith(cacheFirst(event));
}
Expand Down
15 changes: 9 additions & 6 deletions workers/staticFetch.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
function staticStrategy(event) {
event.waitUntil(async function() {
event.waitUntil(async function () {
const url = new URL(event.request.url);
if(url.origin !== location.origin) return;
if(event.request.method !== 'GET') return;
if(url.pathname.indexOf(self.context.environment.key) > -1) {
if (url.origin !== location.origin) return;
if (event.request.method !== 'GET') return;
if (url.pathname.indexOf('/nullstack/') > -1) {
return event.respondWith(networkFirst(event));
}
if (url.pathname.indexOf(self.context.environment.key) > -1) {
return event.respondWith(cacheFirst(event));
}
if(url.pathname.indexOf('.') > -1) {
if (url.pathname.indexOf('.') > -1) {
return event.respondWith(staleWhileRevalidate(event));
}
if(url.pathname === '/') {
if (url.pathname === '/') {
return event.respondWith(networkFirst(event));
}
event.respondWith(networkDataFirst(event));
Expand Down