Skip to content

Commit

Permalink
feat: support for multiple paths in in source configuration (#230)
Browse files Browse the repository at this point in the history
* feat: support for multiple paths in in source configuration

* fix: use array for isc path properties

* fix: support both array and string path properties

* fix: fix linting

* fix: have a string usecase in declaration tests by transforming json array to string

* fix: remove file-level eslint-disable-max-depth

* fix: change conditional for cache config and path length

* fix: change conditional for adding all different types of config

* fix: remove fallback to empty object

* fix: change comment

* fix: undo changing config fixtures to use an array as path

* fix: update comments

* Update node/declaration.ts

Co-authored-by: Eduardo Bouças <[email protected]>

* fix: change mutation of config.path

* fix: formatting

Co-authored-by: khen <[email protected]>
Co-authored-by: Eduardo Bouças <[email protected]>
  • Loading branch information
3 people authored Dec 6, 2022
1 parent 94c6ec6 commit d4ec906
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 11 deletions.
2 changes: 1 addition & 1 deletion node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const enum Cache {

export interface FunctionConfig {
cache?: Cache
path?: string
path?: string | string[]
}

const getConfigExtractor = () => {
Expand Down
64 changes: 58 additions & 6 deletions node/declaration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,20 @@ const deployConfig = {
layers: [],
}

test('In source config takes precedence over netlify.toml config', () => {
test('In-source config takes precedence over netlify.toml config', () => {
const tomlConfig = [
{ function: 'geolocation', path: '/geo', cache: 'off' },
{ function: 'json', path: '/json', cache: 'manual' },
]

const funcConfig = {
geolocation: { path: '/geo-isc', cache: 'manual' },
geolocation: { path: ['/geo-isc', '/*'], cache: 'manual' },
json: { path: '/json', cache: 'off' },
} as Record<string, FunctionConfig>

const expectedDeclarations = [
{ function: 'geolocation', path: '/geo-isc', cache: 'manual' },
{ function: 'geolocation', path: '/*', cache: 'manual' },
{ function: 'json', path: '/json', cache: 'off' },
]

Expand All @@ -30,14 +31,14 @@ test('In source config takes precedence over netlify.toml config', () => {
expect(declarations).toEqual(expectedDeclarations)
})

test("Declarations don't break if no in source config is provided", () => {
test("Declarations don't break if no in-source config is provided", () => {
const tomlConfig = [
{ function: 'geolocation', path: '/geo', cache: 'off' },
{ function: 'json', path: '/json', cache: 'manual' },
]

const funcConfig = {
geolocation: { path: '/geo-isc', cache: 'manual' },
geolocation: { path: ['/geo-isc'], cache: 'manual' },
json: {},
} as Record<string, FunctionConfig>

Expand All @@ -51,11 +52,11 @@ test("Declarations don't break if no in source config is provided", () => {
expect(declarations).toEqual(expectedDeclarations)
})

test('In source config works independent of the netlify.toml file if a path is defined and otherwise if no path is set', () => {
test('In-source config works independent of the netlify.toml file if a path is defined and otherwise if no path is set', () => {
const tomlConfig = [{ function: 'geolocation', path: '/geo', cache: 'off' }]

const funcConfigWithPath = {
json: { path: '/json', cache: 'off' },
json: { path: ['/json', '/json-isc'], cache: 'off' },
} as Record<string, FunctionConfig>

const funcConfigWithoutPath = {
Expand All @@ -65,6 +66,7 @@ test('In source config works independent of the netlify.toml file if a path is d
const expectedDeclarationsWithISCPath = [
{ function: 'geolocation', path: '/geo', cache: 'off' },
{ function: 'json', path: '/json', cache: 'off' },
{ function: 'json', path: '/json-isc', cache: 'off' },
]

const expectedDeclarationsWithoutISCPath = [{ function: 'geolocation', path: '/geo', cache: 'off' }]
Expand All @@ -75,3 +77,53 @@ test('In source config works independent of the netlify.toml file if a path is d
const declarationsWithoutISCPath = getDeclarationsFromConfig(tomlConfig, funcConfigWithoutPath, deployConfig)
expect(declarationsWithoutISCPath).toEqual(expectedDeclarationsWithoutISCPath)
})

test('In-source config works if only the cache config property is set', () => {
const tomlConfig = [{ function: 'geolocation', path: '/geo', cache: 'off' }]

const funcConfig = {
geolocation: { cache: 'manual' },
} as Record<string, FunctionConfig>

const expectedDeclarations = [{ function: 'geolocation', path: '/geo', cache: 'manual' }]

expect(getDeclarationsFromConfig(tomlConfig, funcConfig, deployConfig)).toEqual(expectedDeclarations)
})

test("In-source config path property works if it's not an array", () => {
const tomlConfig = [{ function: 'json', path: '/json-toml', cache: 'off' }]

const funcConfig = {
json: { path: '/json', cache: 'manual' },
} as Record<string, FunctionConfig>

const expectedDeclarations = [{ function: 'json', path: '/json', cache: 'manual' }]

expect(getDeclarationsFromConfig(tomlConfig, funcConfig, deployConfig)).toEqual(expectedDeclarations)
})

test("In-source config path property works if it's not an array and it's not present in toml or deploy config", () => {
const tomlConfig = [{ function: 'geolocation', path: '/geo', cache: 'off' }]
const funcConfig = {
json: { path: '/json-isc', cache: 'manual' },
} as Record<string, FunctionConfig>

const expectedDeclarations = [
{ function: 'geolocation', path: '/geo', cache: 'off' },
{ function: 'json', path: '/json-isc', cache: 'manual' },
]

expect(getDeclarationsFromConfig(tomlConfig, funcConfig, deployConfig)).toEqual(expectedDeclarations)
})

test('In-source config works if path property is an empty array with cache value specified', () => {
const tomlConfig = [{ function: 'json', path: '/json-toml', cache: 'off' }]

const funcConfig = {
json: { path: [], cache: 'manual' },
} as Record<string, FunctionConfig>

const expectedDeclarations = [{ function: 'json', path: '/json-toml', cache: 'manual' }]

expect(getDeclarationsFromConfig(tomlConfig, funcConfig, deployConfig)).toEqual(expectedDeclarations)
})
33 changes: 29 additions & 4 deletions node/declaration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,44 @@ export const getDeclarationsFromConfig = (
// a function configuration object, we replace the path because that object
// takes precedence.
for (const declaration of [...tomlDeclarations, ...deployConfig.declarations]) {
const config = functionsConfig[declaration.function] ?? {}
const config = functionsConfig[declaration.function]

// If no config is found, add the declaration as is
if (!config) {
declarations.push(declaration)

// If we have a path specified as either a string or non-empty array
// create a declaration for each path
} else if (config.path?.length) {
const paths = Array.isArray(config.path) ? config.path : [config.path]

paths.forEach((path) => {
declarations.push({ ...declaration, ...config, path })
})

// With an in-source config without a path, add the config to the declaration
} else {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { path, ...rest } = config
declarations.push({ ...declaration, ...rest })
}

functionsVisited.add(declaration.function)
declarations.push({ ...declaration, ...config })
}

// Finally, we must create declarations for functions that are not declared
// in the TOML at all.
for (const name in functionsConfig) {
const { path, ...config } = functionsConfig[name]
const { ...config } = functionsConfig[name]
const { path } = functionsConfig[name]

// If we have path specified create a declaration for each path
if (!functionsVisited.has(name) && path) {
declarations.push({ ...config, function: name, path })
const paths = Array.isArray(path) ? path : [path]

paths.forEach((singlePath) => {
declarations.push({ ...config, function: name, path: singlePath })
})
}
}

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"test:dev": "run-s test:dev:*",
"test:ci": "run-s test:ci:*",
"test:dev:vitest": "cross-env FORCE_COLOR=0 vitest run",
"test:dev:vitest:watch": "cross-env FORCE_COLOR=0 vitest watch",
"test:dev:deno": "deno test --allow-all deno",
"test:ci:vitest": "cross-env FORCE_COLOR=0 vitest run",
"test:ci:deno": "deno test --allow-all deno",
Expand Down

0 comments on commit d4ec906

Please sign in to comment.