@objectstack/metadata 4.0.4 → 4.1.0
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 +99 -12
- package/dist/index.cjs +793 -534
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +208 -6151
- package/dist/index.d.ts +208 -6151
- package/dist/index.js +794 -532
- package/dist/index.js.map +1 -1
- package/dist/migrations/index.cjs +156 -0
- package/dist/migrations/index.cjs.map +1 -0
- package/dist/migrations/index.d.cts +103 -0
- package/dist/migrations/index.d.ts +103 -0
- package/dist/migrations/index.js +127 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/node.cjs +793 -534
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +2 -3
- package/dist/node.d.ts +2 -3
- package/dist/node.js +794 -532
- package/dist/node.js.map +1 -1
- package/package.json +28 -8
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **Metadata Loading, Persistence & Customization Layer for ObjectStack.**
|
|
4
4
|
|
|
5
|
-
`@objectstack/metadata` is the central service responsible for loading, validating, persisting and watching all metadata definitions (Objects, Views, Flows, Apps, Agents, etc.) in the ObjectStack platform.
|
|
5
|
+
`@objectstack/metadata` is the central service responsible for loading, validating, optionally persisting, and watching all metadata definitions (Objects, Views, Flows, Apps, Agents, etc.) in the ObjectStack platform.
|
|
6
6
|
|
|
7
7
|
It implements the **`IMetadataService`** contract from `@objectstack/spec` and acts as the single source of truth that all other packages depend on.
|
|
8
8
|
|
|
@@ -40,17 +40,22 @@ It implements the **`IMetadataService`** contract from `@objectstack/spec` and a
|
|
|
40
40
|
|
|
41
41
|
## Core Concepts
|
|
42
42
|
|
|
43
|
-
### 1. Metadata Sources (
|
|
43
|
+
### 1. Metadata Sources (Runtime Boundary)
|
|
44
44
|
|
|
45
|
-
ObjectStack
|
|
45
|
+
ObjectStack separates ObjectOS runtime reads from control-plane metadata
|
|
46
|
+
persistence:
|
|
46
47
|
|
|
47
|
-
|
|
|
48
|
-
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
| `
|
|
48
|
+
| Runtime context | Storage | Mutability | Description |
|
|
49
|
+
|:----------------|:--------|:-----------|:------------|
|
|
50
|
+
| ObjectOS local/dev | Filesystem or local artifact | Read-only at boot | `MetadataPlugin` scans files or hydrates from `dist/objectstack.json`. |
|
|
51
|
+
| ObjectOS production | Artifact API response | Read-only at boot | Metadata is immutable for a `commitId` / `checksum`; project DB stores business rows only. |
|
|
52
|
+
| Control plane / tooling | `DatabaseLoader` when explicitly configured | Writable | Stores project metadata revisions, overlays, and history outside the ObjectOS project DB. |
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
`MetadataPlugin` does **not** automatically bridge ObjectQL to
|
|
55
|
+
`DatabaseLoader`, and it does not register `sys_metadata` /
|
|
56
|
+
`sys_metadata_history` into the ObjectOS manifest. Database-backed metadata
|
|
57
|
+
persistence remains available through `MetadataManager.setDatabaseDriver()` or
|
|
58
|
+
`setDataEngine()` for control-plane services that opt in explicitly.
|
|
54
59
|
|
|
55
60
|
### 2. Loaders
|
|
56
61
|
|
|
@@ -61,7 +66,7 @@ Loaders are pluggable data sources that know how to read/write metadata from dif
|
|
|
61
66
|
| `FilesystemLoader` | `file:` | ✅ | ✅ | ✅ | Implemented |
|
|
62
67
|
| `MemoryLoader` | `memory:` | ✅ | ✅ | ❌ | Implemented |
|
|
63
68
|
| `RemoteLoader` | `http:` | ✅ | ✅ | ❌ | Implemented |
|
|
64
|
-
| `DatabaseLoader` | `datasource:` | ✅ | ✅ | ❌ | Implemented
|
|
69
|
+
| `DatabaseLoader` | `datasource:` | ✅ | ✅ | ❌ | Implemented (read-through LRU cache) |
|
|
65
70
|
|
|
66
71
|
### 3. Serializers
|
|
67
72
|
|
|
@@ -69,7 +74,7 @@ Serializers convert metadata objects to/from different file formats:
|
|
|
69
74
|
|
|
70
75
|
- **JSONSerializer** — `.json` files with optional key sorting
|
|
71
76
|
- **YAMLSerializer** — `.yaml`/`.yml` files (JSON_SCHEMA for security)
|
|
72
|
-
- **TypeScriptSerializer** — `.ts`/`.js` module exports (for `
|
|
77
|
+
- **TypeScriptSerializer** — `.ts`/`.js` module exports (for `ObjectSchema.create()`, `defineView()`, etc.)
|
|
73
78
|
|
|
74
79
|
### 4. Overlay / Customization System
|
|
75
80
|
|
|
@@ -110,7 +115,76 @@ Integrates with the ObjectStack kernel plugin system:
|
|
|
110
115
|
|
|
111
116
|
- Registers as the primary `IMetadataService` provider
|
|
112
117
|
- Auto-loads all metadata types from the filesystem on startup (sorted by `loadOrder`)
|
|
118
|
+
- Can hydrate runtime metadata from a local project artifact (`dist/objectstack.json`)
|
|
113
119
|
- Supports YAML, JSON, TypeScript, and JavaScript metadata formats
|
|
120
|
+
- Keeps ObjectOS metadata read-only; database persistence is not auto-enabled
|
|
121
|
+
|
|
122
|
+
#### Bootstrap Modes
|
|
123
|
+
|
|
124
|
+
`MetadataPluginConfigSchema.bootstrap` controls how the plugin primes metadata
|
|
125
|
+
on `start()`. Pick the mode that matches the deployment target:
|
|
126
|
+
|
|
127
|
+
| Mode | When to use | Behavior |
|
|
128
|
+
|:-----|:------------|:---------|
|
|
129
|
+
| `eager` (default) | Local dev, traditional servers | Scans filesystem (or hydrates the artifact source if set) at boot. |
|
|
130
|
+
| `lazy` | Cold-start sensitive runtimes, on-demand workloads | Skips the filesystem priming pass — reads flow through `MetadataManager.load*` / `list*` and registered loaders (incl. the DatabaseLoader read-through cache). An `artifactSource` is still honored if provided. |
|
|
131
|
+
| `artifact-only` | **Edge / serverless / read-only production** | Refuses to touch the filesystem. Requires `artifactSource.mode = 'local-file'`. Throws if no artifact source is configured. |
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// Edge / serverless: fail-fast if no artifact is wired
|
|
135
|
+
new MetadataPlugin({
|
|
136
|
+
config: { bootstrap: 'artifact-only' },
|
|
137
|
+
artifactSource: { mode: 'local-file', path: './dist/objectstack.json' },
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// On-demand reads via DatabaseLoader, no FS scan
|
|
141
|
+
new MetadataPlugin({
|
|
142
|
+
config: { bootstrap: 'lazy' },
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
#### Persistence Write Gates
|
|
147
|
+
|
|
148
|
+
`MetadataManagerConfigSchema.persistence` is a two-axis runtime gate that lets
|
|
149
|
+
you freeze metadata mutation in sealed deployments while leaving reads open.
|
|
150
|
+
Both flags default to `true` so dev / Studio flows are unaffected.
|
|
151
|
+
|
|
152
|
+
| Flag | Effect when `false` |
|
|
153
|
+
|:-----|:--------------------|
|
|
154
|
+
| `persistence.writable` | `MetadataManager.register()` becomes a no-op (or throws when `validation.throwOnError` is set). Use for read-only project kernels booted from a compiled artifact. |
|
|
155
|
+
| `persistence.overlayWritable` | `MetadataManager.saveOverlay()` is rejected. Use to disable Studio overlays in fully-frozen production deployments. |
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
new MetadataManager({
|
|
159
|
+
persistence: { writable: false, overlayWritable: false },
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
#### DatabaseLoader Read-Through Cache
|
|
164
|
+
|
|
165
|
+
`DatabaseLoader` wraps `load` / `loadMany` / `list` / `stat` results in a
|
|
166
|
+
generic LRU cache (see `src/utils/lru-cache.ts`). Writes invalidate the
|
|
167
|
+
affected entries, so reads always observe writes made through the same loader
|
|
168
|
+
instance; out-of-band SQL writes are honored within `ttl` milliseconds.
|
|
169
|
+
|
|
170
|
+
Configuration lives under `cache.databaseLoader`:
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
new MetadataManager({
|
|
174
|
+
datasource: 'default',
|
|
175
|
+
cache: {
|
|
176
|
+
enabled: true,
|
|
177
|
+
databaseLoader: {
|
|
178
|
+
enabled: true,
|
|
179
|
+
maxSize: 500, // Max cached (type, name) entries
|
|
180
|
+
ttl: 60_000, // Cache TTL in milliseconds
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
The cache exposes diagnostic counters (`size` / `hits` / `misses` / `hitRate`)
|
|
187
|
+
through `LRUCache.stats()` for `metrics` endpoints.
|
|
114
188
|
|
|
115
189
|
## Metadata Types
|
|
116
190
|
|
|
@@ -194,7 +268,7 @@ manager.watchService('object', (event) => {
|
|
|
194
268
|
```typescript
|
|
195
269
|
import { MetadataPlugin } from '@objectstack/metadata/node';
|
|
196
270
|
|
|
197
|
-
const plugin = MetadataPlugin({
|
|
271
|
+
const plugin = new MetadataPlugin({
|
|
198
272
|
rootDir: './src',
|
|
199
273
|
watch: process.env.NODE_ENV === 'development',
|
|
200
274
|
});
|
|
@@ -202,6 +276,19 @@ const plugin = MetadataPlugin({
|
|
|
202
276
|
kernel.use(plugin);
|
|
203
277
|
```
|
|
204
278
|
|
|
279
|
+
### With Local Artifact Boot
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
import { MetadataPlugin } from '@objectstack/metadata/node';
|
|
283
|
+
|
|
284
|
+
const plugin = new MetadataPlugin({
|
|
285
|
+
watch: false,
|
|
286
|
+
artifactSource: { mode: 'local-file', path: './dist/objectstack.json' },
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
kernel.use(plugin);
|
|
290
|
+
```
|
|
291
|
+
|
|
205
292
|
## Package Publishing
|
|
206
293
|
|
|
207
294
|
ObjectStack supports **package-level metadata publishing** — all metadata items within a package are published atomically.
|