Skip to content
Merged
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
19 changes: 2 additions & 17 deletions server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import element from '../shared/element';
import fragment from '../shared/fragment';
import getProxyableMethods from '../shared/getProxyableMethods';
import { usePlugins } from '../shared/plugins';
import { freezeConfigurable } from './configurable';
import context from './context';
import environment from './environment';
import generator from './generator';
Expand Down Expand Up @@ -40,22 +39,8 @@ class Nullstack {
if (this.name.indexOf('Nullstack') > -1) {
loadSettings();
loadSecrets();
setTimeout(() => {
if (server.less) {
server.start();
}
server.ready = (async function () {
generator.starter = () => element(Starter);
typeof context.start === 'function' && await context.start(context);
freezeConfigurable(settings);
freezeConfigurable(secrets);
Object.freeze(worker);
Object.freeze(project);
if (!server.less) {
server.start();
}
})()
}, 0)
generator.starter = () => element(Starter);
setTimeout(server.start, 0)
return context;
}
}
Expand Down
34 changes: 12 additions & 22 deletions server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import fetch from 'node-fetch';
import path from 'path';
import deserialize from '../shared/deserialize';
import prefix from '../shared/prefix';
import { generateContext } from './context';
import context, { generateContext } from './context';
import environment from './environment';
import { generateFile } from './files';
import liveReload from './liveReload';
Expand All @@ -17,9 +17,7 @@ import project from './project';
import registry from './registry';
import generateRobots from './robots';
import template from './template';
import worker, { generateServiceWorker } from './worker';


import { generateServiceWorker } from './worker';

if (!global.fetch) {
global.fetch = fetch;
Expand All @@ -29,14 +27,18 @@ const app = express();
const server = http.createServer(app);
server.port = process.env['NULLSTACK_SERVER_PORT'] || process.env['PORT'] || 5000;

app.use(async (request, response, next) => {
context.start && await context.start()
next()
})

for (const methodName of ['use', 'delete', 'get', 'head', 'options', 'patch', 'post', 'put']) {
server[methodName] = function () {
app[methodName](...arguments);
}
}

server.prerender = async function (originalUrl, options) {
server.less && await server.ready;
if (originalUrl === `/nullstack/${environment.key}/client.css`) {
return generateFile('client.css', server)
}
Expand All @@ -57,14 +59,6 @@ server.prerender = async function (originalUrl, options) {

server.start = function () {

if (!server.less) {
generateFile('client.css', server)
generateFile('client.js', server)
generateManifest(server);
generateServiceWorker();
generateRobots();
}

app.use(cors(server.cors))

app.use(express.static(path.join(__dirname, '..', 'public')));
Expand Down Expand Up @@ -95,20 +89,17 @@ server.start = function () {
response.send(generateManifest(server));
});

if (worker.enabled) {
app.get(`/service-worker.js`, (request, response) => {
response.setHeader('Cache-Control', 'max-age=31536000, immutable');
response.contentType('text/javascript');
response.send(generateServiceWorker());
});
}
app.get(`/service-worker.js`, (request, response) => {
response.setHeader('Cache-Control', 'max-age=31536000, immutable');
response.contentType('text/javascript');
response.send(generateServiceWorker());
});

app.get('/robots.txt', (request, response) => {
response.send(generateRobots());
});

app.post(`/${prefix}/:hash/:methodName.json`, async (request, response) => {
server.less && await server.ready;
const args = deserialize(request.body);
const { hash, methodName } = request.params;
const [invokerHash, boundHash] = hash.split('-');
Expand Down Expand Up @@ -137,7 +128,6 @@ server.start = function () {
});

app.get('*', async (request, response, next) => {
server.less && await server.ready;
if (request.originalUrl.split('?')[0].indexOf('.') > -1) {
return next();
}
Expand Down
15 changes: 15 additions & 0 deletions tests/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@ Nullstack.use([vueable], vueable);

const context = Nullstack.start(Application);

const methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT'];

context.server.use('/api', (request, response, next) => {
request.status = 200;
if (!response.headersSent) {
next();
}
});

for (const method of methods) {
context.server[method.toLowerCase()]('/api', (request, response) => {
response.status(request.status).send(request.method);
});
}

context.start = async function () {
await ContextProject.start(context);
await ContextSecrets.start(context);
Expand Down
10 changes: 5 additions & 5 deletions tests/src/ErrorOnChildNode.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ let page;
beforeAll(async () => {
browser = await puppeteer.launch();
page = await browser.newPage();

await page.goto('http://localhost:6969/error-on-child-node');
});

describe('Error when ChildNode is undefined', () => {

test('Should be able to click on button', async () => {
page.on("console", (msg) => {
page.on("console", async (msg) => {
expect(msg.text()).toMatch('Virtual DOM does not match the DOM. Expected tag thead but instead found undefined. This error usually happens because of an invalid HTML hierarchy like nested forms or tables without tr.');
await page.click('[id=buttonTest]');
await page.waitForSelector('[id=text]');
})
await page.click('[id=buttonTest]');
await page.waitForSelector('[id=text]');
});

})

afterAll(async () => {
Expand Down
22 changes: 5 additions & 17 deletions tests/src/ServerRequestAndResponse.njs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,7 @@ class ServerRequestAndResponse extends Nullstack {

responses = {};

static methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT'];

static async start({server}) {
server.use('/api', (request, response, next) => {
request.status = 200;
if(!response.headersSent) {
next();
}
});
for(const method of ServerRequestAndResponse.methods) {
server[method.toLowerCase()]('/api', (request, response) => {
response.status(request.status).send(request.method);
});
}
static async start({ server }) {
server.cors = {
origin: 'http://localhost:6969',
optionsSuccessStatus: 200
Expand All @@ -26,14 +13,15 @@ class ServerRequestAndResponse extends Nullstack {

async hydrate() {
const responses = {};
for(const method of ServerRequestAndResponse.methods) {
const methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT'];
for (const method of methods) {
const body = method === 'GET' || method === 'HEAD' ? undefined : JSON.stringify({});
const response = await fetch('/api', {method, body});
const response = await fetch('/api', { method, body });
responses[`data-${method.toLowerCase()}`] = response.status === 200;
}
this.responses = responses;
}

render() {
return (
<div {...this.responses} />
Expand Down