Lots of work to get graphql running smoothly

This commit is contained in:
2024-04-26 10:29:04 -05:00
parent 6836ef68ea
commit 3021b6e712
32 changed files with 12661 additions and 439 deletions

View File

@@ -1,30 +1,36 @@
{
"version": 1,
"isRoot": true,
"tools": {
"fsdgencsharp": {
"version": "2.27.0",
"commands": [
"fsdgencsharp"
]
},
"fsdgenmd": {
"version": "2.8.0",
"commands": [
"fsdgenmd"
]
},
"fsdgenaspnet": {
"version": "3.9.0",
"commands": [
"fsdgenaspnet"
]
},
"fsdgenswagger": {
"version": "2.5.0",
"commands": [
"fsdgenswagger"
]
}
}
{
"version": 1,
"isRoot": true,
"tools": {
"fsdgencsharp": {
"version": "2.27.0",
"commands": [
"fsdgencsharp"
]
},
"fsdgenmd": {
"version": "2.8.0",
"commands": [
"fsdgenmd"
]
},
"fsdgenaspnet": {
"version": "3.9.0",
"commands": [
"fsdgenaspnet"
]
},
"fsdgenswagger": {
"version": "2.5.0",
"commands": [
"fsdgenswagger"
]
},
"fsdgenjs": {
"version": "2.9.0",
"commands": [
"fsdgenjs"
]
}
}
}

View File

@@ -1,2 +1,3 @@
fsdgencsharp .\fsd\Oap.Api.v1.fsd ./src/OAP/Oap.Api.v1 --namespace Oap.Api.v1
fsdgenjs .\fsd\Oap.Api.v1.fsd ./src/OAP/Oap.Theme.Svelte/src/lib/oap --module OapApiV1Client --typescript
REM fsdgenaspnet .\fsd\OapApi.v1.fsd ./src/OAP/OapApi.v1 --target core --namespace OapApi.v1 --apinamespace OapApi.v1.Client

View File

@@ -0,0 +1,19 @@
import { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
schema: "http://localhost:5000/oap/api/graphql",
documents: ["./src/**/*.svelte"],
generates: {
"./src/gql/": {
preset: "client",
plugins: [],
config: {
useTypeImports: true,
},
},
},
verbose: true,
debug: true,
};
export default config;

View File

@@ -8,7 +8,7 @@
<body>
<div id="app"></div>
<div id="OapApplicationForm-1" class="OapApplicationForm"></div>
<div id="4j2b7wf1fmjdd1g2twvxhpng4h" class="OapApplicationForm"></div>
<script type="module" src="/src/main.ts"></script>
</body>

File diff suppressed because it is too large Load Diff

View File

@@ -7,18 +7,27 @@
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-check --tsconfig ./tsconfig.json"
"check": "svelte-check --tsconfig ./tsconfig.json",
"codegen": "graphql-codegen"
},
"devDependencies": {
"@graphql-codegen/cli": "^5.0.2",
"@graphql-codegen/client-preset": "^4.2.5",
"@sveltejs/vite-plugin-svelte": "^3.0.2",
"@tsconfig/svelte": "^5.0.2",
"autoprefixer": "^10.4.19",
"graphql": "^16.8.1",
"postcss": "^8.4.38",
"svelte": "^4.2.12",
"svelte": "^4.2.15",
"svelte-check": "^3.6.7",
"svelte2tsx": "^0.7.7",
"tailwindcss": "^3.4.3",
"tslib": "^2.6.2",
"typescript": "^5.2.2",
"typescript": "^5.4.5",
"vite": "^5.2.0"
},
"dependencies": {
"@urql/svelte": "^4.1.1",
"facility-core": "^2.2.0"
}
}

View File

@@ -1,5 +0,0 @@
<script lang="ts">
import Counter from "./lib/Counter.svelte";
</script>
<p>I love bob</p>

View File

