Skip to content

Commit d5e13d7

Browse files
committed
feat: add generic scope-aware module loader package
- ModuleConfigLoader<T> base class with TTL caching + scope resolution - 5 concrete loaders: function, namespace, secrets, storage, invocation - ModuleLoader facade composing all sub-loaders - No hardcoded defaults — throws ModuleNotProvisionedError or AmbiguousScopeError - Integration tests via pgsql-test with metaschema seed adapter - CI workflow using constructiveio/postgres-plus:18
1 parent c262403 commit d5e13d7

12 files changed

Lines changed: 1184 additions & 33 deletions

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: Module Loader Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
workflow_dispatch: {}
9+
10+
concurrency:
11+
group: ${{ github.workflow }}-${{ github.ref }}
12+
cancel-in-progress: true
13+
14+
jobs:
15+
test:
16+
name: Module loader integration tests
17+
runs-on: ubuntu-latest
18+
19+
env:
20+
PGHOST: localhost
21+
PGPORT: 5432
22+
PGUSER: postgres
23+
PGPASSWORD: password
24+
PGDATABASE: postgres
25+
26+
services:
27+
pg_db:
28+
image: constructiveio/postgres-plus:18
29+
env:
30+
POSTGRES_USER: postgres
31+
POSTGRES_PASSWORD: password
32+
ports:
33+
- 5432:5432
34+
options: >-
35+
--health-cmd "pg_isready -U postgres"
36+
--health-interval 10s
37+
--health-timeout 5s
38+
--health-retries 5
39+
40+
steps:
41+
- uses: actions/checkout@v5
42+
43+
- uses: pnpm/action-setup@v6
44+
45+
- uses: actions/setup-node@v5
46+
with:
47+
node-version: '22'
48+
cache: 'pnpm'
49+
50+
- name: Generate function packages
51+
run: node --experimental-strip-types scripts/generate.ts
52+
53+
- name: Install dependencies
54+
run: pnpm install --frozen-lockfile
55+
56+
- name: Build module-loader
57+
run: pnpm --filter @constructive-io/module-loader build
58+
59+
- name: Run module-loader tests
60+
run: pnpm --filter @constructive-io/module-loader test

packages/module-loader/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# @constructive-io/module-loader
2+
3+
Generic scope-aware MetaSchema module resolution for constructive-functions.
4+
5+
Queries `metaschema_modules_public.*_module` tables to resolve schema/table locations dynamically. No hardcoded defaults — throws explicitly if a module is not provisioned.
6+
7+
## Usage
8+
9+
```typescript
10+
import { ModuleLoader } from '@constructive-io/module-loader';
11+
12+
const loader = new ModuleLoader({ pool });
13+
14+
// Resolve function module config for a database
15+
const fnConfig = await loader.function.load(databaseId);
16+
// → { scope, publicSchema, privateSchema, definitionsTable, secretDefinitionsTable }
17+
18+
// With explicit scope (when multiple instances exist)
19+
const orgConfig = await loader.function.load(databaseId, 'org');
20+
21+
// Enumerate all instances
22+
const all = await loader.function.loadAll(databaseId);
23+
```
24+
25+
## Scope Resolution
26+
27+
- `scope` provided → filter by it; throw `ModuleNotProvisionedError` if not found
28+
- `scope` null + 1 instance → return it (unambiguous)
29+
- `scope` null + 0 instances → throw `ModuleNotProvisionedError`
30+
- `scope` null + 2+ instances → throw `AmbiguousScopeError`

0 commit comments

Comments
 (0)