Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
fix: ensure component script may be updated correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
marionebl committed May 24, 2018
1 parent dc4e904 commit a6bfbb3
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export async function analyze(
path: patternPath
}));

const compiler = createCompiler(compilerPatterns, { cwd: path });
const compiler = createCompiler(compilerPatterns, { cwd: path, infrastructure: false });
await Util.promisify(compiler.run).bind(compiler)();

return {
Expand Down Expand Up @@ -122,7 +122,7 @@ function analyzePatternExport(
contextId: `${ctx.candidate.id}:${exportName}`,
exportName,
id: uuid.v4(),
name: ctx.candidate.displayName,
name: exportName !== 'default' ? exportName : ctx.candidate.displayName,
propertyIds: properties.map(p => p.id),
slots,
type: 'pattern'
Expand Down
44 changes: 25 additions & 19 deletions src/compiler/create-compiler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { compilerSafeName } from './compiler-safe-name';
import * as Fs from 'fs';
import * as Path from 'path';
import * as QueryString from 'query-string';
import * as webpack from 'webpack';
Expand All @@ -17,37 +18,42 @@ export interface CompilerPattern {

export function createCompiler(
patterns: CompilerPattern[],
options: { cwd: string }
options: { cwd: string; infrastructure: boolean }
): webpack.Compiler {
const components = patterns.reduce((acc, pattern) => {
acc[compilerSafeName(pattern.id)] = `./${Path.relative(options.cwd, pattern.path)
.split(Path.sep)
.join('/')}`;
const entry: { [name: string]: string } = {};

return acc;
}, {});
if (options.infrastructure) {
entry.renderer = RENDERER_PATH;
entry.preview = PREVIEW_PATH;
}

if (patterns.length > 0) {
const components = patterns.reduce((acc, pattern) => {
acc[compilerSafeName(pattern.id)] = `./${Path.relative(options.cwd, pattern.path)
.split(Path.sep)
.join('/')}`;

return acc;
}, {});

entry.components = `${LOADER_PATH}?${QueryString.stringify({
cwd: options.cwd,
components: JSON.stringify(components)
})}!`;
}

const compiler = webpack({
mode: 'development',
context: options.cwd,
entry: {
components: `${LOADER_PATH}?${QueryString.stringify({
cwd: options.cwd,
components: JSON.stringify(components)
})}!`,
renderer: RENDERER_PATH,
preview: PREVIEW_PATH
},
entry,
output: {
filename: '[name].js',
library: '[name]',
libraryTarget: 'window',
path: '/'
},
plugins: [new webpack.HotModuleReplacementPlugin()]
}
});

compiler.outputFileSystem = new MemoryFs();

compiler.outputFileSystem = new MemoryFs() as typeof Fs;
return compiler;
}
73 changes: 41 additions & 32 deletions src/electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as electronIsDev from 'electron-is-dev';
import * as Fs from 'fs';
import * as getPort from 'get-port';
import * as stringEscape from 'js-string-escape';
import { PreviewMessageType, ServerMessageType } from '../message';
import { PreviewMessageType, ServerMessage, ServerMessageType } from '../message';
import * as MimeTypes from 'mime-types';
import { Project } from '../model';
import * as Path from 'path';
Expand Down Expand Up @@ -78,16 +78,17 @@ async function createWindow(): Promise<void> {
const port = await (getPort({ port: 1879 }) as Promise<number>);
const server = await createServer({ port });

const send = (message: ServerMessage): void => {
Sender.send(message);
server.emit('message', message);
};

Sender.receive(async message => {
if (!message) {
return;
}

// Reflect messages to client
Sender.send(message);

// Emit messages to preview
server.emit('message', message);
send(message);

// Handle messages that require
// access to system / fs
Expand All @@ -110,15 +111,15 @@ async function createWindow(): Promise<void> {
const contents = result.contents as Types.SerializedProject;
contents.path = projectPath;

Sender.send({
send({
type: ServerMessageType.OpenFileResponse,
id: message.id,
payload: { path: projectPath, contents }
});
}
}

Sender.send({
send({
id: uuid.v4(),
type: ServerMessageType.StartApp,
payload: String(port)
Expand Down Expand Up @@ -150,7 +151,7 @@ async function createWindow(): Promise<void> {

await Persistence.persist(path, project);

Sender.send({
send({
type: ServerMessageType.CreateNewFileResponse,
id: message.id,
payload: {
Expand Down Expand Up @@ -188,7 +189,7 @@ async function createWindow(): Promise<void> {
const contents = result.contents as Types.SerializedProject;
contents.path = path;

Sender.send({
send({
type: ServerMessageType.OpenFileResponse,
id: message.id,
payload: { path, contents }
Expand Down Expand Up @@ -217,7 +218,7 @@ async function createWindow(): Promise<void> {
const content = await readFile(path);
const mimeType = MimeTypes.lookup(path) || 'application/octet-stream';

Sender.send({
send({
type: ServerMessageType.AssetReadResponse,
id: message.id,
payload: `data:${mimeType};base64,${content.toString('base64')}`
Expand All @@ -237,7 +238,7 @@ async function createWindow(): Promise<void> {
break;
}
case ServerMessageType.CreateScriptBundleRequest: {
const compiler = createCompiler([], { cwd: process.cwd() });
const compiler = createCompiler([], { cwd: process.cwd(), infrastructure: true });

compiler.run(err => {
if (err) {
Expand All @@ -247,12 +248,12 @@ async function createWindow(): Promise<void> {

const outputFileSystem = compiler.outputFileSystem;

Sender.send({
send({
type: ServerMessageType.CreateScriptBundleResponse,
id: message.id,
payload: ['renderer', 'preview']
.map(name => ({name, path: Path.posix.join('/', `${name}.js`)}))
.map(({name, path}) => ({
.map(name => ({ name, path: Path.posix.join('/', `${name}.js`) }))
.map(({ name, path }) => ({
name,
path,
contents: outputFileSystem.readFileSync(path)
Expand Down Expand Up @@ -285,7 +286,7 @@ async function createWindow(): Promise<void> {

const analysis = await Analyzer.analyze(path, project.getPatternLibrary().toJSON());

Sender.send({
send({
type: ServerMessageType.ConnectPatternLibraryResponse,
id: message.id,
payload: analysis
Expand All @@ -301,7 +302,10 @@ async function createWindow(): Promise<void> {
const connections = userStore.get('connections') || [];

const connection = connections
.filter(c => typeof c === 'object' && typeof c.path === 'string' && typeof c.id === 'string')
.filter(
c =>
typeof c === 'object' && typeof c.path === 'string' && typeof c.id === 'string'
)
.find(c => c.id === id);

if (!connection) {
Expand All @@ -310,7 +314,7 @@ async function createWindow(): Promise<void> {

const analysis = await Analyzer.analyze(connection.path, library.toJSON());

Sender.send({
send({
type: ServerMessageType.ConnectPatternLibraryResponse,
id: message.id,
payload: analysis
Expand All @@ -322,33 +326,38 @@ async function createWindow(): Promise<void> {
// Save connections between Alva files and pattern library folders
// in user-specific persistence
const previous = userStore.get('connections') || [];
const previousConnections = (Array.isArray(previous) ? previous : [previous])
.filter(p => typeof p === 'object' && typeof p.path === 'string' && typeof p.id === 'string');
const previousConnections = (Array.isArray(previous) ? previous : [previous]).filter(
p => typeof p === 'object' && typeof p.path === 'string' && typeof p.id === 'string'
);

userStore.set('connections', [...new Set([
...previousConnections,
message.payload
])]);
userStore.set('connections', [...new Set([...previousConnections, message.payload])]);

break;
}
case ServerMessageType.CheckLibraryRequest: {
const id = Project.from(message.payload).getPatternLibrary().getId();
const id = Project.from(message.payload)
.getPatternLibrary()
.getId();
const connections = userStore.get('connections') || [];

connections
.filter(c => typeof c === 'object' && typeof c.path === 'string' && typeof c.id === 'string')
.filter(
c =>
typeof c === 'object' && typeof c.path === 'string' && typeof c.id === 'string'
)
.filter(c => c.id === id)
.forEach(connection => {
Fs.exists(connection.path, exists => {
Sender.send({
send({
id,
type: ServerMessageType.CheckLibraryResponse,
payload: [{
id: connection.id,
path: connection.path,
connected: exists
}]
payload: [
{
id: connection.id,
path: connection.path,
connected: exists
}
]
});
});
});
Expand Down
42 changes: 13 additions & 29 deletions src/electron/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { createCompiler } from '../compiler/create-compiler';
import { EventEmitter } from 'events';
import * as express from 'express';
import * as Http from 'http';
import { ServerMessageType } from '../message';
import { ServerMessage, ServerMessageType } from '../message';
import { previewDocument, PreviewDocumentMode } from '../preview/preview-document';
import * as Types from '../model/types';
import * as uuid from 'uuid';
import { Compiler } from 'webpack';
import { OPEN, Server as WebsocketServer } from 'ws';

export interface ServerOptions {
Expand Down Expand Up @@ -87,7 +88,7 @@ export async function createServer(opts: ServerOptions): Promise<EventEmitter> {
});

app.use('/scripts', (req, res, next) => {
if (req.url === '/components.js') {
if (req.path === '/components.js') {
res.type('js');
res.send(state.payload.bundle || '');
return;
Expand Down Expand Up @@ -132,31 +133,17 @@ export async function createServer(opts: ServerOptions): Promise<EventEmitter> {
});
};

// tslint:disable-next-line:no-any
emitter.on('message', async (message: any) => {
emitter.on('message', async (message: ServerMessage) => {
switch (message.type) {
case ServerMessageType.PatternLibraryChange: {
Object.assign(state.payload, message.payload);

const { payload } = message;

if (compilation.compiler && typeof compilation.compiler.close === 'function') {
compilation.compiler.close();
}

send({
type: 'reload',
id: uuid.v4(),
payload: {}
});

const next = await setup({
analyzerName: payload.analyzerName,
styleguidePath: payload.styleguidePath,
patternsPath: payload.patternsPath
});
const next = await setup();

compilation.path = payload.styleguidePath;
compilation.compiler = next.compiler;
compilation.queue = next.queue;
compilation.listeners = [];
Expand All @@ -173,6 +160,12 @@ export async function createServer(opts: ServerOptions): Promise<EventEmitter> {
compilation.listeners.forEach(l => l(compilation.compiler.outputFileSystem));
});

send({
type: 'update',
id: uuid.v4(),
payload: {}
});

break;
}
case ServerMessageType.PageChange: {
Expand All @@ -188,14 +181,6 @@ export async function createServer(opts: ServerOptions): Promise<EventEmitter> {
send(message);
break;
}
case ServerMessageType.BundleChange: {
send({
type: 'reload',
id: uuid.v4(),
payload: {}
});
break;
}
case ServerMessageType.SketchExportRequest:
case ServerMessageType.ContentRequest: {
send(message);
Expand Down Expand Up @@ -224,11 +209,10 @@ function startServer(options: ServerStartOptions): Promise<void> {
});
}

// tslint:disable-next-line:no-any
async function setup(update: any): Promise<any> {
async function setup(): Promise<{ compiler: Compiler; queue: Queue }> {
const queue: Queue = [];

const compiler = createCompiler([], { cwd: process.cwd() });
const compiler = createCompiler([], { cwd: process.cwd(), infrastructure: true });

compiler.hooks.compile.tap('alva', () => {
queue.unshift({ type: WebpackMessageType.Start, id: uuid.v4() });
Expand Down
8 changes: 3 additions & 5 deletions src/preview/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,6 @@ function listen(store: PreviewStore, handlers: { onReplacement(): void }): void

// TODO: Do type refinements on message here
switch (type) {
case PreviewMessageType.Reload: {
window.location.reload();
break;
}
case PreviewMessageType.Update: {
Promise.all([refetch('renderer'), refetch('components')]).then(() => {
handlers.onReplacement();
Expand Down Expand Up @@ -313,7 +309,9 @@ function createComponentGetter(store: PreviewStore): (props: any, synthetics: an
const component = ((window as any).components || {})[pattern.id];

if (!component) {
throw new Error(`Could not find component with id "${pattern.id}" for pattern "${pattern.name}".`);
throw new Error(
`Could not find component with id "${pattern.id}" for pattern "${pattern.name}".`
);
}

return component[pattern.exportName];
Expand Down

0 comments on commit a6bfbb3

Please sign in to comment.