Login for demo works

main
jaxoncreed 2 years ago
parent a603cc02f4
commit 8ce936a901
  1. 2024
      package-lock.json
  2. 13
      packages/demo-react/src/Layout.tsx
  3. 32
      packages/demo-react/src/dashboard/Dashboard.tsx
  4. 10
      packages/demo-react/src/dashboard/UploadButton.tsx
  5. 2
      packages/jsonld-dataset-proxy/package.json
  6. 6
      packages/solid-react/src/SolidLdoProvider.tsx
  7. 20
      packages/solid-react/src/documentHooks/useAccessRules.ts
  8. 16
      packages/solid-react/src/documentHooks/useBinaryResource.ts
  9. 19
      packages/solid-react/src/documentHooks/useContainerResource.ts
  10. 16
      packages/solid-react/src/documentHooks/useDataResource.ts
  11. 27
      packages/solid-react/src/documentHooks/useDocument.ts
  12. 6
      packages/solid-react/src/index.ts
  13. 6
      packages/solid-react/src/util/useForceReload.ts
  14. 2
      packages/solid/src/createSolidLdoDataset.ts
  15. 6
      packages/solid/src/document/accessRules/AccessRules.ts
  16. 4
      packages/solid/src/document/errors/DocumentError.ts
  17. 11
      packages/solid/src/document/errors/DocumentFetchError.ts
  18. 15
      packages/solid/src/document/resource/Resource.ts
  19. 13
      packages/solid/src/document/resource/dataResource/DataResource.ts
  20. 1
      packages/solid/src/index.ts

