Skip to content

Commit 8ab7004

Browse files
committed
Implement v1 API
1 parent 727e08d commit 8ab7004

File tree

6 files changed

+178
-31
lines changed

6 files changed

+178
-31
lines changed

spec/v1/providers/database.spec.ts

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import * as config from '../../../src/common/config';
2626
import { applyChange } from '../../../src/common/utilities/utils';
2727
import * as functions from '../../../src/v1';
2828
import * as database from '../../../src/v1/providers/database';
29+
import { SameType, use } from '../../common/metaprogramming';
2930

3031
describe('Database Functions', () => {
3132
describe('DatabaseBuilder', () => {
@@ -120,6 +121,35 @@ describe('Database Functions', () => {
120121

121122
return handler(event.data, event.context);
122123
});
124+
125+
it('Should have params of the correct type', () => {
126+
database.ref('foo').onWrite((event, context) => {
127+
const assertion: SameType<
128+
typeof context.params,
129+
Record<string, never>
130+
> = true;
131+
use(assertion);
132+
});
133+
database.ref('foo/{bar}').onWrite((event, context) => {
134+
const assertion: SameType<
135+
typeof context.params,
136+
{
137+
bar: string;
138+
}
139+
> = true;
140+
use(assertion);
141+
});
142+
database.ref('foo/{bar}/{baz}').onWrite((event, context) => {
143+
const assertion: SameType<
144+
typeof context.params,
145+
{
146+
bar: string;
147+
baz: string;
148+
}
149+
> = true;
150+
use(assertion);
151+
});
152+
});
123153
});
124154

125155
describe('#onCreate()', () => {
@@ -168,6 +198,35 @@ describe('Database Functions', () => {
168198

169199
return handler(event.data, event.context);
170200
});
201+
202+
it('Should have params of the correct type', () => {
203+
database.ref('foo').onCreate((event, context) => {
204+
const assertion: SameType<
205+
typeof context.params,
206+
Record<string, never>
207+
> = true;
208+
use(assertion);
209+
});
210+
database.ref('foo/{bar}').onCreate((event, context) => {
211+
const assertion: SameType<
212+
typeof context.params,
213+
{
214+
bar: string;
215+
}
216+
> = true;
217+
use(assertion);
218+
});
219+
database.ref('foo/{bar}/{baz}').onCreate((event, context) => {
220+
const assertion: SameType<
221+
typeof context.params,
222+
{
223+
bar: string;
224+
baz: string;
225+
}
226+
> = true;
227+
use(assertion);
228+
});
229+
});
171230
});
172231

173232
describe('#onUpdate()', () => {
@@ -216,6 +275,35 @@ describe('Database Functions', () => {
216275

217276
return handler(event.data, event.context);
218277
});
278+
279+
it('Should have params of the correct type', () => {
280+
database.ref('foo').onUpdate((event, context) => {
281+
const assertion: SameType<
282+
typeof context.params,
283+
Record<string, never>
284+
> = true;
285+
use(assertion);
286+
});
287+
database.ref('foo/{bar}').onUpdate((event, context) => {
288+
const assertion: SameType<
289+
typeof context.params,
290+
{
291+
bar: string;
292+
}
293+
> = true;
294+
use(assertion);
295+
});
296+
database.ref('foo/{bar}/{baz}').onUpdate((event, context) => {
297+
const assertion: SameType<
298+
typeof context.params,
299+
{
300+
bar: string;
301+
baz: string;
302+
}
303+
> = true;
304+
use(assertion);
305+
});
306+
});
219307
});
220308

221309
describe('#onDelete()', () => {
@@ -265,6 +353,35 @@ describe('Database Functions', () => {
265353
return handler(event.data, event.context);
266354
});
267355
});
356+
357+
it('Should have params of the correct type', () => {
358+
database.ref('foo').onUpdate((event, context) => {
359+
const assertion: SameType<
360+
typeof context.params,
361+
Record<string, never>
362+
> = true;
363+
use(assertion);
364+
});
365+
database.ref('foo/{bar}').onUpdate((event, context) => {
366+
const assertion: SameType<
367+
typeof context.params,
368+
{
369+
bar: string;
370+
}
371+
> = true;
372+
use(assertion);
373+
});
374+
database.ref('foo/{bar}/{baz}').onUpdate((event, context) => {
375+
const assertion: SameType<
376+
typeof context.params,
377+
{
378+
bar: string;
379+
baz: string;
380+
}
381+
> = true;
382+
use(assertion);
383+
});
384+
});
268385
});
269386

