Skip to content

Commit

Permalink
devMode on react provider
Browse files Browse the repository at this point in the history
  • Loading branch information
Natalya Shrits committed Jan 2, 2020
1 parent 7b4ac48 commit fa4a9c3
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 57 deletions.
25 changes: 11 additions & 14 deletions client/core/lib/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,17 @@ export class DynamicoClient {
}
});

const { version, code } = await this.fetcher(url).then(async (res: Response) => {
if (!res.ok) {
throw new ComponentGetFailedError(res.statusText, res);
}
const code = await res.text();
const version = componentVersion || (res.headers.get('dynamico-component-version') as string);
if (this.checkCodeIntegrity && !(await this.checkCodeIntegrity(code))) {
throw new ComponentIntegrityCheckFailed({ name, version });
}
return {
version,
code
};
});
const res = await this.fetcher(url);
if (!res.ok) {
throw new ComponentGetFailedError(res.statusText, res);
}

const code = await res.text();
const version = componentVersion || (res.headers.get('dynamico-component-version') as string);

if (this.checkCodeIntegrity && !(await this.checkCodeIntegrity(code))) {
throw new ComponentIntegrityCheckFailed({ name, version });
}

await this.cache.setItem(name, version, code);

Expand Down
27 changes: 16 additions & 11 deletions client/core/lib/DevClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,38 @@ export interface DevOptions {
}

export interface DevGetOptions extends Options {
callback: Function;
callback: (err: Error | undefined, component: any) => void;
interval?: number;
}

export class DynamicoDevClient extends DynamicoClient {
export class DynamicoDevClient {
interval: number;

private shouldRefresh = false;
private etag = '';
private client: DynamicoClient;

constructor({ dependencies, urlOverride, interval = 1000 }: DevOptions) {
super({
this.client = new DynamicoClient({
url: urlOverride || process.env.DYNAMICO_DEVELOPMENT_SERVER || 'http://localhost:8383',
dependencies,
cache: new NoopStorage()
cache: new NoopStorage(),
fetcher: this.fetcher
});

this.interval = interval;
}

async get(name: string, { callback, interval, ...options }: DevGetOptions) {
const intervalRef = setInterval(async () => {
const view = await super.get(name, options);

if (this.shouldRefresh) {
return callback(view);
}
get(name: string, { callback, interval, ...options }: DevGetOptions) {
const intervalRef = setInterval(() => {
this.client.get(name, options).then(
view => {
if (this.shouldRefresh) {
callback(undefined, view);
}
},
err => callback(err, undefined)
);
}, interval || this.interval);

return () => {
Expand Down
3 changes: 2 additions & 1 deletion client/core/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
"outDir": "./dist",
"rootDir": "./lib",
"lib": ["dom"]
}
},
"exclude": ["dist"]
}
109 changes: 79 additions & 30 deletions client/react/lib/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,29 @@ interface ComponentOptions<T> extends Options {
fallback?: FallbackType<T>;
}

export const DynamicoContext = React.createContext<DynamicoClient | undefined>(undefined);
export const DynamicoContext = React.createContext<{ client?: DynamicoClient; devClient?: DynamicoDevClient }>({});

export const DynamicoProvider: FunctionComponent<{ client: DynamicoClient }> = ({ client, children }) => (
<DynamicoContext.Provider value={client}>{children}</DynamicoContext.Provider>
);
export interface DynamicoProviderProps {
client: DynamicoClient;
devMode?: boolean | Partial<DevOptions>;
}

export const DynamicoProvider: FunctionComponent<DynamicoProviderProps> = ({ client, devMode, children }) => {
const context = React.useMemo(() => {
if (!devMode) {
return { client };
}

const devClient = new DynamicoDevClient({
dependencies: client.dependencies,
...(typeof devMode === 'object' ? devMode : {})
});

return { client, devClient };
}, [client, devMode]);

return <DynamicoContext.Provider value={context}>{children}</DynamicoContext.Provider>;
};

interface FallbackBuilderProps<T> {
fallback: FallbackType<T> | null;
Expand All @@ -64,34 +82,65 @@ export const dynamico = function<T = any>(
const [Component, setComponent]: [Component, setComponent] = useState({});
const [status, setStatus]: [Status, setStatus] = useState<Status>({ currentStatus: ComponentStatus.Loading });

const dynamicoClient = useContext<DynamicoClient | undefined>(DynamicoContext);
let release = () => {};

const getComponent = async () => {
if (!dynamicoClient) {
throw `Couldn't find dynamico client in the context, make sure you use DynamicoContext.Provider`;
}
if (devMode) {
const devClient = new DynamicoDevClient({
dependencies: dynamicoClient.dependencies,
...(typeof devMode === 'object' ? devMode : {})
});

release = await devClient.get(name, { ...options, callback: (view: any) => setComponent({ view }) });

return;
}

setComponent({ view: await dynamicoClient.get(name, options) });
};
const { client: dynamicoClient, devClient } = useContext(DynamicoContext);

useEffect(() => {
getComponent().catch(error => {
setStatus({
currentStatus: ComponentStatus.Error,
error
});
});
let release = () => {};

const setError = (error: Error) => setStatus({ currentStatus: ComponentStatus.Error, error });

const getComponent = async () => {
if (!dynamicoClient) {
throw `Couldn't find dynamico client in the context, make sure you use DynamicoContext.Provider`;
}

if (devMode || devClient) {
const devOptions = typeof devMode === 'object' ? devMode : {};

const client =
devClient ||
new DynamicoDevClient({
dependencies: dynamicoClient.dependencies,
...devOptions
});

let usingFallbackComponent = false;

release = client.get(name, {
interval: devOptions.interval,
...options,
callback: async (err, view: any) => {
if (!err) {
usingFallbackComponent = false;
return setComponent({ view });
}

console.warn(`failed getting component ${name} from dev server`, err);

if (!devMode) {
return setError(err);
}

if (usingFallbackComponent) {
return;
}
usingFallbackComponent = true;

try {
setComponent({ view: await dynamicoClient.get(name, options) });
} catch (e) {
return setError(e);
}
}
});

return;
}

setComponent({ view: await dynamicoClient.get(name, options) });
};

getComponent().catch(setError);

return () => release();
}, []);
Expand Down
3 changes: 2 additions & 1 deletion client/react/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
"outDir": "./dist",
"rootDir": "./lib",
"lib": ["dom"]
}
},
"exclude": ["dist"]
}

0 comments on commit fa4a9c3

Please sign in to comment.