Skip to content
This repository has been archived by the owner on May 7, 2024. It is now read-only.

Commit

Permalink
partial typescript migration
Browse files Browse the repository at this point in the history
  • Loading branch information
janosh committed Aug 4, 2021
1 parent 71c768f commit 2bffa7d
Show file tree
Hide file tree
Showing 13 changed files with 312 additions and 56 deletions.
16 changes: 12 additions & 4 deletions .eslintrc.yml
@@ -1,21 +1,29 @@
root: true
env:
browser: true
es2020: true
node: true
extends:
- eslint:recommended
parser: '@typescript-eslint/parser'
parserOptions:
sourceType: module
ecmaVersion: 2020
plugins: [svelte3]
plugins: [svelte3, '@typescript-eslint']
extends:
- eslint:recommended
- plugin:@typescript-eslint/recommended
overrides:
- files: ['*.svelte']
processor: svelte3/svelte3
settings:
svelte3/typescript: true
rules:
indent: [error, 2, SwitchCase: 1]
quotes: [error, backtick, avoidEscape: true]
semi: [error, never]
linebreak-style: [error, unix]
no-console: [error, allow: [warn, error]]
no-var: error
spaced-comment: [error, always]
# allow triple slash for typescript file referencing https://git.io/JCeqO
spaced-comment: [error, always, { markers: [/] }]
globals:
$$props: false # declare the Svelte $$props object as a non-writable global variable
8 changes: 7 additions & 1 deletion package.json
Expand Up @@ -33,6 +33,8 @@
"devDependencies": {
"@sveltejs/adapter-static": "^1.0.0-next.13",
"@sveltejs/kit": "^1.0.0-next.118",
"@typescript-eslint/eslint-plugin": "^4.28.2",
"@typescript-eslint/parser": "^4.28.2",
"ava": "^3.15.0",
"dotenv": "^10.0.0",
"eslint": "^7.29.0",
Expand All @@ -44,10 +46,14 @@
"rehype-autolink-headings": "^5.1.0",
"rehype-slug": "^4.0.1",
"svelte": "^3.38.3",
"svelte-check": "^2.2.2",
"svelte-preprocess": "^4.7.4",
"svelte-toc": "^0.1.5",
"svelte2tsx": "^0.4.1",
"typescript": "^4.3.5",
"vite": "^2.3.8"
},
"publishConfig": {
"access": "public"
}
}
}
1 change: 1 addition & 0 deletions src/global.d.ts
@@ -0,0 +1 @@
/// <reference types="@sveltejs/kit" />
9 changes: 0 additions & 9 deletions src/hooks.js

This file was deleted.

