honertia 0.1.31 → 0.1.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +389 -8
- package/dist/cache.d.ts +72 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +107 -0
- package/dist/effect/bridge.d.ts +2 -2
- package/dist/effect/bridge.d.ts.map +1 -1
- package/dist/effect/bridge.js +40 -2
- package/dist/effect/index.d.ts +2 -1
- package/dist/effect/index.d.ts.map +1 -1
- package/dist/effect/index.js +3 -1
- package/dist/effect/services.d.ts +39 -0
- package/dist/effect/services.d.ts.map +1 -1
- package/dist/effect/services.js +14 -0
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -792,24 +792,39 @@ export const showAbout = action(
|
|
|
792
792
|
)
|
|
793
793
|
```
|
|
794
794
|
|
|
795
|
-
### GET with Authentication
|
|
795
|
+
### GET with Authentication and Caching
|
|
796
796
|
|
|
797
797
|
```typescript
|
|
798
|
-
import { Effect } from 'effect'
|
|
799
|
-
import { action, authorize, render, DatabaseService } from 'honertia/effect'
|
|
798
|
+
import { Effect, Schema as S, Duration } from 'effect'
|
|
799
|
+
import { action, authorize, render, DatabaseService, cache } from 'honertia/effect'
|
|
800
800
|
import { eq } from 'drizzle-orm'
|
|
801
801
|
import { projects } from '~/db/schema'
|
|
802
802
|
|
|
803
|
+
const ProjectSchema = S.Struct({
|
|
804
|
+
id: S.String,
|
|
805
|
+
userId: S.String,
|
|
806
|
+
name: S.String,
|
|
807
|
+
description: S.NullOr(S.String),
|
|
808
|
+
createdAt: S.Date,
|
|
809
|
+
updatedAt: S.Date,
|
|
810
|
+
})
|
|
811
|
+
|
|
803
812
|
export const listProjects = action(
|
|
804
813
|
Effect.gen(function* () {
|
|
805
814
|
const auth = yield* authorize()
|
|
806
815
|
const db = yield* DatabaseService
|
|
807
816
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
817
|
+
// Cache expensive database query for 5 minutes
|
|
818
|
+
const userProjects = yield* cache(
|
|
819
|
+
`projects:user:${auth.user.id}`,
|
|
820
|
+
Effect.tryPromise(() =>
|
|
821
|
+
db.query.projects.findMany({
|
|
822
|
+
where: eq(projects.userId, auth.user.id),
|
|
823
|
+
orderBy: (p, { desc }) => [desc(p.createdAt)],
|
|
824
|
+
})
|
|
825
|
+
),
|
|
826
|
+
S.Array(ProjectSchema),
|
|
827
|
+
Duration.minutes(5)
|
|
813
828
|
)
|
|
814
829
|
|
|
815
830
|
return yield* render('Projects/Index', { projects: userProjects })
|
|
@@ -1532,6 +1547,371 @@ return yield* httpError(429, 'Rate limited')
|
|
|
1532
1547
|
|
|
1533
1548
|
---
|
|
1534
1549
|
|
|
1550
|
+
## Caching
|
|
1551
|
+
|
|
1552
|
+
Honertia provides a `CacheService` for caching expensive database operations. It's automatically provided and backed by Cloudflare KV by default, but can be swapped for Redis, Memcached, or any other implementation.
|
|
1553
|
+
|
|
1554
|
+
### Setup
|
|
1555
|
+
|
|
1556
|
+
Add KV to your `wrangler.toml`:
|
|
1557
|
+
|
|
1558
|
+
```toml
|
|
1559
|
+
[[kv_namespaces]]
|
|
1560
|
+
binding = "KV"
|
|
1561
|
+
id = "your-kv-namespace-id"
|
|
1562
|
+
```
|
|
1563
|
+
|
|
1564
|
+
Update your bindings type in `src/types.ts`:
|
|
1565
|
+
|
|
1566
|
+
```typescript
|
|
1567
|
+
export type Bindings = {
|
|
1568
|
+
DATABASE_URL: string
|
|
1569
|
+
BETTER_AUTH_SECRET: string
|
|
1570
|
+
KV: KVNamespace // Add this
|
|
1571
|
+
}
|
|
1572
|
+
```
|
|
1573
|
+
|
|
1574
|
+
No additional registration needed - `CacheService` is automatically available in all actions.
|
|
1575
|
+
|
|
1576
|
+
### Basic Usage
|
|
1577
|
+
|
|
1578
|
+
```typescript
|
|
1579
|
+
import { Effect, Schema as S, Duration } from 'effect'
|
|
1580
|
+
import { action, authorize, render, DatabaseService, cache } from 'honertia/effect'
|
|
1581
|
+
import { eq } from 'drizzle-orm'
|
|
1582
|
+
import { projects } from '~/db/schema'
|
|
1583
|
+
|
|
1584
|
+
const ProjectSchema = S.Struct({
|
|
1585
|
+
id: S.String,
|
|
1586
|
+
userId: S.String,
|
|
1587
|
+
name: S.String,
|
|
1588
|
+
description: S.NullOr(S.String),
|
|
1589
|
+
createdAt: S.Date,
|
|
1590
|
+
updatedAt: S.Date,
|
|
1591
|
+
})
|
|
1592
|
+
|
|
1593
|
+
export const listProjects = action(
|
|
1594
|
+
Effect.gen(function* () {
|
|
1595
|
+
const auth = yield* authorize()
|
|
1596
|
+
const db = yield* DatabaseService
|
|
1597
|
+
|
|
1598
|
+
// Cache the database query for 5 minutes
|
|
1599
|
+
const userProjects = yield* cache(
|
|
1600
|
+
`projects:user:${auth.user.id}`,
|
|
1601
|
+
Effect.tryPromise({
|
|
1602
|
+
try: () =>
|
|
1603
|
+
db.query.projects.findMany({
|
|
1604
|
+
where: eq(projects.userId, auth.user.id),
|
|
1605
|
+
orderBy: (p, { desc }) => [desc(p.createdAt)],
|
|
1606
|
+
}),
|
|
1607
|
+
catch: (error) => new Error(String(error)),
|
|
1608
|
+
}),
|
|
1609
|
+
S.Array(ProjectSchema),
|
|
1610
|
+
Duration.minutes(5)
|
|
1611
|
+
)
|
|
1612
|
+
|
|
1613
|
+
return yield* render('Projects/Index', { projects: userProjects })
|
|
1614
|
+
})
|
|
1615
|
+
)
|
|
1616
|
+
```
|
|
1617
|
+
|
|
1618
|
+
### Cache Functions
|
|
1619
|
+
|
|
1620
|
+
| Function | Description |
|
|
1621
|
+
|----------|-------------|
|
|
1622
|
+
| `cache(key, compute, schema, ttl)` | Get from cache or compute and store |
|
|
1623
|
+
| `cacheGet(key, schema)` | Get value from cache (returns `Option`) |
|
|
1624
|
+
| `cacheSet(key, value, schema, ttl)` | Store value in cache |
|
|
1625
|
+
| `cacheInvalidate(key)` | Delete a single cache key |
|
|
1626
|
+
| `cacheInvalidatePrefix(prefix)` | Delete all keys with prefix |
|
|
1627
|
+
|
|
1628
|
+
### Cache Invalidation
|
|
1629
|
+
|
|
1630
|
+
Invalidate cache when data changes:
|
|
1631
|
+
|
|
1632
|
+
```typescript
|
|
1633
|
+
import { Effect, Schema as S } from 'effect'
|
|
1634
|
+
import {
|
|
1635
|
+
action,
|
|
1636
|
+
authorize,
|
|
1637
|
+
validateRequest,
|
|
1638
|
+
DatabaseService,
|
|
1639
|
+
redirect,
|
|
1640
|
+
asTrusted,
|
|
1641
|
+
dbMutation,
|
|
1642
|
+
requiredString,
|
|
1643
|
+
cacheInvalidate,
|
|
1644
|
+
} from 'honertia/effect'
|
|
1645
|
+
import { projects } from '~/db/schema'
|
|
1646
|
+
|
|
1647
|
+
const CreateProjectSchema = S.Struct({
|
|
1648
|
+
name: requiredString,
|
|
1649
|
+
description: S.optional(S.String),
|
|
1650
|
+
})
|
|
1651
|
+
|
|
1652
|
+
export const createProject = action(
|
|
1653
|
+
Effect.gen(function* () {
|
|
1654
|
+
const auth = yield* authorize()
|
|
1655
|
+
const input = yield* validateRequest(CreateProjectSchema, {
|
|
1656
|
+
errorComponent: 'Projects/Create',
|
|
1657
|
+
})
|
|
1658
|
+
const db = yield* DatabaseService
|
|
1659
|
+
|
|
1660
|
+
yield* dbMutation(db, async (db) => {
|
|
1661
|
+
await db.insert(projects).values(
|
|
1662
|
+
asTrusted({
|
|
1663
|
+
name: input.name,
|
|
1664
|
+
description: input.description ?? null,
|
|
1665
|
+
userId: auth.user.id,
|
|
1666
|
+
})
|
|
1667
|
+
)
|
|
1668
|
+
})
|
|
1669
|
+
|
|
1670
|
+
// Invalidate the user's project list cache
|
|
1671
|
+
yield* cacheInvalidate(`projects:user:${auth.user.id}`)
|
|
1672
|
+
|
|
1673
|
+
return yield* redirect('/projects')
|
|
1674
|
+
})
|
|
1675
|
+
)
|
|
1676
|
+
```
|
|
1677
|
+
|
|
1678
|
+
### Invalidate by Prefix
|
|
1679
|
+
|
|
1680
|
+
Delete all cache keys matching a prefix:
|
|
1681
|
+
|
|
1682
|
+
```typescript
|
|
1683
|
+
import { cacheInvalidatePrefix } from 'honertia/effect'
|
|
1684
|
+
|
|
1685
|
+
// Invalidate all caches for a user
|
|
1686
|
+
yield* cacheInvalidatePrefix(`user:${userId}:`)
|
|
1687
|
+
|
|
1688
|
+
// Invalidate all project-related caches
|
|
1689
|
+
yield* cacheInvalidatePrefix('projects:')
|
|
1690
|
+
```
|
|
1691
|
+
|
|
1692
|
+
### Manual Get/Set
|
|
1693
|
+
|
|
1694
|
+
For more control over cache operations:
|
|
1695
|
+
|
|
1696
|
+
```typescript
|
|
1697
|
+
import { Effect, Option, Schema as S, Duration } from 'effect'
|
|
1698
|
+
import { cacheGet, cacheSet } from 'honertia/effect'
|
|
1699
|
+
|
|
1700
|
+
const UserSchema = S.Struct({
|
|
1701
|
+
id: S.String,
|
|
1702
|
+
name: S.String,
|
|
1703
|
+
email: S.String,
|
|
1704
|
+
})
|
|
1705
|
+
|
|
1706
|
+
// Check cache first
|
|
1707
|
+
const cached = yield* cacheGet(`user:${id}`, UserSchema)
|
|
1708
|
+
|
|
1709
|
+
if (Option.isSome(cached)) {
|
|
1710
|
+
return cached.value
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
// Compute value
|
|
1714
|
+
const user = yield* fetchUser(id)
|
|
1715
|
+
|
|
1716
|
+
// Store in cache
|
|
1717
|
+
yield* cacheSet(`user:${id}`, user, UserSchema, Duration.hours(1))
|
|
1718
|
+
|
|
1719
|
+
return user
|
|
1720
|
+
```
|
|
1721
|
+
|
|
1722
|
+
### Using CacheService Directly
|
|
1723
|
+
|
|
1724
|
+
For advanced use cases, access the underlying service:
|
|
1725
|
+
|
|
1726
|
+
```typescript
|
|
1727
|
+
import { Effect } from 'effect'
|
|
1728
|
+
import { CacheService } from 'honertia/effect'
|
|
1729
|
+
|
|
1730
|
+
const handler = action(
|
|
1731
|
+
Effect.gen(function* () {
|
|
1732
|
+
const cache = yield* CacheService
|
|
1733
|
+
|
|
1734
|
+
// Raw get (returns string | null)
|
|
1735
|
+
const raw = yield* cache.get('my-key')
|
|
1736
|
+
|
|
1737
|
+
// Raw put
|
|
1738
|
+
yield* cache.put('my-key', JSON.stringify({ data: 'value' }), {
|
|
1739
|
+
expirationTtl: 3600, // seconds
|
|
1740
|
+
})
|
|
1741
|
+
|
|
1742
|
+
// Delete
|
|
1743
|
+
yield* cache.delete('my-key')
|
|
1744
|
+
|
|
1745
|
+
// List keys by prefix
|
|
1746
|
+
const keys = yield* cache.list({ prefix: 'user:' })
|
|
1747
|
+
})
|
|
1748
|
+
)
|
|
1749
|
+
```
|
|
1750
|
+
|
|
1751
|
+
### Custom Cache Implementation
|
|
1752
|
+
|
|
1753
|
+
Swap out Cloudflare KV for Redis or any other backend by providing a custom `CacheService` layer:
|
|
1754
|
+
|
|
1755
|
+
```typescript
|
|
1756
|
+
import { Effect, Layer } from 'effect'
|
|
1757
|
+
import { CacheService, CacheClientError, type CacheClient } from 'honertia/effect'
|
|
1758
|
+
import { createClient } from 'redis'
|
|
1759
|
+
|
|
1760
|
+
const createRedisCacheClient = (redisUrl: string): CacheClient => {
|
|
1761
|
+
const client = createClient({ url: redisUrl })
|
|
1762
|
+
|
|
1763
|
+
return {
|
|
1764
|
+
get: (key) =>
|
|
1765
|
+
Effect.tryPromise({
|
|
1766
|
+
try: () => client.get(key),
|
|
1767
|
+
catch: (e) => new CacheClientError('Redis get failed', e),
|
|
1768
|
+
}),
|
|
1769
|
+
put: (key, value, options) =>
|
|
1770
|
+
Effect.tryPromise({
|
|
1771
|
+
try: () =>
|
|
1772
|
+
client.set(key, value, options?.expirationTtl ? { EX: options.expirationTtl } : undefined),
|
|
1773
|
+
catch: (e) => new CacheClientError('Redis set failed', e),
|
|
1774
|
+
}).pipe(Effect.asVoid),
|
|
1775
|
+
delete: (key) =>
|
|
1776
|
+
Effect.tryPromise({
|
|
1777
|
+
try: () => client.del(key),
|
|
1778
|
+
catch: (e) => new CacheClientError('Redis delete failed', e),
|
|
1779
|
+
}).pipe(Effect.asVoid),
|
|
1780
|
+
list: (options) =>
|
|
1781
|
+
Effect.tryPromise({
|
|
1782
|
+
try: async () => {
|
|
1783
|
+
const keys = await client.keys(options?.prefix ? `${options.prefix}*` : '*')
|
|
1784
|
+
return { keys: keys.map((name) => ({ name })) }
|
|
1785
|
+
},
|
|
1786
|
+
catch: (e) => new CacheClientError('Redis keys failed', e),
|
|
1787
|
+
}),
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
// Provide in your app setup
|
|
1792
|
+
const RedisCacheLayer = Layer.succeed(
|
|
1793
|
+
CacheService,
|
|
1794
|
+
createRedisCacheClient(process.env.REDIS_URL!)
|
|
1795
|
+
)
|
|
1796
|
+
```
|
|
1797
|
+
|
|
1798
|
+
### Testing with Cache
|
|
1799
|
+
|
|
1800
|
+
Create a test layer that uses an in-memory store:
|
|
1801
|
+
|
|
1802
|
+
```typescript
|
|
1803
|
+
import { Effect, Layer, Option, Schema as S, Duration } from 'effect'
|
|
1804
|
+
import { CacheService, cache, cacheGet, cacheInvalidate, type CacheClient } from 'honertia/effect'
|
|
1805
|
+
import { describe, it, expect } from 'bun:test'
|
|
1806
|
+
|
|
1807
|
+
const makeTestCache = (): Layer.Layer<CacheService> => {
|
|
1808
|
+
const store = new Map<string, { value: string; expiresAt: number }>()
|
|
1809
|
+
|
|
1810
|
+
const client: CacheClient = {
|
|
1811
|
+
get: (key) =>
|
|
1812
|
+
Effect.sync(() => {
|
|
1813
|
+
const entry = store.get(key)
|
|
1814
|
+
if (!entry || entry.expiresAt < Date.now()) {
|
|
1815
|
+
store.delete(key)
|
|
1816
|
+
return null
|
|
1817
|
+
}
|
|
1818
|
+
return entry.value
|
|
1819
|
+
}),
|
|
1820
|
+
put: (key, value, options) =>
|
|
1821
|
+
Effect.sync(() => {
|
|
1822
|
+
const ttlMs = (options?.expirationTtl ?? 3600) * 1000
|
|
1823
|
+
store.set(key, { value, expiresAt: Date.now() + ttlMs })
|
|
1824
|
+
}),
|
|
1825
|
+
delete: (key) =>
|
|
1826
|
+
Effect.sync(() => {
|
|
1827
|
+
store.delete(key)
|
|
1828
|
+
}),
|
|
1829
|
+
list: (options) =>
|
|
1830
|
+
Effect.sync(() => ({
|
|
1831
|
+
keys: [...store.keys()]
|
|
1832
|
+
.filter((k) => !options?.prefix || k.startsWith(options.prefix))
|
|
1833
|
+
.map((name) => ({ name })),
|
|
1834
|
+
})),
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
return Layer.succeed(CacheService, client)
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1840
|
+
const TestSchema = S.Struct({
|
|
1841
|
+
id: S.String,
|
|
1842
|
+
name: S.String,
|
|
1843
|
+
})
|
|
1844
|
+
|
|
1845
|
+
describe('cache', () => {
|
|
1846
|
+
it('returns cached value on second call', () =>
|
|
1847
|
+
Effect.gen(function* () {
|
|
1848
|
+
let callCount = 0
|
|
1849
|
+
|
|
1850
|
+
const compute = Effect.sync(() => {
|
|
1851
|
+
callCount++
|
|
1852
|
+
return { id: '1', name: 'Test' }
|
|
1853
|
+
})
|
|
1854
|
+
|
|
1855
|
+
const first = yield* cache('test:1', compute, TestSchema, Duration.hours(1))
|
|
1856
|
+
const second = yield* cache('test:1', compute, TestSchema, Duration.hours(1))
|
|
1857
|
+
|
|
1858
|
+
expect(first).toEqual(second)
|
|
1859
|
+
expect(callCount).toBe(1) // Only computed once
|
|
1860
|
+
}).pipe(Effect.provide(makeTestCache()), Effect.runPromise))
|
|
1861
|
+
|
|
1862
|
+
it('recomputes after invalidation', () =>
|
|
1863
|
+
Effect.gen(function* () {
|
|
1864
|
+
let callCount = 0
|
|
1865
|
+
|
|
1866
|
+
const compute = Effect.sync(() => {
|
|
1867
|
+
callCount++
|
|
1868
|
+
return { id: '1', name: `Call ${callCount}` }
|
|
1869
|
+
})
|
|
1870
|
+
|
|
1871
|
+
yield* cache('test:1', compute, TestSchema, Duration.hours(1))
|
|
1872
|
+
yield* cacheInvalidate('test:1')
|
|
1873
|
+
yield* cache('test:1', compute, TestSchema, Duration.hours(1))
|
|
1874
|
+
|
|
1875
|
+
expect(callCount).toBe(2) // Computed twice
|
|
1876
|
+
}).pipe(Effect.provide(makeTestCache()), Effect.runPromise))
|
|
1877
|
+
|
|
1878
|
+
it('returns Option.none for missing keys', () =>
|
|
1879
|
+
Effect.gen(function* () {
|
|
1880
|
+
const result = yield* cacheGet('nonexistent', TestSchema)
|
|
1881
|
+
expect(Option.isNone(result)).toBe(true)
|
|
1882
|
+
}).pipe(Effect.provide(makeTestCache()), Effect.runPromise))
|
|
1883
|
+
})
|
|
1884
|
+
```
|
|
1885
|
+
|
|
1886
|
+
### Cache Key Patterns
|
|
1887
|
+
|
|
1888
|
+
Recommended cache key patterns:
|
|
1889
|
+
|
|
1890
|
+
```typescript
|
|
1891
|
+
// User-scoped data
|
|
1892
|
+
`user:${userId}:profile`
|
|
1893
|
+
`user:${userId}:settings`
|
|
1894
|
+
`user:${userId}:notifications`
|
|
1895
|
+
|
|
1896
|
+
// Resource lists
|
|
1897
|
+
`projects:user:${userId}`
|
|
1898
|
+
`posts:category:${categoryId}`
|
|
1899
|
+
|
|
1900
|
+
// Individual resources
|
|
1901
|
+
`project:${projectId}`
|
|
1902
|
+
`user:${userId}`
|
|
1903
|
+
|
|
1904
|
+
// Computed data
|
|
1905
|
+
`stats:daily:${date}`
|
|
1906
|
+
`leaderboard:weekly`
|
|
1907
|
+
|
|
1908
|
+
// API responses
|
|
1909
|
+
`api:weather:${city}`
|
|
1910
|
+
`api:exchange:${currency}`
|
|
1911
|
+
```
|
|
1912
|
+
|
|
1913
|
+
---
|
|
1914
|
+
|
|
1535
1915
|
## Services Reference
|
|
1536
1916
|
|
|
1537
1917
|
| Service | Description | Usage |
|
|
@@ -1540,6 +1920,7 @@ return yield* httpError(429, 'Rate limited')
|
|
|
1540
1920
|
| `AuthService` | Better-auth instance | `const auth = yield* AuthService` |
|
|
1541
1921
|
| `AuthUserService` | Current user session | `const user = yield* AuthUserService` |
|
|
1542
1922
|
| `BindingsService` | Cloudflare bindings | `const { KV } = yield* BindingsService` |
|
|
1923
|
+
| `CacheService` | KV-backed cache client | `const cache = yield* CacheService` |
|
|
1543
1924
|
| `RequestService` | Request context | `const req = yield* RequestService` |
|
|
1544
1925
|
|
|
1545
1926
|
### Using BindingsService
|
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache Module
|
|
3
|
+
*
|
|
4
|
+
* Simple cache abstraction for storing expensive DB operations.
|
|
5
|
+
* Uses CacheService which is automatically provided and backed by Cloudflare KV by default.
|
|
6
|
+
* Can be swapped for Redis, Memcached, or any other implementation.
|
|
7
|
+
*/
|
|
8
|
+
import { Effect, Option, Schema, ParseResult, Duration } from 'effect';
|
|
9
|
+
import { CacheService, CacheClientError } from './effect/services.js';
|
|
10
|
+
declare const CacheError_base: Schema.TaggedErrorClass<CacheError, "CacheError", {
|
|
11
|
+
readonly _tag: Schema.tag<"CacheError">;
|
|
12
|
+
} & {
|
|
13
|
+
reason: typeof Schema.String;
|
|
14
|
+
cause: Schema.optional<typeof Schema.Unknown>;
|
|
15
|
+
}>;
|
|
16
|
+
export declare class CacheError extends CacheError_base {
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Cache a computed value with automatic serialization and TTL.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const user = yield* cache(
|
|
24
|
+
* `user:${id}`,
|
|
25
|
+
* Effect.tryPromise(() => db.query.users.findFirst({ where: eq(users.id, id) })),
|
|
26
|
+
* UserSchema,
|
|
27
|
+
* Duration.hours(1)
|
|
28
|
+
* )
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare const cache: <V, E, R>(key: string, compute: Effect.Effect<V, E, R>, schema: Schema.Schema<V>, ttl: Duration.DurationInput) => Effect.Effect<V, E | CacheError | CacheClientError | ParseResult.ParseError, R | CacheService>;
|
|
32
|
+
/**
|
|
33
|
+
* Get a value from cache without computing.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const cached = yield* cacheGet(`user:${id}`, UserSchema)
|
|
38
|
+
* if (Option.isSome(cached)) {
|
|
39
|
+
* return cached.value
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare const cacheGet: <V>(key: string, schema: Schema.Schema<V>) => Effect.Effect<Option.Option<V>, CacheError | CacheClientError | ParseResult.ParseError, CacheService>;
|
|
44
|
+
/**
|
|
45
|
+
* Set a value in cache.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* yield* cacheSet(`user:${id}`, user, UserSchema, Duration.hours(1))
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare const cacheSet: <V>(key: string, value: V, schema: Schema.Schema<V>, ttl: Duration.DurationInput) => Effect.Effect<void, CacheError | CacheClientError | ParseResult.ParseError, CacheService>;
|
|
53
|
+
/**
|
|
54
|
+
* Invalidate a cache key.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* yield* cacheInvalidate(`user:${id}`)
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare const cacheInvalidate: (key: string) => Effect.Effect<void, CacheClientError, CacheService>;
|
|
62
|
+
/**
|
|
63
|
+
* Invalidate all cache keys with a given prefix.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* yield* cacheInvalidatePrefix(`user:${userId}:`)
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare const cacheInvalidatePrefix: (prefix: string) => Effect.Effect<void, CacheClientError, CacheService>;
|
|
71
|
+
export {};
|
|
72
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AACtE,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;;;;;;;AAMrE,qBAAa,UAAW,SAAQ,eAG9B;CAAG;AAML;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,KAAK,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAC3B,KAAK,MAAM,EACX,SAAS,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC/B,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EACxB,KAAK,QAAQ,CAAC,aAAa,KAC1B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,UAAU,GAAG,gBAAgB,GAAG,WAAW,CAAC,UAAU,EAAE,CAAC,GAAG,YAAY,CAqB5F,CAAA;AAEJ;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,EACxB,KAAK,MAAM,EACX,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KACvB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,GAAG,gBAAgB,GAAG,WAAW,CAAC,UAAU,EAAE,YAAY,CAYnG,CAAA;AAEJ;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,EACxB,KAAK,MAAM,EACX,OAAO,CAAC,EACR,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EACxB,KAAK,QAAQ,CAAC,aAAa,KAC1B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,gBAAgB,GAAG,WAAW,CAAC,UAAU,EAAE,YAAY,CAQvF,CAAA;AAEJ;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAC1B,KAAK,MAAM,KACV,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,gBAAgB,EAAE,YAAY,CAIjD,CAAA;AAEJ;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,MAAM,KACb,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,gBAAgB,EAAE,YAAY,CAWjD,CAAA"}
|
package/dist/cache.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache Module
|
|
3
|
+
*
|
|
4
|
+
* Simple cache abstraction for storing expensive DB operations.
|
|
5
|
+
* Uses CacheService which is automatically provided and backed by Cloudflare KV by default.
|
|
6
|
+
* Can be swapped for Redis, Memcached, or any other implementation.
|
|
7
|
+
*/
|
|
8
|
+
import { Effect, Option, Schema, Duration } from 'effect';
|
|
9
|
+
import { CacheService } from './effect/services.js';
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Errors
|
|
12
|
+
// ============================================================================
|
|
13
|
+
export class CacheError extends Schema.TaggedError()('CacheError', {
|
|
14
|
+
reason: Schema.String,
|
|
15
|
+
cause: Schema.optional(Schema.Unknown),
|
|
16
|
+
}) {
|
|
17
|
+
}
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Composable API
|
|
20
|
+
// ============================================================================
|
|
21
|
+
/**
|
|
22
|
+
* Cache a computed value with automatic serialization and TTL.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const user = yield* cache(
|
|
27
|
+
* `user:${id}`,
|
|
28
|
+
* Effect.tryPromise(() => db.query.users.findFirst({ where: eq(users.id, id) })),
|
|
29
|
+
* UserSchema,
|
|
30
|
+
* Duration.hours(1)
|
|
31
|
+
* )
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export const cache = (key, compute, schema, ttl) => Effect.gen(function* () {
|
|
35
|
+
const cacheService = yield* CacheService;
|
|
36
|
+
// Check cache first
|
|
37
|
+
const cached = yield* cacheService.get(key);
|
|
38
|
+
if (cached !== null) {
|
|
39
|
+
return yield* Schema.decodeUnknown(Schema.parseJson(schema))(cached);
|
|
40
|
+
}
|
|
41
|
+
// Compute value
|
|
42
|
+
const value = yield* compute;
|
|
43
|
+
// Store in cache
|
|
44
|
+
const serialized = yield* Schema.encode(Schema.parseJson(schema))(value);
|
|
45
|
+
const ttlSeconds = Duration.toSeconds(Duration.decode(ttl));
|
|
46
|
+
yield* cacheService.put(key, serialized, { expirationTtl: ttlSeconds });
|
|
47
|
+
return value;
|
|
48
|
+
});
|
|
49
|
+
/**
|
|
50
|
+
* Get a value from cache without computing.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const cached = yield* cacheGet(`user:${id}`, UserSchema)
|
|
55
|
+
* if (Option.isSome(cached)) {
|
|
56
|
+
* return cached.value
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export const cacheGet = (key, schema) => Effect.gen(function* () {
|
|
61
|
+
const cacheService = yield* CacheService;
|
|
62
|
+
const cached = yield* cacheService.get(key);
|
|
63
|
+
if (cached === null) {
|
|
64
|
+
return Option.none();
|
|
65
|
+
}
|
|
66
|
+
const decoded = yield* Schema.decodeUnknown(Schema.parseJson(schema))(cached);
|
|
67
|
+
return Option.some(decoded);
|
|
68
|
+
});
|
|
69
|
+
/**
|
|
70
|
+
* Set a value in cache.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* yield* cacheSet(`user:${id}`, user, UserSchema, Duration.hours(1))
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export const cacheSet = (key, value, schema, ttl) => Effect.gen(function* () {
|
|
78
|
+
const cacheService = yield* CacheService;
|
|
79
|
+
const serialized = yield* Schema.encode(Schema.parseJson(schema))(value);
|
|
80
|
+
const ttlSeconds = Duration.toSeconds(Duration.decode(ttl));
|
|
81
|
+
yield* cacheService.put(key, serialized, { expirationTtl: ttlSeconds });
|
|
82
|
+
});
|
|
83
|
+
/**
|
|
84
|
+
* Invalidate a cache key.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* yield* cacheInvalidate(`user:${id}`)
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export const cacheInvalidate = (key) => Effect.gen(function* () {
|
|
92
|
+
const cacheService = yield* CacheService;
|
|
93
|
+
yield* cacheService.delete(key);
|
|
94
|
+
});
|
|
95
|
+
/**
|
|
96
|
+
* Invalidate all cache keys with a given prefix.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* yield* cacheInvalidatePrefix(`user:${userId}:`)
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export const cacheInvalidatePrefix = (prefix) => Effect.gen(function* () {
|
|
104
|
+
const cacheService = yield* CacheService;
|
|
105
|
+
const list = yield* cacheService.list({ prefix });
|
|
106
|
+
yield* Effect.forEach(list.keys, (key) => cacheService.delete(key.name), { concurrency: 10 });
|
|
107
|
+
});
|
package/dist/effect/bridge.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Layer, ManagedRuntime } from 'effect';
|
|
7
7
|
import type { Context as HonoContext, MiddlewareHandler, Env } from 'hono';
|
|
8
|
-
import { DatabaseService, AuthService, AuthUserService, HonertiaService, RequestService, ResponseFactoryService, BindingsService } from './services.js';
|
|
8
|
+
import { DatabaseService, AuthService, AuthUserService, HonertiaService, RequestService, ResponseFactoryService, BindingsService, CacheService } from './services.js';
|
|
9
9
|
/**
|
|
10
10
|
* Configuration for the Effect bridge.
|
|
11
11
|
*
|
|
@@ -61,7 +61,7 @@ declare module 'hono' {
|
|
|
61
61
|
/**
|
|
62
62
|
* Build the Effect layer from Hono context.
|
|
63
63
|
*/
|
|
64
|
-
export declare function buildContextLayer<E extends Env, CustomServices = never>(c: HonoContext<E>, config?: EffectBridgeConfig<E, CustomServices>): Layer.Layer<RequestService | ResponseFactoryService | HonertiaService | DatabaseService | AuthService | AuthUserService | BindingsService | CustomServices, never, never>;
|
|
64
|
+
export declare function buildContextLayer<E extends Env, CustomServices = never>(c: HonoContext<E>, config?: EffectBridgeConfig<E, CustomServices>): Layer.Layer<RequestService | ResponseFactoryService | HonertiaService | DatabaseService | AuthService | AuthUserService | BindingsService | CacheService | CustomServices, never, never>;
|
|
65
65
|
/**
|
|
66
66
|
* Get the Effect runtime from Hono context.
|
|
67
67
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/effect/bridge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAU,KAAK,EAAE,cAAc,EAAU,MAAM,QAAQ,CAAA;AAG9D,OAAO,KAAK,EAAE,OAAO,IAAI,WAAW,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAC1E,OAAO,EACL,eAAe,EACf,WAAW,EACX,eAAe,EACf,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,eAAe,
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/effect/bridge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAU,KAAK,EAAE,cAAc,EAAU,MAAM,QAAQ,CAAA;AAG9D,OAAO,KAAK,EAAE,OAAO,IAAI,WAAW,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAC1E,OAAO,EACL,eAAe,EACf,WAAW,EACX,eAAe,EACf,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,YAAY,EAUb,MAAM,eAAe,CAAA;AAGtB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,GAAG,EAAE,cAAc,GAAG,KAAK;IACvE;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;IAC3E;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC;AAED;;GAEG;AACH,QAAA,MAAM,cAAc,eAA0B,CAAA;AAE9C;;GAEG;AACH,QAAA,MAAM,aAAa,eAAyB,CAAA;AAa5C,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAM7D;AAqCD;;GAEG;AACH,OAAO,QAAQ,MAAM,CAAC;IACpB,UAAU,kBAAkB;QAC1B,CAAC,cAAc,CAAC,CAAC,EAAE,cAAc,CAAC,cAAc,CAC5C,eAAe,GACf,WAAW,GACX,eAAe,GACf,eAAe,GACf,cAAc,GACd,sBAAsB,EACxB,KAAK,CACN,CAAA;QACD,CAAC,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAC1C;CACF;AA2GD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,GAAG,EAAE,cAAc,GAAG,KAAK,EACrE,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EACjB,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAC,EAAE,cAAc,CAAC,GAC7C,KAAK,CAAC,KAAK,CACV,cAAc,GACd,sBAAsB,GACtB,eAAe,GACf,eAAe,GACf,WAAW,GACX,eAAe,GACf,eAAe,GACf,YAAY,GACZ,cAAc,EAChB,KAAK,EACL,KAAK,CACN,CA6EA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,GAAG,EAC5C,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GAChB,cAAc,CAAC,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,SAAS,CAEvD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,GAAG,EAAE,cAAc,GAAG,KAAK,EAChE,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAC,EAAE,cAAc,CAAC,GAC7C,iBAAiB,CAAC,CAAC,CAAC,CA6CtB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,GAAG,EAC3C,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAErC"}
|
package/dist/effect/bridge.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { Effect, Layer, ManagedRuntime, Option } from 'effect';
|
|
7
7
|
import { HonertiaConfigurationError } from './errors.js';
|
|
8
8
|
import { ErrorCodes } from './error-catalog.js';
|
|
9
|
-
import { DatabaseService, AuthService, AuthUserService, HonertiaService, RequestService, ResponseFactoryService, BindingsService, } from './services.js';
|
|
9
|
+
import { DatabaseService, AuthService, AuthUserService, HonertiaService, RequestService, ResponseFactoryService, BindingsService, CacheService, CacheClientError, } from './services.js';
|
|
10
10
|
import { TestCaptureService } from './test-layers.js';
|
|
11
11
|
/**
|
|
12
12
|
* Symbol for storing Effect runtime in Hono context.
|
|
@@ -88,6 +88,41 @@ function createResponseFactory(c) {
|
|
|
88
88
|
notFound: () => c.notFound(),
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Create a CacheClient from Cloudflare KV binding.
|
|
93
|
+
*/
|
|
94
|
+
function createKVCacheClient(kv) {
|
|
95
|
+
return {
|
|
96
|
+
get: (key) => Effect.tryPromise({
|
|
97
|
+
try: () => kv.get(key),
|
|
98
|
+
catch: (e) => new CacheClientError('Failed to get from cache', e),
|
|
99
|
+
}),
|
|
100
|
+
put: (key, value, options) => Effect.tryPromise({
|
|
101
|
+
try: () => kv.put(key, value, options),
|
|
102
|
+
catch: (e) => new CacheClientError('Failed to set cache', e),
|
|
103
|
+
}),
|
|
104
|
+
delete: (key) => Effect.tryPromise({
|
|
105
|
+
try: () => kv.delete(key),
|
|
106
|
+
catch: (e) => new CacheClientError('Failed to delete from cache', e),
|
|
107
|
+
}),
|
|
108
|
+
list: (options) => Effect.tryPromise({
|
|
109
|
+
try: () => kv.list(options),
|
|
110
|
+
catch: (e) => new CacheClientError('Failed to list cache keys', e),
|
|
111
|
+
}),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Create a no-op CacheClient that fails with helpful errors when KV is not configured.
|
|
116
|
+
*/
|
|
117
|
+
function createUnconfiguredCacheClient() {
|
|
118
|
+
const error = new CacheClientError('CacheService requires KV binding. Add KV to your wrangler.toml and ensure it is available in c.env.KV');
|
|
119
|
+
return {
|
|
120
|
+
get: () => Effect.fail(error),
|
|
121
|
+
put: () => Effect.fail(error),
|
|
122
|
+
delete: () => Effect.fail(error),
|
|
123
|
+
list: () => Effect.fail(error),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
91
126
|
/**
|
|
92
127
|
* Create a HonertiaRenderer from Hono context.
|
|
93
128
|
*/
|
|
@@ -115,6 +150,9 @@ export function buildContextLayer(c, config) {
|
|
|
115
150
|
const honertiaLayer = Layer.succeed(HonertiaService, createHonertiaRenderer(c));
|
|
116
151
|
// Bindings layer - always available, typed via module augmentation
|
|
117
152
|
const bindingsLayer = Layer.succeed(BindingsService, (c.env ?? {}));
|
|
153
|
+
// Cache layer - backed by KV if available, otherwise unconfigured client
|
|
154
|
+
const kv = c.env?.KV;
|
|
155
|
+
const cacheLayer = Layer.succeed(CacheService, kv ? createKVCacheClient(kv) : createUnconfiguredCacheClient());
|
|
118
156
|
// Database layer - provide helpful error proxy if not configured
|
|
119
157
|
const db = c.var?.db;
|
|
120
158
|
const databaseLayer = Layer.succeed(DatabaseService, (db ??
|
|
@@ -123,7 +161,7 @@ export function buildContextLayer(c, config) {
|
|
|
123
161
|
const auth = c.var?.auth;
|
|
124
162
|
const authLayer = Layer.succeed(AuthService, (auth ??
|
|
125
163
|
createUnconfiguredServiceProxy('AuthService', 'auth: (c) => createAuth(...)', 'auth: (c) => betterAuth({ database: c.var.db, ... })', ErrorCodes.CFG_301_AUTH_NOT_CONFIGURED)));
|
|
126
|
-
let baseLayer = Layer.mergeAll(requestLayer, responseLayer, honertiaLayer, bindingsLayer, databaseLayer, authLayer);
|
|
164
|
+
let baseLayer = Layer.mergeAll(requestLayer, responseLayer, honertiaLayer, bindingsLayer, cacheLayer, databaseLayer, authLayer);
|
|
127
165
|
if (c.var?.authUser) {
|
|
128
166
|
baseLayer = Layer.merge(baseLayer, Layer.succeed(AuthUserService, c.var.authUser));
|
|
129
167
|
}
|
package/dist/effect/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Re-exports all Effect-related functionality.
|
|
5
5
|
*/
|
|
6
|
-
export { DatabaseService, AuthService, AuthUserService, EmailService, HonertiaService, RequestService, ResponseFactoryService, BindingsService, type AuthUser, type EmailClient, type HonertiaRenderer, type RequestContext, type ResponseFactory, type HonertiaDatabaseType, type HonertiaAuthType, type HonertiaBindingsType, type DatabaseType, type SchemaType, type AuthType, type BindingsType, } from './services.js';
|
|
6
|
+
export { DatabaseService, AuthService, AuthUserService, EmailService, HonertiaService, RequestService, ResponseFactoryService, BindingsService, CacheService, CacheClientError, type AuthUser, type EmailClient, type HonertiaRenderer, type RequestContext, type ResponseFactory, type CacheClient, type HonertiaDatabaseType, type HonertiaAuthType, type HonertiaBindingsType, type DatabaseType, type SchemaType, type AuthType, type BindingsType, } from './services.js';
|
|
7
7
|
export { ValidationError, UnauthorizedError, NotFoundError, ForbiddenError, HttpError, RouteConfigurationError, HonertiaConfigurationError, Redirect, isStructuredError, toStructuredError, type AppError, type StructuredErrorCapable, } from './errors.js';
|
|
8
8
|
export type { ErrorCategory, ErrorContext, SourceLocation, CodeSnippet, RouteContext, HandlerContext, RequestContext as ErrorRequestContext, ServiceContext, FixType, FixPosition, FixOperation, PostAction, FixSuggestion, ErrorDocs, HonertiaStructuredError, FieldError, ValidationErrorData, ConfigurationErrorData, BindingErrorData, ErrorDefinition, FixGenerator, } from './error-types.js';
|
|
9
9
|
export { ErrorCodes, ErrorCatalog, createStructuredError, getConfigErrorCode, getErrorDefinition, getErrorsByCategory, type ErrorCode, } from './error-catalog.js';
|
|
@@ -21,5 +21,6 @@ export { RouteRegistry, getGlobalRegistry, resetGlobalRegistry, type HttpMethod,
|
|
|
21
21
|
export { describeRoute, createRouteTester, generateTestCases, type TestUserType, type TestUser, type TestRequestOptions, type TestExpectation, type TestContext, type TestCaseOptions, type TestFn, type TestAppConfig, } from './testing.js';
|
|
22
22
|
export { TestLayer, TestCaptureService, type TestCaptures, } from './test-layers.js';
|
|
23
23
|
export { BoundModels, BoundModelNotFound, bound, pluralize, parseBindings, toHonoPath, type ParsedBinding, type BoundModel, } from './binding.js';
|
|
24
|
+
export { CacheError, cache, cacheGet, cacheSet, cacheInvalidate, cacheInvalidatePrefix, } from '../cache.js';
|
|
24
25
|
export { RequireAuthLayer, RequireGuestLayer, isAuthenticated, currentUser, requireAuth, requireGuest, shareAuth, shareAuthMiddleware, effectAuthRoutes, betterAuthFormAction, betterAuthLogoutAction, loadUser, type AuthRoutesConfig, type BetterAuthFormActionConfig, type BetterAuthLogoutConfig, type BetterAuthActionResult, } from './auth.js';
|
|
25
26
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/effect/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,eAAe,EACf,WAAW,EACX,eAAe,EACf,YAAY,EACZ,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,YAAY,GAClB,MAAM,eAAe,CAAA;AAGtB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,SAAS,EACT,uBAAuB,EACvB,0BAA0B,EAC1B,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,QAAQ,EACb,KAAK,sBAAsB,GAC5B,MAAM,aAAa,CAAA;AAGpB,YAAY,EACV,aAAa,EACb,YAAY,EACZ,cAAc,EACd,WAAW,EACX,YAAY,EACZ,cAAc,EACd,cAAc,IAAI,mBAAmB,EACrC,cAAc,EACd,OAAO,EACP,WAAW,EACX,YAAY,EACZ,UAAU,EACV,aAAa,EACb,SAAS,EACT,uBAAuB,EACvB,UAAU,EACV,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EACf,YAAY,GACb,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,UAAU,EACV,YAAY,EACZ,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,SAAS,GACf,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EACjB,KAAK,sBAAsB,GAC5B,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAA;AAG3B,cAAc,aAAa,CAAA;AAG3B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,6BAA6B,EAC7B,QAAQ,EACR,eAAe,EACf,WAAW,EACX,SAAS,EACT,KAAK,SAAS,EACd,KAAK,OAAO,EACZ,KAAK,qBAAqB,GAC3B,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,aAAa,EACb,cAAc,GACf,MAAM,yBAAyB,CAAA;AAGhC,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,aAAa,EACb,MAAM,EACN,MAAM,EACN,eAAe,EACf,uBAAuB,GACxB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,MAAM,EACN,SAAS,EACT,UAAU,EACV,aAAa,EACb,KAAK,MAAM,GACZ,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,QAAQ,EACR,MAAM,EACN,gBAAgB,EAChB,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,SAAS,EACT,WAAW,EACX,YAAY,EACZ,KAAK,GACN,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,MAAM,EACX,KAAK,aAAa,GACnB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,KAAK,YAAY,GAClB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,KAAK,EACL,SAAS,EACT,aAAa,EACb,UAAU,EACV,KAAK,aAAa,EAClB,KAAK,UAAU,GAChB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,WAAW,EACX,YAAY,EACZ,SAAS,EACT,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,QAAQ,EACR,KAAK,gBAAgB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC5B,MAAM,WAAW,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/effect/index.ts"],"names":[],"mappings":"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"}
|
package/dist/effect/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Re-exports all Effect-related functionality.
|
|
5
5
|
*/
|
|
6
6
|
// Services
|
|
7
|
-
export { DatabaseService, AuthService, AuthUserService, EmailService, HonertiaService, RequestService, ResponseFactoryService, BindingsService, } from './services.js';
|
|
7
|
+
export { DatabaseService, AuthService, AuthUserService, EmailService, HonertiaService, RequestService, ResponseFactoryService, BindingsService, CacheService, CacheClientError, } from './services.js';
|
|
8
8
|
// Errors
|
|
9
9
|
export { ValidationError, UnauthorizedError, NotFoundError, ForbiddenError, HttpError, RouteConfigurationError, HonertiaConfigurationError, Redirect, isStructuredError, toStructuredError, } from './errors.js';
|
|
10
10
|
// Error Catalog
|
|
@@ -37,5 +37,7 @@ export { describeRoute, createRouteTester, generateTestCases, } from './testing.
|
|
|
37
37
|
export { TestLayer, TestCaptureService, } from './test-layers.js';
|
|
38
38
|
// Route Model Binding
|
|
39
39
|
export { BoundModels, BoundModelNotFound, bound, pluralize, parseBindings, toHonoPath, } from './binding.js';
|
|
40
|
+
// Cache
|
|
41
|
+
export { CacheError, cache, cacheGet, cacheSet, cacheInvalidate, cacheInvalidatePrefix, } from '../cache.js';
|
|
40
42
|
// Auth
|
|
41
43
|
export { RequireAuthLayer, RequireGuestLayer, isAuthenticated, currentUser, requireAuth, requireGuest, shareAuth, shareAuthMiddleware, effectAuthRoutes, betterAuthFormAction, betterAuthLogoutAction, loadUser, } from './auth.js';
|
|
@@ -212,5 +212,44 @@ export interface ResponseFactory {
|
|
|
212
212
|
declare const ResponseFactoryService_base: Context.TagClass<ResponseFactoryService, "honertia/ResponseFactory", ResponseFactory>;
|
|
213
213
|
export declare class ResponseFactoryService extends ResponseFactoryService_base {
|
|
214
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Cache Service - KV-backed caching for expensive operations
|
|
217
|
+
*
|
|
218
|
+
* Automatically provided by setupHonertia when KV binding is available.
|
|
219
|
+
* Falls back to a no-op implementation if KV is not configured.
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* ```typescript
|
|
223
|
+
* // In your action
|
|
224
|
+
* const cacheService = yield* CacheService
|
|
225
|
+
* const cached = yield* cacheService.get('user:123')
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
export interface CacheClient {
|
|
229
|
+
get(key: string): Effect.Effect<string | null, CacheClientError>;
|
|
230
|
+
put(key: string, value: string, options?: {
|
|
231
|
+
expirationTtl?: number;
|
|
232
|
+
}): Effect.Effect<void, CacheClientError>;
|
|
233
|
+
delete(key: string): Effect.Effect<void, CacheClientError>;
|
|
234
|
+
list(options?: {
|
|
235
|
+
prefix?: string;
|
|
236
|
+
}): Effect.Effect<{
|
|
237
|
+
keys: Array<{
|
|
238
|
+
name: string;
|
|
239
|
+
}>;
|
|
240
|
+
}, CacheClientError>;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Error from cache client operations.
|
|
244
|
+
*/
|
|
245
|
+
export declare class CacheClientError {
|
|
246
|
+
readonly reason: string;
|
|
247
|
+
readonly cause?: unknown | undefined;
|
|
248
|
+
readonly _tag = "CacheClientError";
|
|
249
|
+
constructor(reason: string, cause?: unknown | undefined);
|
|
250
|
+
}
|
|
251
|
+
declare const CacheService_base: Context.TagClass<CacheService, "honertia/Cache", CacheClient>;
|
|
252
|
+
export declare class CacheService extends CacheService_base {
|
|
253
|
+
}
|
|
215
254
|
export {};
|
|
216
255
|
//# sourceMappingURL=services.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../src/effect/services.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../src/effect/services.ts"],"names":[],"mappings":"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"}
|
package/dist/effect/services.js
CHANGED
|
@@ -47,3 +47,17 @@ export class RequestService extends Context.Tag('honertia/Request')() {
|
|
|
47
47
|
}
|
|
48
48
|
export class ResponseFactoryService extends Context.Tag('honertia/ResponseFactory')() {
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Error from cache client operations.
|
|
52
|
+
*/
|
|
53
|
+
export class CacheClientError {
|
|
54
|
+
reason;
|
|
55
|
+
cause;
|
|
56
|
+
_tag = 'CacheClientError';
|
|
57
|
+
constructor(reason, cause) {
|
|
58
|
+
this.reason = reason;
|
|
59
|
+
this.cause = cause;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export class CacheService extends Context.Tag('honertia/Cache')() {
|
|
63
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "honertia",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
4
4
|
"description": "Inertia.js-style server-driven SPA adapter for Hono",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
"./cli": {
|
|
31
31
|
"types": "./dist/cli/index.d.ts",
|
|
32
32
|
"import": "./dist/cli/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./cache": {
|
|
35
|
+
"types": "./dist/cache.d.ts",
|
|
36
|
+
"import": "./dist/cache.js"
|
|
33
37
|
}
|
|
34
38
|
},
|
|
35
39
|
"files": [
|