2024
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -28,18 +28,10 @@ export const Layout: FunctionComponent = () => {
} }
return ( return (
<div> <div>
<header <header style={{ display: "flex" }}>
style={{
height: 50,
borderBottom: "1px solid black",
display: "flex",
alignItems: "center",
padding: 10,
}}
>
{session.isLoggedIn ? ( {session.isLoggedIn ? (
<> <>
<p>Logged in as {session.webId}</p> <span>Logged in as {session.webId}</span>
<button onClick={logout}>Log Out</button> <button onClick={logout}>Log Out</button>
</> </>
) : ( ) : (
@ -54,6 +46,7 @@ export const Layout: FunctionComponent = () => {
</> </>
)} )}
</header> </header>
<hr />
{session.isLoggedIn ? <RouterProvider router={router} /> : undefined} {session.isLoggedIn ? <RouterProvider router={router} /> : undefined}
</div> </div>
); );

@ -1,10 +1,38 @@
import React from "react"; import React, { useCallback, useEffect, useMemo } from "react";
import type { FunctionComponent } from "react"; import type { FunctionComponent } from "react";
import { UploadButton } from "./UploadButton";
import { useSolidAuth } from "@ldo/solid-react";
export const Dashboard: FunctionComponent = () => { export const Dashboard: FunctionComponent = () => {
const { session } = useSolidAuth();
const containerUri = useMemo(() => {
if (!session.webId) return "";
// HACK: this is a hard coded hack to find the root container. Solid doesn't
// have an official way of doing this.
const rootContainer = session.webId.replace("profile/card#me", "");
return `${rootContainer}demo-ldo/`;
}, [session.webId]);
// const mainContainer = useContainerResource(containerUri);
// useEffect(() => {
// // Upon load check to see if the root folder exists
// mainContainer.checkExists().then(async (doesExist) => {
// // If not, create it
// if (!doesExist) {
// await mainContainer.create();
// const accessRules = mainContainer.accessRules;
// }
// });
// }, [mainContainer]);
return ( return (
<div> <div>
<p>Dashboard</p> <div>
<UploadButton />
</div>
<hr />
</div> </div>
); );
}; };

@ -0,0 +1,10 @@
import React, { useCallback } from "react";
import type { FunctionComponent } from "react";
export const UploadButton: FunctionComponent = () => {
const upload = useCallback(() => {
const _message = prompt("Type a message for your post");
}, []);
return <button onClick={upload}>Make a New Post</button>;
};

@ -39,7 +39,7 @@
"dist" "dist"
], ],
"dependencies": { "dependencies": {
"@rdfjs/data-model": "^2.0.1", "@rdfjs/data-model": "^1.2.0",
"@ldo/rdf-utils": "^0.0.0", "@ldo/rdf-utils": "^0.0.0",
"@ldo/subscribable-dataset": "^0.0.0", "@ldo/subscribable-dataset": "^0.0.0",
"@rdfjs/dataset": "^1.1.0", "@rdfjs/dataset": "^1.1.0",

@ -1,4 +1,4 @@
import React, { createContext } from "react"; import React, { createContext, useContext } from "react";
import { import {
useMemo, useMemo,
type FunctionComponent, type FunctionComponent,
@ -16,6 +16,10 @@ export const SolidLdoDatasetReactContext =
// @ts-ignore // @ts-ignore
createContext<SolidLdoDataset>(undefined); createContext<SolidLdoDataset>(undefined);
export function useSolidLdoDataset() {
return useContext(SolidLdoDatasetReactContext);
}
export interface SolidLdoProviderProps extends PropsWithChildren { export interface SolidLdoProviderProps extends PropsWithChildren {
onDocumentError?: OnDocumentErrorCallback; onDocumentError?: OnDocumentErrorCallback;
} }

@ -0,0 +1,20 @@
import { useMemo } from "react";
import type { UseDocumentOptions } from "./useDocument";
import { useTrackStateUpdate } from "./useDocument";
import type { Resource } from "@ldo/solid";
import { useSolidLdoDataset } from "../SolidLdoProvider";
export function useAccessRules(
resource: string | Resource,
options?: UseDocumentOptions,
) {
const solidLdoDataset = useSolidLdoDataset();
const document = useMemo(() => {
return solidLdoDataset.getAccessRules(resource);
}, [resource, solidLdoDataset]);
useTrackStateUpdate(document, options);
return document;
}

@ -0,0 +1,16 @@
import { useMemo } from "react";
import { useSolidLdoDataset } from "../SolidLdoProvider";
import type { UseDocumentOptions } from "./useDocument";
import { useTrackStateUpdate } from "./useDocument";
export function useBinaryResource(uri: string, options?: UseDocumentOptions) {
const solidLdoDataset = useSolidLdoDataset();
const document = useMemo(() => {
return solidLdoDataset.getBinaryResource(uri);
}, [uri, solidLdoDataset]);
useTrackStateUpdate(document, options);
return document;
}

@ -0,0 +1,19 @@
import { useMemo } from "react";
import type { UseDocumentOptions } from "./useDocument";
import { useTrackStateUpdate } from "./useDocument";
import { useSolidLdoDataset } from "../SolidLdoProvider";
export function useContainerResource(
uri: string,
options?: UseDocumentOptions,
) {
const solidLdoDataset = useSolidLdoDataset();
const document = useMemo(() => {
return solidLdoDataset.getContainerResource(uri);
}, [uri, solidLdoDataset]);
useTrackStateUpdate(document, options);
return document;
}

@ -0,0 +1,16 @@
import { useMemo } from "react";
import { useSolidLdoDataset } from "../SolidLdoProvider";
import type { UseDocumentOptions } from "./useDocument";
import { useTrackStateUpdate } from "./useDocument";
export function useDataResource(uri: string, options?: UseDocumentOptions) {
const solidLdoDataset = useSolidLdoDataset();
const document = useMemo(() => {
return solidLdoDataset.getDataResource(uri);
}, [uri, solidLdoDataset]);
useTrackStateUpdate(document, options);
return document;
}

@ -0,0 +1,27 @@
import { useEffect } from "react";
import type { FetchableDocument } from "@ldo/solid";
import { useForceUpdate } from "../util/useForceReload";
export interface UseDocumentOptions {
suppressLoadOnMount: boolean;
}
export function useTrackStateUpdate(
document: FetchableDocument,
options?: UseDocumentOptions,
) {
const forceUpdate = useForceUpdate();
useEffect(() => {
// Set up the listener for state update
function onStateUpdateCallback() {
forceUpdate();
}
document.onStateUpdate(onStateUpdateCallback);
// Load the resource if load on mount is true
if (!options?.suppressLoadOnMount) {
document.read();
}
return () => document.offStateUpdate(onStateUpdateCallback);
}, []);
}

@ -1,2 +1,8 @@
export * from "./BrowserSolidLdoProvider"; export * from "./BrowserSolidLdoProvider";
export * from "./SolidAuthContext"; export * from "./SolidAuthContext";
// documentHooks
export * from "./documentHooks/useAccessRules";
export * from "./documentHooks/useBinaryResource";
export * from "./documentHooks/useContainerResource";
export * from "./documentHooks/useDataResource";

@ -0,0 +1,6 @@
import { useState } from "react";
export function useForceUpdate() {
const [, setValue] = useState(0);
return () => setValue((value) => value + 1);
}

@ -9,7 +9,7 @@ import type {
SolidLdoDatasetContext, SolidLdoDatasetContext,
} from "./SolidLdoDatasetContext"; } from "./SolidLdoDatasetContext";
import crossFetch from "cross-fetch"; import crossFetch from "cross-fetch";
import { EventEmitter } from "stream"; import { EventEmitter } from "events";
import { createDataset, createDatasetFactory } from "@ldo/dataset"; import { createDataset, createDatasetFactory } from "@ldo/dataset";
export interface CreateSolidLdoDatasetOptions { export interface CreateSolidLdoDatasetOptions {

@ -63,9 +63,11 @@ export class AccessRules extends FetchableDocument {
return undefined; return undefined;
} catch (err: unknown) { } catch (err: unknown) {
if (typeof err === "object" && (err as Error).message) { if (typeof err === "object" && (err as Error).message) {
this.setError(new DocumentError(this, (err as Error).message)); this.setError(new DocumentError(this, 500, (err as Error).message));
} }
this.setError(new DocumentError(this, "Error Fetching Access Rules")); this.setError(
new DocumentError(this, 500, "Error Fetching Access Rules"),
);
} }
} }
} }