@@ -1,3 +1,52 @@
<script lang="ts">
import { Client, setContextClient, queryStore } from "@urql/svelte";
import OapApplicationFormStep from "./components/OapApplicationFormStep.svelte";
import { graphql } from "./gql";
export let contentItemId: string;
export let client: Client;
setContextClient(client);
const query = graphql(/* GraphQL */ `
query OapApplicationForm($contentItemId: ID!) {
oapApplicationForm(where: { contentItemId: $contentItemId }) {
contentItemId
list {
contentItems {
__typename
...OapApplicationFormStep
}
}
}
}
`);
const content = queryStore({
client,
query,
variables: {
contentItemId,
},
});
</script>
<div>
This is an application form
</div>
{#if $content.fetching}
<p>Loading...</p>
{:else if $content.error}
<p>Oh no... {$content.error.message}</p>
{:else if !$content.data}
<p>No content data??</p>
{:else if $content.data?.oapApplicationForm}
{#each $content.data?.oapApplicationForm as oapApplicationForm}
{#if oapApplicationForm?.list}
{#each oapApplicationForm.list.contentItems ?? [] as contentItem}
{#if contentItem?.__typename === "OapApplicationFormStep"}
<OapApplicationFormStep fragment={contentItem} />
{/if}
{/each}
{/if}
{/each}
{/if}
</div>

View File

@@ -0,0 +1,40 @@
<script context="module" lang="ts">
import { graphql } from "../gql";
export const ButtonPartFragment = graphql(/* GraphQL */ `
fragment ButtonPart on Button {
button {
type
text
}
formInputElement {
name
}
formElement {
id
}
}
`);
export function isButtonType(buttonType: string | undefined | null): buttonType is HTMLButtonElement['type'] {
return !!(buttonType as HTMLButtonElement['type']);
}
</script>
<script lang="ts">
import { type FragmentType, useFragment } from "../gql";
export let fragment: FragmentType<typeof ButtonPartFragment>;
const content = useFragment(ButtonPartFragment, fragment);
const buttonType: HTMLButtonElement['type'] = isButtonType(content.button?.type) ? content.button?.type : "button";
</script>
<button
class="block cursor-pointer rounded-md bg-amber-300 px-4 py-2 text-gray-800 hover:bg-amber-500 disabled:cursor-not-allowed disabled:bg-gray-400 disabled:text-gray-600"
type={buttonType}
name={content.formInputElement?.name}
id={content.formElement?.id}
>
{content.button?.text}
</button>

View File

@@ -0,0 +1,16 @@
<script context="module" lang="ts">
import { RichTextFragment } from "./RichText.svelte";
export const ExplanationPartFragment = RichTextFragment;
</script>
<script lang="ts">
import { type FragmentType } from "../gql";
import RichText from "./RichText.svelte";
export let fragment: FragmentType<typeof ExplanationPartFragment>;
</script>
<div class="text-sm text-gray-600">
<RichText {fragment} />
</div>

View File

@@ -0,0 +1,24 @@
<script context="module" lang="ts">
import { graphql } from "../gql";
export const FlowPartFragment = graphql(/* GraphQL */ `
fragment FlowPart on FlowPart {
widgets {
contentType
}
}
`);
</script>
<script lang="ts">
import { type FragmentType, useFragment } from "../gql";
export let fragment: FragmentType<typeof FlowPartFragment>;
const content = useFragment(FlowPartFragment, fragment);
const widgets = content.widgets ?? [];
</script>
{#each widgets as widget}
<p>a widget: {widget?.contentType}</p>
{/each}

View File

@@ -0,0 +1,43 @@
<script context="module" lang="ts">
import { graphql } from "../gql";
export const FormFragment = graphql(/* GraphQL */ `
fragment Form on Form {
displayText
form {
action
method
}
formElement {
id
}
flow {
...FlowPart
}
}
`);
</script>
<script lang="ts">
import { useFragment, type FragmentType } from "../gql";
import FlowPart from "./FlowPart.svelte";
export let antiForgeryToken: string;
export let fragment: FragmentType<typeof FormFragment>;
const content = useFragment(FormFragment, fragment);
</script>
<form
id={content.formElement?.id}
action={content.form?.action}
method={content.form?.method}
>
{antiForgeryToken}
<div class="flex flex-col gap-2">
{#if content.flow}
<FlowPart fragment={content.flow} />
{/if}
</div>
</form>

View File

@@ -0,0 +1,27 @@
<script context="module" lang="ts">
import { graphql } from "../gql";
export const LabelPartFragment = graphql(/* GraphQL */ `
fragment LabelPart on Label {
displayText
formElement {
id
}
label {
for
value
}
contentType
}
`);
</script>
<script lang="ts">
import { useFragment, type FragmentType } from "../gql";
export let fragment: FragmentType<typeof LabelPartFragment>;
const content = useFragment(LabelPartFragment, fragment);
</script>
<label id={content.formElement?.id} for={content.label?.for}>
{content.label?.value}
</label>

View File

@@ -0,0 +1,38 @@
<script context="module" lang="ts">
import { graphql } from "../gql";
export const OapApplicationFormStepFragment = graphql(/* GraphQL */ `
fragment OapApplicationFormStep on OapApplicationFormStep {
contentItemId
htmlBody {
...RichText
}
flow {
...FlowPart
}
}
`);
</script>
<script lang="ts">
import { type FragmentType, useFragment } from "../gql";
import RichText from "./RichText.svelte";
import FlowPart from "./FlowPart.svelte";
export let fragment: FragmentType<typeof OapApplicationFormStepFragment>;
const content = useFragment(OapApplicationFormStepFragment, fragment);
</script>
<h2 class="text-lg font-bold">{content.contentItemId}</h2>
{#if content.htmlBody}
<div class="mt-2 mb-6">
<RichText fragment={content.htmlBody} />
</div>
{/if}
{#if content.flow}
<FlowPart fragment={content.flow} />
{/if}

View File

@@ -0,0 +1,21 @@
<script context="module" lang="ts">
import { graphql } from "../gql";
export const RichTextFragment = graphql(/* GraphQL */ `
fragment RichText on HtmlBodyPart {
html
}
`);
</script>
<script lang="ts">
import { useFragment, type FragmentType } from "../gql";
export let fragment: FragmentType<typeof RichTextFragment>;
const content = useFragment(RichTextFragment, fragment);
</script>
<div class="richtext">
{content.html}
</div>

View File

@@ -0,0 +1,67 @@
/* eslint-disable */
import type { ResultOf, DocumentTypeDecoration, TypedDocumentNode } from '@graphql-typed-document-node/core';
import type { FragmentDefinitionNode } from 'graphql';
import type { Incremental } from './graphql';
export type FragmentType<TDocumentType extends DocumentTypeDecoration<any, any>> = TDocumentType extends DocumentTypeDecoration<
infer TType,
any
>
? [TType] extends [{ ' $fragmentName'?: infer TKey }]
? TKey extends string
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never;
// return non-nullable if `fragmentType` is non-nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>>
): TType;
// return nullable if `fragmentType` is nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | null | undefined
): TType | null | undefined;
// return array of non-nullable if `fragmentType` is array of non-nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
): ReadonlyArray<TType>;
// return array of nullable if `fragmentType` is array of nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined
): ReadonlyArray<TType> | null | undefined;
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined
): TType | ReadonlyArray<TType> | null | undefined {
return fragmentType as any;
}
export function makeFragmentData<
F extends DocumentTypeDecoration<any, any>,
FT extends ResultOf<F>
>(data: FT, _fragment: F): FragmentType<F> {
return data as FragmentType<F>;
}
export function isFragmentReady<TQuery, TFrag>(
queryNode: DocumentTypeDecoration<TQuery, any>,
fragmentNode: TypedDocumentNode<TFrag>,
data: FragmentType<TypedDocumentNode<Incremental<TFrag>, any>> | null | undefined
): data is FragmentType<typeof fragmentNode> {
const deferredFields = (queryNode as { __meta__?: { deferredFields: Record<string, (keyof TFrag)[]> } }).__meta__
?.deferredFields;
if (!deferredFields) return true;
const fragDef = fragmentNode.definitions[0] as FragmentDefinitionNode | undefined;
const fragName = fragDef?.name?.value;
const fields = (fragName && deferredFields[fragName]) || [];
return fields.length > 0 && fields.every(field => data && field in data);
}

View File

@@ -0,0 +1,72 @@
/* eslint-disable */
import * as types from './graphql';
import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
/**
* Map of all GraphQL operations in the project.
*
* This map has several performance disadvantages:
* 1. It is not tree-shakeable, so it will include all operations in the project.
* 2. It is not minifiable, so the string of a GraphQL query will be multiple times inside the bundle.
* 3. It does not support dead code elimination, so it will add unused operations.
*
* Therefore it is highly recommended to use the babel or swc plugin for production.
*/
const documents = {
"\n\t\tquery OapApplicationForm($contentItemId: ID!) {\n\t\t\toapApplicationForm(where: { contentItemId: $contentItemId }) {\n\t\t\t\tcontentItemId\n\t\t\t\tlist {\n\t\t\t\t\tcontentItems {\n\t\t\t\t\t\t__typename\n\t\t\t\t\t\t...OapApplicationFormStep\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t": types.OapApplicationFormDocument,
"\n fragment ButtonPart on Button {\n button {\n type\n text\n }\n formInputElement {\n name\n }\n formElement {\n id\n }\n }\n ": types.ButtonPartFragmentDoc,
"\n fragment FlowPart on FlowPart {\n widgets {\n contentType\n }\n }\n ": types.FlowPartFragmentDoc,
"\n\t\tfragment Form on Form {\n\t\t\tdisplayText\n\t\t\tform {\n\t\t\t\taction\n\t\t\t\tmethod\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tflow {\n\t\t\t\t...FlowPart\n\t\t\t}\n\t\t}\n\t": types.FormFragmentDoc,
"\n\t\tfragment LabelPart on Label {\n\t\t\tdisplayText\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tlabel {\n\t\t\t\tfor\n\t\t\t\tvalue\n\t\t\t}\n\t\t\tcontentType\n\t\t}\n\t": types.LabelPartFragmentDoc,
"\n\t\tfragment OapApplicationFormStep on OapApplicationFormStep {\n\t\t\tcontentItemId\n\t\t\thtmlBody {\n\t\t\t\t...RichText\n\t\t\t}\n\t\t\tflow {\n\t\t\t\t...FlowPart\n\t\t\t}\n\t\t}\n\t": types.OapApplicationFormStepFragmentDoc,
"\n\t\tfragment RichText on HtmlBodyPart {\n\t\t\thtml\n\t\t}\n\t": types.RichTextFragmentDoc,
};
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*
*
* @example
* ```ts
* const query = graphql(`query GetUser($id: ID!) { user(id: $id) { name } }`);
* ```
*
* The query argument is unknown!
* Please regenerate the types.
*/
export function graphql(source: string): unknown;
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n\t\tquery OapApplicationForm($contentItemId: ID!) {\n\t\t\toapApplicationForm(where: { contentItemId: $contentItemId }) {\n\t\t\t\tcontentItemId\n\t\t\t\tlist {\n\t\t\t\t\tcontentItems {\n\t\t\t\t\t\t__typename\n\t\t\t\t\t\t...OapApplicationFormStep\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t"): (typeof documents)["\n\t\tquery OapApplicationForm($contentItemId: ID!) {\n\t\t\toapApplicationForm(where: { contentItemId: $contentItemId }) {\n\t\t\t\tcontentItemId\n\t\t\t\tlist {\n\t\t\t\t\tcontentItems {\n\t\t\t\t\t\t__typename\n\t\t\t\t\t\t...OapApplicationFormStep\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n fragment ButtonPart on Button {\n button {\n type\n text\n }\n formInputElement {\n name\n }\n formElement {\n id\n }\n }\n "): (typeof documents)["\n fragment ButtonPart on Button {\n button {\n type\n text\n }\n formInputElement {\n name\n }\n formElement {\n id\n }\n }\n "];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n fragment FlowPart on FlowPart {\n widgets {\n contentType\n }\n }\n "): (typeof documents)["\n fragment FlowPart on FlowPart {\n widgets {\n contentType\n }\n }\n "];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n\t\tfragment Form on Form {\n\t\t\tdisplayText\n\t\t\tform {\n\t\t\t\taction\n\t\t\t\tmethod\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tflow {\n\t\t\t\t...FlowPart\n\t\t\t}\n\t\t}\n\t"): (typeof documents)["\n\t\tfragment Form on Form {\n\t\t\tdisplayText\n\t\t\tform {\n\t\t\t\taction\n\t\t\t\tmethod\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tflow {\n\t\t\t\t...FlowPart\n\t\t\t}\n\t\t}\n\t"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n\t\tfragment LabelPart on Label {\n\t\t\tdisplayText\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tlabel {\n\t\t\t\tfor\n\t\t\t\tvalue\n\t\t\t}\n\t\t\tcontentType\n\t\t}\n\t"): (typeof documents)["\n\t\tfragment LabelPart on Label {\n\t\t\tdisplayText\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tlabel {\n\t\t\t\tfor\n\t\t\t\tvalue\n\t\t\t}\n\t\t\tcontentType\n\t\t}\n\t"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n\t\tfragment OapApplicationFormStep on OapApplicationFormStep {\n\t\t\tcontentItemId\n\t\t\thtmlBody {\n\t\t\t\t...RichText\n\t\t\t}\n\t\t\tflow {\n\t\t\t\t...FlowPart\n\t\t\t}\n\t\t}\n\t"): (typeof documents)["\n\t\tfragment OapApplicationFormStep on OapApplicationFormStep {\n\t\t\tcontentItemId\n\t\t\thtmlBody {\n\t\t\t\t...RichText\n\t\t\t}\n\t\t\tflow {\n\t\t\t\t...FlowPart\n\t\t\t}\n\t\t}\n\t"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n\t\tfragment RichText on HtmlBodyPart {\n\t\t\thtml\n\t\t}\n\t"): (typeof documents)["\n\t\tfragment RichText on HtmlBodyPart {\n\t\t\thtml\n\t\t}\n\t"];
export function graphql(source: string) {
return (documents as any)[source] ?? {};
}
export type DocumentType<TDocumentNode extends DocumentNode<any, any>> = TDocumentNode extends DocumentNode< infer TType, any> ? TType : never;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
export * from "./fragment-masking";
export * from "./gql";

View File

@@ -1,10 +0,0 @@
<script lang="ts">
let count: number = 0
const increment = () => {
count += 1
}
</script>
<button on:click={increment}>
count is {count}
</button>

View File

@@ -0,0 +1,157 @@
// DO NOT EDIT: generated by fsdgenjs
import { HttpClientUtility, IServiceResult, IHttpClientOptions } from 'facility-core';
import { IOapApiV1Client, IGetApplicationsRequest, IGetApplicationsResponse, ICreateApplicationRequest, ICreateApplicationResponse, IGetApplicationRequest, IGetApplicationResponse, IUpdateApplicationRequest, IUpdateApplicationResponse, IApplication, IApplicationCreateSet, IApplicationChangeSet, IApplicationTermsCreateSet, IApplicationTerms, ApplicationStatus } from './oapApiV1ClientTypes';
export * from './oapApiV1ClientTypes';
/** Provides access to OapApiV1Client over HTTP via fetch. */
export function createHttpClient({ fetch, baseUri }: IHttpClientOptions): IOapApiV1Client {
return new OapApiV1ClientHttpClient(fetch, baseUri);
}
const { fetchResponse, createResponseError, createRequiredRequestFieldError } = HttpClientUtility;
type IFetch = HttpClientUtility.IFetch;
type IFetchRequest = HttpClientUtility.IFetchRequest;
class OapApiV1ClientHttpClient implements IOapApiV1Client {
constructor(fetch: IFetch, baseUri?: string) {
if (typeof fetch !== 'function') {
throw new TypeError('fetch must be a function.');
}
if (typeof baseUri === 'undefined') {
baseUri = 'https://oaprotection.org/api/v1';
}
if (/[^\/]$/.test(baseUri)) {
baseUri += '/';
}
this._fetch = fetch;
this._baseUri = baseUri;
}
/** Gets applications for the current user. */
public getApplications(request: IGetApplicationsRequest, context?: unknown): Promise<IServiceResult<IGetApplicationsResponse>> {
let uri = 'applications';
const query: string[] = [];
request.status == null || query.push('status=' + request.status);
request.limit == null || query.push('limit=' + request.limit.toString());
request.nextToken == null || query.push('nextToken=' + encodeURIComponent(request.nextToken));
if (query.length) {
uri = uri + '?' + query.join('&');
}
const fetchRequest: IFetchRequest = {
method: 'GET',
};
return fetchResponse(this._fetch, this._baseUri + uri, fetchRequest, context)
.then(result => {
const status = result.response.status;
let value: IGetApplicationsResponse | null = null;
if (status === 200) {
if (result.json) {
value = result.json as IGetApplicationsResponse | null;
}
}
if (!value) {
return createResponseError(status, result.json) as IServiceResult<IGetApplicationsResponse>;
}
return { value: value };
});
}
/** Creates a new application for the current user. */
public createApplication(request: ICreateApplicationRequest, context?: unknown): Promise<IServiceResult<ICreateApplicationResponse>> {
const uri = 'applications/';
if (!request.applicationCreateSet) {
return Promise.resolve(createRequiredRequestFieldError('applicationCreateSet'));
}
const fetchRequest: IFetchRequest = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(request.applicationCreateSet)
};
return fetchResponse(this._fetch, this._baseUri + uri, fetchRequest, context)
.then(result => {
const status = result.response.status;
let value: ICreateApplicationResponse | null = null;
if (status === 200) {
if (result.json) {
value = { application: result.json } as ICreateApplicationResponse;
}
}
else if (status === 201) {
value = {};
}
if (!value) {
return createResponseError(status, result.json) as IServiceResult<ICreateApplicationResponse>;
}
return { value: value };
});
}
/** Gets the specified application for the current user. */
public getApplication(request: IGetApplicationRequest, context?: unknown): Promise<IServiceResult<IGetApplicationResponse>> {
const uriPartId = request.id != null && encodeURIComponent(request.id);
if (!uriPartId) {
return Promise.resolve(createRequiredRequestFieldError('id'));
}
const uri = `applications/${uriPartId}`;
const fetchRequest: IFetchRequest = {
method: 'GET',
};
return fetchResponse(this._fetch, this._baseUri + uri, fetchRequest, context)
.then(result => {
const status = result.response.status;
let value: IGetApplicationResponse | null = null;
if (status === 200) {
if (result.json) {
value = { application: result.json } as IGetApplicationResponse;
}
}
else if (status === 304) {
value = { notModified: true };
}
if (!value) {
return createResponseError(status, result.json) as IServiceResult<IGetApplicationResponse>;
}
let headerValue: string | null | undefined;
headerValue = result.response.headers.get('eTag');
if (headerValue != null) {
value.eTag = headerValue;
}
return { value: value };
});
}
/** Updates the application. */
public updateApplication(request: IUpdateApplicationRequest, context?: unknown): Promise<IServiceResult<IUpdateApplicationResponse>> {
const uriPartId = request.id != null && encodeURIComponent(request.id);
if (!uriPartId) {
return Promise.resolve(createRequiredRequestFieldError('id'));
}
const uri = `applications/${uriPartId}`;
if (!request.applicationChangeSet) {
return Promise.resolve(createRequiredRequestFieldError('applicationChangeSet'));
}
const fetchRequest: IFetchRequest = {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(request.applicationChangeSet)
};
return fetchResponse(this._fetch, this._baseUri + uri, fetchRequest, context)
.then(result => {
const status = result.response.status;
let value: IUpdateApplicationResponse | null = null;
if (status === 200) {
if (result.json) {
value = { application: result.json } as IUpdateApplicationResponse;
}
}
if (!value) {
return createResponseError(status, result.json) as IServiceResult<IUpdateApplicationResponse>;
}
return { value: value };
});
}
private _fetch: IFetch;
private _baseUri: string;
}

View File

@@ -0,0 +1,122 @@
// DO NOT EDIT: generated by fsdgenjs
import { IServiceResult } from 'facility-core';
export interface IOapApiV1Client {
/** Gets applications for the current user. */
getApplications(request: IGetApplicationsRequest, context?: unknown): Promise<IServiceResult<IGetApplicationsResponse>>;
/** Creates a new application for the current user. */
createApplication(request: ICreateApplicationRequest, context?: unknown): Promise<IServiceResult<ICreateApplicationResponse>>;
/** Gets the specified application for the current user. */
getApplication(request: IGetApplicationRequest, context?: unknown): Promise<IServiceResult<IGetApplicationResponse>>;
/** Updates the application. */
updateApplication(request: IUpdateApplicationRequest, context?: unknown): Promise<IServiceResult<IUpdateApplicationResponse>>;
}
/** Request for GetApplications. */
export interface IGetApplicationsRequest {
/** Filter applications by the given status. */
status?: ApplicationStatus;
/** The limit of returned results. */
limit?: number;
/** The token presenting the next page of applications to get. */
nextToken?: string;
}
/** Response for GetApplications. */
export interface IGetApplicationsResponse {
/** The applications. */
applications?: IApplication[];
/** The total number of applications. */
total?: number;
/** The token representing the next page of results. */
nextToken?: string;
/** True if this is the last page of results, false otherwise. */
isLastPage?: boolean;
}
/** Request for CreateApplication. */
export interface ICreateApplicationRequest {
/** The application to create. */
applicationCreateSet?: IApplicationCreateSet;
}
/** Response for CreateApplication. */
export interface ICreateApplicationResponse {
/** The created application. */
application?: IApplication;
}
/** Request for GetApplication. */
export interface IGetApplicationRequest {
/** The widget ID. */
id?: string;
}
/** Response for GetApplication. */
export interface IGetApplicationResponse {
/** The requested widget. */
application?: IApplication;
eTag?: string;
notModified?: boolean;
}
/** Request for UpdateApplication. */
export interface IUpdateApplicationRequest {
/** The application ID. */
id?: string;
/** The application update set. */
applicationChangeSet?: IApplicationChangeSet;
}
/** Response for UpdateApplication. */
export interface IUpdateApplicationResponse {
/** The updated Application. */
application?: IApplication;
}
/** An application. */
export interface IApplication {
/** A unique identifier for the application. */
id?: string;
/** The current status of this application. */
status?: ApplicationStatus;
/** Terms the user must accept to start, continue an accept an application. */
terms?: IApplicationTerms;
}
export interface IApplicationCreateSet {
/** Terms a user must accept to start an application. */
terms?: IApplicationTermsCreateSet;
}
export interface IApplicationChangeSet {
}
export interface IApplicationTermsCreateSet {
hasReadInstructions?: boolean;
}
export interface IApplicationTerms {
hasReadInstructions?: boolean;
}
export enum ApplicationStatus {
InProgress = 'InProgress',
Submitted = 'Submitted',
}

View File

@@ -1,9 +1,24 @@
import { cacheExchange, Client, fetchExchange } from "@urql/svelte";
import "./app.css";
import OapApplicationForm from "./OapApplicationForm.svelte";
console.log(document.getElementsByClassName("OapApplicationForm"))
const oapApplicationForm = new OapApplicationForm({
target: document.getElementsByClassName("OapApplicationForm")[0],
const client = new Client({
url: "https://localhost:5001/oap/api/graphql",
exchanges: [cacheExchange, fetchExchange],
});
var oapApplicationForms = document.getElementsByClassName("OapApplicationForm");
let oapApplicationForm: OapApplicationForm;
if (oapApplicationForms.length === 1) {
oapApplicationForm = new OapApplicationForm({
target: oapApplicationForms[0],
props: {
contentItemId: oapApplicationForms[0].id,
client,
},
});
}
export { oapApplicationForm };

View File

@@ -1,20 +1,21 @@
{
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"resolveJsonModule": true,
/**
* Typecheck JS in `.svelte` and `.js` files by default.
* Disable checkJs if you'd like to use dynamic types in JS.
* Note that setting allowJs false does not prevent the use
* of JS in `.svelte` files.
*/
"allowJs": true,
"checkJs": true,
"isolatedModules": true
},
"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
"references": [{ "path": "./tsconfig.node.json" }]
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"resolveJsonModule": true,
/**
* Typecheck JS in `.svelte` and `.js` files by default.
* Disable checkJs if you'd like to use dynamic types in JS.
* Note that setting allowJs false does not prevent the use
* of JS in `.svelte` files.
*/
"allowJs": true,
"checkJs": true,
"isolatedModules": true
},
"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
"exclude": ["src/lib/oap/*.ts"],
"references": [{ "path": "./tsconfig.node.json" }]
}

View File

@@ -12,4 +12,10 @@ export default defineConfig({
manifest: true,
minify: false,
},
server: {
cors: {
origin: "*",
methods: "OPTIONS,GET,POST",
},
},
});

View File

@@ -2,4 +2,4 @@
@Model.Header.TitlePart.Title
</h1>
<div id="@Model.ContentItem.ContentType-@Model.ContentItem.Id" class="@Model.ContentItem.ContentType"></div>
<div id="@Model.ContentItem.ContentItemId" class="@Model.ContentItem.ContentType"></div>

View File

@@ -1,6 +1,6 @@
{
"index.html": {
"file": "index-bxmYv9y4.js",
"file": "index-DmYf-7v-.js",
"name": "index",
"src": "index.html",
"isEntry": true,

File diff suppressed because it is too large Load Diff

View File

@@ -1,339 +0,0 @@
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
(function polyfill() {
const relList = document.createElement("link").relList;
if (relList && relList.supports && relList.supports("modulepreload")) {
return;
}
for (const link of document.querySelectorAll('link[rel="modulepreload"]')) {
processPreload(link);
}
new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.type !== "childList") {
continue;
}
for (const node of mutation.addedNodes) {
if (node.tagName === "LINK" && node.rel === "modulepreload")
processPreload(node);
}
}
}).observe(document, { childList: true, subtree: true });
function getFetchOpts(link) {
const fetchOpts = {};
if (link.integrity)
fetchOpts.integrity = link.integrity;
if (link.referrerPolicy)
fetchOpts.referrerPolicy = link.referrerPolicy;
if (link.crossOrigin === "use-credentials")
fetchOpts.credentials = "include";
else if (link.crossOrigin === "anonymous")
fetchOpts.credentials = "omit";
else
fetchOpts.credentials = "same-origin";
return fetchOpts;
}
function processPreload(link) {
if (link.ep)
return;
link.ep = true;
const fetchOpts = getFetchOpts(link);
fetch(link.href, fetchOpts);
}
})();
function noop() {
}
function run(fn) {
return fn();
}
function blank_object() {
return /* @__PURE__ */ Object.create(null);
}
function run_all(fns) {
fns.forEach(run);
}
function is_function(thing) {
return typeof thing === "function";
}
function safe_not_equal(a, b) {
return a != a ? b == b : a !== b || a && typeof a === "object" || typeof a === "function";
}
function is_empty(obj) {
return Object.keys(obj).length === 0;
}
function insert(target, node, anchor) {
target.insertBefore(node, anchor || null);
}
function detach(node) {
if (node.parentNode) {
node.parentNode.removeChild(node);
}
}
function element(name) {
return document.createElement(name);
}
function children(element2) {
return Array.from(element2.childNodes);
}
let current_component;
function set_current_component(component) {
current_component = component;
}
const dirty_components = [];
const binding_callbacks = [];
let render_callbacks = [];
const flush_callbacks = [];
const resolved_promise = /* @__PURE__ */ Promise.resolve();
let update_scheduled = false;
function schedule_update() {
if (!update_scheduled) {
update_scheduled = true;
resolved_promise.then(flush);
}
}
function add_render_callback(fn) {
render_callbacks.push(fn);
}
const seen_callbacks = /* @__PURE__ */ new Set();
let flushidx = 0;
function flush() {
if (flushidx !== 0) {
return;
}
const saved_component = current_component;
do {
try {
while (flushidx < dirty_components.length) {
const component = dirty_components[flushidx];
flushidx++;
set_current_component(component);
update(component.$$);
}
} catch (e) {
dirty_components.length = 0;
flushidx = 0;
throw e;
}
set_current_component(null);
dirty_components.length = 0;
flushidx = 0;
while (binding_callbacks.length)
binding_callbacks.pop()();
for (let i = 0; i < render_callbacks.length; i += 1) {
const callback = render_callbacks[i];
if (!seen_callbacks.has(callback)) {
seen_callbacks.add(callback);
callback();
}
}
render_callbacks.length = 0;
} while (dirty_components.length);
while (flush_callbacks.length) {
flush_callbacks.pop()();
}
update_scheduled = false;
seen_callbacks.clear();
set_current_component(saved_component);
}
function update($$) {
if ($$.fragment !== null) {
$$.update();
run_all($$.before_update);
const dirty = $$.dirty;
$$.dirty = [-1];
$$.fragment && $$.fragment.p($$.ctx, dirty);
$$.after_update.forEach(add_render_callback);
}
}
function flush_render_callbacks(fns) {
const filtered = [];
const targets = [];
render_callbacks.forEach((c) => fns.indexOf(c) === -1 ? filtered.push(c) : targets.push(c));
targets.forEach((c) => c());
render_callbacks = filtered;
}
const outroing = /* @__PURE__ */ new Set();
function transition_in(block, local) {
if (block && block.i) {
outroing.delete(block);
block.i(local);
}
}
function mount_component(component, target, anchor) {
const { fragment, after_update } = component.$$;
fragment && fragment.m(target, anchor);
add_render_callback(() => {
const new_on_destroy = component.$$.on_mount.map(run).filter(is_function);
if (component.$$.on_destroy) {
component.$$.on_destroy.push(...new_on_destroy);
} else {
run_all(new_on_destroy);
}
component.$$.on_mount = [];
});
after_update.forEach(add_render_callback);
}
function destroy_component(component, detaching) {
const $$ = component.$$;
if ($$.fragment !== null) {
flush_render_callbacks($$.after_update);
run_all($$.on_destroy);
$$.fragment && $$.fragment.d(detaching);
$$.on_destroy = $$.fragment = null;
$$.ctx = [];
}
}
function make_dirty(component, i) {
if (component.$$.dirty[0] === -1) {
dirty_components.push(component);
schedule_update();
component.$$.dirty.fill(0);
}
component.$$.dirty[i / 31 | 0] |= 1 << i % 31;
}
function init(component, options, instance, create_fragment2, not_equal, props, append_styles = null, dirty = [-1]) {
const parent_component = current_component;
set_current_component(component);
const $$ = component.$$ = {
fragment: null,
ctx: [],
// state
props,
update: noop,
not_equal,
bound: blank_object(),
// lifecycle
on_mount: [],
on_destroy: [],
on_disconnect: [],
before_update: [],
after_update: [],
context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),
// everything else
callbacks: blank_object(),
dirty,
skip_bound: false,
root: options.target || parent_component.$$.root
};
append_styles && append_styles($$.root);
let ready = false;
$$.ctx = instance ? instance(component, options.props || {}, (i, ret, ...rest) => {
const value = rest.length ? rest[0] : ret;
if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
if (!$$.skip_bound && $$.bound[i])
$$.bound[i](value);
if (ready)
make_dirty(component, i);
}
return ret;
}) : [];
$$.update();
ready = true;
run_all($$.before_update);
$$.fragment = create_fragment2 ? create_fragment2($$.ctx) : false;
if (options.target) {
if (options.hydrate) {
const nodes = children(options.target);
$$.fragment && $$.fragment.l(nodes);
nodes.forEach(detach);
} else {
$$.fragment && $$.fragment.c();
}
if (options.intro)
transition_in(component.$$.fragment);
mount_component(component, options.target, options.anchor);
flush();
}
set_current_component(parent_component);
}
class SvelteComponent {
constructor() {
/**
* ### PRIVATE API
*
* Do not use, may change at any time
*
* @type {any}
*/
__publicField(this, "$$");
/**
* ### PRIVATE API
*
* Do not use, may change at any time
*
* @type {any}
*/
__publicField(this, "$$set");
}
/** @returns {void} */
$destroy() {
destroy_component(this, 1);
this.$destroy = noop;
}
/**
* @template {Extract<keyof Events, string>} K
* @param {K} type
* @param {((e: Events[K]) => void) | null | undefined} callback
* @returns {() => void}
*/
$on(type, callback) {
if (!is_function(callback)) {
return noop;
}
const callbacks = this.$$.callbacks[type] || (this.$$.callbacks[type] = []);
callbacks.push(callback);
return () => {
const index = callbacks.indexOf(callback);
if (index !== -1)
callbacks.splice(index, 1);
};
}
/**
* @param {Partial<Props>} props
* @returns {void}
*/
$set(props) {
if (this.$$set && !is_empty(props)) {
this.$$.skip_bound = true;
this.$$set(props);
this.$$.skip_bound = false;
}
}
}
const PUBLIC_VERSION = "4";
if (typeof window !== "undefined")
(window.__svelte || (window.__svelte = { v: /* @__PURE__ */ new Set() })).v.add(PUBLIC_VERSION);
function create_fragment(ctx) {
let div;
return {
c() {
div = element("div");
div.textContent = "This is an application form";
},
m(target, anchor) {
insert(target, div, anchor);
},
p: noop,
i: noop,
o: noop,
d(detaching) {
if (detaching) {
detach(div);
}
}
};
}
class OapApplicationForm extends SvelteComponent {
constructor(options) {
super();
init(this, options, null, create_fragment, safe_not_equal, {});
}
}
console.log(document.getElementsByClassName("OapApplicationForm"));
new OapApplicationForm({
target: document.getElementsByClassName("OapApplicationForm")[0]
});

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Overseas Auto Protection - Svelte</title>
<script type="module" crossorigin src="/index-bxmYv9y4.js"></script>
<script type="module" crossorigin src="/index-DmYf-7v-.js"></script>
<link rel="stylesheet" crossorigin href="/index-ClWnXPkW.css">
</head>
<body>

View File

@@ -23,7 +23,6 @@ if (!app.Environment.IsDevelopment())
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseOrchardCore();

View File

@@ -7,6 +7,9 @@
}
},
"OrchardCore": {
"OrchardCore_Apis_GraphQL": {
"MaxDepth": 50
},
"OrchardCore_AutoSetup": {
"AutoSetupPath": "",
"Tenants": [