diff --git a/.eslintrc.js b/.eslintrc.js index 2ffae08d..aba61082 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,15 +1,24 @@ module.exports = { parser: '@typescript-eslint/parser', + ignorePatterns: [ + 'src/gen/**/*.ts', + 'src/**/*.test.ts', + ], env: { node: true, }, + plugins: [ + "jsdoc", + ], extends: [ 'plugin:@typescript-eslint/eslint-recommended', 'plugin:@typescript-eslint/recommended', + 'plugin:jsdoc/recommended-typescript-error', ], rules: { '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/ban-ts-ignore': 'off', '@typescript-eslint/no-explicit-any': 'off', + 'jsdoc/tag-lines': 'off', // not documented on jsdoc plugin site, unsure how to correct. }, }; diff --git a/package.json b/package.json index 53040d8b..1d8a1836 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "@typescript-eslint/parser": "^4.22.0", "codecov": "^3.8.3", "eslint": "^7.24.0", + "eslint-plugin-jsdoc": "^40.1.0", "glob-run": "^0.1.7", "grpc-tools": "^1.11.3", "husky": "^6.0.0", diff --git a/src/api/documents/v0/collection-group-ref.ts b/src/api/documents/v0/collection-group-ref.ts index 14164e3e..3c9c96f5 100644 --- a/src/api/documents/v0/collection-group-ref.ts +++ b/src/api/documents/v0/collection-group-ref.ts @@ -41,8 +41,10 @@ export class CollectionGroupRef { } /** - * Create a CollectionGroupRef referencing a sub-collection of this collection - * @param name + * Create a CollectionGroupRef referencing a sub-collection of this collection. + * + * @param name of the sub-collection + * @returns a reference to the sub-collection */ public collection( name: string @@ -56,7 +58,8 @@ export class CollectionGroupRef { } /** - * Create a new collection query object + * Create a new collection query object. + * * @returns a new collection query object */ public query(): Query { @@ -88,9 +91,12 @@ export class CollectionGroupRef { } /** - * Creates a collection group reference from a collection reference - * @param ref - * @param dc + * Creates a collection group reference from a collection reference. + * + * @internal + * @param ref a collection reference. + * @param dc a document service client. + * @returns a collection group reference. */ public static fromCollectionRef( ref: CollectionRef, diff --git a/src/api/documents/v0/collection-ref.ts b/src/api/documents/v0/collection-ref.ts index 1c4245f6..ac65d819 100644 --- a/src/api/documents/v0/collection-ref.ts +++ b/src/api/documents/v0/collection-ref.ts @@ -38,10 +38,12 @@ export class CollectionRef { } /** - * Return a reference to a subcollection within the documents of this collection. + * Return a reference to a sub-collection within the documents of this collection. * - * Useful when querying subcollection documents across all/many parent documents. E.g. Querying landmarks from multiple cities. - * @param name + * Useful when querying sub-collection documents across all/many parent documents. E.g. Querying landmarks from multiple cities. + * + * @param name the name of the collection + * @returns a reference to all sub-collections matching the name provided. */ public collection(name: string): CollectionGroupRef { return CollectionGroupRef.fromCollectionRef( @@ -52,7 +54,8 @@ export class CollectionRef { /** * Return a reference to a document in the collection. - * @param documentId id the document unique id (required) + * + * @param id the unique id of the document * @returns new collection document reference */ public doc(id: string): DocumentRef { @@ -60,8 +63,9 @@ export class CollectionRef { } /** - * Create a new collection query object - * @returns a new collection query object + * Create a new collection query object. + * + * @returns a new collection query object. */ public query(): Query { return new Query(this.documentClient, this); diff --git a/src/api/documents/v0/document-ref.ts b/src/api/documents/v0/document-ref.ts index 0b7f73d9..e5ad01f1 100644 --- a/src/api/documents/v0/document-ref.ts +++ b/src/api/documents/v0/document-ref.ts @@ -27,7 +27,7 @@ import { MAX_COLLECTION_DEPTH } from './constants'; export type DocumentStructure = Record; /** - * Document Ref + * Document Ref. * * Provides a Document Reference class. * Used to create references to collections. @@ -49,6 +49,7 @@ export class DocumentRef { /** * Return the collection document reference value. + * * @returns the collection document reference value, or null if not found */ public async get(): Promise { @@ -78,6 +79,7 @@ export class DocumentRef { * Set the document content for this document reference in the database. If the * document does not exist an new item will be created, otherwise an * existing document will be update with the new value. + * * @param value content the document content to store (required) */ public async set(value: T): Promise { @@ -133,6 +135,7 @@ export class DocumentRef { /** * Gets a Collection instance that refers to the collection at the specified path. + * * @param name The name of the collection (required) * @returns The Collection instance */ diff --git a/src/api/documents/v0/documents.ts b/src/api/documents/v0/documents.ts index dabfb917..fc69c846 100644 --- a/src/api/documents/v0/documents.ts +++ b/src/api/documents/v0/documents.ts @@ -35,6 +35,7 @@ export class Documents { /** * Gets a Collection instance that refers to the collection at the specified path. + * * @param name The name of the collection (required) * @returns The Collection instance */ @@ -47,7 +48,8 @@ export class Documents { let DOCUMENTS = undefined; /** - * Documents + * Documents API client. + * * @returns a Documents API client. * @example * ```typescript diff --git a/src/api/documents/v0/query.test.ts b/src/api/documents/v0/query.test.ts index af86df11..6db31f18 100644 --- a/src/api/documents/v0/query.test.ts +++ b/src/api/documents/v0/query.test.ts @@ -198,8 +198,7 @@ describe('Query Tests', () => { test('Providing an invalid paging token should throw error', async () => { const q = documents().collection('test').query(); - //@ts-ignore - q.pagingFrom('test'); + q.pagingFrom('test' as any); await expect(q.fetch()).rejects.toStrictEqual( new InvalidArgumentError('Invalid paging token provided!') @@ -213,14 +212,13 @@ describe('Query Tests', () => { message: 'UNIMPLEMENTED', }; let documentsClient: Documents; - let mockStream = new PassThrough(); + const mockStream = new PassThrough(); let queryStreamMock; beforeAll(() => { queryStreamMock = jest .spyOn(GrpcKeyDocumentsClient.prototype, 'queryStream') - // @ts-ignore - .mockReturnValueOnce(mockStream); + .mockReturnValueOnce(mockStream as any); documentsClient = documents(); }); @@ -253,15 +251,14 @@ describe('Query Tests', () => { describe('Given DocumentServiceClient.QueryStream succeeds', () => { let documentsClient: Documents; - let mockStream = new PassThrough(); + const mockStream = new PassThrough(); let queryStreamMock; let mockKey; beforeAll(() => { queryStreamMock = jest .spyOn(GrpcKeyDocumentsClient.prototype, 'queryStream') - // @ts-ignore - .mockReturnValueOnce(mockStream); + .mockReturnValueOnce(mockStream as any); documentsClient = documents(); }); diff --git a/src/api/documents/v0/query.ts b/src/api/documents/v0/query.ts index d9ec7690..727a5f45 100644 --- a/src/api/documents/v0/query.ts +++ b/src/api/documents/v0/query.ts @@ -41,7 +41,8 @@ export interface FetchResponse { } /** - * Convenience method to convert ProtobufMap objects to standard JavaScript Maps + * Convenience method to convert ProtobufMap objects to standard JavaScript Maps. + * * @param protoMap map to convert * @returns the map */ @@ -122,7 +123,7 @@ export class Query { /** * Set the query paging continuation token. * - * @param pagingToken + * @param pagingToken used to determine where to continue paging from. * @returns the Query operation */ public pagingFrom(pagingToken: PagingToken): Query { @@ -133,7 +134,7 @@ export class Query { /** * Set the query fetch limit. * - * @param limit + * @param limit the maximum number for results to return. * @returns the Query operation */ public limit(limit: number): Query { @@ -216,6 +217,7 @@ export class Query { /** * Queries the collection and returns a readable stream. + * * @returns all query results as a stream * @example * ```typescript diff --git a/src/api/errors/index.ts b/src/api/errors/index.ts index a167fe54..abf19002 100644 --- a/src/api/errors/index.ts +++ b/src/api/errors/index.ts @@ -53,8 +53,9 @@ const STATUS_CODE_MAP: Record Error> = { }; /** - * Translates gRPC service errors to Nitric API errors - * @param error - Original gRPC service error + * Translates gRPC service errors to Nitric API errors. + * + * @param error the original gRPC service error * @returns Nitric API error that maps to the provided service error code */ export const fromGrpcError = (error: ServiceError): Error => { diff --git a/src/api/events/v0/events.ts b/src/api/events/v0/events.ts index 3dd36d5f..8761246f 100644 --- a/src/api/events/v0/events.ts +++ b/src/api/events/v0/events.ts @@ -25,6 +25,12 @@ import * as grpc from '@grpc/grpc-js'; import type { NitricEvent } from '../../../types'; import { fromGrpcError, InvalidArgumentError } from '../../errors'; +/** + * Construct event and topic service clients. + * + * @internal + * @returns event and topic service clients. + */ function newEventServiceClients(): { event: EventServiceClient; topic: TopicServiceClient; @@ -55,7 +61,8 @@ export class Topic { } /** - * Publishes an event to a nitric topic + * Publishes an event to a nitric topic. + * * @param event The event to publish * @param opts Additional publishing options * @returns NitricEvent containing the unique id of the event (if not provided it will be generated) @@ -152,14 +159,13 @@ export class Eventing { * Get a reference to a Topic. * * @param name Name of the topic, as defined in nitric.yaml. - * + * @returns a topic resource. * @example * ```typescript * import { Eventing } from "@nitric/sdk"; * const eventing = new Eventing(); * const topic = eventing.topic('notifications'); * ``` - * */ public topic(name: string): Topic { if (!name) { @@ -172,9 +178,8 @@ export class Eventing { /** * Retrieve all available topic references by querying for available topics. * - * @retuns A promise containing the list of available nitric topics - * - * Example: + * @returns A promise containing the list of available nitric topics + * @example * ```typescript * import { Eventing } from "@nitric/sdk"; * @@ -202,7 +207,8 @@ export class Eventing { let EVENTS = undefined; /** - * Events + * Events API client. + * * @returns an Events API client. * @example * ```typescript diff --git a/src/api/queues/v0/queues.ts b/src/api/queues/v0/queues.ts index 6cc38b6c..0c8814ec 100644 --- a/src/api/queues/v0/queues.ts +++ b/src/api/queues/v0/queues.ts @@ -37,7 +37,13 @@ interface FailedMessage { message: string; } -/** @internal */ +/** + * Converts and SDK task representation to a wire representation to be sent to the Nitric Server. + * + * @internal + * @param task to convert + * @returns the wire representation of the task + */ function taskToWire(task: Task) { const wireTask = new NitricTask(); @@ -48,6 +54,11 @@ function taskToWire(task: Task) { return wireTask; } +/** + * Constructs a new queue service client. + * + * @returns a queue service client. + */ function newQueueServiceClient(): QueueServiceClient { return new QueueServiceClient( SERVICE_BIND, @@ -269,7 +280,8 @@ export class ReceivedTask implements Task { let QUEUES = undefined; /** - * Queues + * Queues API Client. + * * @returns a Queues API client. * @example * ```typescript diff --git a/src/api/secrets/v0/secrets.ts b/src/api/secrets/v0/secrets.ts index b858bb33..3a4288bf 100644 --- a/src/api/secrets/v0/secrets.ts +++ b/src/api/secrets/v0/secrets.ts @@ -41,10 +41,11 @@ export class Secrets { } /** - * Get a reference to a secret - * @retuns A Secret reference + * Get a reference to a secret. * - * Example: + * @param name the name of the secret + * @returns A Secret reference. + * @example * ```typescript * import { secrets } from "@nitric/sdk"; * @@ -72,10 +73,10 @@ export class Secret { } /** - * Creates a new SecretVersion containing the given value + * Creates a new SecretVersion containing the given value. * - * @param secret - The secret value to store - * @returns {Promise} a version reference for a secret + * @param secret the value to store + * @returns A Promise which returns a reference to the newly created version of the secret * @example * ```typescript * import { secrets } from "@nitric/sdk"; @@ -115,8 +116,9 @@ export class Secret { } /** - * Returns a reference to the latest version of a secret - * @returns {SecretVersion} a reference to the latest version of the secret + * Returns a reference to the latest version of a secret. + * + * @returns a reference to the latest version of the secret * @example * ```typescript * import { secrets } from "@nitric/sdk"; @@ -126,25 +128,25 @@ export class Secret { * const latestVersion = secret.latest(); * } * ``` - * */ public latest(): SecretVersion { return this.version('latest'); } /** - * Creates a reference to a specific version of a secret - * @returns {SecretVersion} a secret version reference, the version may or may not exist + * Creates a reference to a specific version of a secret. + * + * @param version the ID of the version reference to be created. + * @returns a secret version reference, the version may or may not exist. * @example * ```typescript * import { secrets } from "@nitric/sdk"; * * const secret = secrets().secret('secret'); - * // NOTE: Version identifiers can difer between providers + * // NOTE: Version identifiers can differ between providers * // In most cases 'latest' should be used * const latestVersion = secret.version('1'); * ``` - * */ public version(version: string): SecretVersion { if (!version) { @@ -179,10 +181,9 @@ class SecretVersion { } /** - * Accesses the stored secret value from this version, it can be used to access the underlying secret data + * Accesses the stored secret value from this version, it can be used to access the underlying secret data. * - * @param secret - The secret value to store - * @returns {Promise} Retrieve the SecretValue for this secret version + * @returns A Promise that return the stored value in this version of the secret. * @example * ```typescript * import { secrets } from "@nitric/sdk"; @@ -247,7 +248,7 @@ class SecretValue { } /** - * @returns {Uint8Array} Value of the secret as a byte array + * @returns A Uint8Array (byte array) containing the value of the secret * @example * ```typescript * import { secrets } from "@nitric/sdk"; @@ -265,7 +266,9 @@ class SecretValue { }; /** - * @returns {string} Secret value as a string + * Return the secret value as a string. + * + * @returns the secret value as a string * @example * ```typescript * import { secrets } from "@nitric/sdk"; @@ -287,8 +290,9 @@ class SecretValue { let SECRETS = undefined; /** - * Secrets - * @returns {Secrets} a Secrets API client. + * Secrets API Client. + * + * @returns a Secrets API client. * @example * ```typescript * import { secrets } from "@nitric/sdk"; diff --git a/src/api/storage/v0/storage.ts b/src/api/storage/v0/storage.ts index 8d53d52a..9e9cf816 100644 --- a/src/api/storage/v0/storage.ts +++ b/src/api/storage/v0/storage.ts @@ -65,7 +65,8 @@ export class Bucket { } /** - * Retrieve a list of files on the bucket + * Retrieve a list of files on the bucket. + * * @returns An array of file references */ public async files(): Promise { @@ -130,9 +131,10 @@ export class File { } /** - * Get a pre-signed download URL for the file + * Get a pre-signed download URL for the file. + * * @param opts the option passed to the signUrl function. - * @returns a download URL string + * @returns a download URL string. */ public getDownloadUrl(opts?: SignUrlOptions): Promise { return this.signUrl(FileMode.Read, opts); @@ -140,18 +142,21 @@ export class File { /** * Get a pre-signed upload URL for the file. + * * @param opts the option passed to the signUrl function. - * @returns a upload URL string + * @returns a upload URL string. */ public getUploadUrl(opts?: SignUrlOptions): Promise { return this.signUrl(FileMode.Write, opts); } /** - * Create a presigned url for reading or writing for the given file reference + * Create a presigned url for reading or writing for the given file reference. + * * @param mode the mode the url will access the file with. E.g. reading or writing. + * @param opts file URL signing options. * @param opts.expiry how long the URL should be valid for in seconds. - * @deprecated for simplicity we suggest using getUploadUrl or getDownloadUrl + * @deprecated for simplicity we suggest using getUploadUrl or getDownloadUrl. */ public async signUrl( mode: FileMode, @@ -183,9 +188,10 @@ export class File { } /** - * Write an array of bytes to the file - * @param body The file contents to write - * @returns A void promise + * Write an array of bytes to the file. + * + * @param body The file contents to write. + * @returns A promise that resolves when the write operation completes. * * Example: * ```typescript @@ -219,8 +225,9 @@ export class File { } /** - * Read the contents of this file as an array of bytes - * @returns A byte array of the contents of the read blob + * Read the contents of this file as an array of bytes. + * + * @returns A promise that returns a byte array of the contents of the read blob. * * Example: * ```typescript @@ -248,8 +255,9 @@ export class File { } /** - * Delete this file from the bucket - * @returns A void promise + * Delete this file from the bucket. + * + * @returns A void promise. * * Example: * ```typescript @@ -281,7 +289,8 @@ export class File { let STORAGE = undefined; /** - * Storage + * Storage API client. + * * @returns a Storage API client. * @example * ```typescript diff --git a/src/faas/v0/context.ts b/src/faas/v0/context.ts index be3ec9ec..15d73d40 100644 --- a/src/faas/v0/context.ts +++ b/src/faas/v0/context.ts @@ -28,28 +28,36 @@ export abstract class TriggerContext< protected response: Resp; /** + * Noop base context http method. * + * @returns undefined */ public get http(): HttpContext | undefined { return undefined; } /** + * Noop base context event method. * + * @returns undefined */ public get event(): EventContext | undefined { return undefined; } /** + * Return the request object from this context. * + * @returns the request object. */ get req(): Req { return this.request; } /** + * Return the response object from this context. * + * @returns the response object. */ get res(): Resp { return this.response; @@ -154,7 +162,8 @@ export class HttpResponse { } /** - * Helper method to encode to JSON string for JSON http responses + * Helper method to encode to JSON string for JSON http responses. + * * @returns HttpContext with body property set with an encoded JSON string and json headers set. */ get json() { diff --git a/src/faas/v0/handler.ts b/src/faas/v0/handler.ts index 874e6601..5e18330c 100644 --- a/src/faas/v0/handler.ts +++ b/src/faas/v0/handler.ts @@ -36,7 +36,6 @@ export type EventMiddleware = GenericMiddleware; * The handlers are passed to each other via the 'next' argument. * * @param handlers one or more handler functions to be chained together into a single root function. - * * @returns - A root function composed of a chain of user provided functions */ export const createHandler = ( diff --git a/src/faas/v0/json.ts b/src/faas/v0/json.ts index a6034aa0..d74b10ed 100644 --- a/src/faas/v0/json.ts +++ b/src/faas/v0/json.ts @@ -22,8 +22,8 @@ const decodeData = (data: string | Uint8Array): string => { /** * HttpMiddleware that takes a ctx.req containing raw data (string | Uint8Array) and parses it as JSON into ctx.body - * @param ctx HttpContext containing the raw request data. - * @returns HttpContext with body property added containing a decoded JSON object from the req data. + * + * @returns a middleware decorator */ export const json = (): HttpMiddleware => (ctx: HttpContext, next) => { (ctx.req as any).body = JSON.parse(decodeData(ctx.req.data)); @@ -31,7 +31,8 @@ export const json = (): HttpMiddleware => (ctx: HttpContext, next) => { }; /** - * Helper method to encode to JSON string for JSON http responses + * Helper method to encode to JSON string for JSON http responses. + * * @param ctx HttpContext * @returns HttpContext with body property set with an encoded JSON string and json headers set. */ diff --git a/src/faas/v0/start.ts b/src/faas/v0/start.ts index c4325332..46a33236 100644 --- a/src/faas/v0/start.ts +++ b/src/faas/v0/start.ts @@ -72,6 +72,9 @@ export class Faas { /** * Add an event handler to this Faas server + * + * @param handlers the functions to call to respond to events + * @returns self */ event(...handlers: EventMiddleware[]): Faas { this.eventHandler = createHandler(...handlers); @@ -79,7 +82,10 @@ export class Faas { } /** - * Add a http handler to this Faas server + * Add an http handler to this Faas server + * + * @param handlers the functions to call to respond to http requests + * @returns self */ http(...handlers: HttpMiddleware[]): Faas { this.httpHandler = createHandler(...handlers); @@ -88,6 +94,8 @@ export class Faas { /** * Get http handler for this server + * + * @returns the registered HTTP handler for this server */ private getHttpHandler(): HttpMiddleware | TriggerMiddleware | undefined { return this.httpHandler || this.anyHandler; @@ -95,6 +103,8 @@ export class Faas { /** * Get event handler for this server + * + * @returns the registered event handler for this server */ private getEventHandler(): EventMiddleware | TriggerMiddleware | undefined { return this.eventHandler || this.anyHandler; @@ -102,6 +112,9 @@ export class Faas { /** * Start the Faas server + * + * @param handlers to use as the default when no other handler is registered for the request type + * @returns a promise that resolves when the server terminates */ async start(...handlers: TriggerMiddleware[]): Promise { this.anyHandler = handlers.length && createHandler(...handlers); @@ -261,18 +274,27 @@ const getFaasInstance = (): Faas => { /** * Register a HTTP handler + * + * @param handlers the functions to call to respond to http requests + * @returns the FaaS service factory */ export const http = (...handlers: HttpMiddleware[]): Faas => getFaasInstance().http(...handlers); /** * Register an event handler + * + * @param handlers the functions to call to respond to events + * @returns the FaaS service factory */ export const event = (...handlers: EventMiddleware[]): Faas => getFaasInstance().event(...handlers); /** * Start the FaaS server with a universal handler + * + * @param handlers default handlers + * @returns a promise that resolves when the server terminates */ export const start = async (...handlers: TriggerMiddleware[]): Promise => await getFaasInstance().start(...handlers); diff --git a/src/resources/api.ts b/src/resources/api.ts index 7db53dac..167f022a 100644 --- a/src/resources/api.ts +++ b/src/resources/api.ts @@ -117,6 +117,10 @@ export class Route { /** * Register a handler function for GET requests to this route + * + * @param middleware that should be run on any GET request to this route + * @param opts the options for this method, such as security definitions + * @returns a Promise that resolves if the handler stops running */ async get( middleware: HttpMiddleware | HttpMiddleware[], @@ -127,6 +131,10 @@ export class Route { /** * Register a handler function for POST requests to this route + * + * @param middleware that should respond to any matching requests to this route and method + * @param opts the options for this method, such as security definitions + * @returns a Promise that resolves if the handler stops running */ async post( middleware: HttpMiddleware | HttpMiddleware[], @@ -137,6 +145,10 @@ export class Route { /** * Register a handler function for PUT requests to this route + * + * @param middleware that should respond to any matching requests to this route and method + * @param opts the options for this method, such as security definitions + * @returns a Promise that resolves if the handler stops running */ async put( middleware: HttpMiddleware | HttpMiddleware[], @@ -147,6 +159,10 @@ export class Route { /** * Register a handler function for PATCH requests to this route + * + * @param middleware that should respond to any matching requests to this route and method + * @param opts the options for this method, such as security definitions + * @returns a Promise that resolves if the handler stops running */ async patch( middleware: HttpMiddleware | HttpMiddleware[], @@ -157,6 +173,10 @@ export class Route { /** * Register a handler function for DELETE requests to this route + * + * @param middleware that should respond to any matching requests to this route and method + * @param opts the options for this method, such as security definitions + * @returns a Promise that resolves if the handler stops running */ async delete( middleware: HttpMiddleware | HttpMiddleware[], @@ -167,6 +187,10 @@ export class Route { /** * Register a handler function for OPTIONS requests to this route + * + * @param middleware that should respond to any matching requests to this route and method + * @param opts the options for this method, such as security definitions + * @returns a Promise that resolves if the handler stops running */ async options( middleware: HttpMiddleware | HttpMiddleware[], @@ -176,9 +200,11 @@ export class Route { } /** - * Register a handler function for GET, POST, PATCH, PUT and DELETE requests to this route. + * Register a handler function for GET, POST, PATCH, PUT and DELETE requests to this route * - * Most useful when routing isn't important or you're doing you own internal routing. + * @param middleware that should respond to matching requests to this route and all HTTP methods + * @param opts the options for this method, such as security definitions + * @returns a Promise that resolves if the handler stops running */ async all( middleware: HttpMiddleware | HttpMiddleware[], @@ -308,9 +334,11 @@ export class Api extends Base { /** * Registers a new route with a GET handler in a single method. + * * @param match the route path matcher e.g. '/home'. Supports path params via colon prefix e.g. '/customers/:customerId' * @param middleware the middleware/handler to register for calls to GET - * @returns {Promise} that resolves when the handler terminates. + * @param opts the options for this method, such as security definitions + * @returns A Promise that resolves when the handler terminates. */ async get( match: string, @@ -322,9 +350,11 @@ export class Api extends Base { /** * Registers a new route with a POST handler in a single method. + * * @param match the route path matcher e.g. '/home'. Supports path params via colon prefix e.g. '/customers/:customerId' * @param middleware the middleware/handler to register for calls to POST - * @returns {Promise} that resolves when the handler terminates. + * @param opts the options for this method, such as security definitions + * @returns A Promise that resolves when the handler terminates. */ async post( match: string, @@ -336,9 +366,11 @@ export class Api extends Base { /** * Registers a new route with a PUT handler in a single method. + * * @param match the route path matcher e.g. '/home'. Supports path params via colon prefix e.g. '/customers/:customerId' * @param middleware the middleware/handler to register for calls to PUT - * @returns {Promise} that resolves when the handler terminates. + * @param opts the options for this method, such as security definitions + * @returns A Promise that resolves when the handler terminates. */ async put( match: string, @@ -350,9 +382,11 @@ export class Api extends Base { /** * Registers a new route with a PATCH handler in a single method. + * * @param match the route path matcher e.g. '/home'. Supports path params via colon prefix e.g. '/customers/:customerId' * @param middleware the middleware/handler to register for calls to PATCH - * @returns {Promise} that resolves when the handler terminates. + * @param opts the options for this method, such as security definitions + * @returns A Promise that resolves when the handler terminates. */ async patch( match: string, @@ -364,9 +398,11 @@ export class Api extends Base { /** * Registers a new route with a DELETE handler in a single method. + * * @param match the route path matcher e.g. '/home'. Supports path params via colon prefix e.g. '/customers/:customerId' * @param middleware the middleware/handler to register for calls to DELETE - * @returns {Promise} that resolves when the handler terminates. + * @param opts the options for this method, such as security definitions + * @returns A Promise that resolves when the handler terminates. */ async delete( match: string, @@ -378,9 +414,11 @@ export class Api extends Base { /** * Registers a new route with a OPTIONS handler in a single method. + * * @param match the route path matcher e.g. '/home'. Supports path params via colon prefix e.g. '/customers/:customerId' * @param middleware the middleware/handler to register for calls to DELETE - * @returns {Promise} that resolves when the handler terminates. + * @param opts the options for this method, such as security definitions + * @returns A Promise that resolves when the handler terminates. */ async options( match: string, @@ -391,8 +429,9 @@ export class Api extends Base { } /** - * Retrieves the Invocation URL of this API at runtime - * @returns {Promise} that contains the url of this API + * Retrieves the Invocation URL of this API at runtime. + * + * @returns Promise that returns the URL of this API */ async url(): Promise { const { @@ -417,7 +456,8 @@ export class Api extends Base { } /** - * Register this api as a required resource for the calling function/container + * Register this api as a required resource for the calling function/container. + * * @returns a promise that resolves when the registration is complete */ protected async register(): Promise { @@ -478,9 +518,9 @@ export class Api extends Base { * The returned API object can be used to register Routes and Methods, with Handlers. * e.g. api.route('/customers').get(getCustomerHandler) * - * @param name - * @param options - * @returns + * @param name the name of the API + * @param options additional options for creating the API + * @returns an API resource */ export const api: ( name: string, @@ -488,8 +528,10 @@ export const api: ( ) => Api = make(Api); /** - * Create a jwt security definition - * @returns + * Create a JWT security definition. + * + * @param opts security definition options + * @returns the new security definition. */ export const jwt = ( opts: Omit diff --git a/src/resources/bucket.ts b/src/resources/bucket.ts index a305a3b0..a76e313b 100644 --- a/src/resources/bucket.ts +++ b/src/resources/bucket.ts @@ -33,7 +33,8 @@ const everything: BucketPermission[] = ['reading', 'writing', 'deleting']; */ export class BucketResource extends SecureResource { /** - * Register this bucket as a required resource for the calling function/container + * Register this bucket as a required resource for the calling function/container. + * * @returns a promise that resolves when the registration is complete */ protected async register(): Promise { @@ -81,7 +82,7 @@ export class BucketResource extends SecureResource { return ResourceType.BUCKET; } - protected unwrapDetails(resp: ResourceDetailsResponse): {} { + protected unwrapDetails(resp: ResourceDetailsResponse): never { throw new Error('details unimplemented for bucket'); } diff --git a/src/resources/collection.ts b/src/resources/collection.ts index de76e26e..ae96ab30 100644 --- a/src/resources/collection.ts +++ b/src/resources/collection.ts @@ -37,6 +37,7 @@ export class CollectionResource< > extends SecureResource { /** * Register this collection as a required resource for the calling function/container + * * @returns a promise that resolves when the registration is complete */ protected async register(): Promise { @@ -94,7 +95,7 @@ export class CollectionResource< return ResourceType.COLLECTION; } - protected unwrapDetails(resp: ResourceDetailsResponse): {} { + protected unwrapDetails(resp: ResourceDetailsResponse): never { throw new Error('details unimplemented for collection'); } @@ -115,6 +116,14 @@ export class CollectionResource< const newCollection = make(CollectionResource); +/** + * Create a reference to a named queue in this project. + * + * If the queue hasn't been referenced before, this is a request for a new resource. Otherwise, the existing queue with the same name will be used. + * + * @param name the name of the queue. + * @returns a reference to the queue. + */ export function collection( name: string ): CollectionResource { diff --git a/src/resources/common.test.ts b/src/resources/common.test.ts index 1bb184af..026bc061 100644 --- a/src/resources/common.test.ts +++ b/src/resources/common.test.ts @@ -53,7 +53,7 @@ describe('common', () => { const test = res('same'); let detailsSpy; - let details: ResourceDetails<{}>; + let details: ResourceDetails; beforeAll(async () => { detailsSpy = jest diff --git a/src/resources/common.ts b/src/resources/common.ts index 798eadf7..03add4c7 100644 --- a/src/resources/common.ts +++ b/src/resources/common.ts @@ -33,7 +33,7 @@ export interface ResourceDetails { details: T; } -export abstract class Resource { +export abstract class Resource { /** * Unique name for the resource by type within the stack. * @@ -132,7 +132,7 @@ export type newer = (name: string, ...args: any[]) => T; /** * Provides a new resource instance. * - * @param name the _unique_ name of the resource within the stack + * @param T the type of resource to construct * @returns the resource */ export const make = ( diff --git a/src/resources/queue.ts b/src/resources/queue.ts index b14b8aa4..febc8d83 100644 --- a/src/resources/queue.ts +++ b/src/resources/queue.ts @@ -31,7 +31,8 @@ export type QueuePermission = 'sending' | 'receiving'; */ export class QueueResource extends SecureResource { /** - * Register this queue as a required resource for the calling function/container + * Register this queue as a required resource for the calling function/container. + * * @returns a promise that resolves when the registration is complete */ protected async register(): Promise { @@ -78,18 +79,17 @@ export class QueueResource extends SecureResource { return ResourceType.QUEUE; } - protected unwrapDetails(resp: ResourceDeclareResponse): {} { + protected unwrapDetails(resp: ResourceDeclareResponse): never { throw new Error('details unimplemented for queue'); } /** - * Return a queue reference and register the permissions required by the currently scoped function for this resource. + * Return a queue reference and registers the permissions required by the currently scoped function for this resource. * * e.g. const taskQueue = resources.queue('work').for('sending') * - * @param perm - * @param perms - * @returns + * @param perms the access that the currently scoped function is requesting to this resource. + * @returns a useable queue. */ public for(...perms: QueuePermission[]): Queue { this.registerPolicy(...perms); diff --git a/src/resources/schedule.ts b/src/resources/schedule.ts index e49aed0f..4a257371 100644 --- a/src/resources/schedule.ts +++ b/src/resources/schedule.ts @@ -49,7 +49,7 @@ class Rate { private readonly faas: Faas; constructor(schedule: Schedule, rate: string, ...mw: EventMiddleware[]) { - const [_, frequency] = rate.split(' '); + const [, frequency] = rate.split(' '); const normalizedFrequency = frequency.toLocaleLowerCase() as Frequency; // This will automatically parse the int off of a valid rate expression e.g. "10 minutes" === 10 @@ -116,7 +116,7 @@ class Schedule { * * @param rate to run the schedule, e.g. '7 days'. All rates accept a number and a frequency. Valid frequencies are 'days', 'hours' or 'minutes'. * @param mw the handler/middleware to run on a schedule - * @returns {Promise} that resolves when the schedule worker stops running. + * @returns A promise that resolves when the schedule worker stops running. */ every = (rate: string, ...mw: EventMiddleware[]): Promise => { // handle singular frequencies. e.g. schedule('something').every('day') @@ -140,7 +140,7 @@ class Schedule { * Provides a new schedule, which can be configured with a rate/cron and a callback to run on the schedule. * * @param description of the schedule, e.g. "Nightly" - * @returns + * @returns a named schedule. */ export const schedule = (description: string): Schedule => { return new Schedule(description); diff --git a/src/resources/secret.ts b/src/resources/secret.ts index 1cd30dbf..89f4ad13 100644 --- a/src/resources/secret.ts +++ b/src/resources/secret.ts @@ -75,7 +75,7 @@ export class SecretResource extends SecureResource { return ResourceType.SECRET; } - protected unwrapDetails(resp: ResourceDetailsResponse): {} { + protected unwrapDetails(resp: ResourceDetailsResponse): never { throw new Error('details unimplemented for secret'); } diff --git a/src/resources/topic.ts b/src/resources/topic.ts index cf01543a..81b441cc 100644 --- a/src/resources/topic.ts +++ b/src/resources/topic.ts @@ -56,6 +56,7 @@ class Subscription { export class TopicResource extends SecureResource { /** * Register this topic as a required resource for the calling function/container + * * @returns a promise that resolves when the registration is complete */ protected async register(): Promise { @@ -100,6 +101,7 @@ export class TopicResource extends SecureResource { /** * Register and start a subscription handler that will be called for all events from this topic. + * * @param mw handler middleware which will be run for every incoming event * @returns Promise which resolves when the handler server terminates */ @@ -112,7 +114,14 @@ export class TopicResource extends SecureResource { return ResourceType.TOPIC; } - protected unwrapDetails(resp: ResourceDeclareResponse): {} { + /** + * Unwraps the response details. + * + * Not used for topics. + * + * @param resp {never} + */ + protected unwrapDetails(resp: ResourceDeclareResponse): never { throw new Error('details unimplemented for topic'); } @@ -124,7 +133,7 @@ export class TopicResource extends SecureResource { * @param perms the required permission set * @returns a usable topic reference */ - public for(...perms: TopicPermission[]) { + public for(...perms: TopicPermission[]): Topic { this.registerPolicy(...perms); return events().topic(this.name); } diff --git a/yarn.lock b/yarn.lock index 930639d6..ebf0ce2f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -317,6 +317,15 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@es-joy/jsdoccomment@~0.37.0": + version "0.37.0" + resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.37.0.tgz#aaafb4bb6c88288aa7899aef0f3b1b851c36f908" + integrity sha512-hjK0wnsPCYLlF+HHB4R/RbUjOWeLW2SlarB67+Do5WsKILOkmIZvvPJFbtWSmbypxcjpoECLAMzoao0D4Bg5ZQ== + dependencies: + comment-parser "1.3.1" + esquery "^1.4.0" + jsdoc-type-pratt-parser "~4.0.0" + "@esbuild/android-arm@0.15.14": version "0.15.14" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.15.14.tgz#5d0027f920eeeac313c01fd6ecb8af50c306a466" @@ -1636,6 +1645,11 @@ commander@^6.2.0: resolved "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz" integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== +comment-parser@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.3.1.tgz#3d7ea3adaf9345594aedee6563f422348f165c1b" + integrity sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA== + compare-func@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz" @@ -1959,7 +1973,7 @@ debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@^4.3.1: +debug@^4.3.1, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -2345,6 +2359,11 @@ escape-string-regexp@^2.0.0: resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + escodegen@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz" @@ -2357,6 +2376,19 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" +eslint-plugin-jsdoc@^40.1.0: + version "40.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-40.1.0.tgz#fec2f649a60167fa5a94f05ce2c6c041caaab129" + integrity sha512-ANvrhiu62VlSorARM0hup60VQsS3hNyp0Ca7cnJDj8tpJzM7tNhBVqMVYXSuLzEmqrpwx6aAh+NAN2DdAGG5fQ== + dependencies: + "@es-joy/jsdoccomment" "~0.37.0" + comment-parser "1.3.1" + debug "^4.3.4" + escape-string-regexp "^4.0.0" + esquery "^1.5.0" + semver "^7.3.8" + spdx-expression-parse "^3.0.1" + eslint-scope@^5.0.0, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" @@ -2446,6 +2478,13 @@ esquery@^1.4.0: dependencies: estraverse "^5.1.0" +esquery@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" @@ -4027,6 +4066,11 @@ jsbn@~0.1.0: resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= +jsdoc-type-pratt-parser@~4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz#136f0571a99c184d84ec84662c45c29ceff71114" + integrity sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ== + jsdom@^16.4.0: version "16.5.1" resolved "https://registry.npmjs.org/jsdom/-/jsdom-16.5.1.tgz" @@ -5589,7 +5633,7 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.3.5: +semver@^7.3.5, semver@^7.3.8: version "7.3.8" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== @@ -5790,7 +5834,7 @@ spdx-exceptions@^2.1.0: resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz" integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== -spdx-expression-parse@^3.0.0: +spdx-expression-parse@^3.0.0, spdx-expression-parse@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==