=> {
+ if (
+ typeof window === 'undefined'
+ ? !nodeCrypto || !nodeCrypto.createHash
+ : !cryptoSubtle
+ ) {
+ // if (process.env.NODE_ENV !== 'production') {
+ // console.warn(
+ // '[@urql/exchange-persisted-fetch]: The ' +
+ // (typeof window === 'undefined'
+ // ? 'Node Crypto'
+ // : 'window.crypto.subtle') +
+ // ' API is not available.\n' +
+ // 'This is an unexpected error. Please report it by filing a GitHub Issue.'
+ // );
+ // }
+
+ return Promise.resolve('');
+ }
+
+ // Node.js support
+ if (typeof window === 'undefined') {
+ return Promise.resolve(
+ '' + nodeCrypto.createHash('sha256').update(query).digest('hex')
+ );
+ }
+
+ let buf: Uint8Array;
+ if (typeof TextEncoder !== 'undefined') {
+ buf = new TextEncoder().encode(query);
+ } else {
+ buf = new Uint8Array(query.length);
+ for (let i = 0, l = query.length; i < l; i++) {
+ // NOTE: We assume that the input GraphQL Query only uses UTF-8 at most
+ // since GraphQL mostly consists of ASCII, this is completely fine
+ buf[i] = query.charCodeAt(i);
+ }
+ }
+
+ const out = await sha256Browser(buf);
+
+ let hash = '';
+ for (let i = 0, l = out.length; i < l; i++) {
+ const hex = out[i].toString(16);
+ hash += '00'.slice(0, Math.max(0, 2 - hex.length)) + hex;
+ }
+
+ return hash;
+};
diff --git a/src/generated/.gitignore b/src/generated/.gitignore
new file mode 100644
index 000000000..5bbc7c5f7
--- /dev/null
+++ b/src/generated/.gitignore
@@ -0,0 +1,2 @@
+graphql.schema.urql.json
+graphql.ts
diff --git a/src/generated/index.ts b/src/generated/index.ts
new file mode 100644
index 000000000..acae838cc
--- /dev/null
+++ b/src/generated/index.ts
@@ -0,0 +1 @@
+export * from './graphql';
diff --git a/src/global.d.ts b/src/global.d.ts
new file mode 100644
index 000000000..5024a5f33
--- /dev/null
+++ b/src/global.d.ts
@@ -0,0 +1,11 @@
+///
+///
+///
+
+/* eslint-disable */
+declare module "*.json" {
+ const value: any;
+ export default value;
+}
+
+declare module '@iconify/svelte';
diff --git a/src/gql/home/mods.graphql b/src/gql/home/mods.graphql
new file mode 100644
index 000000000..0afd5db29
--- /dev/null
+++ b/src/gql/home/mods.graphql
@@ -0,0 +1,13 @@
+query GetMods ($offset: Int!, $limit: Int!) {
+ getMods(filter: { limit: $limit, offset: $offset }) {
+ count
+ mods {
+ id
+ name
+ logo
+ views
+ downloads
+ short_description
+ }
+ }
+}
diff --git a/src/lib/home/NotableCard.svelte b/src/lib/home/NotableCard.svelte
new file mode 100644
index 000000000..edda95f32
--- /dev/null
+++ b/src/lib/home/NotableCard.svelte
@@ -0,0 +1,23 @@
+
+
+
+
+
+
diff --git a/src/lib/mods/ModCard.svelte b/src/lib/mods/ModCard.svelte
new file mode 100644
index 000000000..6c176f3e7
--- /dev/null
+++ b/src/lib/mods/ModCard.svelte
@@ -0,0 +1,43 @@
+
+
+
+
+

