@architect/inventory 2.2.1-RC.0 → 3.0.0-RC.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/changelog.md +54 -1
  2. package/package.json +12 -10
  3. package/readme.md +5 -4
  4. package/src/config/_upsert.js +1 -1
  5. package/src/config/arc.js +3 -3
  6. package/src/config/pragmas/app.js +1 -1
  7. package/src/config/pragmas/events.js +3 -2
  8. package/src/config/pragmas/http.js +5 -4
  9. package/src/config/pragmas/index.js +16 -5
  10. package/src/config/pragmas/meta/custom-lambdas.js +10 -0
  11. package/src/config/pragmas/{src-dirs.js → meta/src-dirs.js} +13 -10
  12. package/src/config/pragmas/plugins.js +109 -4
  13. package/src/config/pragmas/populate-lambda/_custom-lambdas.js +10 -0
  14. package/src/config/pragmas/populate-lambda/_events.js +17 -11
  15. package/src/config/pragmas/populate-lambda/_http.js +18 -10
  16. package/src/config/pragmas/populate-lambda/_scheduled.js +18 -10
  17. package/src/config/pragmas/populate-lambda/_tables-streams.js +20 -23
  18. package/src/config/pragmas/populate-lambda/_ws.js +26 -0
  19. package/src/config/pragmas/populate-lambda/get-handler.js +86 -13
  20. package/src/config/pragmas/populate-lambda/get-lambda.js +23 -0
  21. package/src/config/pragmas/populate-lambda/get-runtime.js +8 -7
  22. package/src/config/pragmas/populate-lambda/index.js +134 -84
  23. package/src/config/pragmas/queues.js +3 -2
  24. package/src/config/pragmas/scheduled.js +3 -2
  25. package/src/config/pragmas/shared.js +41 -44
  26. package/src/config/pragmas/sort/http.js +3 -2
  27. package/src/config/pragmas/static.js +5 -4
  28. package/src/config/pragmas/tables-indexes.js +3 -10
  29. package/src/config/pragmas/tables-streams.js +7 -5
  30. package/src/config/pragmas/tables.js +1 -1
  31. package/src/config/pragmas/validate/_events.js +1 -1
  32. package/src/config/pragmas/validate/_http.js +4 -4
  33. package/src/config/pragmas/validate/_lib.js +3 -10
  34. package/src/config/pragmas/validate/_scheduled.js +2 -2
  35. package/src/config/pragmas/validate/_shared.js +1 -1
  36. package/src/config/pragmas/validate/_tables-streams.js +6 -8
  37. package/src/config/pragmas/validate/_tables.js +2 -2
  38. package/src/config/pragmas/validate/index.js +2 -2
  39. package/src/config/pragmas/views.js +39 -37
  40. package/src/config/pragmas/ws.js +6 -4
  41. package/src/config/project/index.js +36 -20
  42. package/src/config/project/plugins/env.js +71 -0
  43. package/src/config/project/plugins/index.js +7 -0
  44. package/src/config/project/plugins/runtimes.js +67 -0
  45. package/src/config/project/prefs/dotenv.js +81 -0
  46. package/src/config/project/{prefs.js → prefs/index.js} +41 -22
  47. package/src/config/project/validate/index.js +15 -8
  48. package/src/defaults/index.js +20 -13
  49. package/src/env/index.js +76 -61
  50. package/src/get.js +1 -2
  51. package/src/index.js +17 -15
  52. package/src/lib/asap-src.js +3 -3
  53. package/src/lib/error-fmt.js +2 -10
  54. package/src/lib/get-lambda-dirs.js +37 -0
  55. package/src/lib/index.js +42 -0
  56. package/src/lib/is.js +3 -1
  57. package/src/lib/merge-env-vars.js +32 -0
  58. package/src/lib/pragmas.js +19 -3
  59. package/src/read/index.js +1 -3
  60. package/src/read/reader.js +2 -2
  61. package/src/validate/config.js +12 -6
  62. package/src/validate/index.js +17 -18
  63. package/src/validate/layers.js +2 -2
  64. package/src/validate/paths.js +17 -0
  65. package/src/validate/tables-children.js +5 -5
  66. package/src/config/pragmas/indexes.js +0 -19
  67. package/src/config/pragmas/macros.js +0 -5
  68. package/src/config/pragmas/populate-lambda/_plugins.js +0 -25
  69. package/src/config/pragmas/populate-lambda/_websockets.js +0 -19
  70. package/src/config/project/plugins.js +0 -31
  71. package/src/lib/http-methods.js +0 -2
