refactor: regenerate svelte kit
							parent
							
								
									d335d0ac45
								
							
						
					
					
						commit
						d88181665d
					
				| @ -1,20 +0,0 @@ | |||||||
| module.exports = { |  | ||||||
| 	root: true, |  | ||||||
| 	parser: '@typescript-eslint/parser', |  | ||||||
| 	extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], |  | ||||||
| 	plugins: ['svelte3', '@typescript-eslint'], |  | ||||||
| 	ignorePatterns: ['*.cjs'], |  | ||||||
| 	overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], |  | ||||||
| 	settings: { |  | ||||||
| 		'svelte3/typescript': () => require('typescript') |  | ||||||
| 	}, |  | ||||||
| 	parserOptions: { |  | ||||||
| 		sourceType: 'module', |  | ||||||
| 		ecmaVersion: 2019 |  | ||||||
| 	}, |  | ||||||
| 	env: { |  | ||||||
| 		browser: true, |  | ||||||
| 		es2017: true, |  | ||||||
| 		node: true |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
| @ -1,6 +0,0 @@ | |||||||
| { |  | ||||||
| 	"useTabs": true, |  | ||||||
| 	"singleQuote": false, |  | ||||||
| 	"trailingComma": "all", |  | ||||||
| 	"printWidth": 100 |  | ||||||
| } |  | ||||||
| @ -0,0 +1,17 @@ | |||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"log" | ||||||
|  | 
 | ||||||
|  | 	"github.com/hhhapz/codequest/db" | ||||||
|  | 	"github.com/hhhapz/codequest/models" | ||||||
|  | 	"github.com/k0kubun/pp/v3" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	d, _ := db.NewDB("db.sqlite") | ||||||
|  | 	models.SetLogger(log.Printf) | ||||||
|  | 
 | ||||||
|  | 	pp.Println(models.QuestionSubmissions(context.Background(), d.DB, "2", "idk", 2)) | ||||||
|  | } | ||||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								| @ -1,42 +0,0 @@ | |||||||
| { |  | ||||||
| 	"name": "~TODO~", |  | ||||||
| 	"version": "0.0.1", |  | ||||||
| 	"scripts": { |  | ||||||
| 		"dev": "svelte-kit dev", |  | ||||||
| 		"build": "svelte-kit build", |  | ||||||
| 		"preview": "svelte-kit preview", |  | ||||||
| 		"check": "svelte-check --tsconfig ./tsconfig.json", |  | ||||||
| 		"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch", |  | ||||||
| 		"lint": "prettier --ignore-path .gitignore  --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .", |  | ||||||
| 		"format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. ." |  | ||||||
| 	}, |  | ||||||
| 	"devDependencies": { |  | ||||||
| 		"@sveltejs/adapter-static": "^1.0.0-next.18", |  | ||||||
| 		"@sveltejs/kit": "next", |  | ||||||
| 		"@types/cookie": "^0.4.0", |  | ||||||
| 		"@typescript-eslint/eslint-plugin": "^4.19.0", |  | ||||||
| 		"@typescript-eslint/parser": "^4.19.0", |  | ||||||
| 		"autoprefixer": "^10.3.4", |  | ||||||
| 		"cssnano": "^5.0.8", |  | ||||||
| 		"eslint": "^7.22.0", |  | ||||||
| 		"eslint-config-prettier": "^8.1.0", |  | ||||||
| 		"eslint-plugin-svelte3": "^3.2.0", |  | ||||||
| 		"postcss": "^8.3.6", |  | ||||||
| 		"postcss-load-config": "^3.1.0", |  | ||||||
| 		"prettier": "~2.2.1", |  | ||||||
| 		"prettier-plugin-svelte": "^2.2.0", |  | ||||||
| 		"svelte": "^3.34.0", |  | ||||||
| 		"svelte-check": "^2.0.0", |  | ||||||
| 		"svelte-preprocess": "^4.9.4", |  | ||||||
| 		"tailwindcss": "^2.2.15", |  | ||||||
| 		"tslib": "^2.0.0", |  | ||||||
| 		"typescript": "^4.0.0" |  | ||||||
| 	}, |  | ||||||
| 	"type": "module", |  | ||||||
| 	"dependencies": { |  | ||||||
| 		"@fontsource/fira-mono": "^4.2.2", |  | ||||||
| 		"@lukeed/uuid": "^2.0.0", |  | ||||||
| 		"cookie": "^0.4.1", |  | ||||||
| 		"daisyui": "^1.14.1" |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @ -1,21 +0,0 @@ | |||||||
| const tailwindcss = require("tailwindcss"); |  | ||||||
| const autoprefixer = require("autoprefixer"); |  | ||||||
| const cssnano = require("cssnano"); |  | ||||||
| 
 |  | ||||||
| const mode = process.env.NODE_ENV; |  | ||||||
| const dev = mode === "development"; |  | ||||||
| 
 |  | ||||||
| const config = { |  | ||||||
| 	plugins: [ |  | ||||||
| 		//Some plugins, like tailwindcss/nesting, need to run before Tailwind,
 |  | ||||||
| 		tailwindcss(), |  | ||||||
| 		//But others, like autoprefixer, need to run after,
 |  | ||||||
| 		autoprefixer(), |  | ||||||
| 		!dev && |  | ||||||
| 			cssnano({ |  | ||||||
| 				preset: "default", |  | ||||||
| 			}), |  | ||||||
| 	], |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| module.exports = config; |  | ||||||
| @ -1,28 +0,0 @@ | |||||||
| import preprocess from "svelte-preprocess"; |  | ||||||
| import adapter from '@sveltejs/adapter-static' |  | ||||||
| 
 |  | ||||||
| /** @type {import('@sveltejs/kit').Config} */ |  | ||||||
| const config = { |  | ||||||
| 	// Consult https://github.com/sveltejs/svelte-preprocess
 |  | ||||||
| 	// for more information about preprocessors
 |  | ||||||
| 	preprocess: [ |  | ||||||
| 		preprocess({ |  | ||||||
| 			postcss: true, |  | ||||||
| 		}), |  | ||||||
| 	], |  | ||||||
| 
 |  | ||||||
| 	kit: { |  | ||||||
| 		// hydrate the <div id="svelte"> element in src/app.html
 |  | ||||||
| 		target: "#svelte", |  | ||||||
| 		files: { |  | ||||||
| 			hooks: "web_src/hooks", |  | ||||||
| 			lib: "web_src/lib", |  | ||||||
| 			routes: "web_src/routes", |  | ||||||
| 			serviceWorker: "web_src/service-worker", |  | ||||||
| 			template: "web_src/app.html", |  | ||||||
| 		}, |  | ||||||
| 		adapter: adapter({}), |  | ||||||
| 	}, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| export default config; |  | ||||||
| @ -1,23 +0,0 @@ | |||||||
| { |  | ||||||
| 	"compilerOptions": { |  | ||||||
| 		"moduleResolution": "node", |  | ||||||
| 		"module": "es2020", |  | ||||||
| 		"lib": ["es2020", "DOM"], |  | ||||||
| 		"target": "es2019", |  | ||||||
| 		"importsNotUsedAsValues": "error", |  | ||||||
| 		"isolatedModules": true, |  | ||||||
| 		"resolveJsonModule": true, |  | ||||||
| 		"sourceMap": true, |  | ||||||
| 		"esModuleInterop": true, |  | ||||||
| 		"skipLibCheck": true, |  | ||||||
| 		"forceConsistentCasingInFileNames": true, |  | ||||||
| 		"baseUrl": ".", |  | ||||||
| 		"allowJs": true, |  | ||||||
| 		"checkJs": true, |  | ||||||
| 		"paths": { |  | ||||||
| 			"$lib": ["web_src/lib"], |  | ||||||
| 			"$lib/*": ["web_src/lib/*"] |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 	"include": ["web_src/**/*.d.ts", "web_src/**/*.js", "web_src/**/*.ts", "web_src/**/*.svelte"] |  | ||||||
| } |  | ||||||
| @ -1,13 +0,0 @@ | |||||||
| <!DOCTYPE html> |  | ||||||
| <html lang="en"> |  | ||||||
| 	<head> |  | ||||||
| 		<meta charset="utf-8" /> |  | ||||||
| 		<link rel="icon" href="/favicon.png" /> |  | ||||||
| 		<meta name="viewport" content="width=device-width, initial-scale=1" /> |  | ||||||
| 
 |  | ||||||
| 		%svelte.head% |  | ||||||
| 	</head> |  | ||||||
| 	<body> |  | ||||||
| 		<div id="svelte">%svelte.body%</div> |  | ||||||
| 	</body> |  | ||||||
| </html> |  | ||||||
| @ -1,5 +0,0 @@ | |||||||
| @import "@fontsource/fira-mono"; |  | ||||||
| 
 |  | ||||||
| @tailwind base; |  | ||||||
| @tailwind components; |  | ||||||
| @tailwind utilities; |  | ||||||
| @ -1 +0,0 @@ | |||||||
| /// <reference types="@sveltejs/kit" />
 |  | ||||||
| @ -1,23 +0,0 @@ | |||||||
| import cookie from 'cookie'; |  | ||||||
| import { v4 as uuid } from '@lukeed/uuid'; |  | ||||||
| import type { Handle } from '@sveltejs/kit'; |  | ||||||
| 
 |  | ||||||
| export const handle: Handle = async ({ request, resolve }) => { |  | ||||||
| 	const cookies = cookie.parse(request.headers.cookie || ''); |  | ||||||
| 	request.locals.userid = cookies.userid || uuid(); |  | ||||||
| 
 |  | ||||||
| 	// TODO https://github.com/sveltejs/kit/issues/1046
 |  | ||||||
| 	if (request.query.has('_method')) { |  | ||||||
| 		request.method = request.query.get('_method').toUpperCase(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	const response = await resolve(request); |  | ||||||
| 
 |  | ||||||
| 	if (!cookies.userid) { |  | ||||||
| 		// if this is the first time the user has visited this app,
 |  | ||||||
| 		// set a cookie so that we recognise them when they return
 |  | ||||||
| 		response.headers['set-cookie'] = `userid=${request.locals.userid}; Path=/; HttpOnly`; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return response; |  | ||||||
| }; |  | ||||||
| @ -1,5 +0,0 @@ | |||||||
| <script lang="ts"> |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <header> |  | ||||||
| </header> |  | ||||||
| @ -1,160 +0,0 @@ | |||||||
| /* eslint-disable */ |  | ||||||
| // @ts-nocheck
 |  | ||||||
| /* |  | ||||||
| * This file is a generated Typescript file for GRPC Gateway, DO NOT MODIFY |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| import * as fm from "../../../../../fetch.pb" |  | ||||||
| import * as GoogleProtobufEmpty from "../../../../../google/protobuf/empty.pb" |  | ||||||
| import * as GoogleProtobufTimestamp from "../../../../../google/protobuf/timestamp.pb" |  | ||||||
| export type Token = { |  | ||||||
|   token?: string |  | ||||||
|   expires?: GoogleProtobufTimestamp.Timestamp |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type OAuthCodeRequest = { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type OAuthCodeResponse = { |  | ||||||
|   redirectURI?: string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type TokenRequest = { |  | ||||||
|   code?: string |  | ||||||
|   state?: string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type DeleteTokenRequest = { |  | ||||||
|   all?: boolean |  | ||||||
|   token?: Token |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type User = { |  | ||||||
|   id?: string |  | ||||||
|   name?: string |  | ||||||
|   email?: string |  | ||||||
|   picture?: string |  | ||||||
|   admin?: boolean |  | ||||||
|   createdAt?: GoogleProtobufTimestamp.Timestamp |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type PartData = { |  | ||||||
|   completed?: boolean |  | ||||||
|   pointsWorth?: number |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type Question = { |  | ||||||
|   id?: string |  | ||||||
|   title?: string |  | ||||||
|   text?: string |  | ||||||
|   part1?: PartData |  | ||||||
|   part2?: PartData |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type QuestionsResponse = { |  | ||||||
|   questions?: Question[] |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type QuestionByIDRequest = { |  | ||||||
|   id?: string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type QuestionInputRequest = { |  | ||||||
|   id?: string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type QuestionInput = { |  | ||||||
|   id?: string |  | ||||||
|   input?: string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type SubmitRequestData = { |  | ||||||
|   answer?: string |  | ||||||
|   part?: number |  | ||||||
|   code?: string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type SubmitRequest = { |  | ||||||
|   id?: string |  | ||||||
|   body?: SubmitRequestData |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type SubmitResponse = { |  | ||||||
|   correct?: boolean |  | ||||||
|   points?: number |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type UpdateFields = { |  | ||||||
|   name?: string |  | ||||||
|   gradeLevel?: number |  | ||||||
|   admin?: boolean |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type UserRequest = { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type AllUsersRequest = { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type UpdateUserRequest = { |  | ||||||
|   email?: string |  | ||||||
|   body?: UpdateFields |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type UserByEmailRequest = { |  | ||||||
|   email?: string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type DeleteUserRequest = { |  | ||||||
|   email?: string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export type AllUsersResponse = { |  | ||||||
|   users?: User[] |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export class AuthService { |  | ||||||
|   static OAuthCode(req: OAuthCodeRequest, initReq?: fm.InitReq): Promise<OAuthCodeResponse> { |  | ||||||
|     return fm.fetchReq<OAuthCodeRequest, OAuthCodeResponse>(`/v1/auth/code?${fm.renderURLSearchParams(req, [])}`, {...initReq, method: "GET"}) |  | ||||||
|   } |  | ||||||
|   static Token(req: TokenRequest, initReq?: fm.InitReq): Promise<Token> { |  | ||||||
|     return fm.fetchReq<TokenRequest, Token>(`/v1/auth/token?${fm.renderURLSearchParams(req, [])}`, {...initReq, method: "GET"}) |  | ||||||
|   } |  | ||||||
|   static DeleteToken(req: DeleteTokenRequest, initReq?: fm.InitReq): Promise<GoogleProtobufEmpty.Empty> { |  | ||||||
|     return fm.fetchReq<DeleteTokenRequest, GoogleProtobufEmpty.Empty>(`/v1/auth/token`, {...initReq, method: "DELETE"}) |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| export class QuestService { |  | ||||||
|   static Questions(req: GoogleProtobufEmpty.Empty, initReq?: fm.InitReq): Promise<QuestionsResponse> { |  | ||||||
|     return fm.fetchReq<GoogleProtobufEmpty.Empty, QuestionsResponse>(`/v1/questions?${fm.renderURLSearchParams(req, [])}`, {...initReq, method: "GET"}) |  | ||||||
|   } |  | ||||||
|   static QuestionByID(req: QuestionByIDRequest, initReq?: fm.InitReq): Promise<Question> { |  | ||||||
|     return fm.fetchReq<QuestionByIDRequest, Question>(`/v1/questions/${req["id"]}?${fm.renderURLSearchParams(req, ["id"])}`, {...initReq, method: "GET"}) |  | ||||||
|   } |  | ||||||
|   static QuestionInput(req: QuestionInputRequest, initReq?: fm.InitReq): Promise<QuestionInput> { |  | ||||||
|     return fm.fetchReq<QuestionInputRequest, QuestionInput>(`/v1/questions/${req["id"]}/input?${fm.renderURLSearchParams(req, ["id"])}`, {...initReq, method: "GET"}) |  | ||||||
|   } |  | ||||||
|   static Submit(req: SubmitRequest, initReq?: fm.InitReq): Promise<SubmitResponse> { |  | ||||||
|     return fm.fetchReq<SubmitRequest, SubmitResponse>(`/v1/questions/${req["id"]}`, {...initReq, method: "POST", body: JSON.stringify(req["Body"])}) |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| export class UserService { |  | ||||||
|   static User(req: UserRequest, initReq?: fm.InitReq): Promise<User> { |  | ||||||
|     return fm.fetchReq<UserRequest, User>(`/v1/users/me?${fm.renderURLSearchParams(req, [])}`, {...initReq, method: "GET"}) |  | ||||||
|   } |  | ||||||
|   static UserByEmail(req: UserByEmailRequest, initReq?: fm.InitReq): Promise<User> { |  | ||||||
|     return fm.fetchReq<UserByEmailRequest, User>(`/v1/admin/users/${req["email"]}?${fm.renderURLSearchParams(req, ["email"])}`, {...initReq, method: "GET"}) |  | ||||||
|   } |  | ||||||
|   static AllUsers(req: AllUsersRequest, initReq?: fm.InitReq): Promise<AllUsersResponse> { |  | ||||||
|     return fm.fetchReq<AllUsersRequest, AllUsersResponse>(`/v1/admin/users?${fm.renderURLSearchParams(req, [])}`, {...initReq, method: "GET"}) |  | ||||||
|   } |  | ||||||
|   static UpdateUser(req: UpdateUserRequest, initReq?: fm.InitReq): Promise<User> { |  | ||||||
|     return fm.fetchReq<UpdateUserRequest, User>(`/v1/users/me`, {...initReq, method: "PUT", body: JSON.stringify(req["Body"])}) |  | ||||||
|   } |  | ||||||
|   static AdminUpdateUser(req: UpdateUserRequest, initReq?: fm.InitReq): Promise<User> { |  | ||||||
|     return fm.fetchReq<UpdateUserRequest, User>(`/v1/admin/users/${req["email"]}`, {...initReq, method: "PUT", body: JSON.stringify(req["Body"])}) |  | ||||||
|   } |  | ||||||
|   static DeleteUser(req: DeleteUserRequest, initReq?: fm.InitReq): Promise<User> { |  | ||||||
|     return fm.fetchReq<DeleteUserRequest, User>(`/v1/admin/users/${req["email"]}`, {...initReq, method: "DELETE"}) |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @ -1,232 +0,0 @@ | |||||||
| /* eslint-disable */ |  | ||||||
| // @ts-nocheck
 |  | ||||||
| /* |  | ||||||
| * This file is a generated Typescript file for GRPC Gateway, DO NOT MODIFY |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| export interface InitReq extends RequestInit { |  | ||||||
|   pathPrefix?: string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export function fetchReq<I, O>(path: string, init?: InitReq): Promise<O> { |  | ||||||
|   const {pathPrefix, ...req} = init || {} |  | ||||||
| 
 |  | ||||||
|   const url = pathPrefix ? `${pathPrefix}${path}` : path |  | ||||||
| 
 |  | ||||||
|   return fetch(url, req).then(r => r.json().then((body: O) => { |  | ||||||
|     if (!r.ok) { throw body; } |  | ||||||
|     return body; |  | ||||||
|   })) as Promise<O> |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // NotifyStreamEntityArrival is a callback that will be called on streaming entity arrival
 |  | ||||||
| export type NotifyStreamEntityArrival<T> = (resp: T) => void |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * fetchStreamingRequest is able to handle grpc-gateway server side streaming call |  | ||||||
|  * it takes NotifyStreamEntityArrival that lets users respond to entity arrival during the call |  | ||||||
|  * all entities will be returned as an array after the call finishes. |  | ||||||
|  **/ |  | ||||||
| export async function fetchStreamingRequest<S, R>(path: string, callback?: NotifyStreamEntityArrival<R>, init?: InitReq) { |  | ||||||
|   const {pathPrefix, ...req} = init || {} |  | ||||||
|   const url = pathPrefix ?`${pathPrefix}${path}` : path |  | ||||||
|   const result = await fetch(url, req) |  | ||||||
|   // needs to use the .ok to check the status of HTTP status code
 |  | ||||||
|   // http other than 200 will not throw an error, instead the .ok will become false.
 |  | ||||||
|   // see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#
 |  | ||||||
|   if (!result.ok) { |  | ||||||
|     const resp = await result.json() |  | ||||||
|     const errMsg = resp.error && resp.error.message ? resp.error.message : "" |  | ||||||
|     throw new Error(errMsg) |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (!result.body) { |  | ||||||
|     throw new Error("response doesnt have a body") |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   await result.body |  | ||||||
|     .pipeThrough(new TextDecoderStream()) |  | ||||||
|     .pipeThrough<R>(getNewLineDelimitedJSONDecodingStream<R>()) |  | ||||||
|     .pipeTo(getNotifyEntityArrivalSink((e: R) => { |  | ||||||
|       if (callback) { |  | ||||||
|         callback(e) |  | ||||||
|       } |  | ||||||
|     })) |  | ||||||
| 
 |  | ||||||
|   // wait for the streaming to finish and return the success respond
 |  | ||||||
|   return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * JSONStringStreamController represents the transform controller that's able to transform the incoming |  | ||||||
|  * new line delimited json content stream into entities and able to push the entity to the down stream |  | ||||||
|  */ |  | ||||||
| interface JSONStringStreamController<T> extends TransformStreamDefaultController { |  | ||||||
|   buf?: string |  | ||||||
|   pos?: number |  | ||||||
|   enqueue: (s: T) => void |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * getNewLineDelimitedJSONDecodingStream returns a TransformStream that's able to handle new line delimited json stream content into parsed entities |  | ||||||
|  */ |  | ||||||
| function getNewLineDelimitedJSONDecodingStream<T>(): TransformStream<string, T> { |  | ||||||
|   return new TransformStream({ |  | ||||||
|     start(controller: JSONStringStreamController<T>) { |  | ||||||
|       controller.buf = '' |  | ||||||
|       controller.pos = 0 |  | ||||||
|     }, |  | ||||||
| 
 |  | ||||||
|     transform(chunk: string, controller: JSONStringStreamController<T>) { |  | ||||||
|       if (controller.buf === undefined) { |  | ||||||
|         controller.buf = '' |  | ||||||
|       } |  | ||||||
|       if (controller.pos === undefined) { |  | ||||||
|         controller.pos = 0 |  | ||||||
|       } |  | ||||||
|       controller.buf += chunk |  | ||||||
|       while (controller.pos < controller.buf.length) { |  | ||||||
|         if (controller.buf[controller.pos] === '\n') { |  | ||||||
|           const line = controller.buf.substring(0, controller.pos) |  | ||||||
|           const response = JSON.parse(line) |  | ||||||
|           controller.enqueue(response.result) |  | ||||||
|           controller.buf = controller.buf.substring(controller.pos + 1) |  | ||||||
|           controller.pos = 0 |  | ||||||
|         } else { |  | ||||||
|           ++controller.pos |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * getNotifyEntityArrivalSink takes the NotifyStreamEntityArrival callback and return |  | ||||||
|  * a sink that will call the callback on entity arrival |  | ||||||
|  * @param notifyCallback |  | ||||||
|  */ |  | ||||||
| function getNotifyEntityArrivalSink<T>(notifyCallback: NotifyStreamEntityArrival<T>) { |  | ||||||
|   return new WritableStream<T>({ |  | ||||||
|     write(entity: T) { |  | ||||||
|       notifyCallback(entity) |  | ||||||
|     } |  | ||||||
|   }) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type Primitive = string | boolean | number; |  | ||||||
| type RequestPayload = Record<string, unknown>; |  | ||||||
| type FlattenedRequestPayload = Record<string, Primitive | Array<Primitive>>; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Checks if given value is a plain object |  | ||||||
|  * Logic copied and adapted from below source:  |  | ||||||
|  * https://github.com/char0n/ramda-adjunct/blob/master/src/isPlainObj.js
 |  | ||||||
|  * @param  {unknown} value |  | ||||||
|  * @return {boolean} |  | ||||||
|  */ |  | ||||||
| function isPlainObject(value: unknown): boolean { |  | ||||||
|   const isObject = |  | ||||||
|     Object.prototype.toString.call(value).slice(8, -1) === "Object"; |  | ||||||
|   const isObjLike = value !== null && isObject; |  | ||||||
| 
 |  | ||||||
|   if (!isObjLike || !isObject) { |  | ||||||
|     return false; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   const proto = Object.getPrototypeOf(value); |  | ||||||
| 
 |  | ||||||
|   const hasObjectConstructor = |  | ||||||
|     typeof proto === "object" && |  | ||||||
|     proto.constructor === Object.prototype.constructor; |  | ||||||
| 
 |  | ||||||
|   return hasObjectConstructor; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Checks if given value is of a primitive type |  | ||||||
|  * @param  {unknown} value |  | ||||||
|  * @return {boolean} |  | ||||||
|  */ |  | ||||||
| function isPrimitive(value: unknown): boolean { |  | ||||||
|   return ["string", "number", "boolean"].some(t => typeof value === t); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Checks if given primitive is zero-value |  | ||||||
|  * @param  {Primitive} value |  | ||||||
|  * @return {boolean} |  | ||||||
|  */ |  | ||||||
| function isZeroValuePrimitive(value: Primitive): boolean { |  | ||||||
|   return value === false || value === 0 || value === ""; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Flattens a deeply nested request payload and returns an object |  | ||||||
|  * with only primitive values and non-empty array of primitive values |  | ||||||
|  * as per https://github.com/googleapis/googleapis/blob/master/google/api/http.proto
 |  | ||||||
|  * @param  {RequestPayload} requestPayload |  | ||||||
|  * @param  {String} path |  | ||||||
|  * @return {FlattenedRequestPayload>} |  | ||||||
|  */ |  | ||||||
| function flattenRequestPayload<T extends RequestPayload>( |  | ||||||
|   requestPayload: T, |  | ||||||
|   path: string = "" |  | ||||||
| ): FlattenedRequestPayload { |  | ||||||
|   return Object.keys(requestPayload).reduce( |  | ||||||
|     (acc: T, key: string): T => { |  | ||||||
|       const value = requestPayload[key]; |  | ||||||
|       const newPath = path ? [path, key].join(".") : key; |  | ||||||
| 
 |  | ||||||
|       const isNonEmptyPrimitiveArray = |  | ||||||
|         Array.isArray(value) && |  | ||||||
|         value.every(v => isPrimitive(v)) && |  | ||||||
|         value.length > 0; |  | ||||||
| 
 |  | ||||||
|       const isNonZeroValuePrimitive = |  | ||||||
|         isPrimitive(value) && !isZeroValuePrimitive(value as Primitive); |  | ||||||
| 
 |  | ||||||
|       let objectToMerge = {}; |  | ||||||
| 
 |  | ||||||
|       if (isPlainObject(value)) { |  | ||||||
|         objectToMerge = flattenRequestPayload(value as RequestPayload, newPath); |  | ||||||
|       } else if (isNonZeroValuePrimitive || isNonEmptyPrimitiveArray) { |  | ||||||
|         objectToMerge = { [newPath]: value }; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       return { ...acc, ...objectToMerge }; |  | ||||||
|     }, |  | ||||||
|     {} as T |  | ||||||
|   ) as FlattenedRequestPayload; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Renders a deeply nested request payload into a string of URL search |  | ||||||
|  * parameters by first flattening the request payload and then removing keys |  | ||||||
|  * which are already present in the URL path. |  | ||||||
|  * @param  {RequestPayload} requestPayload |  | ||||||
|  * @param  {string[]} urlPathParams |  | ||||||
|  * @return {string} |  | ||||||
|  */ |  | ||||||
| export function renderURLSearchParams<T extends RequestPayload>( |  | ||||||
|   requestPayload: T, |  | ||||||
|   urlPathParams: string[] = [] |  | ||||||
| ): string { |  | ||||||
|   const flattenedRequestPayload = flattenRequestPayload(requestPayload); |  | ||||||
| 
 |  | ||||||
|   const urlSearchParams = Object.keys(flattenedRequestPayload).reduce( |  | ||||||
|     (acc: string[][], key: string): string[][] => { |  | ||||||
|       // key should not be present in the url path as a parameter
 |  | ||||||
|       const value = flattenedRequestPayload[key]; |  | ||||||
|       if (urlPathParams.find(f => f === key)) { |  | ||||||
|         return acc; |  | ||||||
|       } |  | ||||||
|       return Array.isArray(value) |  | ||||||
|         ? [...acc, ...value.map(m => [key, m.toString()])] |  | ||||||
|         : (acc = [...acc, [key, value.toString()]]); |  | ||||||
|     }, |  | ||||||
|     [] as string[][] |  | ||||||
|   ); |  | ||||||
| 
 |  | ||||||
|   return new URLSearchParams(urlSearchParams).toString(); |  | ||||||
| } |  | ||||||
| @ -1,7 +0,0 @@ | |||||||
| <script> |  | ||||||
| 	import "../app.postcss"; |  | ||||||
| 	import Header from "$lib/header/Header.svelte"; |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <Header /> |  | ||||||
| <slot /> |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| <script context="module"> |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <script> |  | ||||||
| 	import { onMount } from "svelte"; |  | ||||||
| 
 |  | ||||||
| 	let dflt = "hello"; |  | ||||||
| 
 |  | ||||||
| 	onMount(() => { |  | ||||||
| 		dflt = "sup"; |  | ||||||
| 	}); |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <svelte:head> |  | ||||||
| 	<title>About</title> |  | ||||||
| </svelte:head> |  | ||||||
| 
 |  | ||||||
| <p>{dflt}</p> |  | ||||||
| 
 |  | ||||||
											
												
													File diff suppressed because one or more lines are too long
												
											
										
									
								
		Loading…
	
		Reference in New Issue