open-index/open-npm huggingface dataset:
npm package: @smoothless/appwrite-db-docs
Description: MCP server that generates database documentation from appwrite.config.json files
Author: MCP Community
Latest version: 0.1.1

# Appwrite DB Documentation MCP Server

An MCP (Model Context Protocol) server that automatically generates database documentation from Appwrite configuration files.

## Overview

This MCP server scans your codebase for `appwrite.config.json` files, extracts database schema information, and generates a `DB.md` file with a clean summary of your database structure.

## Features

- 🔍 **Auto-discovery**: Locates `appwrite.config.json` files in your project
- 📊 **Schema parsing**: Extracts database collections, attributes, and relationships
- 📝 **Clean documentation**: Generates simple, readable markdown tables
- 🔄 **Format support**: Handles both modern and legacy Appwrite config formats

## Installation

### Via MCP Registry (Recommended)

Add this server to your Claude Desktop MCP settings:

```json
{
  "mcpServers": {
    "appwrite-db-docs": {
      "command": "npx",
      "args": ["@smoothless/appwrite-db-docs"],
      "env": {}
    }
  }
}
```

### Manual Installation

```bash
npm install @smoothless/appwrite-db-docs
```

Then add to your MCP settings:

```json
{
  "mcpServers": {
    "appwrite-db-docs": {
      "command": "node",
      "args": ["node_modules/@smoothless/appwrite-db-docs/dist/index.js"],
      "env": {}
    }
  }
}
```

## Usage

Once configured, you can use the server in Claude Desktop by asking it to generate database documentation:

- "Generate database documentation for my project"
- "Create a DB.md file from my Appwrite config"
- "Document my database schema"

## Tools Provided

- **`generate_db_docs`**: Finds appwrite.config.json and generates DB.md documentation
  - `project_root` (required): Root directory to search for appwrite.config.json
  - `output_path` (optional): Custom path for DB.md output

## Example Output

The server generates clean, simple documentation like this:

```markdown
# Database Structure

- **Name**: my_database
- **ID**: `abc123`

| Table | Columns | Row Security |
|-------|---------|--------------|
| **users** | name (string), email (string), created_at (datetime) | ✅ |
| **posts** | title (string), content (string), user_id (relationship) | ❌ |
```

## Requirements

- Node.js 18.0.0 or higher
- Appwrite project with `appwrite.config.json` file

## Development

```bash
git clone https://github.com/modelcontextprotocol/servers.git
cd servers/src/appwrite-db-docs
npm install
npm run build
npm run dev
```

## License

MIT
npm package: @smootok/vcloud
Description: Retrieve the function location from it reference in NodeJS.
Author: 4D SAS
Latest version: 0.1.12

### Example

```javascript
const { Client } = require('@smootok/vcloud');

(async () => {
  const c = new Client({
    url: 'https://mycloud.vmware.com',
    org: 'MyOrg',
    user: 'admin',
    pass: 'P@$$w0Rd',
  });

  // Optional: Initialize the token
  c.setToken({
    token: 'TOKEN_HERE',
    type: 'Bearer',
  });

  const session = await c.session.getCurrent();
  console.log(session.roles);
  const orgs = await c.org.getCurrent();
  console.log(orgs);
  const [{ id }] = orgs;
  console.log(id);
  const org = await c.org.getById(id);
  console.log(org);
})();
```
npm package: @smoovy/component
Description: Simple component manager
Author: Davide Perozzi
Latest version: 0.2.6
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