+
+
+
+
{mod.name}
+
+ {mod.views}
+ {mod.downloads}
+
+
+
+
{mod.short_description}
+
+
+
+
+
+
diff --git a/src/lib/mods/ModGrid.svelte b/src/lib/mods/ModGrid.svelte
new file mode 100644
index 000000000..27dc83dc5
--- /dev/null
+++ b/src/lib/mods/ModGrid.svelte
@@ -0,0 +1,48 @@
+
+
+{#if totalMods}
+
+{/if}
+
+{#if $mods.fetching}
+ Loading...
+{:else if $mods.error}
+ Oh no... {$mods.error.message}
+{:else}
+
+ {#each $mods.data.getMods.mods as mod}
+
+ {/each}
+
+{/if}
+
+{#if totalMods}
+
+{/if}
diff --git a/src/lib/utils/PageControls.svelte b/src/lib/utils/PageControls.svelte
new file mode 100644
index 000000000..91f23ab23
--- /dev/null
+++ b/src/lib/utils/PageControls.svelte
@@ -0,0 +1,55 @@
+
+
+{#if $currentPage > startPage}
+
+
+{/if}
+
+{#if $currentPage > startPage + 1}
+ ...
+{/if}
+
+{#if $currentPage > startPage}
+
+{/if}
+
+
+
+{#if $currentPage < totalPages}
+
+{/if}
+
+{#if $currentPage < totalPages - 1}
+ ...
+{/if}
+
+{#if $currentPage < totalPages}
+
+
+{/if}
+
+
diff --git a/src/routes/$layout.svelte b/src/routes/$layout.svelte
new file mode 100644
index 000000000..34f9cc2d5
--- /dev/null
+++ b/src/routes/$layout.svelte
@@ -0,0 +1,14 @@
+
+ SMR
+
+
+
+
+
+
+
diff --git a/src/routes/_global.postcss b/src/routes/_global.postcss
new file mode 100644
index 000000000..9f228fc5a
--- /dev/null
+++ b/src/routes/_global.postcss
@@ -0,0 +1,14 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+body {
+ @apply antialiased text-gray-600 dark:text-gray-300 bg-gray-100 dark:bg-gray-900;
+ @apply leading-normal tracking-normal text-base font-normal break-words;
+ @apply text-base lg:text-xl;
+ font-family: Roboto, Helvetica Neue, sans-serif;
+}
+
+main {
+ @apply p-8 pt-32 md:pt-24 mx-auto;
+}
diff --git a/src/routes/index.svelte b/src/routes/index.svelte
new file mode 100644
index 000000000..8c7015937
--- /dev/null
+++ b/src/routes/index.svelte
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/static/assets/android-chrome-192x192.png b/static/assets/android-chrome-192x192.png
new file mode 100644
index 000000000..2ea50d023
Binary files /dev/null and b/static/assets/android-chrome-192x192.png differ
diff --git a/static/assets/android-chrome-512x512.png b/static/assets/android-chrome-512x512.png
new file mode 100644
index 000000000..1292c45e5
Binary files /dev/null and b/static/assets/android-chrome-512x512.png differ
diff --git a/static/assets/apple-touch-icon.png b/static/assets/apple-touch-icon.png
new file mode 100644
index 000000000..c965dcd34
Binary files /dev/null and b/static/assets/apple-touch-icon.png differ
diff --git a/static/assets/browserconfig.xml b/static/assets/browserconfig.xml
new file mode 100644
index 000000000..21e6cbc29
--- /dev/null
+++ b/static/assets/browserconfig.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+ #da8517
+
+
+
diff --git a/static/assets/favicon-16x16.png b/static/assets/favicon-16x16.png
new file mode 100644
index 000000000..f7ba0a961
Binary files /dev/null and b/static/assets/favicon-16x16.png differ
diff --git a/static/assets/favicon-32x32.png b/static/assets/favicon-32x32.png
new file mode 100644
index 000000000..b1042c5f1
Binary files /dev/null and b/static/assets/favicon-32x32.png differ
diff --git a/static/assets/favicon.ico b/static/assets/favicon.ico
new file mode 100644
index 000000000..f61384d23
Binary files /dev/null and b/static/assets/favicon.ico differ
diff --git a/static/assets/mstile-150x150.png b/static/assets/mstile-150x150.png
new file mode 100644
index 000000000..53254db43
Binary files /dev/null and b/static/assets/mstile-150x150.png differ
diff --git a/static/assets/safari-pinned-tab.svg b/static/assets/safari-pinned-tab.svg
new file mode 100644
index 000000000..5412ec044
--- /dev/null
+++ b/static/assets/safari-pinned-tab.svg
@@ -0,0 +1,147 @@
+
+
+
diff --git a/static/favicon.ico b/static/favicon.ico
new file mode 100644
index 000000000..d75d248ef
Binary files /dev/null and b/static/favicon.ico differ
diff --git a/static/images/no_image.png b/static/images/no_image.png
new file mode 100644
index 000000000..31786b1b8
Binary files /dev/null and b/static/images/no_image.png differ
diff --git a/static/manifest.json b/static/manifest.json
new file mode 100644
index 000000000..62928c127
--- /dev/null
+++ b/static/manifest.json
@@ -0,0 +1,21 @@
+{
+ "name": "Satisfactory Mod Repo",
+ "short_name": "SMR",
+ "theme_color": "#da8517",
+ "background_color": "#da8517",
+ "display": "standalone",
+ "scope": "/",
+ "start_url": "/",
+ "icons": [
+ {
+ "src": "/assets/android-chrome-192x192.png?v=69P26YMB35",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/assets/android-chrome-512x512.png?v=69P26YMB35",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ]
+}
diff --git a/static/robots.txt b/static/robots.txt
new file mode 100644
index 000000000..e9e57dc4d
--- /dev/null
+++ b/static/robots.txt
@@ -0,0 +1,3 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
+Disallow:
diff --git a/svelte.config.cjs b/svelte.config.cjs
new file mode 100644
index 000000000..4eed451f2
--- /dev/null
+++ b/svelte.config.cjs
@@ -0,0 +1,37 @@
+const sveltePreprocess = require('svelte-preprocess');
+const adapterNode = require('@sveltejs/adapter-node');
+const adapterStatic = require('@sveltejs/adapter-static');
+
+/** @type {import('@sveltejs/kit').Config} */
+module.exports = {
+ // Consult https://github.com/sveltejs/svelte-preprocess
+ // for more information about preprocessors
+ preprocess: sveltePreprocess({
+ postcss: true
+ }),
+ kit: {
+ // By default, `npm run build` will create a standard Node app.
+ // You can create optimized builds for different platforms by
+ // specifying a different adapter
+ adapter: process.env.SVELTE_ADAPTER === 'node' ? adapterNode({
+ out: 'build/node'
+ }) : adapterStatic({
+ pages: 'build/static',
+ assets: 'build/static'
+ }),
+
+ ssr: process.env.SVELTE_ADAPTER === 'node',
+
+ // hydrate the element in src/app.html
+ target: '#svelte',
+
+ vite: {
+ ssr: {
+ noExternal: ['node-fetch']
+ },
+ optimizeDeps: {
+ exclude: ["@urql/svelte"]
+ }
+ }
+ }
+};
diff --git a/tailwind.config.cjs b/tailwind.config.cjs
new file mode 100644
index 000000000..15a12c710
--- /dev/null
+++ b/tailwind.config.cjs
@@ -0,0 +1,29 @@
+const { tailwindExtractor } = require('tailwindcss/lib/lib/purgeUnusedStyles');
+const colors = require('tailwindcss/colors');
+
+module.exports = {
+ purge: {
+ content: [
+ './src/**/*.html',
+ './src/**/*.svelte'
+ ],
+ options: {
+ defaultExtractor: (content) => [
+ ...tailwindExtractor(content),
+ // Match Svelte class: directives (https://github.com/tailwindlabs/tailwindcss/discussions/1731)
+ ...[...content.matchAll(/(?:class:)*([\w\d-/:%.]+)/gm)].map(([_match, group, ..._rest]) => group),
+ ],
+ keyframes: true,
+ },
+ },
+ darkMode: 'class',
+ theme: {
+ colors: {
+ gray: colors.trueGray,
+ }
+ },
+ variants: {
+ extend: {},
+ },
+ plugins: [],
+};
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 000000000..7d2e2894a
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,28 @@
+{
+ "compilerOptions": {
+ "moduleResolution": "node",
+ "target": "es2018",
+ /**
+ 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",
+ "isolatedModules": true,
+ /**
+ To have warnings/errors of the Svelte compiler at the correct position,
+ enable source maps by default.
+ */
+ "sourceMap": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "baseUrl": ".",
+ "allowJs": true,
+ "checkJs": true,
+ "paths": {
+ "$app/*": [".svelte/dev/runtime/app/*", ".svelte/build/runtime/app/*"],
+ "$lib/*": ["src/lib/*"]
+ }
+ },
+ "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"]
+}