15 changes: 15 additions & 0 deletions src/hooks.ts
@@ -0,0 +1,15 @@
// https://kit.svelte.dev/docs#hooks-getsession
export function getSession(): Record<string, string> {
const keys = [`ALGOLIA_APP_ID`, `ALGOLIA_SEARCH_KEY`]

for (const key of keys) {
if (!process.env[key]) {
// eslint-disable-next-line no-console
console.error(`missing secret key: ${key}`)
}
}

const session = Object.fromEntries(keys.map((key) => [key, process.env[key] as string]))

return session
}
40 changes: 22 additions & 18 deletions src/lib/Search.svelte
@@ -1,13 +1,19 @@
<script>
import { onMount, createEventDispatcher } from 'svelte'
<script lang="ts">
import { onMount, createEventDispatcher, SvelteComponent } from 'svelte'
import algoliasearch, { SearchClient } from 'algoliasearch/lite'
import SearchIcon from './SearchIcon.svelte'
import { onClickOutside } from './actions'
import type { Hit } from '@algolia/client-search'
export let appId, searchKey, indices
type SearchHit = Hit<Record<string, unknown>>
export let appId: string
export let searchKey: string
export let indices: Record<string, typeof SvelteComponent>
export let loadingStr = `Searching...`
export let noResultMsg = (query) => `No results for '${query}'`
export let resultCounter = (hits) =>
export let noResultMsg = (query: string): string => `No results for '${query}'`
export let resultCounter = (hits: SearchHit[]): string =>
hits.length > 0 ? `<span>Results: ${hits.length}<span>` : ``
export let placeholder = `Search`
export let ariaLabel = `Search`
Expand All @@ -19,12 +25,15 @@
if (!val) console.error(`Invalid ${key}: ${val}`)
}
let client, input, query, promise
let client: SearchClient
let input: HTMLInputElement
let query = ``
let promise: Promise<{ index: string | undefined; hits: SearchHit[] }[]>
onMount(() => (client = window.algoliasearch(appId, searchKey)))
onMount(() => (client = algoliasearch(appId, searchKey)))
const processHits = (hits) =>
hits.map((hit) => {
function processHits(hits: SearchHit[]) {
return hits.map((hit) => {
for (const [key, val] of Object.entries(hit)) {
if (key.endsWith(`Orig`)) continue
const processedVal =
Expand All @@ -36,25 +45,20 @@
}
return hit
})
}
async function search() {
const { results } = await client.multipleQueries(
const { results } = await client.search(
Object.keys(indices).map((indexName) => ({ indexName, query }))
)
return results.map(({ hits, index }) => ({ hits: processHits(hits), index }))
}
const src = `https://cdn.jsdelivr.net/npm/algoliasearch@latest/dist/algoliasearch-lite.umd.js`
</script>

<svelte:head>
<script async defer {src}></script>
</svelte:head>
<aside use:onClickOutside={() => (hasFocus = false)} class="svelte-algolia">
<input
type="text"
type=":stringtext"
bind:this={input}
bind:value={query}
on:keyup={() => (promise = search())}
Expand All @@ -69,7 +73,7 @@
}}
title={ariaLabel}>
<SearchIcon
alt="Search Icon"
ariaLabel="Search Icon"
height="{hasFocus ? 1.9 : 2.3}ex"
style="cursor: pointer;" />
</button>
Expand Down
14 changes: 0 additions & 14 deletions src/lib/actions.js

This file was deleted.

21 changes: 21 additions & 0 deletions src/lib/actions.ts
@@ -0,0 +1,21 @@
export function onClickOutside(
node: HTMLElement,
cb?: () => void
): { destroy(): void } {
const dispatchOnClickOutside = (event: Event) => {
const clickWasOutside = node && !node.contains(event.target as Node)

if (clickWasOutside && !event.defaultPrevented) {
node.dispatchEvent(new CustomEvent(`clickOutside`))
if (cb) cb()
}
}

document.addEventListener(`click`, dispatchOnClickOutside)

return {
destroy() {
document.removeEventListener(`click`, dispatchOnClickOutside)
},
}
}
File renamed without changes.
4 changes: 2 additions & 2 deletions src/routes/index.svx
Expand Up @@ -4,7 +4,7 @@
import Example from '../components/Example.svelte'
import GitHubCorner from '../components/GitHubCorner.svelte'

import LensIcon from '../lib/SearchIcon.svelte'
import SearchIcon from '../lib/SearchIcon.svelte'
import Docs from '../docs.svx'
</script>

Expand All @@ -24,7 +24,7 @@ Utility for server-side Algolia index updates plus a client-side search componen

## Live Demo

This is what Svelte-Algolia integrated into a nav bar might look like. Click the <LensIcon /> icon to try it out!
This is what Svelte-Algolia integrated into a nav bar might look like. Click the <SearchIcon /> icon to try it out!

<Example />

Expand Down
8 changes: 5 additions & 3 deletions svelte.config.js
@@ -1,9 +1,11 @@
import 'dotenv/config'
import adapter from '@sveltejs/adapter-static'
import { mdsvex } from 'mdsvex'
import { indexAlgolia } from './src/lib/main.js'
import fs from 'fs'

import adapter from '@sveltejs/adapter-static'
import { mdsvex } from 'mdsvex'
import preprocess from "svelte-preprocess"

import headingSlugs from 'rehype-slug'
import linkHeadings from 'rehype-autolink-headings'
import { s } from 'hastscript'
Expand Down Expand Up @@ -61,7 +63,7 @@ if (process.env.NODE_ENV === `production`) {

export default {
extensions: [`.svelte`, `.svx`],
preprocess: mdsvex({ rehypePlugins }),
preprocess: [preprocess(), mdsvex({ rehypePlugins })],
kit: {
adapter: adapter(),

Expand Down
19 changes: 19 additions & 0 deletions tsconfig.json
@@ -0,0 +1,19 @@
// https://github.com/sveltejs/language-tools/blob/master/docs/preprocessors/typescript.md
{
"compilerOptions": {
"strict": true,
"module": "es2020",
"target": "es2020",
"moduleResolution": "node", // needed for import { ... } from 'svelte' in TS files

// Svelte Preprocess cannot figure out whether you have a value or a type, so tell TypeScript
// to enforce using `import type` instead of `import` for Types.
"importsNotUsedAsValues": "error",

// To have warnings/errors of the Svelte compiler at the correct position,
// enable source maps by default.
"sourceMap": true,

"forceConsistentCasingInFileNames": true
}
}

0 comments on commit 2bffa7d

Please sign in to comment.