270387
describe('handler namespace', () => {

spec/v1/providers/firestore.spec.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { Timestamp } from 'firebase-admin/firestore';
2525

2626
import * as functions from '../../../src/v1';
2727
import * as firestore from '../../../src/v1/providers/firestore';
28+
import { SameType, use } from '../../common/metaprogramming';
2829

2930
describe('Firestore Functions', () => {
3031
function constructValue(fields: any) {
@@ -117,7 +118,11 @@ describe('Firestore Functions', () => {
117118
'projects/project1/databases/(default)/documents/users/{uid}';
118119
const cloudFunction = firestore
119120
.document('users/{uid}')
120-
.onWrite(() => null);
121+
.onWrite((snap, context) => {
122+
const assertion: SameType<typeof context.params, { uid: string }> =
123+
true;
124+
use(assertion);
125+
});
121126

122127
expect(cloudFunction.__endpoint).to.deep.equal(
123128
expectedEndpoint(resource, 'document.write')
@@ -130,7 +135,11 @@ describe('Firestore Functions', () => {
130135
const cloudFunction = firestore
131136
.namespace('v2')
132137
.document('users/{uid}')
133-
.onWrite(() => null);
138+
.onWrite((snap, context) => {
139+
const assertion: SameType<typeof context.params, { uid: string }> =
140+
true;
141+
use(assertion);
142+
});
134143

135144
expect(cloudFunction.__endpoint).to.deep.equal(
136145
expectedEndpoint(resource, 'document.write')
@@ -156,7 +165,11 @@ describe('Firestore Functions', () => {
156165
.database('myDB')
157166
.namespace('v2')
158167
.document('users/{uid}')
159-
.onWrite(() => null);
168+
.onWrite((snap, context) => {
169+
const assertion: SameType<typeof context.params, { uid: string }> =
170+
true;
171+
use(assertion);
172+
});
160173

161174
expect(cloudFunction.__endpoint).to.deep.equal(
162175
expectedEndpoint(resource, 'document.write')
@@ -171,7 +184,13 @@ describe('Firestore Functions', () => {
171184
memory: '256MB',
172185
})
173186
.firestore.document('doc')
174-
.onCreate((snap) => snap);
187+
.onCreate((snap, context) => {
188+
const assertion: SameType<
189+
typeof context.params,
190+
Record<string, never>
191+
> = true;
192+
use(assertion);
193+
});
175194

176195
expect(fn.__endpoint.region).to.deep.equal(['us-east1']);
177196
expect(fn.__endpoint.availableMemoryMb).to.deep.equal(256);

src/v1/cloud-functions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export interface Event {
6464
* - Authorization of the request that triggered the event, if applicable and
6565
* available.
6666
*/
67-
export interface EventContext {
67+
export interface EventContext<Params = Record<string, string>> {
6868
/**
6969
* Authentication information for the user that triggered the function.
7070
* This object contains `uid` and `token` properties for authenticated users.
@@ -126,7 +126,7 @@ export interface EventContext {
126126
* provided to the [`ref()`](providers_database_.html#ref) method for a Realtime
127127
* Database trigger. Cannot be accessed while inside the handler namespace.
128128
*/
129-
params: { [option: string]: any };
129+
params: Params;
130130

131131
/**
132132
* The resource that emitted the event. Valid values are:

src/v1/function-builder.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,8 @@ export class FunctionBuilder {
424424
* information about the user who triggered the Cloud Function.
425425
* @param ref Path of the database to listen to.
426426
*/
427-
ref: (path: string) => database._refWithOptions(path, this.options),
427+
ref: <Ref extends string>(path: Ref) =>
428+
database._refWithOptions(path, this.options),
428429
};
429430
}
430431

@@ -437,7 +438,7 @@ export class FunctionBuilder {
437438
* collection is named "users" and the document is named "Ada", then the
438439
* path is "/users/Ada".
439440
*/
440-
document: (path: string) =>
441+
document: <Path extends string>(path: Path) =>
441442
firestore._documentWithOptions(path, this.options),
442443

443444
/** @hidden */

src/v1/providers/database.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import { getApp } from '../../common/app';
2424
import { Change } from '../../common/change';
2525
import { firebaseConfig } from '../../common/config';
26+
import { ParamsOf } from '../../common/params';
2627
import { DataSnapshot } from '../../common/providers/database';
2728
import { normalizePath } from '../../common/utilities/path';
2829
import { applyChange } from '../../common/utilities/utils';
@@ -90,7 +91,7 @@ export function instance(instance: string) {
9091
* @param path The path within the Database to watch for write events.
9192
* @return Firebase Realtime Database builder interface.
9293
*/
93-
export function ref(path: string) {
94+
export function ref<Ref extends string>(path: Ref) {
9495
return _refWithOptions(path, {});
9596
}
9697

@@ -114,20 +115,20 @@ export class InstanceBuilder {
114115
/**
115116
* @return Firebase Realtime Database reference builder interface.
116117
*/
117-
ref(path: string): RefBuilder {
118+
ref<Ref extends string>(path: Ref): RefBuilder<Ref> {
118119
const normalized = normalizePath(path);
119-
return new RefBuilder(
120+
return new RefBuilder<Ref>(
120121
() => `projects/_/instances/${this.instance}/refs/${normalized}`,
121122
this.options
122123
);
123124
}
124125
}
125126

126127
/** @hidden */
127-
export function _refWithOptions(
128-
path: string,
128+
export function _refWithOptions<Ref extends string>(
129+
path: Ref,
129130
options: DeploymentOptions
130-
): RefBuilder {
131+
): RefBuilder<Ref> {
131132
const resourceGetter = () => {
132133
const normalized = normalizePath(path);
133134
const databaseURL = firebaseConfig().databaseURL;
@@ -160,15 +161,15 @@ export function _refWithOptions(
160161
return `projects/_/instances/${instance}/refs/${normalized}`;
161162
};
162163

163-
return new RefBuilder(resourceGetter, options);
164+
return new RefBuilder<Ref>(resourceGetter, options);
164165
}
165166

166167
/**
167168
* The Firebase Realtime Database reference builder interface.
168169
*
169170
* Access via [`functions.database.ref()`](functions.database#.ref).
170171
*/
171-
export class RefBuilder {
172+
export class RefBuilder<Ref extends string> {
172173
/** @hidden */
173174
constructor(
174175
private triggerResource: () => string,
@@ -186,7 +187,7 @@ export class RefBuilder {
186187
onWrite(
187188
handler: (
188189
change: Change<DataSnapshot>,
189-
context: EventContext
190+
context: EventContext<ParamsOf<Ref>>
190191
) => PromiseLike<any> | any
191192
): CloudFunction<Change<DataSnapshot>> {
192193
return this.onOperation(handler, 'ref.write', this.changeConstructor);
@@ -204,7 +205,7 @@ export class RefBuilder {
204205
onUpdate(
205206
handler: (
206207
change: Change<DataSnapshot>,
207-
context: EventContext
208+
context: EventContext<ParamsOf<Ref>>
208209
) => PromiseLike<any> | any
209210
): CloudFunction<Change<DataSnapshot>> {
210211
return this.onOperation(handler, 'ref.update', this.changeConstructor);
@@ -221,7 +222,7 @@ export class RefBuilder {
221222
onCreate(
222223
handler: (
223224
snapshot: DataSnapshot,
224-
context: EventContext
225+
context: EventContext<ParamsOf<Ref>>
225226
) => PromiseLike<any> | any
226227
): CloudFunction<DataSnapshot> {
227228
const dataConstructor = (raw: Event) => {
@@ -245,7 +246,7 @@ export class RefBuilder {
245246
onDelete(
246247
handler: (
247248
snapshot: DataSnapshot,
248-
context: EventContext
249+
context: EventContext<ParamsOf<Ref>>
249250
) => PromiseLike<any> | any
250251
): CloudFunction<DataSnapshot> {
251252
const dataConstructor = (raw: Event) => {

0 commit comments

Comments
 (0)