# @smoovy/component
[![Version](https://flat.badgen.net/npm/v/@smoovy/component)](https://www.npmjs.com/package/@smoovy/component) ![Size](https://flat.badgen.net/bundlephobia/minzip/@smoovy/component)

Very basic component manager

## Installation
```sh
npm install --save @smoovy/component
```

## Basic usage
every properties are static, so you can't use multiple managers in different scopes. To create a component simply use the `@component` decorator like this:

```ts
import { component } from '@smoovy/component';

@component({
  // this is a simple `querySelectorAll` call
  selector: 'footer'
})
export class Footer {
  public constructor(
    protected element: HTMLElement
  ) {
    // do init stuff with the element
  }
}
```

## Lifecycle
The lifecycle is straight forward: Component gets created -> Component gets destroyed. In order to capture the destroy event and do some cleanup tasks, use the interface `OnDestroy`:

```ts
@component({
  selector: 'footer'
})
export class Footer implements OnDestroy {
  public constructor(
    protected element: HTMLElement
  ) {
    this.element.style.display = 'block';
  }

  public onDestroy() {
    this.element.style.display = null;
  }
}
```

## Conditional rendering
Sometimes you don't want a component to be initialized. E.g. it's only an animation for desktop devices with a screen size bigger than 1024px. You can add a condition to the component initialization like this:

```ts
@component({
  ...
  condition: () => window.innerWidth > 1024
})
export class Footer {
  ...
}
```

## Update components
Sometimes you need to refresh the component state. For instance if the route hase changed. You want to get rid of all the old components and inject the new ones:

```ts
import { ComponentManager } from '@smoovy/component';

// since there can only be one manager the update is quit simple
ComponentManager.update();

// only update components inside this scope element
// otherwise the root will be used, which is `document.body`
ComponentManager.update(document.querySelector('footer'));

// do not remove old components. Keep them running, even
// if they're not in the dom. This can be usefule if you
// have animations handled by components that are no longer
// in the dom and still need some time
ComponentManager.update(document.body, false);
setTimeout(() => ComponentManager.update(document.body), 200);
```

## Development commands
```js
// Serve with parcel
npm run serve

// Build with rollup
npm run build

// Run Jest unit tests
npm run test

// Run TSLinter
npm run lint
```

## License
See the [LICENSE](../../LICENSE) file for license rights and limitations (MIT).
npm package: @smoovy/emitter
Description: Simple event emitter
Author: Davide Perozzi
Latest version: 1.1.0

# @smoovy/emitter
[![Version](https://flat.badgen.net/npm/v/@smoovy/emitter)](https://www.npmjs.com/package/@smoovy/emitter) ![Size](https://flat.badgen.net/bundlephobia/minzip/@smoovy/emitter)

## Installation
```sh
yarn add @smoovy/emitter
```
or
```sh
npm install --save @smoovy/emitter
```

## The event emitter
Import the emitter as usual:
```js
import { EventEmitter } from '@smoovy/emitter';
```

### Usage
To use the event emitter you can either create a new instance directly or use it as a parent class.

```js
const emitter = new EventEmitter();
// or
class UltraFancyEmitter extends EventEmitter {}
```

### Emitting events
You have multiple options when it comes to the emission of events:

```js
// Emit a single value
emitter.emit('eventName', 'A random string');

// Emit an other data type (object)
emitter.emit('eventName', { name: 'Mistadobalina' });

// Emit multiple events with different data types
emitter.emit({
  eventName1: 'Some data',
  eventName2: [ 1, 2, 3, 4 ]
});
```

### Listening/Unlistening for events
Listening to events is pretty simple:

```js
emitter.on('eventName', (data) => {
  // Handle your data
});
```

To unlisten you have two options:
```js
const listener = (data) => {};
const unlisten = emitter.on('eventName', listener);

// Unlisten from callback or...
unlisten();

// Unlisten the old-fashioned way
emitter.off('eventName', listener);
```

When you have many listeners going wild in your application, you can use this litte helper function to stack those:

```js
import { listenCompose } from '@smoovy/listener';

const unlisten = listenCompose(
  emitter.on('eventName1', () => {}),
  emitter.on('eventName2', () => {}),
  emitter.on('eventName3', () => {})
);

// Easily unsubcribe from all simultaneously
unlisten();
```
> `listenCompose` simply merges all "unsubscribe callbacks" into one

### Reflecting events
Reflect events to a different emitter. Muted events will not be reflects:
```js
const reflectedEmitter = new Emitter();

// Reflect events to reflectedEmitter
emitter.reflectEvents(reflectedEmitter);

// Listen for events
reflectedEmitter.on('eventName1', (msg) => console.log(msg));

// Dispatch event in base emitter
emitter.emit('eventName1', 'reflected'); // Displays 'reflected'

// Remove reflected emitters
emitter.unreflectEvents();
```

## License
See the [LICENSE](../../LICENSE) file for license rights and limitations (MIT).
npm package: @smoovy/grid
Description: scrollable infinite grid handler
Author: Davide Perozzi
Latest version: 0.0.8

# @smoovy/grid
[![Version](https://flat.badgen.net/npm/v/@smoovy/grid)](https://www.npmjs.com/package/@smoovy/grid) ![Size](https://flat.badgen.net/bundlephobia/minzip/@smoovy/grid)

## Installation
```sh
yarn add @smoovy/grid
```
or
```sh
npm install --save @smoovy/grid
```

## Development commands
```js
yarn dev
yarn build
yarn test
```

## License
See the [LICENSE](../../LICENSE) file for license rights and limitations (MIT).
npm package: @smoovy/listener
Description: Helpers for listening when it gets too verbose to hear
Author: Davide Perozzi
Latest version: 1.0.2

# @smoovy/listener
[![Version](https://flat.badgen.net/npm/v/@smoovy/listener)](https://www.npmjs.com/package/@smoovy/listener) ![Size](https://flat.badgen.net/bundlephobia/minzip/@smoovy/listener)

Very simple subscribe/unsubscribe system.

## Installation
```sh
yarn add @smoovy/listener
```
or
```
npm install --save @smoovy/listener
```

## Usage
Listen to elements

```js
import { listen } from '@smoovy/listener';

// single type
listen(window, 'mousemove', event => console.log(event));

// multi type
listen(document.body, ['mouseup', 'mousecancel'], event => console.log(event));
```

Unlistening from events

```js
const unlisten = listen(window, 'mousemove', event => console.log(event));

// to unlisten from window mousemove simply call the unlisten function
unlisten();
```

In case you have many listeners and want to unsubscribe/unlisten from all at once,
you can use the `listenCompose` helper function:

```js
import { listen, listenCompose } from '@smoovy/listener';

const unlisten = listenCompose(
  listen(window, 'mousemove', event => console.log(event)),
  listen(window, 'click', event => console.log(event)),

  // custom callback on unlisten
  () => console.log('all listeners are now inactive')
);

unlisten();
```

## License
See the [LICENSE](../../LICENSE) file for license rights and limitations (MIT).
npm package: @smoovy/router
Description: Simple router
Author: Davide Perozzi
Latest version: 1.2.18

# @smoovy/router
[![Version](https://flat.badgen.net/npm/v/@smoovy/router)](https://www.npmjs.com/package/@smoovy/router) ![Size](https://flat.badgen.net/bundlephobia/minzip/@smoovy/router)

A simple router for the browser with features like caching, preloading and page transitions.

## Installation
```sh
npm install --save @smoovy/router
```

## Usage
Import the router as usual and initialize it wit a base url:
```js
import { Router } from '@smoovy/router';

const router = new Router();
```

... TBA

## License
See the [LICENSE](../../LICENSE) file for license rights and limitations (MIT).
npm package: @smoovy/scroller-shared
Description: Scroller shared components
Author: Davide Perozzi
Latest version: 0.0.17
Deprecated: Moved to @smoovy/scroller

# @smoovy/scroller-shared
[![Version](https://flat.badgen.net/npm/v/@smoovy/scroller-shared)](https://www.npmjs.com/package/@smoovy/scroller-shared) ![Size](https://flat.badgen.net/bundlephobia/minzip/@smoovy/scroller-shared)

Some base components for a basic scroller.

## Installation
```sh
npm install --save @smoovy/scroller-shared
```

## Usage
Choose the component you want to add to your scroller module and simply include it. E.g.:
```js
import { MouseWheelInput } from '@smoovy/scroller-shared';
```

## Inputs
| Class | Config key | Options
| - | - | - |
| MouseWheelInput | mouseWheel | `target: HTMLElement`<br>`multiplier: number`<br>`multiplierFirefox: number`
| TouchSwipeInput | touchSwipe | `target: HTMLElement`<br>`multiplier: number`

## Transformers
| Class | Config key | Options
| - | - | - |
| ClampTransformer | clamp | -

## Outputs
| Class | Config key | Options
| - | - | - |
| CssTransformOutput | cssTransform | `sectionSelector: string`<br>`sectionPadding: number`<br>`firefoxFix: boolean`

## Modularity
To reduce the final bundle size even more, you can only import the components you're really using. E.g.:

```js
import { MouseWheelInput } from '@smoovy/scroller-shared/m/inputs/mouse-wheel-input';
```

## Development commands
```js
// Serve with parcel
npm run serve

// Build with rollup
npm run build

// Run Jest unit tests
npm run test

// Run TSLinter
npm run lint
```

## License
See the [LICENSE](../../LICENSE) file for license rights and limitations (MIT).
npm package: @smoovy/scroller-tween
Description: Scroller tween module
Author: Davide Perozzi
Latest version: 0.0.17
Deprecated: Moved to @smoovy/scroller

# @smoovy/scroller-tween
[![Version](https://flat.badgen.net/npm/v/@smoovy/scroller-tween)](https://www.npmjs.com/package/@smoovy/scroller-tween) ![Size](https://flat.badgen.net/bundlephobia/minzip/@smoovy/scroller-tween)

A tween-based scrolling module for [@smoovy/scroller-core](../scroller-core)

## Installation
```sh
npm install --save @smoovy/scroller-tween
```

## Usage
Import the tween module and expose it in your scroller:
```js
import { Scroller } from '@smoovy/scroller-core';
import { ScrollerTweenModule } from '@smoovy/scroller-tween';

class YourScroller extends Scroller {
  get moduleCtor() {
    return ScrollerTweenModule;
  }
}
```

## Transformers
| Class | Config key | Options
| - | - | - |
| TweenTransformer | tween | `duration: number`<br>`easing: EasingImpl`

## Development commands
```js
// Serve with parcel
npm run serve

// Build with rollup
npm run build

// Run Jest unit tests
npm run test

// Run TSLinter
npm run lint
```

## License
See the [LICENSE](../../LICENSE) file for license rights and limitations (MIT).
npm package: @smoovy/ticker
Description: Simple and easy-to-use ticker
Author: Davide Perozzi
Latest version: 1.0.4

# @smoovy/ticker
[![Version](https://flat.badgen.net/npm/v/@smoovy/ticker)](https://www.npmjs.com/package/@smoovy/ticker) ![Size](https://flat.badgen.net/bundlephobia/minzip/@smoovy/ticker)

A simple ticker using `requestAnimationFrame`.

## Installation
```sh
yarn add @smoovy/ticker
```
or
```sh
npm install --save @smoovy/ticker
```

## Usage
Import the ticker as usual:
```js
import { Ticker } from '@smoovy/ticker';
```

### Creating a ticker
```js
const ticker = new Ticker();
```

### Listening for the tick
Everytime you start listening for the tick, the ticker creates a new "thread",
which you can control:
```js
const thread = ticker.add(delta => {
  // Animate with delta value
});
```
> The delta value is the time difference to the tick before in milliseconds

To introduce the last two parameters passed to the callback, here's an example on how to kill a thread after 2 seconds:
```js
const thread = ticker.add((delta, time, kill) => {
  if (time >= 2000) {
    kill();
  }
});
```
You can also kill it like this:
```js
setTimeout(() => thread.kill(), 2000);
```
> Once the thread is marked as dead it will be removed on the next animation frame. After that, the reference will be removed.

### Overriding the tick automation
If you want to execute the tick function manually, you can enable the `override` flag. This prevents the internal ticking, after at least one thread is available:
```js
ticker.override = true;
```
You can then call the `tick` method manually:
```js
function tick(time) {
  ticker.tick(
    1    /** A static delta value */,
    time /** Optional time value */
  );

  requestAnimationFrame(tick);
};

requestAnimationFrame(tick);
```

## License
See the [LICENSE](../../LICENSE) file for license rights and limitations (MIT).
npm package: @smoovy/utils
Description: Some basic functionality to make better websites
Author: Davide Perozzi
Latest version: 1.0.3

# @smoovy/utils
[![Version](https://flat.badgen.net/npm/v/@smoovy/utils)](https://www.npmjs.com/package/@smoovy/utils) ![Size](https://flat.badgen.net/bundlephobia/minzip/@smoovy/utils)

These are just some utilities I need for my websites. I think they're pretty self-explanatory. So you can just click through the files to find out more!

## Installation
```sh
yarn add @smoovy/utils
```
or
```sh
npm install --save @smoovy/utils
```

## License
See the [LICENSE](../../LICENSE) file for license rights and limitations (MIT).
npm package: @smoozzy/app
Description: Bootstrap for Vue app
Author: Smoozzy Code
Latest version: 0.6.0

# Smoozzy App

This project is a bootstrap for Vue applications. It's similar to `createApp` from Vue 3 (see proposal [Global mounting/configuration API change](https://github.com/vuejs/rfcs/pull/29)).

The bootstrap creates a Vue application with the following plugins and extensions:

- [Vue Router](http://router.vuejs.org/)
- [Vuex](https://vuex.vuejs.org)


## Basic application example

```javascript
import bootstrap from '@smoozzy/app';

bootstrap({
    router: { /* Router configuration */ },
    store: { /* Vuex configuration */ },
}).$mount('#app');
```


## Documentation

You can read detailed [documentation](./docs/index.md)

1. [Overview](./docs/01-overview.md)
2. [Vue plugins](./docs/02-vue-plugins.md)
3. [Modules](./docs/03-modules.md)
4. Modals
5. I18n
6. Example
7. [Bootstrap from scratch](./docs/07-from-scratch.md)
8. [Development guide](./docs/08-development.md)


## Issues

If you found bug or unexpected behavior feel free to [report issue](../../issues)


## Changelog

Detailed changes for each release are documented in the [release notes](./CHANGELOG.md)


## Development

Please read [development guide](./docs/08-development.md)


## License

[MIT](http://opensource.org/licenses/MIT)
npm package: @smoozzy/eslint-config
Description: Shareable config for Smoozzy projects
Author: Smoozzy Code
Latest version: 0.3.0

# Smoozzy ESLint Config

Shareable config for Smoozzy projects


## How to use

Install ESLint

```sh
npm install eslint @smoozzy/eslint-config
```

Create config `.eslintrc.js`

```javascript
module.exports = {
    root: true,

    env: {
        browser: true,
    },

    parserOptions: {
        ecmaVersion: 2018,
        sourceType: 'module',
    },

    extends: [
        '@smoozzy/eslint-config',
    ],
};

```


## ESLint and Plugins

* [ESLint](https://eslint.org/docs/rules/) (v5.0+)
* [Jest](https://github.com/jest-community/eslint-plugin-jest) (v23.0+)
* [Jest Formatting](https://github.com/dangreenisrael/eslint-plugin-jest-formatting) (v1.0+)
* [Vue](https://github.com/vuejs/eslint-plugin-vue) (v5.0+)


### Jest plugin

You can add Jest version explicitly to config file or the config tries to detect Jest version automatically

```javascript
module.exports = {
    // ...

    settings: {
        jest: {
            version: 26,  
        },
    },
};
```


## Further Reading

__ECMAScript features sets__

* [Speaking JavaScript](http://speakingjs.com/es5/) by Axel Rauschmayer (ES5)
* [Exploring ES6](https://exploringjs.com/es6/) by Axel Rauschmayer (ES6)
* [ECMAScript 2016: the final feature set](https://2ality.com/2016/01/ecmascript-2016.html) (ES7)
* [ECMAScript 2017: the final feature set](https://2ality.com/2016/02/ecmascript-2017.html)
* [ECMAScript 2018: the final feature set](https://2ality.com/2017/02/ecmascript-2018.html)
* [ECMAScript 2019: the final feature set](https://2ality.com/2018/02/ecmascript-2019.html)
* [ECMAScript 2020: the final feature set](https://2ality.com/2019/12/ecmascript-2020.html)

__ESLint__

* [Awesome ESLint](https://github.com/dustinspecker/awesome-eslint)
* [Configuring ESLint](https://eslint.org/docs/user-guide/configuring)
* [Shareable Configs](https://eslint.org/docs/developer-guide/shareable-configs)
npm package: @smorcuend/timber-ui
Description: UI components toolkit
Author: Sergio Morcuende
Latest version: 0.2.0
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

# Timber UI [![Storybook](https://cdn.jsdelivr.net/gh/storybookjs/brand@main/badge/badge-storybook.svg)](https://642d1db67e8afcfb103ed81f-mcgfwxpoyu.chromatic.com/)

Timber UI provides a simple, customizable, and accessible library of Vue components for UI on Cesefor's products.

Powered by Storybook that helps you build UI components in isolation from your app's business logic, data, and context.
That makes it easy to develop hard-to-reach states.

## Development

1. Clone repository
2. Install dependencies 
`npm install`
3. Start TimberUI framework `npm run storybook`
npm package: @smore/async-content
Description: Utility web components for asynchronously rendering HTML content
Author: Nate Moore
Latest version: 0.2.0

![Built With Stencil](https://img.shields.io/badge/-Built%20With%20Stencil-16161d.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjIuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI%2BCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI%2BCgkuc3Qwe2ZpbGw6I0ZGRkZGRjt9Cjwvc3R5bGU%2BCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik00MjQuNywzNzMuOWMwLDM3LjYtNTUuMSw2OC42LTkyLjcsNjguNkgxODAuNGMtMzcuOSwwLTkyLjctMzAuNy05Mi43LTY4LjZ2LTMuNmgzMzYuOVYzNzMuOXoiLz4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTQyNC43LDI5Mi4xSDE4MC40Yy0zNy42LDAtOTIuNy0zMS05Mi43LTY4LjZ2LTMuNkgzMzJjMzcuNiwwLDkyLjcsMzEsOTIuNyw2OC42VjI5Mi4xeiIvPgo8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNDI0LjcsMTQxLjdIODcuN3YtMy42YzAtMzcuNiw1NC44LTY4LjYsOTIuNy02OC42SDMzMmMzNy45LDAsOTIuNywzMC43LDkyLjcsNjguNlYxNDEuN3oiLz4KPC9zdmc%2BCg%3D%3D&colorA=16161d&style=flat-square)

# @smore/async-content

Web components for asynchronously rendering HTML content.
Use them with [any framework](https://stenciljs.com/docs/framework-integration), or no framework at all!

## Usage

Minimal example
```tsx
<async-content src="docs/hello-world.html">
  <async-placeholder> <pre> Loading... </pre> </async-placeholder>
  <async-error> <pre> An error occured! </pre> </async-error>
</async-content>
```

Better Placeholder/Error rendering
```tsx
<async-content src="docs/hello-world.html">
  <async-placeholder component="my-spinner" />
  <async-error errorRender={({ status, message }) => {
    return [
      <h1> Oops, { status } Error</h1>
      <p> { message } </p>
    ]
  }} />
</async-content>
```

## Documentation
[`<async-content>`](./src/component/async-content/readme.md)
[`<async-placeholder>`](./src/component/async-placeholder/readme.md)
[`<async-error>`](./src/component/async-error/readme.md)


## Installation

### Script tag
- Put a script tag similar to this `<script src='https://unpkg.com/@smore/async-content@0.2.0/dist/async-content.js'></script>` in the head of your index.html
- Then you can use the element anywhere in your template, JSX, html etc

### Node Modules
- Run `npm install @smore/async-content --save`
- Put a script tag similar to this `<script src='node_modules/@smore/async-content/dist/async-content.js'></script>` in the head of your index.html
- Then you can use the element anywhere in your template, JSX, html etc

### In a stencil-starter app
- Run `npm install @smore/async-content --save`
- Add an import to the npm packages `import '@smore/async-content';`
- Then you can use the element anywhere in your template, JSX, html etc
npm package: @smore/core
Description: A modular Web Component library full of micro-interactions and UX utilities
Author: Nate Moore
Latest version: 0.0.1-alpha.3

![Built With Stencil](https://img.shields.io/badge/-Built%20With%20Stencil-16161d.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjIuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI%2BCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI%2BCgkuc3Qwe2ZpbGw6I0ZGRkZGRjt9Cjwvc3R5bGU%2BCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik00MjQuNywzNzMuOWMwLDM3LjYtNTUuMSw2OC42LTkyLjcsNjguNkgxODAuNGMtMzcuOSwwLTkyLjctMzAuNy05Mi43LTY4LjZ2LTMuNmgzMzYuOVYzNzMuOXoiLz4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTQyNC43LDI5Mi4xSDE4MC40Yy0zNy42LDAtOTIuNy0zMS05Mi43LTY4LjZ2LTMuNkgzMzJjMzcuNiwwLDkyLjcsMzEsOTIuNyw2OC42VjI5Mi4xeiIvPgo8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNDI0LjcsMTQxLjdIODcuN3YtMy42YzAtMzcuNiw1NC44LTY4LjYsOTIuNy02OC42SDMzMmMzNy45LDAsOTIuNywzMC43LDkyLjcsNjguNlYxNDEuN3oiLz4KPC9zdmc%2BCg%3D%3D&colorA=16161d&style=flat-square)

# @smore/core
npm package: @smore/directives
Description: Functional component directives for Stencil
Author: Nate Moore
Latest version: 0.0.1

Functional Components for use as directives in Stencil apps.

> Note that this library does NOT expose any web components. The directives only work within Stencil apps, because they rely on JSX and vDOM.

## Installation

```bash
npm install @smore/directives
```

From here, simply import the directive you'd like to use into your Stencil component file.


## Directives

#### If

If the value prop is truthy, the contents are rendered.

Using this directive is more semantically meaningful than the common JSX trick `{ this.on && <div> On </div> }`

```tsx
import { If } '@smore/directives';

<If value={this.on}> On </If>
```

#### For

For is able to work with array values (`any[]`) and expects a [render prop](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce) as its only child. The render prop should be a function (essentially an `Array.map` callback) that returns a JSX element. It is called for each item in the array.

```tsx
import { For } '@smore/directives';

<For value={this.items}>
    { (item: any, index: number) => (<li> Item {index}: {item.name} </li> )}
</For>
```

#### Loop

Loop expects [render prop](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce) as its only child. The `value` prop controls how many times the loop should be called. The render prop should be a function that returns a JSX element. It is called for each iteration of the loop, and is passed the index of that iteration.

```tsx
import { Loop } '@smore/directives';

<Loop value={this.max}>
    { (index: number) => (<li> Item {index} </li> )}
</Loop>
```

#### Switch

Switch works pretty much like Javascript's built-in `switch`, `case`, and `default` expressions. No surprises here.

```tsx
import { Switch, Case, Default } '@smore/directives';

<Switch value={this.direction}>
    <Case value='enter'> Hello world! </Case>
    <Case value='exit'> Goodbye world! </Case>
    <Default> Fallback </Default>
</Switch>
```
npm package: @smorgasbord/themes
Description: Smorgasbord Themes
Author: Abios AB
Latest version: 1.0.0

<img src="https://img.abiosgaming.com/other/abios-logo-and-text.png" alt="Abios logo" height="30" >

# @smorgasbord/themes

> Themes for the Smorgasbord Design system

## Installation

```bash
yarn add @smorgasbord/themes
```

## Usage

### JavaScript

```js
import "@smorgasbord/themes"
```

### CSS

```css
@import '~@smorgasbord/themes/lib/light.css';
```
npm package: @smorgasbord/tokens
Description: Smorgasbord Design Tokens
Author: Abios AB
Latest version: 0.0.8

<img src="https://img.abiosgaming.com/other/abios-logo-and-text.png" alt="Abios logo" height="30" >

# @smorgasbord/tokens

> Design Tokens for the Smorgasbord Design System

## Installation

```bash
yarn add @smorgasbord/tokens
```

## Usage

### JavaScript

```js
import "@smorgasbord/tokens"
```

### CSS

```css
@import '~@smorgasbord/tokens/lib/main.css';
```
npm package: @smosm/agenticpulse
Description: AgenticPulse behavior intelligence SDK for tracking friction, feedback, and product signals.
Latest version: 0.1.0

# @smosm/agenticpulse

AgenticPulse behavior intelligence SDK for browser-based tracking, friction detection, and smart feedback collection.

## Install

```bash
npm install @smosm/agenticpulse
```

## Usage

```js
import AgenticPulse from "@smosm/agenticpulse";

AgenticPulse.init({
  projectId: "YOUR_PROJECT_ID",
  userId: "optional_user",
  autoTrack: true,
});
```

## API

### `init(config)`

```js
AgenticPulse.init({
  projectId: "YOUR_PROJECT_ID",
  userId: "optional_user",
  autoTrack: true,
  batchInterval: 5000,
  endpointBase: "https://your-api.com/api",
});
```

### `track(eventName, data)`

```js
AgenticPulse.track("checkout_clicked", {
  step: "pricing",
  plan: "pro",
});
```

### `feedback(payload)`

```js
AgenticPulse.feedback({
  message: "Checkout did not complete",
  intent: "purchase",
  severity: "high",
});
```

### `flush()`

```js
AgenticPulse.flush();
```

## Browser-only

This package is intended for browser execution. If you use Next.js, initialize it from a client component or inside a browser-only effect.

## Syncing from the app repo

This package mirrors the hosted SDK in `public/agenticpulse.js`.

From the repo root:

```bash
npm run sdk:sync
```
npm package: @smotaal.io/tools
Description: Frictionlessly-opinionated tools used across smotaal.io and related projects
Latest version: 0.0.5

﻿# @smotaal.io/tools

Frictionlessly opinionated tools used across [smotaal.io](https://smotaal.io/) and related projects.

## Gettting Started

### Internal

This package is included in the monorepo for internal use.

### External

This package can be installed as a dependency which will also install the relevant tools along with other third-party dependencies.
npm package: @smotaal/grammar
Description: Regular expression markup grammars
Latest version: 0.0.2

# SMotaal's Grammar

Regular expression markup grammars.

These grammars represent the set of barebone elements needed for fine-enough grained parsing with a one-size-fits semi-contextual tokenizer. Naturally, they rely on abstractions that do not currently have a well-defined conceptual paradigm.

<blockquote>

**Note**: All grammars are not yet stable.

These grammars are constantly being revised to meet experimental requirements of [`@smotaal/tokenizer`](https://github.com/smotaal/markup/tree/master/packages/tokenizer/). They do not conform to any particular specifications at the moment.

</blockquote>

That said, they have been used reliably and responsibly to build the prototype of the Markout client-side engine I use on my own site.

See [<samp>Changelog</samp>][changelog].

## `JS` JavaScript

- `javascript-grammar` aims for spec-level granularity.
- `javascript-extended-grammar` intends to go rouge.
- `typescript-grammar` is there to make `markout` happy.

## `HTML` Hypertext Markup Language

- `html-grammar` aims for spec-level granularity.

## `CSS` Cascading Style Sheets

- `css-grammar` is there to make `html-grammar` happy.

## `MOMD` Markout-Markdown

- `markdown-grammar` is there to make `markout` happy.

[package:repository]: https://github.com/SMotaal/markup/tree/master/packages/grammar
[changelog]: ./CHANGELOG.md
npm package: @smotaal/grammars
Description: Regular expression markup grammars
Latest version: 0.0.1
Deprecated: Renamed to @smotaal/grammar

# SMotaal's Grammars

Regular expression markup grammars.

These grammars represent the set of barebone elements needed for fine-enough grained parsing with a one-size-fits semi-contextual tokenizer. Naturally, they rely on abstractions that do not currently have a well-defined conceptual paradigm.

<blockquote>

**Note**: All grammars are not yet stable.

These grammars are constantly being revised to meet experimental requirements of [`@smotaal/tokenizer`](https://github.com/smotaal/markup/tree/master/packages/tokenizer/). They do not conform to any particular specifications at the moment.

</blockquote>

That said, they have been used reliably and responsibly to build the prototype of the Markout client-side engine I use on my own site.

## `JS` JavaScript

- `javascript-grammar` aims for spec-level granularity.
- `javascript-extended-grammar` intends to go rouge.
- `typescript-grammar` is there to make `markout` happy.

## `HTML` Hypertext Markup Language

- `html-grammar` aims for spec-level granularity.

## `CSS` Cascading Style Sheets

- `css-grammar` is there to make `html-grammar` happy.

## `MOMD` Markout-Markdown

- `markdown-grammar` is there to make `markout` happy.
npm package: @smotaal/tokenizer
Description: Nestable markup tokenizer using Regular Expressions
Latest version: 0.0.7

# SMotaal's Tokenizer

Nestable syntax tokenizer using Regular Expressions.

**What it tries to do**

- Provide simplified mechisms for defining syntaxes.
- Provide a way to work with tokens directly from strings.
- Provide a highlighter-inspired WYSIWYG for debugging.

**What it does NOT try to do**

- Everything else for now

> **Important Note:** This package is designed for ECMAScript module supporting runtimes, including all major browsers and Node.js 12 or later.

See [<samp>Changelog</samp>][changelog].

## Getting Started

<figcaption><b>Single-Mode</b></figcaption>

```js
import {Parser} from '@smotaal/tokenizer/tokenizer.js';
import {javascript} from '@smotaal/grammar/javascript/javascript-grammar.js';

const parser = new Parser();
export const {modes, mappings} = parser;
parser.register(javascript);

parser.tokenize('/* source */', {sourceType: 'javascript'});
```

<figcaption><b>Extended-Mode</b></figcaption>

```js
import {Parser, extensions} from '@smotaal/tokenizer/tokenizer.extended.js';
const parser = new Parser();

export const {modes, mappings} = parser;

for (const id in extensions.modes) parser.register(extensions.modes[id]);

parser.tokenize('/* source */', {sourceType: 'javascript'});
```

## Demo

You can see a [live demo](https://smotaal.io/markup/markup).

<figure>

<figcaption><i>Parameters</i></figcaption>

```url example
examples/browser/#‹specifier›!‹mode›*‹iterations›**‹repeats›
```

<b>`#`</b><samp>‹specifier›</samp>

- `#` followed by a relative URL
- `#https://` followed by an absolute URL
- `#unpkg:` followed by package or module path
- `#cdnjs:` followed by package or module path

<b>`!`</b><samp>‹mode›</samp>

- `!es` JavaScript
- `!css` CSS
- `!html` HTML
- `!md` Markdown

<b>`*`</b><samp>‹iterations›</samp>

- repeats the tokenization of the source text

<b>`**`</b><samp>‹repeat›</samp>

- repeats the tokenized (and rendered) source text

</figure>

[package:repository]: https://github.com/SMotaal/markup/tree/master/packages/tokenizer
[changelog]: ./CHANGELOG.md
npm package: @smotion/core
Description: Concise aliases for framer-motion HTML elements like motion.div.
Author: Jérôme Albrecht
Latest version: 1.0.1

# @smotion/core

> Concise aliases for Framer Motion components like `motion.div`, `motion.span`, and more.

A lightweight utility that gives you shorter JSX syntax when using Framer Motion.

---

## Why?

Instead of writing:

```tsx
import { motion } from "framer-motion";

<motion.div animate={{ opacity: 1 }} />;
```

You can simply write:

```tsx
import { M } from "@smotion/core";

<M.div animate={{ opacity: 1 }} />;
```

## Installation

```bash
npm install @smotion/core
```

or with Yarn:

```bash
yarn add @smotion/core
```

> Note: `framer-motion` is a peer dependency and must be installed in your project.

```bash
npm install framer-motion
```

## Usage

```tsx
import { M } from "@smotion/core";

<M.div
  animate={{ opacity: 1 }}
  initial={{ opacity: 0 }}
  transition={{ duration: 0.5 }}
>
  Hello world
</M.div>;
```

Supported elements:

- M.div
- M.span
- M.section
- M.article
- M.main
- M.nav
- etc.

You can extend the list if needed by modifying the source.

## Development

Clone the repo and build:

```bash
npm install
npm run build
```

## License

MIT — Jérôme Albrecht
npm package: @smounters/imperium-cron
Description: Cron scheduling for @smounters/imperium
Latest version: 1.2.1

# @smounters/imperium-cron

Cron scheduling for [`@smounters/imperium`](https://www.npmjs.com/package/@smounters/imperium). Decorate methods with `@Cron()` and they run on a schedule. Jobs auto-stop on application shutdown.

Part of the [Imperium monorepo](https://github.com/smounters/imperium).

Built on [croner](https://github.com/Hexagon/croner) — lightweight, zero-dependency cron scheduler.

## Install

```bash
pnpm add @smounters/imperium-cron
```

## Usage

```ts
import { Injectable, Module } from "@smounters/imperium/decorators";
import { Cron, CronModule } from "@smounters/imperium-cron";

@Injectable()
class MarketSync {
  @Cron("*/30 * * * * *") // every 30 seconds
  async syncPrices() {
    // fetch latest prices
  }

  @Cron("0 0 * * *", { name: "daily-cleanup" })
  async cleanup() {
    // remove old data
  }
}

@Module({
  imports: [CronModule.register({ providers: [MarketSync] })],
})
class AppModule {}
```

## API

### `@Cron(expression, options?)`

Method decorator. Registers the method to run on a cron schedule.

- `expression` — cron expression (supports seconds: `* * * * * *`)
- `options.name` — optional human-readable name for logging

### `CronModule.register({ providers })`

Dynamic module. Pass providers that contain `@Cron()` methods. Only providers with at least one `@Cron()` method are scanned.

### `CronService`

Injectable service for introspection:

- `getJobs()` — returns list of registered jobs with name, expression, running status
- `stopAll()` — stops all jobs (called automatically on shutdown)

## Documentation

Full guide: **[smounters.github.io/imperium/guide/cron](https://smounters.github.io/imperium/guide/cron)**

## License

MIT
npm package: @smounters/imperium-events
Description: Typed event emitter for @smounters/imperium
Latest version: 1.2.1

# @smounters/imperium-events

Typed in-process event emitter for [`@smounters/imperium`](https://www.npmjs.com/package/@smounters/imperium). Decorate methods with `@OnEvent()` and emit from any service. Supports wildcard patterns.

Part of the [Imperium monorepo](https://github.com/smounters/imperium).

## Install

```bash
pnpm add @smounters/imperium-events
```

## Usage

```ts
import { Injectable, Module } from "@smounters/imperium/decorators";
import { OnEvent, EventModule, EventService } from "@smounters/imperium-events";

// --- Listener ---

@Injectable()
class TradeNotifier {
  @OnEvent("trade.opened")
  async onTradeOpened(payload: { symbol: string; price: number }) {
    // push notification, log, update stats
  }

  @OnEvent("trade.*") // wildcard — matches trade.opened, trade.closed, etc.
  async auditLog(payload: unknown) {
    // write to audit log
  }
}

// --- Emitter ---

@Injectable()
class TradingEngine {
  constructor(private readonly events: EventService) {}

  async executeTrade(symbol: string, price: number) {
    // ... execute trade logic
    await this.events.emit("trade.opened", { symbol, price });
  }
}

// --- Module ---

@Module({
  imports: [EventModule.register({ listeners: [TradeNotifier] })],
  providers: [TradingEngine],
})
class TradingModule {}
```

## API

### `@OnEvent(pattern)`

Method decorator. Registers the method as a handler for events matching the pattern.

- `"trade.opened"` — exact match
- `"trade.*"` — wildcard, matches any single segment

### `EventModule.register({ listeners })`

Dynamic module. Pass providers that contain `@OnEvent()` methods.

### `EventService`

Injectable service:

- `emit(event, payload?)` — emit an event. All matching handlers run concurrently. Errors in individual handlers are caught and logged without blocking others.
- `getHandlers()` — returns registered handlers (for introspection/testing)

## Documentation

Full guide: **[smounters.github.io/imperium/guide/events](https://smounters.github.io/imperium/guide/events)**

## License

MIT
npm package: @smove/sdk
Description: 🛠 An SDK for building applications on top of fts.
Latest version: 0.0.2

# Pancakeswap SDK

[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
[![Actions Status](https://github.com/pancakeswap/pancakeswap-sdk/workflows/CI/badge.svg)](https://github.com/pancakeswap/pancakeswap-sdk)
[![npm version](https://img.shields.io/npm/v/@pancakeswap-lib/sdk/latest.svg)](https://www.npmjs.com/package/@pancakeswap-lib/sdk/v/latest)

## Running tests

To run the tests, follow these steps. You must have at least node v10 and [yarn](https://yarnpkg.com/) installed.

First clone the repository:

```sh
git clone https://github.com/pancakeswap/pancakeswap-sdk.git
```

Move into the pancakeswap-sdk working directory

```sh
cd pancakeswap-sdk/
```

Install dependencies

```sh
yarn install
```

Run tests

```sh
yarn test
```

You should see output like the following:

```sh
yarn run v1.22.4
$ tsdx test
 PASS  test/constants.test.ts
 PASS  test/pair.test.ts
 PASS  test/fraction.test.ts
 PASS  test/miscellaneous.test.ts
 PASS  test/entities.test.ts
 PASS  test/trade.test.ts

Test Suites: 1 skipped, 6 passed, 6 of 7 total
Tests:       3 skipped, 82 passed, 85 total
Snapshots:   0 total
Time:        5.091s
Ran all test suites.
✨  Done in 6.61s.
```
npm package: @smove/uikit
Description: Set of UI components for pancake projects
Latest version: 0.0.9

# 🥞 SMove UIkit

[![Version](https://img.shields.io/npm/v/@smove/uikit)](https://www.npmjs.com/package/@smove/uikit) [![Size](https://img.shields.io/bundlephobia/min/@smove/uikit)](https://www.npmjs.com/package/@smove/uikit)

SMove UIkit is a set of React components and hooks used to build pages on SMove's apps. It also contains a theme file for dark and light mode.

## Install

`yarn add @smove/uikit`

## Setup

### Theme

Before using SMove UIkit, you need to provide the theme file to styled-component.

```
import { ThemeProvider } from 'styled-components'
import { light, dark } from '@smove/uikit'
...
<ThemeProvider theme={isDark}>...</ThemeProvider>
```

### Reset

A reset CSS is available as a global styled component.

```
import { ResetCSS } from '@smove/uikit'
...
<ResetCSS />
```
npm package: @smpl/utils
Description: This is a collection of classes and functions we use throughout our projects. Whenever you copy a function over from one project to another, ask yourself: will this be needed again?
Author: Fabian Off
Latest version: 1.3.0

# Content

This is a collection of classes and functions we use throughout our projects.
Whenever you copy a function over from one project to another, ask yourself: will this be needed again?

If yes, then move your function into here and have everybody use it.

# Conventions

All functions have to be implemented in typescript!
npm package: @smplcty/db
Description: Tiny TypeScript helpers for pg: env-driven Pool factory, withClient checkout-run-release wrapper, parameterized UPDATE statement generator, and friendly error messages for common pg constraint codes.
Latest version: 3.0.0

# @smplcty/db

Tiny TypeScript helpers for `pg` — an env-driven `Pool` factory, a
`withClient` checkout-run-release wrapper, a parameterized UPDATE
statement generator, and friendly error messages for common
Postgres constraint codes.

This package does **not** reinvent `pg`. It's a handful of thin
domain helpers we reach for on every service. Bring your own `pg`
as a peer dependency.

## Install

```sh
pnpm add @smplcty/db pg
pnpm add -D @types/pg
```

Requires Node ≥ 20 and `pg` ≥ 8.

## Usage

### `connect(prefix?)` — env-driven Pool factory

```ts
import connect from '@smplcty/db';

// Reads DATABASE_URL
const pool = connect();

// Reads REPLICA_DATABASE_URL, falls back to DATABASE_URL
const replica = connect('REPLICA');
```

If `${PREFIX}_DATABASE_URL` is unset, it falls through to
`DATABASE_URL`. No `.env` loading — do that at the edge of your
application.

### `withClient(pool, fn)` — checkout-run-release

```ts
import connect, { withClient } from '@smplcty/db';

const pool = connect();

const rows = await withClient(pool, async (client) => {
  const { rows } = await client.query('select 1 as n');
  return rows;
});
```

The client is always released, even on error.

### `updateMutation(table, fieldset, updated?)` — UPDATE builder

Generates a parameterized `UPDATE … FROM jsonb_to_record($1)` query
that updates only rows whose values actually changed, and writes
`current_timestamp` to `updated_at`:

```ts
import { updateMutation } from '@smplcty/db';

const sql = updateMutation('users', [
  ['user_id', 'int', true],       // key field
  ['email',   'text'],
  ['name',    'text'],
]);

await client.query(sql, [JSON.stringify({
  user_id: 42,
  email: 'new@example.com',
  name: 'New Name',
})]);
```

The `IS DISTINCT FROM` predicates skip rows where nothing actually
changed, so `updated_at` isn't touched for no-op writes.

### `friendlyError(err)` — human-readable constraint errors

Maps common `pg` error codes (unique violation, foreign key
violation, not-null violation, string truncation, …) to
user-friendly messages:

```ts
import { friendlyError } from '@smplcty/db';

try {
  await client.query('insert into users (email) values ($1)', [dupe]);
} catch (err) {
  // "A user with that email already exists."
  throw new Error(friendlyError(err));
}
```

Unknown codes return a generic "unexpected database error" message.

## Development

```sh
pnpm install
pnpm test         # boots docker-compose Postgres on port 54322
pnpm run lint
pnpm run typecheck
pnpm run build
```

Tests set `DATABASE_URL` themselves via the docker-compose fixture
when unset; in CI, set `DATABASE_URL` before running `pnpm test`
and the fixture is skipped.

## License

MIT
npm package: @smplcty/dev-backend
Description: Local Lambda dev server — reads a routes config, loads .env, serves Lambda handlers over HTTP with API Gateway v2 event translation.
Latest version: 0.2.0

# @smplcty/dev-backend

Local Lambda dev server. Reads a routes config, loads env vars, and
serves Lambda handlers over HTTP with API Gateway v2 event
translation.

## Install

```sh
pnpm dlx @smplcty/dev-backend
```

Or as a dev dependency:

```sh
pnpm add -D @smplcty/dev-backend
```

## Usage

```sh
dev-backend [config-path]
```

Default config path is `backend.routes.json` in the current
directory.

## Config

`backend.routes.json` — committed to your frontend repo:

```json
{
  "port": 4000,
  "envFile": ".env.backend",
  "routes": {
    "/graphql": "../handle-graphql/dist/index.js",
    "/sign-in": {
      "handler": "../../mabulu-inc/sign-in/dist/index.js",
      "envFile": ".env.sign-in"
    },
    "/sign-in/verify": {
      "handler": "../../mabulu-inc/sign-in-verify/dist/index.js",
      "envFile": ".env.sign-in"
    },
    "/ai-insights": "../handle-ai-insights/dist/index.js"
  }
}
```

### Route formats

**String** — just a handler path. Uses the base `envFile`:

```json
"/graphql": "../handle-graphql/dist/index.js"
```

**Object** — handler path plus a per-route env file override:

```json
"/sign-in": {
  "handler": "../../mabulu-inc/sign-in/dist/index.js",
  "envFile": ".env.sign-in"
}
```

Per-route env files override the base env file's values for that
handler only. This solves the case where two handlers need different
`DATABASE_URL` values (e.g. graphql vs sign-in connect to different
databases).

All paths are resolved relative to the config file's location.

### Env files

`.env.backend` — shared variables (gitignored):

```
DATABASE_URL=postgresql://...
TWILIO_ACCOUNT_SID=AC...
TWILIO_AUTH_TOKEN=...
TWILIO_VERIFY_SERVICE_SID=VA...
LOG_LEVEL=debug
```

`.env.sign-in` — overrides for sign-in handlers (gitignored):

```
DATABASE_URL=postgresql://...different-db
```

Env files use standard `KEY=VALUE` format. Comments (`#`) and blank
lines are skipped. Surrounding quotes are stripped. Existing env vars
are not overridden.

## How it works

1. Loads the base env file into `process.env`.
2. For each route, if it has a per-route `envFile`, temporarily
   overrides the relevant env vars, imports the handler module
   (so module-level init like Pool creation uses the right values),
   then restores the originals.
3. Starts an HTTP server that translates incoming requests into
   API Gateway v2 proxy events and calls the matching handler.
4. CORS headers are set on all responses.

## License

MIT