h1v3 0.7.6 → 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,6 +101,175 @@ This allows you to, in the browser, do:
|
|
|
101
101
|
const meta = import("/store_meta") with { type: "json" }
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
+
## Client-side libraries
|
|
105
|
+
|
|
106
|
+
You can vendor the (free) dependencies and client files for the library using npx
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npx h1v3 vendor-deps
|
|
110
|
+
npx h1v3 vendor-client
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
This will create folders such as:
|
|
114
|
+
- `/public/vendor/h1v3@0.7.6` (see below for suggestion on isolating your code from the library version)
|
|
115
|
+
- `/public/vendor/lit@3.3.1` (see https://lit.dev/)
|
|
116
|
+
|
|
117
|
+
You will also need to provide a vendored library of WebAwesome Pro:
|
|
118
|
+
|
|
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
|
+
|
|
121
|
+
# Usage patterns - Client-side
|
|
122
|
+
|
|
123
|
+
## Importing the library
|
|
124
|
+
|
|
125
|
+
When using the library in your website, you may wish to create a single import location which isolates your code from the version of h1v3 you are using. You can also use it to explicitly declare which bits of the library you are depending upon.
|
|
126
|
+
|
|
127
|
+
e.g. /public/js/h1v3.js
|
|
128
|
+
```javascript
|
|
129
|
+
export { default as bus } from "/vendor/h1v3@0.7.6/client/bus.js";
|
|
130
|
+
export { EVENT_USER_PROFILE_CHANGED } from "/vendor/h1v3@0.7.6/client/events.js";
|
|
131
|
+
export { styled } from "/vendor/h1v3@0.7.6/client/components/partials/wa-utils.js";
|
|
132
|
+
export * from "/vendor/h1v3@0.7.6/client/system.js";
|
|
133
|
+
```
|
|
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
|
+
|
|
272
|
+
|
|
104
273
|
# Implicit Google API dependencies
|
|
105
274
|
|
|
106
275
|
Note - this is an incomplete list...
|
|
@@ -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));
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
export const waDist = "/vendor
|
|
1
|
+
export const waDist = "/vendor/webawesome-pro";
|
|
2
2
|
|
|
3
3
|
// firebase
|
|
4
4
|
export * from "./firebase.js";
|
|
5
5
|
|
|
6
6
|
// vendor: webawesome
|
|
7
|
-
import "/vendor
|
|
8
|
-
import "/vendor
|
|
9
|
-
import "/vendor
|
|
10
|
-
import "/vendor
|
|
11
|
-
import "/vendor
|
|
12
|
-
import "/vendor
|
|
13
|
-
import "/vendor
|
|
7
|
+
import "/vendor/webawesome-pro/components/button/button.js";
|
|
8
|
+
import "/vendor/webawesome-pro/components/input/input.js";
|
|
9
|
+
import "/vendor/webawesome-pro/components/card/card.js";
|
|
10
|
+
import "/vendor/webawesome-pro/components/divider/divider.js";
|
|
11
|
+
import "/vendor/webawesome-pro/components/icon/icon.js";
|
|
12
|
+
import "/vendor/webawesome-pro/components/dialog/dialog.js";
|
|
13
|
+
import "/vendor/webawesome-pro/components/callout/callout.js";
|
|
14
14
|
|
|
15
15
|
// vendor: lit
|
|
16
16
|
export { html, LitElement, css, render } from "/vendor/lit@3.3.1/dist/lit-core.min.js";
|
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 });
|