Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add function logs API [EXT-6001] #2520

Merged
merged 15 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions lib/adapters/REST/endpoints/function-log.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { AxiosInstance } from 'contentful-sdk-core'
import * as raw from './raw'
import type {
CollectionProp,
GetFunctionLogParams,
GetManyFunctionLogParams,
} from '../../../common-types'
import type { RestEndpoint } from '../types'
import type { FunctionLogProps } from '../../../entities/function-log'

const FunctionLogAlphaHeaders = {
'x-contentful-enable-alpha-feature': 'function-logs',
}

const baseURL = (params: GetManyFunctionLogParams) =>
`/spaces/${params.spaceId}/environments/${params.environmentId}/app_installations/${params.appInstallationId}/functions/${params.functionId}/logs`
michaelpineirocontentful marked this conversation as resolved.
Show resolved Hide resolved

const getURL = (params: GetFunctionLogParams) =>
`/spaces/${params.spaceId}/environments/${params.environmentId}/app_installations/${params.appInstallationId}/functions/${params.functionId}/logs/${params.logId}`

export const get: RestEndpoint<'FunctionLog', 'get'> = (
http: AxiosInstance,
params: GetFunctionLogParams
) => {
return raw.get<FunctionLogProps>(http, getURL(params), {
headers: {
...FunctionLogAlphaHeaders,
},
})
}

export const getMany: RestEndpoint<'FunctionLog', 'getMany'> = (
http: AxiosInstance,
params: GetManyFunctionLogParams
) => {
return raw.get<CollectionProp<FunctionLogProps>>(http, baseURL(params), {
params: params.query,
headers: {
...FunctionLogAlphaHeaders,
},
})
}
6 changes: 4 additions & 2 deletions lib/adapters/REST/endpoints/function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ export const getMany: RestEndpoint<'Function', 'getMany'> = (
http: AxiosInstance,
params: GetManyFunctionParams
) => {
return raw.get<CollectionProp<FunctionProps>>(http, getManyUrl(params))
return raw.get<CollectionProp<FunctionProps>>(http, getManyUrl(params), { params: params.query })
}

