Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "fastsqla",
"interface": {
"displayName": "FastSQLA"
},
"plugins": [
{
"name": "fastsqla",
"source": {
"source": "local",
"path": "./"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Productivity"
}
]
}
26 changes: 26 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "fastsqla",
"description": "Agent Skills for building FastAPI applications with FastSQLA.",
"owner": {
"name": "Hadrien David",
"email": "h@driendavid.com"
},
"plugins": [
{
"name": "fastsqla",
"source": "./",
"description": "Use FastSQLA's current setup, async session, and pagination APIs correctly.",
"version": "1.0.0",
"author": {
"name": "Hadrien David",
"email": "h@driendavid.com"
},
"homepage": "https://hadrien.github.io/FastSQLA/",
"repository": "https://github.com/hadrien/FastSQLA",
"license": "MIT",
"keywords": ["fastapi", "sqlalchemy", "async", "pagination", "sqlmodel"],
"category": "development"
}
]
}
15 changes: 15 additions & 0 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin.json",
"name": "fastsqla",
"version": "1.0.0",
"description": "Use FastSQLA's current setup, async session, and pagination APIs correctly.",
"author": {
"name": "Hadrien David",
"email": "h@driendavid.com"
},
"homepage": "https://hadrien.github.io/FastSQLA/",
"repository": "https://github.com/hadrien/FastSQLA",
"license": "MIT",
"keywords": ["fastapi", "sqlalchemy", "async", "pagination", "sqlmodel"],
"skills": "./skills/"
}
29 changes: 29 additions & 0 deletions .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "fastsqla",
"version": "1.0.0",
"description": "Use FastSQLA's current setup, async session, and pagination APIs correctly.",
"author": {
"name": "Hadrien David",
"email": "h@driendavid.com",
"url": "https://github.com/hadrien"
},
"homepage": "https://hadrien.github.io/FastSQLA/",
"repository": "https://github.com/hadrien/FastSQLA",
"license": "MIT",
"keywords": ["fastapi", "sqlalchemy", "async", "pagination", "sqlmodel"],
"skills": "./skills/",
"interface": {
"displayName": "FastSQLA",
"shortDescription": "FastSQLA setup, sessions, and pagination",
"longDescription": "Build FastAPI applications with FastSQLA's current async SQLAlchemy and SQLModel APIs.",
"developerName": "Hadrien David",
"category": "Productivity",
"capabilities": ["Read", "Write"],
"websiteURL": "https://hadrien.github.io/FastSQLA/",
"defaultPrompt": [
"Set up FastSQLA in this FastAPI application.",
"Use FastSQLA to add an async database endpoint.",
"Paginate this SQLAlchemy query with FastSQLA."
]
}
}
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ providing boilerplate and intuitive helpers. Additionally, it offers built-in
customizable pagination and automatically manages the `SQLAlchemy` session lifecycle
following [`SQLAlchemy`'s best practices](https://docs.sqlalchemy.org/en/20/orm/session_basics.html#when-do-i-construct-a-session-when-do-i-commit-it-and-when-do-i-close-it).


## Features

* Easy setup at app startup using
Expand Down Expand Up @@ -308,3 +307,33 @@ You can also check the generated openapi doc by opening your browser to
## License

This project is licensed under the terms of the [MIT license](https://github.com/hadrien/FastSQLA/blob/main/LICENSE).

## For coding agents and LLMs

FastSQLA publishes agent-readable documentation alongside the website:

- [`llms.txt`](https://hadrien.github.io/FastSQLA/llms.txt) is the concise documentation
index.
- [`llms-full.txt`](https://hadrien.github.io/FastSQLA/llms-full.txt) contains the
complete documentation in one file.
- Every indexed page has a Markdown twin, such as
[`setup/index.md`](https://hadrien.github.io/FastSQLA/setup/index.md).
- [Context7](https://context7.com/hadrien/fastsqla) serves the current documentation and
FastSQLA-specific usage rules.

The repository also bundles Agent Skills for setup, session management, and pagination.
Install all three as one plugin:

### Claude Code

```bash
claude plugin marketplace add hadrien/FastSQLA
claude plugin install fastsqla@fastsqla
```

### Codex

```bash
codex plugin marketplace add hadrien/FastSQLA
codex plugin add fastsqla@fastsqla
```
17 changes: 16 additions & 1 deletion context7.json
Original file line number Diff line number Diff line change
@@ -1 +1,16 @@
{"url": "https://context7.com/hadrien/fastsqla","public_key": "pk_HGTiXpaLrQ2YW61qLOKbF"}
{
"$schema": "https://context7.com/schema/context7.json",
"url": "https://context7.com/hadrien/fastsqla",
"public_key": "pk_HGTiXpaLrQ2YW61qLOKbF",
"projectTitle": "FastSQLA",
"description": "Async SQLAlchemy sessions and pagination for FastAPI, with optional SQLModel support.",
"folders": ["docs", "skills"],
"excludeFiles": ["CHANGELOG.md"],
"rules": [
"Configure FastAPI with fastsqla.lifespan or new_lifespan(); do not construct engines or sessions manually.",
"Declare fastsqla.Session as an endpoint parameter; FastSQLA commits on success and rolls back on exceptions.",
"Use fastsqla.open_session() outside request handlers, and only while the application lifespan is active.",
"Use fastsqla.Paginate and Page[T] for list endpoints; call await paginate(select(...)).",
"Install FastSQLA[sqlmodel] when using SQLModel; FastSQLA selects SQLModel's AsyncSession automatically."
]
}
48 changes: 48 additions & 0 deletions docs/javascripts/markdown-actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const bindMarkdownCopy = () => {
const button = document.querySelector("[data-copy-markdown]");
if (!button || button.dataset.copyBound === "true") {
return;
}

button.dataset.copyBound = "true";
button.addEventListener("click", async () => {
const actions = button.closest("[data-markdown-url]");
const status = actions?.querySelector("[role='status']");
const label = button.querySelector("[data-copy-label]");
const resetCopyState = () => {
if (label) label.textContent = "Copy for LLM";
if (status) status.textContent = "";
};

try {
if (!actions || !status || !label || !navigator.clipboard) {
throw new Error("Markdown copy controls are unavailable.");
}

const response = await fetch(actions.dataset.markdownUrl);
if (!response.ok) {
throw new Error(`Markdown request failed with status ${response.status}.`);
}

await navigator.clipboard.writeText(await response.text());
label.textContent = "Copied";
status.textContent = "Page Markdown copied";
window.setTimeout(resetCopyState, 2000);
} catch (error) {
if (label) {
label.textContent = "Copy failed";
}
if (status) {
status.textContent = "Page Markdown could not be copied";
}
window.setTimeout(resetCopyState, 2000);
console.error("Unable to copy the Markdown page.", error);
}
});
};

if (typeof document$ === "undefined") {
document.addEventListener("DOMContentLoaded", bindMarkdownCopy);
} else {
document$.subscribe(bindMarkdownCopy);
}
82 changes: 82 additions & 0 deletions docs/stylesheets/markdown-actions.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
.md-typeset h1:has(+ .md-content__markdown-actions) {
margin-block-end: 0.4rem;
}

.md-content__markdown-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0 0.4rem;
margin-block-end: 1.2rem;
}

.md-content__markdown-action {
display: inline-flex;
min-width: 2.2rem;
height: 2.2rem;
align-items: center;
justify-content: center;
gap: 0.3rem;
padding: 0 0.4rem;
border: 0;
border-radius: 0.15rem;
appearance: none;
background: transparent;
color: var(--md-default-fg-color--light);
cursor: pointer;
font: inherit;
font-size: 0.6rem;
font-weight: 500;
line-height: 1;
position: relative;
text-decoration: none;
transition: color 125ms ease-out;
}

.md-typeset .md-content__markdown-action:is(:hover, :focus-visible) {
--markdown-action-border: var(--markdown-action-brand, var(--md-accent-fg-color));
--markdown-action-bg: var(--markdown-action-brand-bg, var(--md-accent-fg-color--transparent));
color: var(--markdown-action-brand, var(--md-accent-fg-color));
text-decoration: none;
}

.md-typeset .md-content__markdown-action:focus-visible {
outline: 0.1rem solid var(--markdown-action-brand, var(--md-accent-fg-color));
outline-offset: 0.1rem;
}

.md-content__markdown-action--icon {
width: 2.2rem;
padding: 0;
}

.md-content__markdown-action::before {
content: ""; position: absolute;
inset: 0.3rem 0;
border: 0.05rem solid var(--markdown-action-border, var(--md-default-fg-color--light));
border-radius: inherit;
background: var(--markdown-action-bg, transparent);
transition: border-color 125ms ease-out, background-color 125ms ease-out;
}
.md-content__markdown-action--icon::before { inset: 0.3rem; }
.md-content__markdown-action--chatgpt { --markdown-action-brand: #10a37f; --markdown-action-brand-bg: #10a37f14; }
.md-content__markdown-action--claude { --markdown-action-brand: #d97757; --markdown-action-brand-bg: #d9775714; }

.md-content__markdown-agents {
display: inline-flex;
gap: 0;
}

.md-content__markdown-action-icon,
.md-content__markdown-action > svg {
width: 0.8rem;
height: 0.8rem;
flex: 0 0 auto;
fill: currentcolor;
}

@media (prefers-reduced-motion: reduce) {
.md-content__markdown-action {
transition: none;
}
}
Loading
Loading