@qaecy/cue-sdk 0.0.6 → 0.0.9
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/PORTAL_MIGRATION.md +346 -0
- package/README.md +50 -3
- package/cue-CcNGkuUu.js +3599 -0
- package/index.d.ts +13 -1
- package/index.js +15 -3
- package/lib/api.d.ts +2 -3
- package/lib/auth.d.ts +52 -2
- package/lib/cache.d.ts +26 -0
- package/lib/cue.d.ts +42 -2
- package/lib/documents.d.ts +84 -0
- package/lib/entities.d.ts +107 -0
- package/lib/models.d.ts +170 -8
- package/lib/privileges.d.ts +53 -0
- package/lib/profile.d.ts +29 -5
- package/lib/project-view.d.ts +107 -0
- package/lib/project.d.ts +17 -2
- package/lib/schema.d.ts +66 -0
- package/lib/signal.d.ts +54 -0
- package/lib/sync.d.ts +76 -3
- package/node.js +46 -380
- package/package.json +1 -1
- package/variables.d.ts +42 -0
- package/cue-BA1pOKTu.js +0 -357
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
# Cue SDK — Portal Migration
|
|
2
|
+
|
|
3
|
+
> **Goal:** All server communication in cue-portal flows through `js-cue-sdk`, replacing direct usage of `js-firebase` and `cue-repos`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Current State
|
|
8
|
+
|
|
9
|
+
| Layer | Status |
|
|
10
|
+
|-------|--------|
|
|
11
|
+
| **js-cue-sdk** — `Cue`, `CueAuth`, `CueProjects`, `CueProfile`, `CuePrivileges`, `CueCache` | ✅ Active — all major modules built |
|
|
12
|
+
| **js-databases** — `IDocStore`, `FirestoreDocStore`, `CueBlobStorage` | ✅ All repos delegating to these |
|
|
13
|
+
| **cue-repos** (Angular) — now thin adapters over the SDK | ✅ Migrated |
|
|
14
|
+
| **js-firebase** (`CueFirebase`) | Kept — CLI, widget, admin depend on it |
|
|
15
|
+
| **cue-views** (Angular) — SPARQL + entity/doc signals | 🔄 In progress — core data classes built, facade + adapters pending |
|
|
16
|
+
|
|
17
|
+
**Remaining `js-firebase` imports in the portal:**
|
|
18
|
+
- `libs/ng/cue-repos/src/lib/firebase.service.ts` — intentional (this IS the `CueFirebase` wrapper)
|
|
19
|
+
- `apps/frontend/cue-portal/src/main.ts` — app bootstrap; addressed in Final phase
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Remaining Work
|
|
24
|
+
|
|
25
|
+
### Phase 6 — Knowledge Graph View State (`CueProjectView`)
|
|
26
|
+
|
|
27
|
+
Full investigation of `cue-views` services completed. The three heaviest SPARQL data classes are already built in `js-cue-sdk`. What remains is a thin facade, the Angular adapter wiring, and gateway API additions for the remaining services.
|
|
28
|
+
|
|
29
|
+
#### Coverage summary — `cue-views` services vs SDK
|
|
30
|
+
|
|
31
|
+
| `cue-views` service | SDK status | Owner after migration |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| `TriplestoreService` | ✅ Replaced by `CueApi.sparql()` | SDK |
|
|
34
|
+
| `AvailableCategoriesService` | ✅ Replaced by `CueProjectSchema` | Angular bridge |
|
|
35
|
+
| `ProjectDocumentsService` | ✅ Replaced by `CueProjectDocuments.fetchOverview()` | Angular bridge |
|
|
36
|
+
| `DocumentInfoService` (SPARQL) | ✅ Replaced by `CueProjectDocuments.requestDocumentData()` | Angular bridge; callbacks stay Angular |
|
|
37
|
+
| `EntityInfoService` (core) | ✅ Replaced by `CueProjectEntities` | Angular bridge |
|
|
38
|
+
| `DocumentDuplicatesService` | ⚠️ Count covered; full path list not yet in SDK | Needs `CueProjectDocuments.fetchDuplicates()` |
|
|
39
|
+
| `DocumentEntitiesService` | ❌ Not covered | Needs new SDK read queries + `CueApi` write methods |
|
|
40
|
+
| `RelatedService` | ❌ Not covered | Needs `CueApi.relatedDocuments()` |
|
|
41
|
+
| `ContentCategoryService` | ❌ Not covered | Needs `CueApi.changeContentCategory()` |
|
|
42
|
+
| `AgentService` | ❌ Not covered | Needs `CueApi.streamPlan()` / `CueApi.streamAct()` |
|
|
43
|
+
| `ResourceService` | ❌ Not covered | Per-document viewer; stays Angular or becomes `CueDocumentResource` |
|
|
44
|
+
| `FileLocationsService` | ❌ Not covered | Low priority; stays Angular or becomes private helper |
|
|
45
|
+
| `FileContentService` | ❌ Not covered | Depends on `FileRepo`; stays Angular-layer |
|
|
46
|
+
| `CueViewsService` | N/A — config/context root | Angular adapter responsibility |
|
|
47
|
+
| `CommandsService` | N/A — thin facade | Angular adapter responsibility |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
#### Phase 6a — `CueProjectView` facade _(next step)_
|
|
52
|
+
|
|
53
|
+
Create `libs/js/cue-sdk/src/lib/project-view.ts` — a single class that composes `CueProjectSchema`, `CueProjectEntities`, and `CueProjectDocuments` and adds `search()`.
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
const view = cue.createProjectView(projectId, { language: 'en', queryCache });
|
|
57
|
+
|
|
58
|
+
// Proxied signals from sub-classes
|
|
59
|
+
view.availableContentCategories // → schema.availableContentCategories
|
|
60
|
+
view.availableEntityCategories // → schema.availableEntityCategories
|
|
61
|
+
view.availableEntityRelationships // → schema.availableEntityRelationships
|
|
62
|
+
view.entityInfoMap // → entities.entityInfoMap
|
|
63
|
+
view.entityGraph // → entities.entityGraph
|
|
64
|
+
view.documentInfoMap // → documents.documentInfoMap
|
|
65
|
+
view.projectDocumentsData // → documents.projectDocumentsData
|
|
66
|
+
|
|
67
|
+
// Proxied methods
|
|
68
|
+
view.requestEntityData(ids, includeMentionCount?)
|
|
69
|
+
view.requestEntityLocations(ids)
|
|
70
|
+
view.fetchEntityRelationships(iri)
|
|
71
|
+
view.fetchEntityDocuments(iri)
|
|
72
|
+
view.requestDocumentData(ids)
|
|
73
|
+
|
|
74
|
+
// New: search
|
|
75
|
+
view.searchResults // ReadonlySignal<DocumentRef[]>
|
|
76
|
+
view.search(term, options?) // Calls CueApi.search(), appends to searchResults
|
|
77
|
+
|
|
78
|
+
// Lifecycle
|
|
79
|
+
view.setLanguage(lang) // Calls schema.setLanguage(); docs.setLanguage()
|
|
80
|
+
view.destroy() // Tears down subscriptions
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`Cue` gains a factory method:
|
|
84
|
+
```ts
|
|
85
|
+
cue.createProjectView(projectId: string, opts: { language: string, queryCache?: QueryCache }): CueProjectView
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Files to create/modify:**
|
|
89
|
+
- `libs/js/cue-sdk/src/lib/project-view.ts` — new `CueProjectView` class
|
|
90
|
+
- `libs/js/cue-sdk/src/lib/cue.ts` — add `createProjectView()` method
|
|
91
|
+
- `libs/js/cue-sdk/src/index.ts` — export `CueProjectView` + related types
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
#### Phase 6b — Angular adapters in `cue-views`
|
|
96
|
+
|
|
97
|
+
Replace the heavy Angular services with thin bridges that subscribe to SDK signals and forward method calls. Each bridge service creates/receives a `CueProjectView` instance from the Angular DI tree.
|
|
98
|
+
|
|
99
|
+
| Angular service | Migration action |
|
|
100
|
+
|---|---|
|
|
101
|
+
| `AvailableCategoriesService` | Replace with computed signals bridging `view.availableContentCategories` etc. via `toSignal(obs)` or `subscribe()` |
|
|
102
|
+
| `ProjectDocumentsService` | Replace signal with bridge to `view.projectDocumentsData`; call `view.fetchOverview()` on project init |
|
|
103
|
+
| `DocumentInfoService` | Delegate `requestDocumentData()` to `view`; keep `documentListHandlers` callbacks (download, navigate) Angular-side |
|
|
104
|
+
| `EntityInfoService` | Delegate all 4 public methods to `view`; bridge `entityInfoMap` and `entityGraph` signals |
|
|
105
|
+
| `TriplestoreService` | Remove — callers switch to `CueApi.sparql()` directly or via `view` |
|
|
106
|
+
|
|
107
|
+
The Angular adapter pattern:
|
|
108
|
+
```ts
|
|
109
|
+
// In cue-views Angular service
|
|
110
|
+
readonly entityInfoMap = toSignal(
|
|
111
|
+
new Observable(obs => this._view.entityInfoMap.subscribe(v => obs.next(v)))
|
|
112
|
+
);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
#### Phase 6c — Gateway API additions (`CueApi`)
|
|
118
|
+
|
|
119
|
+
These are needed before the remaining `cue-views` services can be bridged:
|
|
120
|
+
|
|
121
|
+
| Method | Source service | HTTP call |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| `CueApi.relatedDocuments(contentUUID, k)` | `RelatedService` | `POST {gatewayURL}/endpoints.relatedDocuments` |
|
|
124
|
+
| `CueApi.changeContentCategory(payload)` | `ContentCategoryService` | `PATCH {gatewayURL}/endpoints.contentCategoryChange` |
|
|
125
|
+
| `CueApi.streamPlan(prompt, cb)` | `AgentService` | Streaming `POST {gatewayURL}/endpoints.agentPlan` via `fetchStream()` |
|
|
126
|
+
| `CueApi.streamAct(plan, cb)` | `AgentService` | Streaming `POST {gatewayURL}/endpoints.agentAct` via `fetchStream()` |
|
|
127
|
+
| `CueApi.saveEntityMentions(payload)` | `DocumentEntitiesService` | `POST/DELETE {gatewayURL}/endpoints.entityMentionBatch` |
|
|
128
|
+
| `CueApi.saveSelectors(payload)` | `DocumentEntitiesService` | `POST {gatewayURL}/endpoints.selectorBatch` |
|
|
129
|
+
|
|
130
|
+
The `gatewayURL` and project-scoped `Authorization`/`x-project-id` headers are already in `CueApi` — these are additive methods only.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
#### Phase 6d — SDK data additions
|
|
135
|
+
|
|
136
|
+
Small additions to existing SDK classes:
|
|
137
|
+
|
|
138
|
+
- **`CueProjectDocuments.fetchDuplicates()`** — returns `Record<uuid, string[]>` (all file paths per content UUID where count > 1). `DocumentDuplicatesService` currently holds an in-memory project-keyed cache of this.
|
|
139
|
+
- **`CueProjectEntities` — document-entity reads** — fetch all `qcy:mentions` IRIs for a given `contentIRI`, with `qcy:value` and `qcy:hasEntityCategory`. Currently only in `DocumentEntitiesService`.
|
|
140
|
+
- **`CueProjectEntities` or new `CueDocumentResource`** — type detection (`SELECT ?cl WHERE { <iri> a ?cl }`) + file metadata fetch for per-document-viewer panel. Currently in `ResourceService`.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
#### Phase 6e — `cue-views` cleanup
|
|
145
|
+
|
|
146
|
+
After 6a–6d, the remaining Angular services that have no SDK equivalent are either:
|
|
147
|
+
- **Kept as-is** (framework-specific): `FileContentService` (depends on `FileRepo`), `ResourceService` viewer composition, `DocumentListHandlers` callbacks
|
|
148
|
+
- **Deleted** once bridge services are verified: `TriplestoreService`, `AvailableCategoriesService`, `ProjectDocumentsService`
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
### Final — Remove `js-firebase` from portal bootstrap
|
|
153
|
+
|
|
154
|
+
Replace `main.ts` Firebase init + `FirebaseService` with pure SDK init. `cue-repos` services become either collapsed into the SDK or thin DI wrappers with no direct Firebase imports.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
## Verification Plan
|
|
160
|
+
|
|
161
|
+
After each phase, verify with the following checklist. Run `npx nx build cue-portal` as the baseline — all items below are functional smoke tests.
|
|
162
|
+
|
|
163
|
+
### ✅ Phase 2–5 (already done — verify these haven't regressed)
|
|
164
|
+
|
|
165
|
+
| Area | How to verify |
|
|
166
|
+
|------|--------------|
|
|
167
|
+
| **Auth signals** | Sign in; confirm `cue.auth.user.get()` returns the user, `cue.auth.token.get()` returns a JWT, `cue.auth.isSuperAdmin.get()` reflects the claim |
|
|
168
|
+
| **Privileges** | Select a project where the user is `admin`; confirm `cue.privileges.privileges.get().uploadDocuments === true`; `PrivilegesService.privileges()` should match |
|
|
169
|
+
| **Cloud functions** | In Settings → Members: invite a user, change role, remove — all three `CueProjects` callables should fire without error |
|
|
170
|
+
| **Cache (write)** | Run a SPARQL query with caching enabled; confirm a `.json.gz` file appears in the `db_persistence_eu_west6` bucket at `portal/projects/{pid}/queries/{id}.json.gz` |
|
|
171
|
+
| **Cache (read)** | Run the same query again; confirm it loads from cache (no SPARQL call in the network tab) |
|
|
172
|
+
| **Agent session cache** | Run an agent interaction; confirm `portal/projects/{pid}/agent/{id}.json.gz` is written |
|
|
173
|
+
| **Doc types** | `ProjectDoc`, `UserDoc`, `OrganizationDoc`, `RDFWritingDoc`, `ViewDefinition` all importable from `js-cue-sdk` without errors |
|
|
174
|
+
| **`nx graph`** | `cue-repos` should only have one edge to `js-firebase` (via `firebase.service.ts`) |
|
|
175
|
+
|
|
176
|
+
### 🔲 Phase 6a — `CueProjectView` facade
|
|
177
|
+
|
|
178
|
+
| Area | How to verify |
|
|
179
|
+
|------|--------------|
|
|
180
|
+
| **Category signals** | Open a project; `view.availableContentCategories.get()` and `view.availableEntityCategories.get()` return non-empty arrays |
|
|
181
|
+
| **Entity graph** | `view.entityGraph.get()` returns the full entity graph after project init |
|
|
182
|
+
| **Entity detail** | Call `view.requestEntityData(['<uuid>'])` then read `view.entityInfoMap.get()['<uuid>']` — `value` and `categories` populated |
|
|
183
|
+
| **Entity relationships** | Call `view.fetchEntityRelationships('<iri>')` and confirm incoming/outgoing edges |
|
|
184
|
+
| **Entity documents** | Call `view.fetchEntityDocuments('<iri>')` and confirm document UUIDs |
|
|
185
|
+
| **Document data** | Call `view.requestDocumentData(['<id>'])` then read `view.documentInfoMap.get()['<id>']` |
|
|
186
|
+
| **Project documents overview** | `view.projectDocumentsData.get()` returns `documentsBySuffix` and `documentsByContentCategory` |
|
|
187
|
+
| **Search** | Call `view.search('test')` and confirm `view.searchResults.get()` accumulates results |
|
|
188
|
+
| **Language change** | Call `view.setLanguage('da')` and confirm category labels switch |
|
|
189
|
+
| **Stale-while-revalidate** | With a warm `QueryCache`, confirm the signal fires twice — first with stale data, then fresh |
|
|
190
|
+
| **Destroy** | Call `view.destroy()` and confirm no further signal updates |
|
|
191
|
+
|
|
192
|
+
### ✅ Phase 6b — Angular adapters
|
|
193
|
+
|
|
194
|
+
**Completed.** All 4 `cue-views` services bridged to SDK signals. Build verified (`nx build ng-cue-views` passes). Also fixed a pre-existing ng-packagr `rootDir` issue in `cue-repos` and `cue-views` by overriding `js-cue-sdk` path to dist in `tsconfig.lib.prod.json`.
|
|
195
|
+
|
|
196
|
+
| Area | Status |
|
|
197
|
+
|------|--------|
|
|
198
|
+
| `CueViewsService` — owns `CueProjectView` signal, effects for project/language change | ✅ |
|
|
199
|
+
| `AvailableCategoriesService` — bridges `view.availableContentCategories/EntityCategories/EntityRelationships` | ✅ |
|
|
200
|
+
| `ProjectDocumentsService` — bridges `view.projectDocumentsData` | ✅ |
|
|
201
|
+
| `DocumentInfoService` — bridges `view.documentInfoMap`; keeps `documentListHandlers` Angular-side | ✅ |
|
|
202
|
+
| `EntityInfoService` — bridges `view.entityInfoMap` + `entityGraph`; delegates all 4 methods to view | ✅ |
|
|
203
|
+
| `cue-repos/tsconfig.lib.prod.json` — path override to dist to fix ng-packagr TS6059 | ✅ |
|
|
204
|
+
| `cue-views/tsconfig.lib.prod.json` — same fix | ✅ |
|
|
205
|
+
|
|
206
|
+
### 🔲 Phase 6c — Gateway API additions
|
|
207
|
+
|
|
208
|
+
| Area | How to verify |
|
|
209
|
+
|------|--------------|
|
|
210
|
+
| **Related documents** | Call `cue.api.relatedDocuments(uuid, 10)` from console; confirm response array with `relevance` scores |
|
|
211
|
+
| **Content category change** | Change a document's content category; confirm PATCH fires and SPARQL reflects the update |
|
|
212
|
+
| **Agent plan streaming** | Trigger agent plan build; confirm streaming chunks arrive and plan signal updates incrementally |
|
|
213
|
+
| **Agent act streaming** | Execute a plan; confirm streaming result chunks arrive and final result is saved via `CueCache` |
|
|
214
|
+
|
|
215
|
+
### 🔲 Phase 6d — SDK data additions
|
|
216
|
+
|
|
217
|
+
| Area | How to verify |
|
|
218
|
+
|------|--------------|
|
|
219
|
+
| **Duplicate list** | `view.documents.fetchDuplicates()` returns a map of content UUIDs → array of file paths |
|
|
220
|
+
| **Document entity reads** | `view.entities.fetchDocumentMentions(contentIRI)` returns entity IRIs with labels and categories |
|
|
221
|
+
|
|
222
|
+
### 🔲 Final (portal bootstrap migration — pending)
|
|
223
|
+
|
|
224
|
+
| Area | How to verify |
|
|
225
|
+
|------|--------------|
|
|
226
|
+
| **`nx graph`** | `cue-portal` has zero edges to `js-firebase` |
|
|
227
|
+
| **Cold load** | Full page refresh — auth state restores, project loads, entities visible |
|
|
228
|
+
| **Emulator** | `nx run cue-portal:serve` with emulator; all Firestore + Storage + Auth calls route correctly |
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Architecture Decisions
|
|
233
|
+
|
|
234
|
+
**`js-firebase` stays** — CLI, widget, and admin depend on it directly and always will. The portal's dependency shrinks to the single `FirebaseService` wrapper.
|
|
235
|
+
|
|
236
|
+
**`js-databases` as the abstraction boundary** — `IDocStore` and `CueBlobStorage` are Firebase-agnostic. Switching storage provider only requires changing the backing class in `CueFirebase._init()`.
|
|
237
|
+
|
|
238
|
+
**Vanilla signals in the SDK** — `CueSignal<T>` + `cueComputed()` in `signal.ts`. No external signal library. Angular adapters bridge to Angular signals via `effect(onCleanup => ...)` + `subscribe()`.
|
|
239
|
+
|
|
240
|
+
**`UploadTask` escape hatch** — `FileRepo.uploadRawFile` still returns a native Firebase `UploadTask` because `cue-views/handlers.service.ts` depends on `task.on('state_changed', ...)` for per-file upload progress. Resolved in Phase 6.
|
|
241
|
+
|
|
242
|
+
**`CueCache` uses `firebase/storage` directly** — only needs the `persistence` bucket; no need to instantiate all 6 buckets via `CueBlobStorage`.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## SDK Module Reference
|
|
247
|
+
|
|
248
|
+
| Module | Class | Exposed as | Key members |
|
|
249
|
+
|--------|-------|-----------|-------------|
|
|
250
|
+
| `auth.ts` | `CueAuth` | `cue.auth` | `user`, `token`, `isSuperAdmin`, `userIds` (all `ReadonlySignal`); `signIn()`, `signOut()`, `signInWithRedirect()`, `checkRedirectResult()`, `checkSuperAdmin()`, `getToken()`, `authenticatedFetch()` |
|
|
251
|
+
| `privileges.ts` | `CuePrivileges` | `cue.privileges` | `privileges: ReadonlySignal<Privileges>`; `setProjectRoles(roles)` |
|
|
252
|
+
| `project.ts` | `CueProjects` | `cue.projects` | `inviteUserToProject()`, `changeUserRoleOnProject()`, `removeUserFromProject()` |
|
|
253
|
+
| `profile.ts` | `CueProfile` | `cue.profile` | `getUserInfo(uids)`, `acceptTerms()`, API key management |
|
|
254
|
+
| `cache.ts` | `CueCache` | `cue.cache` | `getQueryCache`, `setQueryCache`, `getAgentSessionCache`, `setAgentSessionCache`, `getUserProjectCache`, `setUserProjectCache` |
|
|
255
|
+
| `signal.ts` | `CueSignal<T>` | exported | Writable reactive state; `get()`, `set()`, `subscribe()` |
|
|
256
|
+
| `signal.ts` | `cueComputed()` | exported | Derived read-only signal from deps |
|
|
257
|
+
| `signal.ts` | `staleWhileRevalidate()` | exported | Serve stale cache data first, then revalidate; generic `QueryCache` interface |
|
|
258
|
+
| `api.ts` | `CueApi` | `cue.api` | `search()`, `sparql()`, `sync` (Node only) |
|
|
259
|
+
| `schema.ts` | `CueProjectSchema` | `view.schema` | `availableContentCategories`, `availableEntityCategories`, `availableEntityRelationships` (all `ReadonlySignal`); `setLanguage()`, `refresh()` |
|
|
260
|
+
| `entities.ts` | `CueProjectEntities` | `view.entities` | `entityInfoMap`, `entityGraph` (all `ReadonlySignal`); `requestEntityData()`, `requestEntityLocations()`, `fetchEntityRelationships()`, `fetchEntityDocuments()`, `entityIri()`, `reset()` |
|
|
261
|
+
| `documents.ts` | `CueProjectDocuments` | `view.documents` | `documentInfoMap`, `projectDocumentsData` (all `ReadonlySignal`); `requestDocumentData()`, `fetchOverview()`, `setLanguage()`, `reset()` |
|
|
262
|
+
| `project-view.ts` _(pending)_ | `CueProjectView` | `cue.createProjectView()` | Facade over schema + entities + documents; adds `search()`, `searchResults`, `setLanguage()`, `destroy()` |
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Firestore Collections Reference
|
|
267
|
+
|
|
268
|
+
| Collection | Document type | Owner |
|
|
269
|
+
|-----------|--------------|-------|
|
|
270
|
+
| `projects` | `ProjectDoc` | `ProjectRepo` → `docStore` |
|
|
271
|
+
| `users` | `UserDoc` | `UserRepo` → `docStore` |
|
|
272
|
+
| `organizations` | `OrganizationDoc` | `OrganizationRepo` → `docStore` |
|
|
273
|
+
| `apiKeys` | `APIKeyDoc` | `APIKeysRepo` → `docStore` |
|
|
274
|
+
| `rdfWriting` | `RDFWritingDoc` | `RDFWritingRepo` → `docStore` |
|
|
275
|
+
| `tiers` | `TierDoc` | `FirebaseService` (raw, portal doesn't use) |
|
|
276
|
+
| `userTermsAcceptance` | `{ uid, timestamp }` | `FirebaseService` (raw) |
|
|
277
|
+
| `chatSessions` | `ChatSessionDoc` | `FirebaseService` (raw) |
|
|
278
|
+
|
|
279
|
+
## Storage Buckets Reference
|
|
280
|
+
|
|
281
|
+
| Bucket name | Key | Owner |
|
|
282
|
+
|-------------|-----|-------|
|
|
283
|
+
| `cue_raw_eu_west6` | `raw` | `FileRepo` → `blobStore` |
|
|
284
|
+
| `cue_processed_eu_west6` | `processed` | `FileRepo` → `blobStore` |
|
|
285
|
+
| `cue_logs_eu_west6` | `logs` | `FileRepo` → `blobStore` |
|
|
286
|
+
| `cue_public_eu_west6` | `public` | `FileRepo` → `blobStore` |
|
|
287
|
+
| `db_persistence_eu_west6` | `persistence` | `CueCache` (via `firebase/storage` directly) |
|
|
288
|
+
| `cue_chat_sessions_eu_west6` | `chatSessions` | `FileRepo` → `blobStore` |
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Completed Work (archive)
|
|
293
|
+
|
|
294
|
+
### Phase 6 (partial) — Knowledge Graph data classes
|
|
295
|
+
|
|
296
|
+
| Class | File | Replaces |
|
|
297
|
+
|---|---|---|
|
|
298
|
+
| `CueProjectSchema` | `schema.ts` | `AvailableCategoriesService` |
|
|
299
|
+
| `CueProjectEntities` | `entities.ts` | `EntityInfoService` |
|
|
300
|
+
| `CueProjectDocuments` | `documents.ts` | `ProjectDocumentsService` + `DocumentInfoService` (SPARQL) |
|
|
301
|
+
|
|
302
|
+
All three classes:
|
|
303
|
+
- Accept `CueApi` + `projectId` — no Angular dependencies
|
|
304
|
+
- Use `CueSignal<T>` / `cueComputed()` — framework-agnostic reactive signals
|
|
305
|
+
- Accept optional `QueryCache` for stale-while-revalidate caching via `staleWhileRevalidate()`
|
|
306
|
+
- Use `js/prefixes` (`qaecyPrefixes`, `prefixCC`) — no inline namespace constants
|
|
307
|
+
- Exported from `libs/js/cue-sdk/src/index.ts`
|
|
308
|
+
|
|
309
|
+
`staleWhileRevalidate<T>(query, fetchFresh, onData, cache?)` helper added to `signal.ts`:
|
|
310
|
+
- Serves cached (stale) data immediately via `cache.get(key)` then fires `onData(stale, true)`
|
|
311
|
+
- Fetches fresh data, fires `onData(fresh, false)`, writes to cache only if data changed
|
|
312
|
+
- Cache key is `contextBasedGuid(query)` (deterministic UUID v5 hash)
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
### `js-databases` — Provider-agnostic storage layer
|
|
317
|
+
|
|
318
|
+
- `IDocStore` interface + `FirestoreDocStore` implementation
|
|
319
|
+
- `CueBlobStorage` covers all 6 named buckets and all file operations
|
|
320
|
+
- `CueFirebase` constructs and exposes `docStore` + `blobStore`
|
|
321
|
+
|
|
322
|
+
### `js-cue-sdk` additions
|
|
323
|
+
|
|
324
|
+
- **`Cue.fromApp(app, config?)`** — static factory that reuses an existing `FirebaseApp` (portal shares auth session with SDK without a second login)
|
|
325
|
+
- **`CueSignal<T>` + `cueComputed()`** — vanilla framework-agnostic reactive primitives
|
|
326
|
+
- **`CueAuth` signals** — `user`, `token`, `isSuperAdmin`, `userIds` all reactive via `onIdTokenChanged`
|
|
327
|
+
- **`CuePrivileges`** — role expansion (`admin → [admin, syncer, member]`), `REQUIRED_ROLES`, `privileges` signal auto-recomputes when roles or superadmin status changes
|
|
328
|
+
- **`CueProjects`** cloud function wrappers: `inviteUserToProject`, `changeUserRoleOnProject`, `removeUserFromProject`
|
|
329
|
+
- **`CueProfile`** cloud function wrappers: `getUserInfo`, `acceptTerms`
|
|
330
|
+
- **`CueCache`** — gzip cache over `db_persistence_eu_west6`; uses `CompressionStream`/`DecompressionStream` (web standard, no `fflate` in SDK)
|
|
331
|
+
- **Doc types in SDK models** — `ProjectDoc`, `OrganizationDoc`, `UserDoc`, `RDFWritingDoc`, `ViewDefinition` (type aliases/interfaces; classes remain in `js-firebase` for CLI/admin)
|
|
332
|
+
|
|
333
|
+
### `cue-repos` — Angular adapters
|
|
334
|
+
|
|
335
|
+
| Service / Repo | Before | After |
|
|
336
|
+
|----------------|--------|-------|
|
|
337
|
+
| All 5 doc repos | Raw `CollectionReference` + `onSnapshot` | `docStore.subscribeToCollection/Doc` |
|
|
338
|
+
| `FileRepo` | Raw `firebase/storage` calls | `blobStore.*` |
|
|
339
|
+
| `CacheRepo` | 200-line `fflate`-based gzip impl | 40-line delegate to `cue.cache` |
|
|
340
|
+
| `PrivilegesService` | Owned all role logic | Thin adapter — syncs from `cue.privileges` signal |
|
|
341
|
+
| `CueSdkService` | — | New: `sdk: Signal<Cue \| undefined>` via `Cue.fromApp()` |
|
|
342
|
+
| `settings.component.ts` | Used `FirebaseService` | Uses `CueSdkService → sdk.projects.*` |
|
|
343
|
+
| `UsersRepo` | Used `FirebaseService.functionGetUserInfo` | Uses `sdk.profile.getUserInfo()` |
|
|
344
|
+
|
|
345
|
+
Doc type imports in `cue-repos` and portal services moved from `js-firebase` → `js-cue-sdk` (7 files, type-only).
|
|
346
|
+
|
package/README.md
CHANGED
|
@@ -12,9 +12,14 @@ npm install @qaecy/cue-sdk firebase
|
|
|
12
12
|
|
|
13
13
|
## Quick start
|
|
14
14
|
|
|
15
|
+
### Demo app
|
|
15
16
|
```typescript
|
|
16
17
|
import { Cue } from '@qaecy/cue-sdk';
|
|
17
18
|
|
|
19
|
+
// Use default demo app (prints a warning — fine for evaluation)
|
|
20
|
+
const cue = new Cue();
|
|
21
|
+
|
|
22
|
+
// Or supply your own configuration
|
|
18
23
|
const cue = new Cue({
|
|
19
24
|
apiKey: 'YOUR_FIREBASE_API_KEY',
|
|
20
25
|
appId: 'YOUR_FIREBASE_APP_ID',
|
|
@@ -53,9 +58,9 @@ await cue.auth.signOut();
|
|
|
53
58
|
|
|
54
59
|
| Option | Type | Required | Description |
|
|
55
60
|
|---|---|---|---|
|
|
56
|
-
| `apiKey` | `string` |
|
|
57
|
-
| `appId` | `string` |
|
|
58
|
-
| `measurementId` | `string` |
|
|
61
|
+
| `apiKey` | `string` | — | Firebase API key (defaults to QAECY demo app) |
|
|
62
|
+
| `appId` | `string` | — | Firebase App ID (defaults to QAECY demo app) |
|
|
63
|
+
| `measurementId` | `string` | — | Firebase Measurement ID (defaults to QAECY demo app) |
|
|
59
64
|
| `environment` | `'production' \| 'emulator'` | — | Target environment (default: `'production'`) |
|
|
60
65
|
| `endpoints` | `Partial<CueEndpoints>` | — | Override individual endpoint URLs (takes precedence over `environment`) |
|
|
61
66
|
|
|
@@ -240,6 +245,48 @@ Access the raw Firebase `Auth` instance for advanced use cases:
|
|
|
240
245
|
const firebaseAuth = cue.auth.firebaseAuth;
|
|
241
246
|
```
|
|
242
247
|
|
|
248
|
+
## E2E tests
|
|
249
|
+
|
|
250
|
+
The SDK ships integration tests in `e2e/` that run against the local Firebase emulator stack.
|
|
251
|
+
|
|
252
|
+
### Prerequisites
|
|
253
|
+
|
|
254
|
+
Start the frontend emulator stack from the `e2e` repo (requires Docker):
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
# From /path/to/e2e
|
|
258
|
+
docker compose up firebase-emulator frontend-seed
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
This spins up Firebase Auth, Firestore, and Storage emulators and seeds the following password-enabled test accounts:
|
|
262
|
+
|
|
263
|
+
| Email | Password | Role |
|
|
264
|
+
|-------|----------|------|
|
|
265
|
+
| `front-regular@example.com` | `Test1234!` | member |
|
|
266
|
+
| `front-super@example.com` | `Test1234!` | superadmin |
|
|
267
|
+
|
|
268
|
+
### Run
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
npx nx run js-cue-sdk:e2e
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Or directly with vitest (from `libs/js/cue-sdk/`):
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
npx vitest run --config vitest.e2e.config.mts
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### What is tested
|
|
281
|
+
|
|
282
|
+
| Suite | Tests |
|
|
283
|
+
|-------|-------|
|
|
284
|
+
| `CueAuth — reactive signals` | `user`, `token`, `isSuperAdmin` (false), `checkSuperAdmin()`, `userIds` |
|
|
285
|
+
| `CueProfile — password management` | `getSignInMethods`, `updatePassword` → sign-in with new pw, old pw rejected, restore |
|
|
286
|
+
| `CueAuth — superadmin claim` | `isSuperAdmin` signal (true), `checkSuperAdmin()` (true) |
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
243
290
|
## License
|
|
244
291
|
|
|
245
292
|
MIT
|