export const getManyForEnvironment: RestEndpoint<'Function', 'getManyForEnvironment'> = (
http: AxiosInstance,
params: GetFunctionForEnvParams
) => {
return raw.get<CollectionProp<FunctionProps>>(http, getFunctionsEnvURL(params))
return raw.get<CollectionProp<FunctionProps>>(http, getFunctionsEnvURL(params), {
params: params.query,
})
}
2 changes: 2 additions & 0 deletions lib/adapters/REST/endpoints/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import * as EnvironmentTemplate from './environment-template'
import * as EnvironmentTemplateInstallation from './environment-template-installation'
import * as Extension from './extension'
import * as Function from './function'
import * as FunctionLog from './function-log'
import * as Http from './http'
import * as Locale from './locale'
import * as Organization from './organization'
Expand Down Expand Up @@ -90,6 +91,7 @@ export default {
EnvironmentTemplateInstallation,
Extension,
Function,
FunctionLog,
Http,
Locale,
Organization,
Expand Down
62 changes: 58 additions & 4 deletions lib/common-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ import type {
WorkflowsChangelogEntryProps,
WorkflowsChangelogQueryOptions,
} from './entities/workflows-changelog-entry'
import type { FunctionLogProps } from './entities/function-log'

export interface DefaultElements<TPlainObject extends object = object> {
toPlainObject(): TPlainObject
Expand Down Expand Up @@ -345,6 +346,31 @@ export interface BasicCursorPaginationOptions extends Omit<BasicQueryOptions, 's
pagePrev?: string
}

// Base interface for shared fields
interface CursorPaginationBase {
limit?: number
}

// Interfaces for each “exclusive” shape
interface CursorPaginationPageNext extends CursorPaginationBase {
pageNext: string
pagePrev?: never
}

interface CursorPaginationPagePrev extends CursorPaginationBase {
pageNext?: never
pagePrev: string
}

interface CursorPaginationNone extends CursorPaginationBase {
pageNext?: never
pagePrev?: never
}

export interface AcceptsQueryOptions {
'accepts[all]'?: string
}

export type KeyValueMap = Record<string, any>

/**
Expand Down Expand Up @@ -560,6 +586,9 @@ type MRInternal<UA extends boolean> = {
'getManyForEnvironment'
>

(opts: MROpts<'FunctionLog', 'get', UA>): MRReturn<'FunctionLog', 'get'>
(opts: MROpts<'FunctionLog', 'getMany', UA>): MRReturn<'FunctionLog', 'getMany'>

(opts: MROpts<'Locale', 'get', UA>): MRReturn<'Locale', 'get'>
(opts: MROpts<'Locale', 'getMany', UA>): MRReturn<'Locale', 'getMany'>
(opts: MROpts<'Locale', 'delete', UA>): MRReturn<'Locale', 'delete'>
Expand Down Expand Up @@ -1556,6 +1585,20 @@ export type MRActions = {
return: CollectionProp<FunctionProps>
}
}

FunctionLog: {
get: {
params: GetFunctionLogParams
return: FunctionLogProps
headers?: RawAxiosRequestHeaders
}
getMany: {
params: GetManyFunctionLogParams
return: CollectionProp<FunctionLogProps>
headers?: RawAxiosRequestHeaders
}
}

Locale: {
get: { params: GetSpaceEnvironmentParams & { localeId: string }; return: LocaleProps }
getMany: {
Expand Down Expand Up @@ -2150,10 +2193,14 @@ export type GetEntryParams = GetSpaceEnvironmentParams & { entryId: string }
export type GetExtensionParams = GetSpaceEnvironmentParams & { extensionId: string }
export type GetEnvironmentTemplateParams = GetOrganizationParams & { environmentTemplateId: string }
export type GetFunctionParams = GetAppDefinitionParams & { functionId: string }
export type GetManyFunctionParams = GetAppDefinitionParams
export type GetFunctionForEnvParams = GetSpaceEnvironmentParams & {
appInstallationId: string
}
export type GetManyFunctionParams = AcceptsQueryParams & GetAppDefinitionParams
export type GetFunctionForEnvParams = AcceptsQueryParams &
GetSpaceEnvironmentParams & {
appInstallationId: string
}
export type GetManyFunctionLogParams = CursorBasedParams &
GetFunctionForEnvParams & { functionId: string }
export type GetFunctionLogParams = GetManyFunctionLogParams & { logId: string }
export type GetOrganizationParams = { organizationId: string }
export type GetReleaseParams = GetSpaceEnvironmentParams & { releaseId: string }
export type GetSnapshotForContentTypeParams = GetSpaceEnvironmentParams & { contentTypeId: string }
Expand Down Expand Up @@ -2221,6 +2268,13 @@ export type GetResourceParams = GetSpaceEnvironmentParams & { resourceTypeId: st
export type QueryParams = { query?: QueryOptions }
export type SpaceQueryParams = { query?: SpaceQueryOptions }
export type PaginationQueryParams = { query?: PaginationQueryOptions }
export type CursorPaginationXORParams = {
query?: (CursorPaginationPageNext | CursorPaginationPagePrev | CursorPaginationNone) & {
limit?: number
}
}
export type CursorBasedParams = CursorPaginationXORParams
export type AcceptsQueryParams = { query?: AcceptsQueryOptions }

export enum ScheduledActionReferenceFilters {
contentTypeAnnotationNotIn = 'sys.contentType.metadata.annotations.ContentType[nin]',
Expand Down
126 changes: 125 additions & 1 deletion lib/create-environment-api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import type { Stream } from 'stream'
import { createRequestConfig } from 'contentful-sdk-core'
import type { BasicCursorPaginationOptions, QueryOptions } from './common-types'
import type {
AcceptsQueryOptions,
BasicCursorPaginationOptions,
CursorBasedParams,
QueryOptions,
} from './common-types'
import type { BasicQueryOptions, MakeRequest } from './common-types'
import entities from './entities'
import type { CreateAppInstallationProps } from './entities/app-installation'
Expand Down Expand Up @@ -46,6 +51,8 @@ import { wrapTag, wrapTagCollection } from './entities/tag'
import { wrapUIConfig } from './entities/ui-config'
import { wrapUserUIConfig } from './entities/user-ui-config'
import { wrapEnvironmentTemplateInstallationCollection } from './entities/environment-template-installation'
import { wrapFunctionCollection } from './entities/function'
import { wrapFunctionLog, wrapFunctionLogCollection } from './entities/function-log'
import type { CreateAppAccessTokenProps } from './entities/app-access-token'
import type { ResourceQueryOptions } from './entities/resource'

Expand Down Expand Up @@ -1667,6 +1674,123 @@ export default function createEnvironmentApi(makeRequest: MakeRequest) {
payload: data,
}).then((payload) => wrapAppAccessToken(makeRequest, payload))
},
/**
* Gets a collection of Functions for a given environment
* @param appInstallationId
* @param {import('../common-types').AcceptsQueryOptions} query - optional query parameter for filtering functions by action
* @return Promise containing wrapped collection of Functions in an environment
* @example ```javascript
* const contentful = require('contentful-management')
*
* const client = contentful.createClient({
* accessToken: '<content_management_api_key>'
* })
*
* client
* .getSpace('<space-id>')
* .then((space) => space.getEnvironment('<environment-id>'))
* .then((environment) => environment.getFunctionsForEnvironment('<app-installation-id>', { 'accepts[all]': '<action>' }))
* .then((functions) => console.log(functions.items))
* .catch(console.error)
* ```
*/
getFunctionsForEnvironment(appInstallationId: string, query?: AcceptsQueryOptions) {
const raw = this.toPlainObject() as EnvironmentProps
return makeRequest({
entityType: 'Function',
action: 'getManyForEnvironment',
params: {
spaceId: raw.sys.space.sys.id,
environmentId: raw.sys.id,
appInstallationId,
query,
},
}).then((data) => wrapFunctionCollection(makeRequest, data))
},
/**
* Gets a collection of FunctionLogs for a given app installation id and FunctionId
* @param appInstallationId
* @param functionId
* @param {import('../common-types').CursorBasedParams} query - optional query parameter for pagination (limit, nextPage, prevPage)
* @return Promise containing wrapped collection of FunctionLogs
* * @example ```javascript
* const contentful = require('contentful-management')
*
* const client = contentful.createClient({
* accessToken: '<content_management_api_key>'
* })
*
* client
* .getSpace('<space-id>')
* .then((space) => space.getEnvironment('<environment-id>'))
* .then((environment) =>
* environment.getFunctionLogs(
* '<app-installation-id>',
* '<function-id>',
* { limit: 10 },
* )
* )
* .then((functionLogs) => console.log(functionLog.items))
* .catch(console.error)
* ```
*/
getFunctionLogs(appInstallationId: string, functionId: string, query?: CursorBasedParams) {
const raw: EnvironmentProps = this.toPlainObject()

return makeRequest({
entityType: 'FunctionLog',
action: 'getMany',
params: {
spaceId: raw.sys.space.sys.id,
environmentId: raw.sys.id,
appInstallationId,
functionId,
query: query ? createRequestConfig({ query }).params : undefined,
},
}).then((data) => wrapFunctionLogCollection(makeRequest, data))
},
/**
* Gets a FunctionLog by appInstallationId, functionId and logId
* @param appInstallationId
* @param functionId
* @param logId
* @return Promise containing a wrapped FunctionLog
* @example ```javascript
* const contentful = require('contentful-management')
*
* const client = contentful.createClient({
* accessToken: '<content_management_api_key>'
* })
*
* client
* .getSpace(<space-id>)
* .then((space) => space.getEnvironment('<environment-id>'))
* .then((environment) =>
* environment.getFunctionLog(
* '<app-installation-id>',
* '<function-id>',
* '<log-id>'
* )
* )
* .then((functionLog) => console.log(functionLog))
* .catch(console.error)
* ```
*/
getFunctionLog(appInstallationId: string, functionId: string, logId: string) {
const raw: EnvironmentProps = this.toPlainObject()

return makeRequest({
entityType: 'FunctionLog',
action: 'get',
params: {
spaceId: raw.sys.space.sys.id,
environmentId: raw.sys.id,
appInstallationId,
functionId,
logId,
},
}).then((data) => wrapFunctionLog(makeRequest, data))
},
/**
* Gets all snapshots of an entry
* @func getEntrySnapshots
Expand Down
Loading