-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added firebaseServerDevFunctions()
- Loading branch information
Showing
25 changed files
with
458 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
apps/demo-api/src/app/function/example/example.development.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { DemoDevelopmentExampleResult, DemoDevelopmentExampleParams } from '@dereekb/demo-firebase'; | ||
import { DemoDevelopmentFunction } from '../function'; | ||
|
||
export const exampleDevelopmentFunction: DemoDevelopmentFunction<DemoDevelopmentExampleParams, DemoDevelopmentExampleResult> = (request) => { | ||
const { data } = request; | ||
|
||
console.log(`exampleDevelopmentFunction() was called: ${data.message}`); | ||
|
||
return { | ||
message: data.message | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
apps/demo-api/src/app/function/model/development.functions.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { DEMO_APP_EXAMPLE_DEVELOPMENT_FUNCTION_KEY } from '@dereekb/demo-firebase'; | ||
import { exampleDevelopmentFunction } from '../example/example.development'; | ||
import { DemoOnCallDevelopmentFunctionMap } from '../function'; | ||
|
||
export const demoDevelopmentFunctionMap: DemoOnCallDevelopmentFunctionMap = { | ||
[DEMO_APP_EXAMPLE_DEVELOPMENT_FUNCTION_KEY]: exampleDevelopmentFunction | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
export * from './crud.functions'; | ||
export * from './schedule.functions'; | ||
export * from './development.functions'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
components/demo-firebase/src/lib/development/development.api.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { DevelopmentFirebaseFunctionConfigMap, developmentFirebaseFunctionMapFactory } from '@dereekb/firebase'; | ||
import { Expose } from 'class-transformer'; | ||
import { IsNotEmpty, IsString, MaxLength } from 'class-validator'; | ||
|
||
export const DEMO_DEVELOPMENT_EXAMPLE_MAX_MESSAGE_LENGTH = 200; | ||
|
||
export class DemoDevelopmentExampleParams { | ||
@Expose() | ||
@IsNotEmpty() | ||
@IsString() | ||
@MaxLength(DEMO_DEVELOPMENT_EXAMPLE_MAX_MESSAGE_LENGTH) | ||
message!: string; | ||
} | ||
|
||
export class DemoDevelopmentExampleResult { | ||
message!: string; | ||
} | ||
|
||
export const DEMO_APP_EXAMPLE_DEVELOPMENT_FUNCTION_KEY = 'example'; | ||
|
||
export type DemoDevelopmentFunctionTypeMap = { | ||
[DEMO_APP_EXAMPLE_DEVELOPMENT_FUNCTION_KEY]: [DemoDevelopmentExampleParams, DemoDevelopmentExampleResult]; | ||
}; | ||
|
||
export const demoDevelopmentFunctionsConfig: DevelopmentFirebaseFunctionConfigMap<DemoDevelopmentFunctionTypeMap> = { | ||
[DEMO_APP_EXAMPLE_DEVELOPMENT_FUNCTION_KEY]: null | ||
}; | ||
|
||
/** | ||
* Used to generate our ProfileFunctionMap for a Functions instance. | ||
*/ | ||
export const demoDevelopmentFunctionMap = developmentFirebaseFunctionMapFactory<DemoDevelopmentFunctionTypeMap>(demoDevelopmentFunctionsConfig); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './development.api'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export * from './auth'; | ||
export * from './development'; | ||
export * from './model'; | ||
export * from './functions'; |
64 changes: 64 additions & 0 deletions
64
packages/firebase-server/src/lib/nest/development/development.app.function.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { inAuthContext } from '@dereekb/firebase-server'; | ||
import { OnCallDevelopmentParams, SCHEDULED_FUNCTION_DEV_FUNCTION_SPECIFIER } from '@dereekb/firebase'; | ||
import { CallableHttpFunction, RunnableHttpFunction } from '../../function/type'; | ||
import { NestAppPromiseGetter } from '../app'; | ||
import { NestApplicationScheduleConfiguredFunctionMap } from '../function/schedule.util'; | ||
import { OnCallWithNestContextFactory } from '../function/v1/call'; | ||
import { OnCallHandlerWithNestContextFactory } from '../function/v2/call'; | ||
import { AbstractFirebaseNestContext } from '../nest.provider'; | ||
import { onCallDevelopmentFunction, OnCallDevelopmentFunctionMap } from './development.function'; | ||
import { makeScheduledFunctionDevelopmentFunction } from './development.schedule.function'; | ||
import { unavailableError } from '../../function/error'; | ||
|
||
export interface FirebaseServerDevFunctionsConfig<N extends AbstractFirebaseNestContext<any, any>, S extends NestApplicationScheduleConfiguredFunctionMap> { | ||
readonly enabled: boolean; | ||
/** | ||
* Whether or not to require an auth context when calling dev functions. True by default. | ||
*/ | ||
readonly secure?: boolean; | ||
readonly nest: NestAppPromiseGetter; | ||
readonly developerFunctionsMap: OnCallDevelopmentFunctionMap<N>; | ||
readonly onCallFactory: OnCallWithNestContextFactory<N> | OnCallHandlerWithNestContextFactory<N>; | ||
readonly disableDevelopmentScheduleFunction?: boolean; | ||
readonly allScheduledFunctions?: S; | ||
} | ||
|
||
export interface FirebaseServerDevFunctions { | ||
readonly dev: RunnableHttpFunction<OnCallDevelopmentParams> | CallableHttpFunction<OnCallDevelopmentParams>; | ||
} | ||
|
||
export function firebaseServerDevFunctions<N extends AbstractFirebaseNestContext<any, any>, S extends NestApplicationScheduleConfiguredFunctionMap>(config: FirebaseServerDevFunctionsConfig<N, S>): FirebaseServerDevFunctions { | ||
const { enabled, secure, nest, developerFunctionsMap, onCallFactory, allScheduledFunctions, disableDevelopmentScheduleFunction } = config; | ||
|
||
let dev: RunnableHttpFunction<OnCallDevelopmentParams> | CallableHttpFunction<OnCallDevelopmentParams>; | ||
|
||
if (enabled) { | ||
const fullFunctionsMap: OnCallDevelopmentFunctionMap<N> = { | ||
...developerFunctionsMap | ||
}; | ||
|
||
if (allScheduledFunctions && disableDevelopmentScheduleFunction != null) { | ||
fullFunctionsMap[SCHEDULED_FUNCTION_DEV_FUNCTION_SPECIFIER] = makeScheduledFunctionDevelopmentFunction({ | ||
allScheduledFunctions | ||
}); | ||
} | ||
|
||
let onCallFunction = onCallDevelopmentFunction(fullFunctionsMap); | ||
|
||
if (secure != false) { | ||
onCallFunction = inAuthContext(onCallFunction); | ||
} | ||
|
||
dev = onCallFactory(onCallFunction)(nest); | ||
} else { | ||
dev = onCallFactory(async (x) => { | ||
throw unavailableError({ | ||
message: 'developer tools service is not enabled.' | ||
}); | ||
})(nest); | ||
} | ||
|
||
return { | ||
dev | ||
}; | ||
} |
11 changes: 11 additions & 0 deletions
11
packages/firebase-server/src/lib/nest/development/development.assert.function.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { NestContextCallableRequest, NestContextCallableRequestWithAuth } from '../function/nest'; | ||
|
||
export interface AssertDevelopmentRequestFunctionContext<N, I = unknown> { | ||
request: NestContextCallableRequest<N, I>; | ||
specifier: string; | ||
} | ||
|
||
/** | ||
* Function that asserts something given the input request. | ||
*/ | ||
export type AssertDevelopmentRequestFunction<N, I = unknown> = (context: AssertDevelopmentRequestFunctionContext<N, I>) => void; |
56 changes: 56 additions & 0 deletions
56
packages/firebase-server/src/lib/nest/development/development.function.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { PromiseOrValue, serverError } from '@dereekb/util'; | ||
import { FirestoreModelIdentity, FirestoreModelTypes, OnCallDevelopmentParams, DevelopmentFirebaseFunctionSpecifierRef, DevelopmentFirebaseFunctionSpecifier } from '@dereekb/firebase'; | ||
import { badRequestError } from '../../function'; | ||
import { OnCallWithAuthorizedNestContext, OnCallWithNestContext } from '../function/call'; | ||
import { NestContextCallableRequest } from '../function/nest'; | ||
import { AssertDevelopmentRequestFunction } from './development.assert.function'; | ||
|
||
// MARK: Function | ||
export type OnCallDevelopmentFunction<N, I = unknown, O = unknown> = (request: NestContextCallableRequest<N, I> & DevelopmentFirebaseFunctionSpecifierRef) => PromiseOrValue<O>; | ||
|
||
export type OnCallDevelopmentFunctionMap<N, T extends FirestoreModelIdentity = FirestoreModelIdentity> = { | ||
[K in FirestoreModelTypes<T>]?: OnCallDevelopmentFunction<N, any, any>; | ||
}; | ||
|
||
export interface OnCallDevelopmentConfig<N> { | ||
preAssert?: AssertDevelopmentRequestFunction<N, OnCallDevelopmentParams>; | ||
} | ||
|
||
/** | ||
* Creates a OnCallWithAuthorizedNestContext function for creating a model. | ||
* | ||
* @param map | ||
* @returns | ||
*/ | ||
export function onCallDevelopmentFunction<N>(map: OnCallDevelopmentFunctionMap<N>, config: OnCallDevelopmentConfig<N> = {}): OnCallWithNestContext<N, OnCallDevelopmentParams, unknown> { | ||
const { preAssert = () => undefined } = config; | ||
|
||
return (request) => { | ||
const specifier = request.data.specifier; | ||
const devFn = map[specifier]; | ||
|
||
if (devFn) { | ||
preAssert({ request, specifier }); | ||
return devFn({ | ||
...request, | ||
specifier, | ||
data: request.data.data | ||
}); | ||
} else { | ||
throw developmentUnknownSpecifierError(specifier); | ||
} | ||
}; | ||
} | ||
|
||
export function developmentUnknownSpecifierError(specifier: DevelopmentFirebaseFunctionSpecifier) { | ||
return badRequestError( | ||
serverError({ | ||
status: 400, | ||
code: 'UNKNOWN_SPECIFIER_ERROR', | ||
message: `Invalid specifier "${specifier}" to run.`, | ||
data: { | ||
specifier | ||
} | ||
}) | ||
); | ||
} |
34 changes: 34 additions & 0 deletions
34
packages/firebase-server/src/lib/nest/development/development.schedule.function.error.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { badRequestError } from '../../function/error'; | ||
|
||
export const NO_RUN_NAME_SPECIFIED_FOR_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_CODE = 'NO_RUN_NAME_SPECIFIED_FOR_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION'; | ||
|
||
export function noRunNameSpecifiedForScheduledFunctionDevelopmentFunction(type: unknown) { | ||
return badRequestError({ | ||
code: NO_RUN_NAME_SPECIFIED_FOR_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_CODE, | ||
message: `Must specify run parameter.` | ||
}); | ||
} | ||
|
||
export const UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_NAME_CODE = 'UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_NAME'; | ||
|
||
export function unknownScheduledFunctionDevelopmentFunctionName(name: unknown) { | ||
return badRequestError({ | ||
code: UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_NAME_CODE, | ||
message: `Unknown function with name "${name}"`, | ||
data: { | ||
name | ||
} | ||
}); | ||
} | ||
|
||
export const UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_TYPE_CODE = 'UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_TYPE'; | ||
|
||
export function unknownScheduledFunctionDevelopmentFunctionType(type: unknown) { | ||
return badRequestError({ | ||
code: UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_TYPE_CODE, | ||
message: `Unknown type "${type}"`, | ||
data: { | ||
type | ||
} | ||
}); | ||
} |
67 changes: 67 additions & 0 deletions
67
packages/firebase-server/src/lib/nest/development/development.schedule.function.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { ScheduledFunctionDevelopmentFirebaseFunctionListEntry, ScheduledFunctionDevelopmentFirebaseFunctionParams, ScheduledFunctionDevelopmentFirebaseFunctionResult } from '@dereekb/firebase'; | ||
import { forEachKeyValue, cachedGetter } from '@dereekb/util'; | ||
import { NestApplicationScheduleConfiguredFunctionMap } from '../function/schedule.util'; | ||
import { OnCallDevelopmentFunction } from './development.function'; | ||
import { noRunNameSpecifiedForScheduledFunctionDevelopmentFunction, unknownScheduledFunctionDevelopmentFunctionName, unknownScheduledFunctionDevelopmentFunctionType } from './development.schedule.function.error'; | ||
|
||
export interface MakeScheduledFunctionDevelopmentFunctionConfig { | ||
readonly allScheduledFunctions: NestApplicationScheduleConfiguredFunctionMap; | ||
} | ||
|
||
export function makeScheduledFunctionDevelopmentFunction(config: MakeScheduledFunctionDevelopmentFunctionConfig): OnCallDevelopmentFunction<unknown, ScheduledFunctionDevelopmentFirebaseFunctionParams, ScheduledFunctionDevelopmentFirebaseFunctionResult> { | ||
const { allScheduledFunctions } = config; | ||
const getListValues = cachedGetter(() => { | ||
const result: ScheduledFunctionDevelopmentFirebaseFunctionListEntry[] = []; | ||
|
||
forEachKeyValue(allScheduledFunctions, { | ||
forEach: (x) => { | ||
const [functionName, config] = x; | ||
|
||
result.push({ | ||
name: functionName.toString() | ||
}); | ||
} | ||
}); | ||
|
||
return result; | ||
}); | ||
|
||
return async (request) => { | ||
const { data } = request; | ||
const { type } = data; | ||
|
||
switch (type) { | ||
case 'run': | ||
const targetRunName = data.run; | ||
|
||
if (!targetRunName) { | ||
throw noRunNameSpecifiedForScheduledFunctionDevelopmentFunction(type); | ||
} | ||
|
||
const targetFunction = allScheduledFunctions[targetRunName]; | ||
|
||
if (!targetFunction) { | ||
throw unknownScheduledFunctionDevelopmentFunctionName(targetRunName); | ||
} | ||
|
||
try { | ||
await targetFunction._runNow(); | ||
} catch (e) { | ||
console.error(`Failed manually running task "${targetRunName}".`, e); | ||
throw e; | ||
} | ||
|
||
return { | ||
type: 'run', | ||
success: true | ||
}; | ||
case 'list': | ||
return { | ||
type: 'list', | ||
list: getListValues() | ||
}; | ||
default: | ||
throw unknownScheduledFunctionDevelopmentFunctionType(type); | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export * from './development.app.function'; | ||
export * from './development.assert.function'; | ||
export * from './development.function'; | ||
export * from './development.schedule.function'; | ||
export * from './development.schedule.function.error'; |
Oops, something went wrong.