@@ -0,0 +1,26 @@
1
+ let { is, getLambdaDirs } = require('../../../lib')
2
+
3
+ module.exports = function populateWebSockets (params) {
4
+ let { item, errors, plugin } = params
5
+ if (plugin) {
6
+ let { name, src } = item
7
+ if (name && src) {
8
+ return { ...item, route: name, ...getLambdaDirs(params, { plugin }) }
9
+ }
10
+ errors.push(`Invalid plugin-generated @ws item: name: ${name}, src: ${src}`)
11
+ return
12
+ }
13
+ else if (is.string(item)) {
14
+ let name = item
15
+ let route = name // Same as name, just what AWS calls it
16
+ let dirs = getLambdaDirs(params, { name })
17
+ return { name, route, ...dirs }
18
+ }
19
+ else if (is.object(item)) {
20
+ let name = Object.keys(item)[0]
21
+ let route = name
22
+ let dirs = getLambdaDirs(params, { name, customSrc: item[name].src })
23
+ return { name, route, ...dirs }
24
+ }
25
+ errors.push(`Invalid @ws item: ${item}`)
26
+ }
@@ -1,14 +1,87 @@
1
- module.exports = function getHandler (config, src, errors) {
2
- let { handler, runtime } = config
3
- let parts = handler.split('.')
4
- if (parts.length !== 2) errors.push(`Invalid handler: ${handler}. Expected {file}.{function}, example: index.handler`)
5
- let ext
6
- if (runtime.startsWith('nodejs')) ext = 'js'
7
- if (runtime.startsWith('python')) ext = 'py'
8
- if (runtime.startsWith('ruby')) ext = 'rb'
9
- if (runtime.startsWith('deno')) ext = 'ts'
10
- // TODO add Go, Java, .NET, etc.
11
- let handlerFile = `${src}/${parts[0]}${ext ? '.' + ext : ''}`
12
- let handlerFunction = parts[1]
13
- return { handlerFile, handlerFunction }
1
+ let { join } = require('path')
2
+ let { existsSync, readFileSync } = require('fs')
3
+
4
+ module.exports = function getHandler ({ config, src, build, errors }) {
5
+ let { handler, runtime, runtimeConfig } = config
6
+ let parts = handler.split('.') // Default is 'index.handler'
7
+ if (parts.length !== 2) {
8
+ errors.push(`Invalid handler: ${handler}. Expected {file}.{method}, example: index.handler`)
9
+ }
10
+
11
+ let { file, ext, handlerModuleSystem } = getExt({ runtime, src, errors })
12
+ file = file || parts[0] // Falls back to 'index'
13
+ ext = ext ? '.' + ext : ''
14
+ let handlerFile = join(src, `${file}${ext}`)
15
+ let handlerMethod = parts[1]
16
+ let customRuntimeType = runtimeConfig?.type
17
+
18
+ // Compiled to an interpreted runtime (eg TypeScript)
19
+ if (customRuntimeType === 'transpiled') {
20
+ handlerFile = join(build, runtimeConfig?.handlerFile || 'index.js')
21
+ }
22
+ // Compiled to a binary
23
+ else if (customRuntimeType === 'compiled') {
24
+ handlerFile = join(build, runtimeConfig.handlerFile || 'handler')
25
+ }
26
+ // Interpreted
27
+ else if (customRuntimeType === 'interpreted') {
28
+ handlerFile = join(src, runtimeConfig.handlerFile || 'index')
29
+ }
30
+
31
+ let handlerConfig = { handlerFile, handlerMethod, handlerModuleSystem }
32
+ return handlerConfig
33
+ }
34
+
35
+ let nodeHandlers = [ 'index.js', 'index.mjs', 'index.cjs' ]
36
+ let denoHandlers = [ 'mod.ts', 'mod.js' ]
37
+ // TODO: these are all prob going away
38
+ .concat([ 'mod.tsx', 'index.ts', 'index.js', 'index.tsx' ])
39
+
40
+ function getExt ({ runtime, src, errors }) {
41
+ try {
42
+ if (runtime.startsWith('node')) {
43
+ if (runtime === 'nodejs12.x') {
44
+ return { ext: 'js', handlerModuleSystem: 'cjs' }
45
+ }
46
+ // This presumes Node.js 14.x+ Lambda releases use the same CJS/ESM pattern
47
+ else {
48
+ let { file, ext = 'js' } = findHandler(nodeHandlers, src)
49
+ let handlerModuleSystem = ext === 'mjs' ? 'esm' : 'cjs'
50
+ let pkgFile = join(src, 'package.json')
51
+ if (existsSync(pkgFile)) {
52
+ let pkg = JSON.parse(readFileSync(pkgFile))
53
+ handlerModuleSystem = getModSystem(pkg)
54
+ }
55
+ return { file, ext, handlerModuleSystem }
56
+ }
57
+ }
58
+ if (runtime.startsWith('python')) return { ext: 'py' }
59
+ if (runtime.startsWith('ruby')) return { ext: 'rb' }
60
+ if (runtime.startsWith('deno')) {
61
+ let { file = 'mod', ext = 'ts' } = findHandler(denoHandlers, src)
62
+ return { file, ext }
63
+ }
64
+ return { ext: '' }
65
+ }
66
+ catch (err) {
67
+ errors.push(`Error getting Lambda handler in ${src}: ${err.message}`)
68
+ return {}
69
+ }
70
+ }
71
+
72
+ function findHandler (arr, src){
73
+ for (let handler of arr) {
74
+ if (existsSync(join(src, handler))) {
75
+ let bits = handler.split('.')
76
+ return { file: bits[0], ext: bits[1] }
77
+ }
78
+ }
79
+ return {}
80
+ }
81
+
82
+ function getModSystem (pkg) {
83
+ if (pkg?.type === 'module') return 'esm'
84
+ else if (pkg?.type === 'commonjs') return 'cjs'
85
+ else if (pkg?.type) throw Error(`Invalid 'type' field: ${pkg.type}`)
86
+ return 'cjs'
14
87
  }
@@ -0,0 +1,23 @@
1
+ // Pragma-specific Lambda constructors
2
+ let getHTTP = require('./_http')
3
+ let getEvents = require('./_events')
4
+ let getCustomLambdas = require('./_custom-lambdas')
5
+ let getScheduled = require('./_scheduled')
6
+ let getWS = require('./_ws')
7
+ let getTablesStreams = require('./_tables-streams')
8
+
9
+ let cl = 'customLambdas'
10
+ let ts = 'tables-streams'
11
+
12
+ module.exports = function getLambda (params) {
13
+ let { type } = params
14
+ if (type === 'http') return getHTTP(params)
15
+ if (type === 'events') return getEvents(params)
16
+ if (type === cl) return getCustomLambdas(params)
17
+ if (type === 'queues') return getEvents(params) // Effectively the same as events
18
+ if (type === 'scheduled') return getScheduled(params)
19
+ if (type === ts) return getTablesStreams(params)
20
+ if (type === 'tables') return getTablesStreams(params) // Shortcut for creating streams
21
+ /* istanbul ignore else: clearer to be explicit here */
22
+ if (type === 'ws') return getWS(params)
23
+ }
@@ -1,16 +1,13 @@
1
- let is = require('../../../lib/is')
2
- let { aliases, runtimes, runtimeList } = require('lambda-runtimes')
1
+ let { is } = require('../../../lib')
2
+ let { aliases, runtimes } = require('lambda-runtimes')
3
3
 
4
4
  // Runtime interpolater
5
- module.exports = function getRuntime (config) {
5
+ module.exports = function getRuntime ({ config, inventory }) {
6
6
  let { runtime } = config
7
7
 
8
- if (runtimeList.includes(runtime) || runtime === 'deno') {
9
- return config
10
- }
11
-
12
8
  if (typeof runtime === 'string') {
13
9
  runtime = runtime.toLowerCase()
10
+ let customRuntime = inventory._project?.customRuntimes?.[runtime]
14
11
 
15
12
  // Runtime is not actually an AWS value, but a shorthand/aliased name
16
13
  if (aliases[runtime]) {
@@ -18,6 +15,10 @@ module.exports = function getRuntime (config) {
18
15
  config.runtime = runtimes[aliased][0]
19
16
  config.runtimeAlias = runtime
20
17
  }
18
+ // Runtime is custom via plugin
19
+ else if (customRuntime) {
20
+ config.runtimeConfig = customRuntime
21
+ }
21
22
  }
22
23
  else if (is.defined(runtime)) {
23
24
  // Someone did something funky like specify a number or bool, so coerce and let it fail validation
@@ -1,113 +1,163 @@
1
+ let { sep } = require('path')
2
+ let { deepFrozenCopy } = require('@architect/utils')
1
3
  let read = require('../../../read')
4
+ let getLambda = require('./get-lambda')
2
5
  let getRuntime = require('./get-runtime')
3
6
  let getHandler = require('./get-handler')
4
7
  let upsert = require('../../_upsert')
5
- let is = require('../../../lib/is')
6
-
7
- // Pragma-specific Lambda constructors
8
- let getHTTP = require('./_http')
9
- let getEvents = require('./_events')
10
- let getPlugins = require('./_plugins')
11
- let getScheduled = require('./_scheduled')
12
- let getWS = require('./_websockets')
13
- let getTablesStreams = require('./_tables-streams')
8
+ let defaultFunctionConfig = require('../../../defaults/function-config')
9
+ let { compiledRuntimes, is } = require('../../../lib')
14
10
 
15
11
  /**
16
- * Build out the Lambda tree
12
+ * Build out the Lambda tree from the Arc manifest or a passed pragma, and plugins
17
13
  */
18
- function populateLambda (type, pragma, inventory, errors) {
19
- if (!pragma || !pragma.length) return null // Jic
20
-
21
- let createDefaultConfig = () => JSON.parse(JSON.stringify(inventory._project.defaultFunctionConfig))
22
- let cwd = inventory._project.src
23
-
24
- // Fill er up
25
- let lambdas = []
26
-
27
- for (let item of pragma) {
28
- // Get name, source dir, and any pragma-specific properties
29
- let results = getLambda({ type, item, cwd, inventory, errors })
30
- // Some lambda populators (e.g. plugins) may return empty results
31
- if (!results) continue
32
- // Some lambda populators (e.g. plugins) may return multiple results
33
- if (!is.array(results)) results = [ results ]
34
-
35
- results.forEach(result => {
36
- let { name, src } = result
37
- // Set up fresh config
38
- let config = createDefaultConfig()
39
-
40
- // Knock out any pragma-specific early
41
- if (type === 'queues') {
42
- config.fifo = config.fifo === undefined ? true : config.fifo
14
+ function populateLambda (type, params) {
15
+ // Passing a pragma array via params allows special overrides
16
+ // See: @tables populating inv['tables-streams']
17
+ let { arc, inventory, errors, pragma } = params
18
+
19
+ let plugins = inventory.plugins?._methods?.set?.[type]
20
+ let pluginLambda = []
21
+ if (plugins) {
22
+ let invCopy = deepFrozenCopy(inventory)
23
+ let pluginResults = plugins.flatMap(fn => {
24
+ try {
25
+ var result = fn({ arc: invCopy._project.arc, inventory: { inv: invCopy } })
43
26
  }
44
- if (type === 'http') {
45
- if (name.startsWith('get ') || name.startsWith('any ')) config.views = true
27
+ catch (err) {
28
+ err.message = `Setter plugin exception: plugin: ${fn.plugin}, method: set.${type}`
29
+ + `\n` + err.message
30
+ throw err
46
31
  }
47
-
48
- // Now let's check in on the function config
49
- let { arc: arcConfig, filepath } = read({ type: 'functionConfig', cwd: src, errors })
50
-
51
- // Set function config file path (if one is present)
52
- let configFile = filepath ? filepath : null
53
-
54
- // Layer any function config over Arc / project defaults
55
- if (arcConfig && arcConfig.aws) {
56
- config = upsert(config, arcConfig.aws)
32
+ if (!result ||
33
+ (!is.object(result) && !is.array(result)) ||
34
+ (is.array(result) && result.some(r => !is.object(r)))) {
35
+ errors.push(`Setter plugins must return a valid response: plugin: ${fn.plugin}, method: set.${type}`)
36
+ return []
37
+ }
38
+ if (is.array(result)) {
39
+ result.forEach(item => {
40
+ item.plugin = fn.plugin
41
+ item.type = fn.type
42
+ })
57
43
  }
58
- if (arcConfig && arcConfig.arc) {
59
- config = upsert(config, arcConfig.arc)
44
+ else {
45
+ result.plugin = fn.plugin
46
+ result.type = fn.type
60
47
  }
48
+ return result
49
+ })
50
+ pluginLambda = populate(type, pluginResults, inventory, errors, true) || []
51
+ }
61
52
 
62
- // Interpolate runtimes
63
- config = getRuntime(config)
53
+ let pragmaLambda = populate(type, pragma || arc[type], inventory, errors) || []
54
+ let aggregate = [ ...pluginLambda, ...pragmaLambda ]
55
+ return aggregate.length ? aggregate : null
56
+ }
64
57
 
65
- // Tidy up any irrelevant params
66
- if (type !== 'http') {
67
- delete config.apigateway
68
- }
58
+ function populate (type, pragma, inventory, errors, plugin) {
59
+ if (!pragma || !pragma.length) return
69
60
 
70
- // Now we know the final source dir + runtime + handler: assemble handler props
71
- let { handlerFile, handlerFunction } = getHandler(config, src, errors)
72
-
73
- let lambda = {
74
- name,
75
- config,
76
- src,
77
- handlerFile,
78
- handlerFunction,
79
- configFile,
80
- ...result, // Any other pragma-specific stuff
81
- }
61
+ let defaultProjectConfig = () => JSON.parse(JSON.stringify(inventory._project.defaultFunctionConfig))
62
+ let { cwd, src: projSrc, build: projBuild } = inventory._project
82
63
 
83
- lambdas.push(lambda)
84
- })
64
+ // Fill er up
65
+ let lambdas = []
66
+
67
+ for (let item of pragma) {
68
+ // Get name, source dir, and any pragma-specific properties
69
+ let result = getLambda({ type, item, cwd, projSrc, projBuild, inventory, errors, plugin })
70
+ // Some Lambda populators (e.g. plugins) may return empty result
71
+ if (!result) continue
72
+
73
+ let { name, src, build } = result
74
+
75
+ // Normalize paths, especially since plugin authors may not use path.join
76
+ src = normalize(src)
77
+ if (build) build = normalize(build)
78
+
79
+ // Set up fresh config, then overlay plugin config
80
+ let config = defaultProjectConfig()
81
+ config = { ...config, ...getKnownProps(configProps, result.config) }
82
+
83
+ // Knock out any pragma-specific early
84
+ if (type === 'queues') {
85
+ config.fifo = config.fifo === undefined ? true : config.fifo
86
+ }
87
+ if (type === 'http') {
88
+ if (name.startsWith('get ') || name.startsWith('any ')) config.views = true
89
+ }
90
+
91
+ // Now let's check in on the function config
92
+ let { arc: arcConfig, filepath } = read({ type: 'functionConfig', cwd: src, errors })
93
+
94
+ // Set function config file path (if one is present)
95
+ let configFile = filepath ? filepath : null
96
+
97
+ // Layer any function config over Arc / project defaults
98
+ if (arcConfig && arcConfig.aws) {
99
+ config = upsert(config, arcConfig.aws)
100
+ }
101
+ if (arcConfig && arcConfig.arc) {
102
+ config = upsert(config, arcConfig.arc)
103
+ }
104
+
105
+ // Interpolate runtimes
106
+ config = getRuntime({ config, inventory })
107
+
108
+ // Disable code sharing on [trans|com]piled functions
109
+ if (compiledRuntimes.includes(config.runtimeConfig?.type)) {
110
+ config.shared = config.views = false
111
+ }
112
+
113
+ // Tidy up any irrelevant properties
114
+ if (!compiledRuntimes.includes(config.runtimeConfig?.type)) {
115
+ // Super important! If we don't clean up the build prop, many explosions will explode
116
+ build = undefined
117
+ }
118
+ if (type !== 'http') {
119
+ delete config.apigateway
120
+ }
121
+
122
+ // Now we know the final source dir + runtime + handler: assemble handler props
123
+ let handlerProps = getHandler({ config, src, build, errors })
124
+
125
+ let lambda = {
126
+ name,
127
+ ...getKnownProps(lambdaProps, result), // Pragma-specific stuff
128
+ config,
129
+ src,
130
+ build,
131
+ ...handlerProps,
132
+ configFile,
133
+ pragma: type !== 'customLambdas' ? type : null,
134
+ }
135
+ // Final tidying of any undefined properties
136
+ Object.keys(lambda).forEach(k => !is.defined(lambda[k]) && delete lambda[k])
137
+
138
+ lambdas.push(lambda)
85
139
  }
86
140
 
87
141
  return lambdas
88
142
  }
89
143
 
90
- let ts = 'tables-streams'
144
+ let normalize = path => path.replace(/[\\\/]/g, sep)
91
145
 
92
- function getLambda (params) {
93
- let { type } = params
94
- params.dir = `src/${type}/`
95
-
96
- if (type === 'http') return getHTTP(params)
97
- if (type === 'events') return getEvents(params)
98
- if (type === 'plugins') return getPlugins(params)
99
- if (type === 'queues') return getEvents(params) // Effectively the same as events
100
- if (type === 'scheduled') return getScheduled(params)
101
- if (type === ts) return getTablesStreams(params)
102
- if (type === 'tables') return getTablesStreams(params) // Shortcut for creating streams
103
- /* istanbul ignore else */ /* Clearer to be explicit here */
104
- if (type === 'ws') return getWS(params)
146
+ // Lambda setter plugins can technically return anything, so this ensures everything is tidy
147
+ let lambdaProps = [ 'cron', 'method', 'path', 'plugin', 'rate', 'route', 'table', 'type' ]
148
+ let configProps = [ ...Object.keys(defaultFunctionConfig()), 'fifo', 'views' ]
149
+ let getKnownProps = (knownProps, raw = {}) => {
150
+ let props = knownProps.flatMap(prop => is.defined(raw[prop]) ? [ [ prop, raw[prop] ] ] : [])
151
+ return Object.fromEntries(props)
105
152
  }
106
153
 
154
+ let cl = 'customLambdas'
155
+ let ts = 'tables-streams'
156
+
107
157
  module.exports = {
108
158
  events: populateLambda.bind({}, 'events'),
109
159
  http: populateLambda.bind({}, 'http'),
110
- plugins: populateLambda.bind({}, 'plugins'),
160
+ [cl]: populateLambda.bind({}, cl),
111
161
  queues: populateLambda.bind({}, 'queues'),
112
162
  scheduled: populateLambda.bind({}, 'scheduled'),
113
163
  tables: populateLambda.bind({}, 'tables'),
@@ -2,9 +2,10 @@ let populate = require('./populate-lambda')
2
2
  let validate = require('./validate')
3
3
 
4
4
  module.exports = function configureQueues ({ arc, inventory, errors }) {
5
- if (!arc.queues || !arc.queues.length) return null
5
+ let queuesPlugins = inventory.plugins?._methods?.set?.queues
6
+ if (!arc?.queues?.length && !queuesPlugins?.length) return null
6
7
 
7
- let queues = populate.queues(arc.queues, inventory, errors)
8
+ let queues = populate.queues({ arc, inventory, errors })
8
9
 
9
10
  validate.queues(queues, '@queues', errors)
10
11
 
@@ -2,9 +2,10 @@ let populate = require('./populate-lambda')
2
2
  let validate = require('./validate')
3
3
 
4
4
  module.exports = function configureScheduled ({ arc, inventory, errors }) {
5
- if (!arc.scheduled || !arc.scheduled.length) return null
5
+ let scheduledPlugins = inventory.plugins?._methods?.set?.scheduled
6
+ if (!arc?.scheduled?.length && !scheduledPlugins?.length) return null
6
7
 
7
- let scheduled = populate.scheduled(arc.scheduled, inventory, errors)
8
+ let scheduled = populate.scheduled({ arc, inventory, errors })
8
9
 
9
10
  validate.scheduled(scheduled, errors)
10
11
 
@@ -1,24 +1,24 @@
1
1
  let { join } = require('path')
2
2
  let validate = require('./validate')
3
- let is = require('../../lib/is')
4
- let { lambdas } = require('../../lib/pragmas')
3
+ let { is, pragmas } = require('../../lib')
4
+ let lambdas = pragmas.lambdas.concat('customLambdas')
5
5
 
6
6
  module.exports = function configureShared ({ arc, pragmas, inventory, errors }) {
7
7
  if (!pragmas.lambdaSrcDirs) return null
8
8
 
9
- let cwd = inventory._project.src
10
- let src = join(cwd, 'src', 'shared')
9
+ let { cwd, src: projSrc } = inventory._project
10
+ let src = join(projSrc, 'shared')
11
11
  let shared = {
12
12
  src,
13
13
  shared: [] // Revert to null later if none are defined
14
14
  }
15
- if (arc.shared && arc.shared.length) {
16
- let foundSrc = false
17
15
 
18
- // First pass to get + check views folder (if any)
16
+ // First pass to get + check shared folder (if any)
17
+ let foundSrc = false
18
+ if (arc?.shared?.length) {
19
19
  for (let share of arc.shared) {
20
20
  if (is.array(share)) {
21
- let key = share[0].toLowerCase()
21
+ let key = share[0]?.toLowerCase()
22
22
  if (key === 'src' && is.string(share[1])) {
23
23
  shared.src = share[1]
24
24
  foundSrc = true
@@ -30,49 +30,49 @@ module.exports = function configureShared ({ arc, pragmas, inventory, errors })
30
30
  }
31
31
  }
32
32
  }
33
+ }
33
34
 
34
- // Proceeding from here resets all views config, so make sure it's only if specific views are specified
35
- let some = !(arc.shared.length === 1 && foundSrc)
36
- if (some) {
37
- // Reset shared settings
38
- for (let pragma of lambdas) {
39
- if (!pragmas[pragma]) continue
40
- for (let { config } of pragmas[pragma]) {
41
- config.shared = false
42
- }
35
+ // Exit if configured shared folder doesn't exist
36
+ if (!is.exists(shared.src)) return null
37
+
38
+ // Proceeding from here resets all shared config, so make sure it's only if specific shared are specified
39
+ let some = arc.shared?.length && !(arc?.shared?.length === 1 && foundSrc)
40
+ if (some) {
41
+ // Reset shared settings
42
+ for (let pragma of lambdas) {
43
+ if (!pragmas[pragma]) continue
44
+ for (let { config } of pragmas[pragma]) {
45
+ config.shared = false
43
46
  }
47
+ }
44
48
 
45
- // Set new shared settings
46
- for (let pragma of arc.shared) {
47
- if (is.array(pragma)) continue // Bail on src setting
48
- if (!is.object(pragma)) {
49
- return errors.push(`@shared invalid setting: ${pragma}`)
50
- }
49
+ // Set new shared settings
50
+ for (let pragma of arc.shared) {
51
+ if (is.array(pragma)) continue // Bail on src setting
52
+ if (!is.object(pragma)) {
53
+ return errors.push(`@shared invalid setting: ${pragma}`)
54
+ }
51
55
 
52
- let p = Object.keys(pragma)[0]
53
- if (!lambdas.includes(p)) {
54
- return errors.push(`${p} is not a valid @shared pragma`)
55
- }
56
+ let p = Object.keys(pragma)[0]
57
+ if (!lambdas.includes(p)) {
58
+ return errors.push(`${p} is not a valid @shared pragma`)
59
+ }
56
60
 
57
- let entries = is.object(pragma[p])
58
- ? Object.entries(pragma[p])
59
- : pragma[p]
60
- for (let lambda of entries) {
61
- let name = p === 'http' ? lambda.join(' ') : lambda
62
- let fn = pragmas[p].find(n => n.name === name)
63
- if (!fn) {
64
- return errors.push(`@shared ${name} not found in @${p} Lambdas`)
65
- }
66
- // Ignore shared into ASAP
67
- if (!fn.arcStaticAssetProxy) fn.config.shared = true
61
+ let entries = is.object(pragma[p])
62
+ ? Object.entries(pragma[p])
63
+ : pragma[p]
64
+ for (let lambda of entries) {
65
+ let name = p === 'http' ? lambda.join(' ') : lambda
66
+ let fn = pragmas[p].find(n => n.name === name)
67
+ if (!fn) {
68
+ return errors.push(`@shared ${name} not found in @${p} Lambdas`)
68
69
  }
70
+ // Ignore shared into ASAP
71
+ if (!fn.arcStaticAssetProxy) fn.config.shared = true
69
72
  }
70
73
  }
71
74
  }
72
75
 
73
- // Exit if default views folder doesn't exist
74
- if (!is.exists(shared.src)) return null
75
-
76
76
  // lambda.config.shared was added by function config defaults, or added above
77
77
  for (let pragma of lambdas) {
78
78
  if (!pragmas[pragma]) continue
@@ -83,8 +83,5 @@ module.exports = function configureShared ({ arc, pragmas, inventory, errors })
83
83
  }
84
84
  }
85
85
 
86
- // De-dupe (in case multiple functions live at the same src path)
87
- shared.shared = [ ...new Set(shared.shared) ]
88
-
89
86
  return shared
90
87
  }
@@ -1,4 +1,4 @@
1
- let methods = require('../../../lib/http-methods')
1
+ let { httpMethods } = require('../../../lib')
2
2
 
3
3
  /**
4
4
  * HTTP route sorter; this is a multifurcating tree, so we'll do a few passes
@@ -32,7 +32,7 @@ module.exports = function sortHTTP (http) {
32
32
 
33
33
  // Multi-pass route sort
34
34
  let sorted = []
35
- methods.forEach(method => {
35
+ httpMethods.forEach(method => {
36
36
  if (!tree[method]) return
37
37
  /* istanbul ignore next: random test shuffles may not trigger all paths */
38
38
  tree[method]
@@ -55,6 +55,7 @@ module.exports = function sortHTTP (http) {
55
55
  if (a.path < b.path) return -1
56
56
  if (a.path > b.path) return 1
57
57
  })
58
+ // Trailing capture sort
58
59
  .sort((a, b) => {
59
60
  if (!a.depth && b.depth === 1 && b.trailingCapture) return -1
60
61
  if (a.depth - b.depth < 0) return
@@ -1,9 +1,10 @@
1
- let asapSrc = require('../../lib/asap-src')
2
- let is = require('../../lib/is')
1
+ let { asapSrc, is } = require('../../lib')
3
2
 
4
3
  module.exports = function configureStatic ({ arc, inventory }) {
4
+ let httpSetters = inventory.plugins?._methods?.set?.http
5
+
5
6
  // @static is inferred by @http
6
- if (!arc.static && !arc.http) return null
7
+ if (!arc.static && !arc.http && !httpSetters) return null
7
8
 
8
9
  let staticPragma = arc.static || []
9
10
  let _static = {
@@ -38,7 +39,7 @@ module.exports = function configureStatic ({ arc, inventory }) {
38
39
  }
39
40
 
40
41
  // Handy shortcut to ASAP for bare @static
41
- if (!arc.http) {
42
+ if (!arc.http && !httpSetters) {
42
43
  inventory._project.rootHandler = 'arcStaticAssetProxy'
43
44
  inventory._project.asapSrc = asapSrc()
44
45
  }
@@ -1,19 +1,15 @@
1
- let is = require('../../lib/is')
1
+ let { is } = require('../../lib')
2
2
  let validate = require('./validate')
3
3
 
4
- function configureTablesIndexes ({ arc, errors }) {
4
+ module.exports = function configureTablesIndexes ({ arc, errors }) {
5
5
  if (!arc['tables-indexes'] || !arc['tables-indexes'].length) return null
6
6
  if (arc['tables-indexes'] && !arc.tables) {
7
7
  errors.push(`Specifying @tables-indexes requires specifying corresponding @tables`)
8
8
  return null
9
9
  }
10
- if (arc['tables-indexes']?.length && arc.indexes?.length) {
11
- errors.push(`Either @tables-indexes or @indexes can be specified, but not both`)
12
- return null
13
- }
14
10
 
15
11
  let indexes = getIndexes(arc, 'tables-indexes', errors)
16
- validate.indexes(indexes, '@tables-indexes', errors)
12
+ validate.tablesIndexes(indexes, '@tables-indexes', errors)
17
13
 
18
14
  return indexes
19
15
  }
@@ -54,6 +50,3 @@ let getIndexes = (arc, pragma, errors) => {
54
50
  error(index)
55
51
  }).filter(Boolean) // Invalid indexes may create undefined entries in the map
56
52
  }
57
-
58
- configureTablesIndexes.getIndexes = getIndexes
59
- module.exports = configureTablesIndexes