Skip to content

Commit

Permalink
Nadav/handle route exports (#1225)
Browse files Browse the repository at this point in the history
* added tests for existing functionality

* work on tests

* added tests for defer

* fixed handle example

* work on handle

* added support for handle

* skipped hydratefallback test

* support root exports

* work on links function

* support for links functions

* removed debugger

* added reoking of route when exportNames change

---------

Co-authored-by: Nadav Abrahami <[email protected]>
  • Loading branch information
nadav-ab and nadavov authored Oct 14, 2024
1 parent 3f1c17c commit 36de4ef
Show file tree
Hide file tree
Showing 7 changed files with 515 additions and 72 deletions.
2 changes: 1 addition & 1 deletion packages/app-core/src/define-app-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ export interface EditablePointOfInterest {
}

export interface IResults<T> {
status: 'ready' | 'invalid' | 'disposed';
status: 'ready' | 'invalid' | 'disposed' | 'loading';
results: T | null;
errorMessage?: string;
}
Expand Down
33 changes: 27 additions & 6 deletions packages/app-core/test-kit/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export class AppDefDriver<T> {
private fs: IMemFileSystem;
private moduleSystem: ICommonJsModuleSystem;
private dirListeners: Array<DirListenerObj> = [];
private manifestListeners: Set<(manifest: IAppManifest<T>) => void> = new Set();
private fileListeners: Record<string, Set<(contents: string | null) => void>> = {};
private exportsListeners: Record<string, Set<(exportNames: string[]) => void>> = {};
private lastManifest: IAppManifest<T> | null = null;
Expand Down Expand Up @@ -62,6 +63,7 @@ export class AppDefDriver<T> {
fsApi: this.fsApi,
onManifestUpdate: (manifest) => {
this.lastManifest = manifest;
this.dispatchManifestUpdate();
},
});
this.lastManifest = manifest;
Expand Down Expand Up @@ -121,9 +123,20 @@ export class AppDefDriver<T> {
movedFilePath,
});
}
addManifestListener(cb: (manifest: IAppManifest<T>) => void) {
this.manifestListeners.add(cb);
}
removeManifestListener(cb: (manifest: IAppManifest<T>) => void) {
this.manifestListeners.delete(cb);
}
private dispatchManifestUpdate() {
for (const listener of this.manifestListeners) {
listener(this.lastManifest!);
}
}
async render({uri = '/'}: {uri?: string} = {}) {
const { app } = this.options;
const { fsApi, importModule, lastManifest } = this;
const { fsApi, importModule } = this;

if (!app.callServerMethod) {
throw new Error('app.callServerMethod is not defined');
Expand All @@ -142,23 +155,31 @@ export class AppDefDriver<T> {
);
},
importModule: this.importModule,
manifest: lastManifest!,
manifest: this.lastManifest!,
onCaughtError() {/**/},
setUri(_uri: string) {
// ToDo: implement
},
uri,
});
const unmount = await app.render(container, createProps(uri));
let lastUri = uri;
const rerender = ({uri = '/'}: {uri?: string} = {})=>{
lastUri = uri;
return app.render(container, createProps(uri));
}
const manifestListener = () => {
void rerender({uri: lastUri});
};
this.addManifestListener(manifestListener);
return {
dispose() {
dispose: ()=> {
unmount();
container.remove();
this.removeManifestListener(manifestListener)
},
container,
rerender({uri = '/'}: {uri?: string} = {}) {
return app.render(container, createProps(uri));
}
rerender
};
}
dispose() {
Expand Down
59 changes: 59 additions & 0 deletions packages/define-remix-app/src/handle-proxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-explicit-any */
export const createHandleProxy = () => {
const lastLoadedHandleRef: { current: any } = { current: null };
const handle = new Proxy({}, {
get: (_, prop) => {
return lastLoadedHandleRef.current?.[prop] as unknown;
},
apply(_, thisArg, argArray) {
return lastLoadedHandleRef.current?.apply(thisArg, argArray);
},
construct(_, argArray) {
return new lastLoadedHandleRef.current(...argArray);
},
defineProperty(_, property, attributes) {
return Object.defineProperty(lastLoadedHandleRef.current, property, attributes);
},
deleteProperty(_, p) {
return delete lastLoadedHandleRef.current[p];
},
getOwnPropertyDescriptor(_, p) {
return Object.getOwnPropertyDescriptor(lastLoadedHandleRef.current, p);
},
getPrototypeOf(_) {
return Object.getPrototypeOf(lastLoadedHandleRef.current);
},
has(_, p) {
return p in lastLoadedHandleRef.current;
},
isExtensible(_) {
return Object.isExtensible(lastLoadedHandleRef.current);
},
ownKeys(_) {
return Object.keys(lastLoadedHandleRef.current)
},
preventExtensions(_) {
return Object.preventExtensions(lastLoadedHandleRef.current);
},
set(_, p, newValue) {
lastLoadedHandleRef.current[p] = newValue;
return true;
},
setPrototypeOf(_, v) {
return Object.setPrototypeOf(lastLoadedHandleRef.current, v);
},


});
return {
handle,
setHandle: (handle: any) => {
lastLoadedHandleRef.current = handle;
}
};
}
17 changes: 17 additions & 0 deletions packages/define-remix-app/src/links-proxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { LinksFunction } from "@remix-run/node";

export const createLinksProxy = () => {
const lastLoadedLinks: { current: null | LinksFunction } = { current: null };
const linksWrapper = ()=>{
if(lastLoadedLinks.current){
return lastLoadedLinks.current();
}
return [];
}
return {
linksWrapper,
setLinks: (linksFunction: LinksFunction) => {
lastLoadedLinks.current = linksFunction;
}
};
}
Loading

0 comments on commit 36de4ef

Please sign in to comment.