diff --git a/astro.config.mjs b/astro.config.mjs index 5d3c99d..e192fbd 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -2,19 +2,22 @@ import sitemap from '@astrojs/sitemap' import svelte from '@astrojs/svelte' import tailwind from '@astrojs/tailwind' import { defineConfig } from 'astro/config' - -import assetMinifier from '@playform/compress' import imageCompressor from 'astro-better-image-service' import assetCompressor from 'astro-compressor' import metadata from 'astro-meta-tags' import insights from 'astro-page-insight' import purgecss from 'astro-purgecss' + +import assetMinifier from '@playform/compress' import { FontaineTransform } from 'fontaine' /** @type {boolean} */ const isProd = process.env.NODE_ENV === 'production' -/** @type {object} */ +/** + * @type {object} + * @todo Move this to a config file. + */ const sitemapConfig = { i18n: { defaultLocale: 'fr', @@ -32,10 +35,16 @@ const assetMinifierConfig = { /** @type {number} */ const port = 4321 -/** @type {string} */ +/** + * @type {string} + * @todo Move this to a config file (at least the production URL). + */ const site = isProd ? 'https://maisonquiroga.art' : `http://localhost:${port}` -/** @type {object} */ +/** + * @type {object} + * @todo Move this to a config file. + */ const vite = { plugins: [ FontaineTransform.vite({ diff --git a/eslint.config.mjs b/eslint.config.mjs index 383bcdd..191ec37 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -6,6 +6,8 @@ import tailwind from 'eslint-plugin-tailwindcss' import neostandard from 'neostandard' import { parser } from 'typescript-eslint' +import restrictedImports from './src/config/imports-policy.mjs' + const standard = neostandard({ ignores: [ ...neostandard.resolveIgnoresFromGitignore(), @@ -24,6 +26,7 @@ export default [ ...astro.configs.recommended, ...svelte.configs['flat/recommended'], ...svelte.configs['flat/prettier'], + ...restrictedImports, { rules: { '@stylistic/comma-dangle': 'off', diff --git a/package.json b/package.json index dad30b1..9cbc29c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "@redtech/maisonquiroga", "version": "0.1.0", + "type": "module", "license": "AGPL-3.0-or-later", "private": true, "packageManager": "yarn@4.3.1", @@ -15,6 +16,7 @@ "check:eslint": "eslint .", "check:prettier": "prettylint .", "check:stylelint": "stylelint '**/*.{css,astro,svelte}'", + "check:todo": "leasot src/**/*.ts", "dev": "astro dev", "format": "run-s format:eslint format:prettier format:stylelint", "format:eslint": "yarn check:eslint --fix", @@ -55,6 +57,8 @@ "eslint-plugin-tailwindcss": "^3.17.4", "fontaine": "^0.5.0", "husky": "^9.1.4", + "leasot": "^14.4.0", + "lowdb": "^7.0.1", "neostandard": "^0.11.2", "npm-run-all2": "^6.2.2", "postcss": "^8.4.41", diff --git a/prettier.config.mjs b/prettier.config.mjs index c038b55..5a3b0a3 100644 --- a/prettier.config.mjs +++ b/prettier.config.mjs @@ -1,3 +1,6 @@ +/** @type {import('prettier').Config} */ +import sortedImports from './src/config/imports-order.mjs' + /** @type {import('prettier').Config} */ export default { // StandardJS @@ -7,61 +10,6 @@ export default { embeddedLanguageFormatting: 'auto', endOfLine: 'lf', htmlWhitespaceSensitivity: 'css', - importOrder: [ - '', - '^(@astrojs/)', - '^(astro/)', - '^(astro:)', - '^(svelte)', - '^(@\\w)', - '^(\\w)', - '^([#])', - '^([~])', - '^([&])', - '^([$])', - '^([+])', - '^([^])', - '^([@])', - '^([%])', - '^([;])', - '^([./])', - '^([../])', - '', - '', - '', - '', - '', - '^(@astrojs/)(.*)$', - '^(astro/)(.*)$', - '^(astro:)(.*)$', - '', - '^(svelte)(.*)$', - '', - '^(@\\w)(.*)$', - '^(\\w)(.*)$', - '', - '^[#/](.*)$', - '', - '^[~/](.*)$', - '', - '^[&/](.*)$', - '', - '^[$/](.*)$', - '', - '^[+/](.*)$', - '', - '^[\\^/](.*)$', - '', - '^[@/](.*)$', - '', - '^[%/](.*)$', - '', - '^[;/](.*)$', - '', - '^[./]', - '', - '^[../]' - ], insertPragma: false, jsxSingleQuote: true, printWidth: 80, @@ -84,5 +32,7 @@ export default { 'prettier-plugin-sh', 'prettier-plugin-svelte', 'prettier-plugin-tailwindcss' - ] + ], + // Sorted imports + ...sortedImports } diff --git a/src/adapters/infrastructure/db/lowdb.ts b/src/adapters/infrastructure/db/lowdb.ts new file mode 100644 index 0000000..e4d33d9 --- /dev/null +++ b/src/adapters/infrastructure/db/lowdb.ts @@ -0,0 +1,71 @@ +/** + * Lowdb adapter + * + * @module lowdb + * @todo Move types to {@link to &/ports.ts} + */ + +import type { Data, Load } from '&/ports.ts' + +import { Low } from 'lowdb' +import { JSONFile } from 'lowdb/node' + +import { map } from '$/utils/adt/maybe.ts' +import { compose } from '$/utils/fun/compose.ts' + +/** Connection to a database. */ +type Conn = Low + +/** + * Generic connect function. + * + * @typeParam A + * @param {string} path - The path used to establish the connection. + * @returns The connection object of type Conn. + */ +type Connect = (path: string) => Conn + +/** Connect to a database. */ +const connect: Connect = (path) => new Low(new JSONFile(path), {}) + +/** + * Read a value from a given connection. + * + * @typeParam A + * @param {Conn} conn - The connection to read the value from. + * @returns A function that when called, returns a Promise. + * @todo {@link null} here is an implementation detail leaked from {@link Low} + */ +type Read = (conn: Readonly>) => () => Promise + +/** Read a value from a given connection. */ +const read: Read = (conn) => async () => await conn.adapter.read() + +/** + * An indeterminacy, returning a {@link Promise}. + * + * @note We may think of a {@link Indet} as a "fp-ts/Task" or an + * "effect-ts/Effect".For us, it is less about what is to be done, as to what + * is to be known. That is, how the future unfolds, so to speak. + * @see {@link https://fr.hegel.net/f111.htm} + * @todo Make this a generic type. + * + * @todo Implement for {@link Maybe}. + * + * @todo Implement for {@link Result} (alias Either). + */ +export type Indet = () => Promise + +/** A determinacy, resolving an indeterminacy. */ +export type Det = (f: A) => (g: Indet) => Indet + +/** A determinacy, resolving an indeterminacy. */ +const det: Det, Conn, Data | null> = (f) => (g) => { + return async () => { + const result = await g() + return result ? await f(result)() : null + } +} + +/** Load data for the database. */ +export const load: Load = map(compose([det, read, connect])) diff --git a/src/adapters/infrastructure/ports.ts b/src/adapters/infrastructure/ports.ts new file mode 100644 index 0000000..6bb3e97 --- /dev/null +++ b/src/adapters/infrastructure/ports.ts @@ -0,0 +1,24 @@ +/** + * Infrastructure ports. + * + * @module ports + */ + +import type { Just, Maybe } from '$/types.ts' + +/** Data read from a database. */ +export type Data = { + [key: Readonly]: { + [key: Readonly]: { + [key: Readonly]: Readonly + } + } +} + +/** + * Load data from a database. + * + * @param {Just} path - The path from which to load the value. + * @returns {Maybe} - The value loaded from the database. + */ +export type Load = (path: Just) => Maybe diff --git a/src/app/stores/CityStore.ts b/src/adapters/stores/CityStore.ts similarity index 83% rename from src/app/stores/CityStore.ts rename to src/adapters/stores/CityStore.ts index 1cc3385..10b75b2 100644 --- a/src/app/stores/CityStore.ts +++ b/src/adapters/stores/CityStore.ts @@ -1,10 +1,12 @@ import type { Readable } from 'svelte/store' + import type { WithContext } from 'schema-dts' -import type { City } from '&/entities' + +import type { City } from '^/entities' import { get, readable } from 'svelte/store' -import { chili, france } from '$/stores/CountryStore' +import { chili, france } from '+/CountryStore' export const paris: Readable> = readable({ '@context': 'https://schema.org', diff --git a/src/app/stores/CountryStore.ts b/src/adapters/stores/CountryStore.ts similarity index 90% rename from src/app/stores/CountryStore.ts rename to src/adapters/stores/CountryStore.ts index 5a409c8..138639a 100644 --- a/src/app/stores/CountryStore.ts +++ b/src/adapters/stores/CountryStore.ts @@ -1,6 +1,8 @@ import type { Readable } from 'svelte/store' + import type { WithContext } from 'schema-dts' -import type { Country } from '&/entities' + +import type { Country } from '^/entities' import { readable } from 'svelte/store' diff --git a/src/app/stores/GeoCoordinatesStore.ts b/src/adapters/stores/GeoCoordinatesStore.ts similarity index 80% rename from src/app/stores/GeoCoordinatesStore.ts rename to src/adapters/stores/GeoCoordinatesStore.ts index acd61d7..106b424 100644 --- a/src/app/stores/GeoCoordinatesStore.ts +++ b/src/adapters/stores/GeoCoordinatesStore.ts @@ -1,10 +1,12 @@ import type { Readable } from 'svelte/store' + import type { WithContext } from 'schema-dts' -import type { GeoCoordinates } from '&/entities' + +import type { GeoCoordinates } from '^/entities' import { get, readable } from 'svelte/store' -import { adresseMaisonQuiroga } from '$/stores/PostalAddressStore' +import { adresseMaisonQuiroga } from '+/PostalAddressStore' const { name, url } = get(adresseMaisonQuiroga) diff --git a/src/app/stores/PostalAddressStore.ts b/src/adapters/stores/PostalAddressStore.ts similarity index 94% rename from src/app/stores/PostalAddressStore.ts rename to src/adapters/stores/PostalAddressStore.ts index 8c3b94e..4bebc99 100644 --- a/src/app/stores/PostalAddressStore.ts +++ b/src/adapters/stores/PostalAddressStore.ts @@ -1,6 +1,8 @@ import type { Readable } from 'svelte/store' + import type { WithContext } from 'schema-dts' -import type { PostalAddress } from '&/entities' + +import type { PostalAddress } from '^/entities' import { readable } from 'svelte/store' diff --git a/src/ui/assets/fonts/AkzidenzGrotesk-300-FR.woff2 b/src/adapters/ui/assets/fonts/AkzidenzGrotesk-300-FR.woff2 similarity index 100% rename from src/ui/assets/fonts/AkzidenzGrotesk-300-FR.woff2 rename to src/adapters/ui/assets/fonts/AkzidenzGrotesk-300-FR.woff2 diff --git a/src/ui/assets/fonts/AkzidenzGrotesk-300.otf b/src/adapters/ui/assets/fonts/AkzidenzGrotesk-300.otf similarity index 100% rename from src/ui/assets/fonts/AkzidenzGrotesk-300.otf rename to src/adapters/ui/assets/fonts/AkzidenzGrotesk-300.otf diff --git a/src/ui/assets/fonts/AkzidenzGrotesk-400-FR.woff2 b/src/adapters/ui/assets/fonts/AkzidenzGrotesk-400-FR.woff2 similarity index 100% rename from src/ui/assets/fonts/AkzidenzGrotesk-400-FR.woff2 rename to src/adapters/ui/assets/fonts/AkzidenzGrotesk-400-FR.woff2 diff --git a/src/ui/assets/fonts/AkzidenzGrotesk-400.otf b/src/adapters/ui/assets/fonts/AkzidenzGrotesk-400.otf similarity index 100% rename from src/ui/assets/fonts/AkzidenzGrotesk-400.otf rename to src/adapters/ui/assets/fonts/AkzidenzGrotesk-400.otf diff --git a/src/ui/assets/fonts/AkzidenzGrotesk-500-FR.woff2 b/src/adapters/ui/assets/fonts/AkzidenzGrotesk-500-FR.woff2 similarity index 100% rename from src/ui/assets/fonts/AkzidenzGrotesk-500-FR.woff2 rename to src/adapters/ui/assets/fonts/AkzidenzGrotesk-500-FR.woff2 diff --git a/src/ui/assets/fonts/AkzidenzGrotesk-500.otf b/src/adapters/ui/assets/fonts/AkzidenzGrotesk-500.otf similarity index 100% rename from src/ui/assets/fonts/AkzidenzGrotesk-500.otf rename to src/adapters/ui/assets/fonts/AkzidenzGrotesk-500.otf diff --git a/src/ui/assets/fonts/AkzidenzGrotesk-700-FR.woff2 b/src/adapters/ui/assets/fonts/AkzidenzGrotesk-700-FR.woff2 similarity index 100% rename from src/ui/assets/fonts/AkzidenzGrotesk-700-FR.woff2 rename to src/adapters/ui/assets/fonts/AkzidenzGrotesk-700-FR.woff2 diff --git a/src/ui/assets/fonts/AkzidenzGrotesk-700.otf b/src/adapters/ui/assets/fonts/AkzidenzGrotesk-700.otf similarity index 100% rename from src/ui/assets/fonts/AkzidenzGrotesk-700.otf rename to src/adapters/ui/assets/fonts/AkzidenzGrotesk-700.otf diff --git a/src/ui/assets/fonts/AkzidenzGrotesk-900-FR.woff2 b/src/adapters/ui/assets/fonts/AkzidenzGrotesk-900-FR.woff2 similarity index 100% rename from src/ui/assets/fonts/AkzidenzGrotesk-900-FR.woff2 rename to src/adapters/ui/assets/fonts/AkzidenzGrotesk-900-FR.woff2 diff --git a/src/ui/assets/fonts/AkzidenzGrotesk-900.otf b/src/adapters/ui/assets/fonts/AkzidenzGrotesk-900.otf similarity index 100% rename from src/ui/assets/fonts/AkzidenzGrotesk-900.otf rename to src/adapters/ui/assets/fonts/AkzidenzGrotesk-900.otf diff --git a/src/ui/assets/images/logo.jpg b/src/adapters/ui/assets/images/logo.jpg similarity index 100% rename from src/ui/assets/images/logo.jpg rename to src/adapters/ui/assets/images/logo.jpg diff --git a/src/ui/assets/images/roberto.jpg b/src/adapters/ui/assets/images/roberto.jpg similarity index 100% rename from src/ui/assets/images/roberto.jpg rename to src/adapters/ui/assets/images/roberto.jpg diff --git a/src/ui/assets/styles/_base.css b/src/adapters/ui/assets/styles/_base.css similarity index 100% rename from src/ui/assets/styles/_base.css rename to src/adapters/ui/assets/styles/_base.css diff --git a/src/ui/assets/styles/_font.css b/src/adapters/ui/assets/styles/_font.css similarity index 100% rename from src/ui/assets/styles/_font.css rename to src/adapters/ui/assets/styles/_font.css diff --git a/src/ui/assets/styles/_text.css b/src/adapters/ui/assets/styles/_text.css similarity index 100% rename from src/ui/assets/styles/_text.css rename to src/adapters/ui/assets/styles/_text.css diff --git a/src/ui/assets/styles/global.css b/src/adapters/ui/assets/styles/global.css similarity index 100% rename from src/ui/assets/styles/global.css rename to src/adapters/ui/assets/styles/global.css diff --git a/src/ui/components/Logo.astro b/src/adapters/ui/atoms/Logo.astro similarity index 100% rename from src/ui/components/Logo.astro rename to src/adapters/ui/atoms/Logo.astro diff --git a/src/ui/components/Bio.astro b/src/adapters/ui/blocks/Bio.astro similarity index 100% rename from src/ui/components/Bio.astro rename to src/adapters/ui/blocks/Bio.astro diff --git a/src/ui/components/BioArticle.svelte b/src/adapters/ui/blocks/BioArticle.svelte similarity index 100% rename from src/ui/components/BioArticle.svelte rename to src/adapters/ui/blocks/BioArticle.svelte diff --git a/src/ui/components/BioFigure.astro b/src/adapters/ui/blocks/BioFigure.astro similarity index 95% rename from src/ui/components/BioFigure.astro rename to src/adapters/ui/blocks/BioFigure.astro index c8d147b..c046a5f 100644 --- a/src/ui/components/BioFigure.astro +++ b/src/adapters/ui/blocks/BioFigure.astro @@ -3,7 +3,7 @@ import { Image } from 'astro:assets' import resolveConfig from 'tailwindcss/resolveConfig' -import tailwindConfig from '#/tailwind.config' +import tailwindConfig from '=/tailwind.config' const { theme } = resolveConfig(tailwindConfig) const { screens } = theme diff --git a/src/ui/components/HeaderTitle.svelte b/src/adapters/ui/blocks/HeaderTitle.svelte similarity index 100% rename from src/ui/components/HeaderTitle.svelte rename to src/adapters/ui/blocks/HeaderTitle.svelte diff --git a/src/ui/components/Meta/MetaGeo.svelte b/src/adapters/ui/blocks/Meta/MetaGeo.svelte similarity index 83% rename from src/ui/components/Meta/MetaGeo.svelte rename to src/adapters/ui/blocks/Meta/MetaGeo.svelte index bef50cd..824ff54 100644 --- a/src/ui/components/Meta/MetaGeo.svelte +++ b/src/adapters/ui/blocks/Meta/MetaGeo.svelte @@ -9,8 +9,8 @@