Skip to content
Open
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
58 changes: 58 additions & 0 deletions packages/flowerbase/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ Install the `@flowerforce/flowerbase` library, which provides the tools required
npm install @flowerforce/flowerbase
```

If you want to use Redis as cache provider, install `redis` in your application too:

```bash
npm install redis
```

Add Typescript

```bash
Expand Down Expand Up @@ -123,6 +129,58 @@ initialize({

This initializes the Flowerbase integration, connecting your application to MongoDB Atlas.

### 🧠 Optional Cache Configuration

Flowerbase can cache server-side Mongo reads and invalidate them automatically after writes.

Supported providers:

- `memory`: in-process cache, useful for local development or single-instance deployments
- `redis`: shared cache for multi-instance deployments

The cache is configured during `initialize()` and is applied to idempotent read operations exposed by the `mongodb-atlas` service. Invalidation is scoped to the current authorization context, so a successful write clears cached reads only for the same `database + collection + runAsSystem + filters` context.

#### Memory cache

```ts
import { initialize } from '@flowerforce/flowerbase';

initialize({
projectId: 'my-project-id',
mongodbUrl: process.env.MONGODB_URL,
jwtSecret: process.env.JWT_SECRET,
cache: {
provider: 'memory',
defaultTtlSeconds: 60,
maxEntries: 1000
}
})
```

#### Redis cache

```ts
import { initialize } from '@flowerforce/flowerbase';

initialize({
projectId: 'my-project-id',
mongodbUrl: process.env.MONGODB_URL,
jwtSecret: process.env.JWT_SECRET,
cache: {
provider: 'redis',
url: process.env.REDIS_URL!,
defaultTtlSeconds: 300
}
})
```

Cache notes:

- no cache provider is enabled by default
- Redis does not fall back to memory automatically
- reads executed with a Mongo session are not cached
- the memory provider supports `maxEntries` and evicts the least recently used entry when the limit is reached

## 🛠️ 5. Server Configuration – Authentication, Rules, and Functions
After setting up the base Flowerbase integration, you can now configure advanced features to control how your backend behaves.

Expand Down
1 change: 1 addition & 0 deletions packages/flowerbase/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"lodash": "^4.17.21",
"node-cron": "^3.0.3",
"nodemon": "^3.1.7",
"redis": "^4.7.0",
"undici": "^7.1.0"
},
"devDependencies": {
Expand Down
39 changes: 39 additions & 0 deletions packages/flowerbase/src/cache/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {
buildCacheKey,
buildCollectionCacheTag,
createCacheProvider
} from '..'

describe('cache provider', () => {
it('stores and invalidates memory entries by tag', async () => {
const cache = await createCacheProvider({ provider: 'memory' })
const tag = buildCollectionCacheTag('main', 'todos')
const key = buildCacheKey({ operation: 'findOne', id: 'todo-1' })

await cache.set(key, { _id: 'todo-1', done: false }, { tags: [tag] })

expect(await cache.get(key)).toEqual({ _id: 'todo-1', done: false })

await cache.invalidateTags([tag])

expect(await cache.get(key)).toBeUndefined()
})

it('evicts the least recently used entry when maxEntries is reached', async () => {
const cache = await createCacheProvider({ provider: 'memory', maxEntries: 2 })
const firstKey = buildCacheKey({ id: 'first' })
const secondKey = buildCacheKey({ id: 'second' })
const thirdKey = buildCacheKey({ id: 'third' })

await cache.set(firstKey, { id: 'first' })
await cache.set(secondKey, { id: 'second' })

expect(await cache.get(firstKey)).toEqual({ id: 'first' })

await cache.set(thirdKey, { id: 'third' })

expect(await cache.get(firstKey)).toEqual({ id: 'first' })
expect(await cache.get(secondKey)).toBeUndefined()
expect(await cache.get(thirdKey)).toEqual({ id: 'third' })
})
})
Loading
Loading