h1v3 0.8.0 → 0.9.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
CHANGED
|
@@ -101,9 +101,9 @@ This allows you to, in the browser, do:
|
|
|
101
101
|
const meta = import("/store_meta") with { type: "json" }
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
-
##
|
|
104
|
+
## Client-side libraries
|
|
105
105
|
|
|
106
|
-
You can
|
|
106
|
+
You can vendor the (free) dependencies and client files for the library using npx
|
|
107
107
|
|
|
108
108
|
```bash
|
|
109
109
|
npx h1v3 vendor-deps
|
|
@@ -118,7 +118,7 @@ You will also need to provide a vendored library of WebAwesome Pro:
|
|
|
118
118
|
|
|
119
119
|
- `/public/vendor/webawesome-pro` - for now this is an explicit dependency although you can symlink it to your current version of webawesome-pro. The system expects the `dist` folder to be available at `/public/vendor/webawesome-pro/dist`.
|
|
120
120
|
|
|
121
|
-
# Usage patterns
|
|
121
|
+
# Usage patterns - Client-side
|
|
122
122
|
|
|
123
123
|
## Importing the library
|
|
124
124
|
|
|
@@ -132,6 +132,143 @@ export { styled } from "/vendor/h1v3@0.7.6/client/components/partials/wa-utils.j
|
|
|
132
132
|
export * from "/vendor/h1v3@0.7.6/client/system.js";
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
+
## Firebase configuration
|
|
136
|
+
|
|
137
|
+
The system expects you to expose your (public) firebase config in an ESM module at `/firebase.config.js`. For example:
|
|
138
|
+
|
|
139
|
+
```javascript
|
|
140
|
+
export default {
|
|
141
|
+
apiKey: "AIzaSyCV6FjdJwU50TUZVRcoFCWqQItjhhQKbXQ",
|
|
142
|
+
authDomain: "ixion-c9e0e.firebaseapp.com",
|
|
143
|
+
databaseURL: "https://ixion-c9e0e-default-rtdb.europe-west1.firebasedatabase.app",
|
|
144
|
+
projectId: "ixion-c9e0e",
|
|
145
|
+
appId: "1:28699144755:web:2ab262d02ccba70979e946"
|
|
146
|
+
};
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
# Usage Patterns - Firebase functions
|
|
150
|
+
|
|
151
|
+
## Basic routes
|
|
152
|
+
|
|
153
|
+
Configure at least the following four event stores:
|
|
154
|
+
- user_profile - in which a user can maintain details of their profile (as determined by the referenced schema)
|
|
155
|
+
- user_teams - where the system will maintain a quick lookup list of a user's teams
|
|
156
|
+
- team_membership - where the system records the master list of users' membership of teams, and their role (member or admin)
|
|
157
|
+
- team_details - where any admin of a team can maintain details of the team they administer (as determined by the referenced schema).
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
```javascript
|
|
161
|
+
import { onValueWritten } from "firebase-functions/database";
|
|
162
|
+
|
|
163
|
+
import * as h1v3 from "h1v3";
|
|
164
|
+
|
|
165
|
+
import paths from "./h1v3.paths.js";
|
|
166
|
+
import userProfileSchema from "./schemas/user-profile-schema.js";
|
|
167
|
+
import teamDetailsSchema from "./schemas/team-details-schema.js";
|
|
168
|
+
import { observe } from "./o11y-provider.js";
|
|
169
|
+
import { region, rtdbInstance } from "./firebase.config.js";
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
const configureEventStore = h1v3.configureEventStore.inject({
|
|
173
|
+
region,
|
|
174
|
+
onValueWritten,
|
|
175
|
+
instance: rtdbInstance,
|
|
176
|
+
paths,
|
|
177
|
+
observe,
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
export const user_profile = configureEventStore(h1v3.userProfile.store, userProfileSchema);
|
|
181
|
+
export const user_teams = configureEventStore(h1v3.userTeams.store);
|
|
182
|
+
export const team_membership = configureEventStore(h1v3.teamMembership.store);
|
|
183
|
+
export const team_details = configureEventStore(h1v3.teamDetails.store, teamDetailsSchema);
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Defining schemas
|
|
187
|
+
|
|
188
|
+
Schemas for the two built-in event stores user_profile and team_details expect a schema defined using a javascript prototype as shown below. Note that there is no required constraint. Instead the schema is a white-list of keys along with the expected type for the associated value.
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
export default {
|
|
192
|
+
name: String,
|
|
193
|
+
age: Number,
|
|
194
|
+
favourite: {
|
|
195
|
+
color: String
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Observability provider
|
|
201
|
+
|
|
202
|
+
h1v3 has a built-in observability provider, but it must be initialised using external logging and trace facilities. An example implementation is shown below. This illustrates initialising the provider with (1) emulated versions of tracing and logging and (2) Google Cloud versions:
|
|
203
|
+
|
|
204
|
+
```javascript
|
|
205
|
+
import { Logging } from "@google-cloud/logging";
|
|
206
|
+
import { google } from "googleapis";
|
|
207
|
+
|
|
208
|
+
import * as h1v3 from "h1v3";
|
|
209
|
+
|
|
210
|
+
import { projectId, serviceName } from "./firebase.config.js";
|
|
211
|
+
|
|
212
|
+
const [trace, log] = process.env.FUNCTIONS_EMULATOR === "true" ? buildEmulated() : buildReal();
|
|
213
|
+
|
|
214
|
+
export const observe = h1v3.o11y.provider({
|
|
215
|
+
trace,
|
|
216
|
+
log,
|
|
217
|
+
projectId,
|
|
218
|
+
serviceName
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
function buildReal() {
|
|
222
|
+
|
|
223
|
+
const scopes = [
|
|
224
|
+
"https://www.googleapis.com/auth/trace.append",
|
|
225
|
+
"https://www.googleapis.com/auth/cloud-platform"
|
|
226
|
+
];
|
|
227
|
+
|
|
228
|
+
google.auth.getClient({ scopes }).then(auth => google.options({ auth })); // we can't await this as firebase will complain
|
|
229
|
+
|
|
230
|
+
return [
|
|
231
|
+
google.cloudtrace("v2"),
|
|
232
|
+
new Logging().log(serviceName)
|
|
233
|
+
];
|
|
234
|
+
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function buildEmulated() {
|
|
238
|
+
|
|
239
|
+
return [
|
|
240
|
+
{
|
|
241
|
+
projects: {
|
|
242
|
+
traces: {
|
|
243
|
+
spans: {
|
|
244
|
+
createSpan(...args) {
|
|
245
|
+
|
|
246
|
+
console.log("[TRACE]", JSON.stringify(args));
|
|
247
|
+
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
entry: (...args) => args,
|
|
255
|
+
write(entry) {
|
|
256
|
+
|
|
257
|
+
console.log("[LOG]", JSON.stringify(entry));
|
|
258
|
+
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
];
|
|
262
|
+
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
|
|
135
272
|
|
|
136
273
|
# Implicit Google API dependencies
|
|
137
274
|
|
|
@@ -20,14 +20,13 @@ function defaultHandleError(err) {
|
|
|
20
20
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export async function inject({ database, authentication, metaURL, handleError = defaultHandleError }) {
|
|
23
|
+
export async function inject({ database, authentication, metaURL, meta, handleError = defaultHandleError }) {
|
|
24
24
|
|
|
25
25
|
if (!database) throw new Error("Missing database");
|
|
26
|
-
if (!metaURL) throw new Error("Missing metaURL");
|
|
26
|
+
if (!(metaURL || meta)) throw new Error("Missing metaURL");
|
|
27
27
|
if (!authentication) throw new Error("Missing authentication");
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
const { default: meta } = await import(metaURL, { with: { type: "json" } });
|
|
29
|
+
meta = meta || await import(metaURL, { with: { type: "json" } });
|
|
31
30
|
|
|
32
31
|
const log = logger(database, authentication, meta.o11y.path);
|
|
33
32
|
const teamMembershipStoreFactory = ({ tid }) => eventStore(database, authentication, populateParameters({ tid }, meta.team.membership.path));
|
package/package.json
CHANGED
|
@@ -35,4 +35,9 @@ export function configureEventStore({ ref, projections, ...rest }, { onValueWrit
|
|
|
35
35
|
);
|
|
36
36
|
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
|
|
39
|
+
configureEventStore.inject = ({ onValueWritten, observe, paths, region, instance }) =>
|
|
40
|
+
|
|
41
|
+
(eventStoreFactory, ...args) =>
|
|
42
|
+
|
|
43
|
+
configureEventStore(eventStoreFactory(paths, ...args), { onValueWritten, observe, region, instance });
|