@ -2,9 +2,11 @@ import type { FetchableDocument } from "../FetchableDocument";
export class DocumentError extends Error { export class DocumentError extends Error {
public readonly document: FetchableDocument; public readonly document: FetchableDocument;
public readonly status: number;
constructor(document: FetchableDocument, message: string) { constructor(document: FetchableDocument, status: number, message: string) {
super(message); super(message);
this.document = document; this.document = document;
this.status = status;
} }
} }

@ -1,11 +0,0 @@
import type { FetchableDocument } from "../FetchableDocument";
import { DocumentError } from "./DocumentError";
export class DocumentFetchError extends DocumentError {
public readonly status: number;
constructor(document: FetchableDocument, status: number, message: string) {
super(document, message);
this.status = status;
}
}

@ -1,7 +1,7 @@
import type { SolidLdoDatasetContext } from "../../SolidLdoDatasetContext"; import type { SolidLdoDatasetContext } from "../../SolidLdoDatasetContext";
import type { DocumentGetterOptions } from "../DocumentStore"; import type { DocumentGetterOptions } from "../DocumentStore";
import { FetchableDocument } from "../FetchableDocument"; import { FetchableDocument } from "../FetchableDocument";
import { DocumentFetchError } from "../errors/DocumentFetchError"; import { DocumentError } from "../errors/DocumentError";
import type { ContainerResource } from "./dataResource/containerResource/ContainerResource"; import type { ContainerResource } from "./dataResource/containerResource/ContainerResource";
export abstract class Resource extends FetchableDocument { export abstract class Resource extends FetchableDocument {
@ -49,14 +49,17 @@ export abstract class Resource extends FetchableDocument {
return; return;
} }
this.endWrite( this.endWrite(
new DocumentFetchError( new DocumentError(this, response.status, `Could not delete ${this.uri}`),
this,
response.status,
`Could not delete ${this.uri}`,
),
); );
} }
async checkExists() {
const response = await this.context.fetch(this.uri, {
method: "OPTIONS",
});
return response.status === 404;
}
/** /**
* =========================================================================== * ===========================================================================
* Static Methods * Static Methods

@ -1,6 +1,5 @@
import { parseRdf } from "@ldo/ldo"; import { parseRdf } from "@ldo/ldo";
import { Resource } from "../Resource"; import { Resource } from "../Resource";
import { DocumentFetchError } from "../../errors/DocumentFetchError";
import { DocumentError } from "../../errors/DocumentError"; import { DocumentError } from "../../errors/DocumentError";
import { namedNode, quad as createQuad } from "@rdfjs/data-model"; import { namedNode, quad as createQuad } from "@rdfjs/data-model";
import type { DatasetChanges } from "@ldo/rdf-utils"; import type { DatasetChanges } from "@ldo/rdf-utils";
@ -27,7 +26,7 @@ export class DataResource extends Resource {
// Handle Error // Handle Error
if (response.status !== 200) { if (response.status !== 200) {
// TODO: Handle edge cases // TODO: Handle edge cases
return new DocumentFetchError( return new DocumentError(
this, this,
response.status, response.status,
`Error fetching resource ${this.uri}`, `Error fetching resource ${this.uri}`,
@ -42,9 +41,13 @@ export class DataResource extends Resource {
}); });
} catch (err) { } catch (err) {
if (typeof err === "object" && (err as Error).message) { if (typeof err === "object" && (err as Error).message) {
return new DocumentError(this, (err as Error).message); return new DocumentError(this, 500, (err as Error).message);
} }
return new DocumentError(this, "Server returned poorly formatted Turtle"); return new DocumentError(
this,
500,
"Server returned poorly formatted Turtle",
);
} }
// Start transaction // Start transaction
const transactionalDataset = const transactionalDataset =
@ -86,7 +89,7 @@ export class DataResource extends Resource {
// Handle Error by rollback // Handle Error by rollback
transactionalDataset.rollback(); transactionalDataset.rollback();
this.endWrite( this.endWrite(
new DocumentFetchError( new DocumentError(
this, this,
response.status, response.status,
`Problem writing to ${this.uri}`, `Problem writing to ${this.uri}`,

@ -4,7 +4,6 @@ export * from "./document/DocumentStore";
// document/errors // document/errors
export * from "./document/errors/DocumentError"; export * from "./document/errors/DocumentError";
export * from "./document/errors/DocumentFetchError";
// document/accessRules // document/accessRules
export * from "./document/accessRules/AccessRules"; export * from "./document/accessRules/AccessRules";

Loading…
Cancel
Save