@architect/inventory 2.2.1 → 3.0.0-RC.3

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 (69) hide show
  1. package/changelog.md +41 -0
  2. package/package.json +8 -6
  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 +104 -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 +104 -86
  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 +2 -2
  27. package/src/config/pragmas/static.js +1 -2
  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 +3 -3
  33. package/src/config/pragmas/validate/_lib.js +1 -1
  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 +34 -18
  42. package/src/config/project/plugins/env.js +33 -0
  43. package/src/config/project/plugins/index.js +7 -0
  44. package/src/config/project/plugins/runtimes.js +56 -0
  45. package/src/config/project/prefs/dotenv.js +73 -0
  46. package/src/config/project/{prefs.js → prefs/index.js} +32 -14
  47. package/src/config/project/validate/index.js +1 -1
  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 +28 -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/reader.js +1 -1
  60. package/src/validate/config.js +12 -6
  61. package/src/validate/index.js +3 -11
  62. package/src/validate/layers.js +2 -2
  63. package/src/validate/tables-children.js +5 -5
  64. package/src/config/pragmas/indexes.js +0 -19
  65. package/src/config/pragmas/macros.js +0 -5
  66. package/src/config/pragmas/populate-lambda/_plugins.js +0 -25
  67. package/src/config/pragmas/populate-lambda/_websockets.js +0 -19
  68. package/src/config/project/plugins.js +0 -31
  69. package/src/lib/http-methods.js +0 -2
@@ -1,4 +1,4 @@
1
- let is = require('../../../lib/is')
1
+ let { is } = require('../../../lib')
2
2
 
3
3
  let patterns = {
4
4
  looseName: new RegExp(/^[a-z][a-zA-Z0-9-_]+$/),
@@ -1,4 +1,4 @@
1
- let is = require('../../../lib/is')
1
+ let { is } = require('../../../lib')
2
2
  let { regex, size, unique } = require('./_lib')
3
3
 
4
4
  /**
@@ -10,7 +10,7 @@ let { regex, size, unique } = require('./_lib')
10
10
  * See: https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-create-rule-schedule.html
11
11
  */
12
12
  module.exports = function validateScheduled (scheduled, errors) {
13
- if (scheduled.length) {
13
+ if (scheduled?.length) {
14
14
  unique(scheduled, '@scheduled', errors)
15
15
 
16
16
  scheduled.forEach(schedule => {
@@ -1,5 +1,5 @@
1
1
  let { join, resolve, sep } = require('path')
2
- let is = require('../../../lib/is')
2
+ let { is } = require('../../../lib')
3
3
 
4
4
  module.exports = function validateShared (src, cwd, errors) {
5
5
  let path = src && resolve(join(cwd, src))
@@ -7,13 +7,11 @@ let { regex, size, unique } = require('./_lib')
7
7
  * See: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html
8
8
  */
9
9
  module.exports = function validateTablesStreams (tablesStreams, errors) {
10
- if (tablesStreams.length) {
11
- unique(tablesStreams, '@tables-streams', errors)
10
+ unique(tablesStreams, '@tables-streams', errors)
12
11
 
13
- tablesStreams.forEach(stream => {
14
- let { name } = stream
15
- size(name, 3, 255, '@tables-streams', errors)
16
- regex(name, 'veryLooseName', '@tables-streams', errors)
17
- })
18
- }
12
+ tablesStreams.forEach(stream => {
13
+ let { name } = stream
14
+ size(name, 3, 255, '@tables-streams', errors)
15
+ regex(name, 'veryLooseName', '@tables-streams', errors)
16
+ })
19
17
  }
@@ -2,13 +2,13 @@ let { regex, size, unique } = require('./_lib')
2
2
  let { deepStrictEqual } = require('assert')
3
3
 
4
4
  /**
5
- * Validate @tables + @indexes
5
+ * Validate @tables + @tables-indexes
6
6
  *
7
7
  * Where possible, attempts to follow DynamoDB validation
8
8
  * See: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html
9
9
  */
10
10
  module.exports = function validateTablesAndIndexes (pragma, pragmaName, errors) {
11
- if (pragma.length) {
11
+ if (pragma?.length) {
12
12
  pragma.forEach(table => {
13
13
  let { name, indexName, partitionKey, sortKey } = table
14
14
 
@@ -4,12 +4,12 @@ module.exports = {
4
4
  aws: require('./_aws'),
5
5
  events: require('./_events'),
6
6
  http: require('./_http'),
7
- indexes: require('./_tables'), // Same ruleset as @tables (more or less)
8
7
  proxy: require('./_proxy'),
9
- tables: require('./_tables'),
10
8
  queues: require('./_events'), // Same ruleset as @events
11
9
  scheduled: require('./_scheduled'),
12
10
  shared: require('./_shared'), // Also includes @views
11
+ tables: require('./_tables'),
12
+ tablesIndexes: require('./_tables'), // Same ruleset as @tables (more or less)
13
13
  tablesStreams: require('./_tables-streams'),
14
14
  websockets: require('./_websockets'),
15
15
 
@@ -1,6 +1,6 @@
1
1
  let { join } = require('path')
2
2
  let validate = require('./validate')
3
- let is = require('../../lib/is')
3
+ let { is } = require('../../lib')
4
4
 
5
5
  module.exports = function configureViews ({ arc, pragmas, inventory, errors }) {
6
6
  if (arc.views && !arc.http) {
@@ -9,46 +9,28 @@ module.exports = function configureViews ({ arc, pragmas, inventory, errors }) {
9
9
  }
10
10
  if (!arc.http) return null
11
11
 
12
- let cwd = inventory._project.src
13
- let src = join(cwd, 'src', 'views')
12
+ let { cwd, src: projSrc } = inventory._project
13
+ let src = join(projSrc, 'views')
14
14
  let views = {
15
15
  src,
16
16
  views: [] // Revert to null later if none are defined
17
17
  }
18
18
 
19
- if (arc.views && arc.views.length) {
20
- let foundSrc = false
21
-
22
- // First pass to get + check views folder (if any)
19
+ // First pass to get + check views folder (if any)
20
+ let foundSrc = false
21
+ if (arc?.views?.length) {
23
22
  for (let view of arc.views) {
24
- let key = view[0].toLowerCase()
25
- if (key === 'src' && is.string(view[1])) {
26
- views.src = view[1]
27
- foundSrc = true
28
- validate.shared(views.src, cwd, errors)
29
- }
30
- }
31
-
32
- // Proceeding from here resets all views config, so make sure it's only if specific views are specified
33
- let some = !(arc.views.length === 1 && foundSrc)
34
- if (some) {
35
- // Reset views settings
36
- for (let route of pragmas.http) {
37
- route.config.views = false
38
- }
39
-
40
- // Set new views settings
41
- for (let view of arc.views) {
42
- let method = view[0].toLowerCase()
43
- let path = view[1]
44
- if (method === 'src') continue
45
- let name = `${method} ${path}`
46
- let route = pragmas.http.find(n => n.name === name)
47
- if (!route) {
48
- return errors.push(`@views ${name} not found in @http routes`)
23
+ if (is.array(view)) {
24
+ let key = view[0]?.toLowerCase()
25
+ if (key === 'src' && is.string(view[1])) {
26
+ views.src = view[1]
27
+ foundSrc = true
28
+ validate.shared(views.src, cwd, errors)
29
+ continue
30
+ }
31
+ if (key === 'src' && !is.string(view[1])) {
32
+ errors.push(`@shared invalid setting: ${key}`)
49
33
  }
50
- // Ignore views into ASAP
51
- if (!route.arcStaticAssetProxy) route.config.views = true
52
34
  }
53
35
  }
54
36
  }
@@ -56,6 +38,29 @@ module.exports = function configureViews ({ arc, pragmas, inventory, errors }) {
56
38
  // Exit if default views folder doesn't exist
57
39
  if (!is.exists(views.src)) return null
58
40
 
41
+ // Proceeding from here resets all views config, so make sure it's only if specific views are specified
42
+ let some = arc.views?.length && !(arc?.views?.length === 1 && foundSrc)
43
+ if (some) {
44
+ // Reset views settings
45
+ for (let route of pragmas.http) {
46
+ route.config.views = false
47
+ }
48
+
49
+ // Set new views settings
50
+ for (let view of arc.views) {
51
+ let method = view[0].toLowerCase()
52
+ let path = view[1]
53
+ if (method === 'src') continue
54
+ let name = `${method} ${path}`
55
+ let route = pragmas.http.find(n => n.name === name)
56
+ if (!route) {
57
+ return errors.push(`@views ${name} not found in @http routes`)
58
+ }
59
+ // Ignore views into ASAP
60
+ if (!route.arcStaticAssetProxy) route.config.views = true
61
+ }
62
+ }
63
+
59
64
  // lambda.config.views was added by Lambda populator defaults, or added above
60
65
  for (let { src, config } of pragmas.http) {
61
66
  if (config.views === true && !views.views.includes(src)) {
@@ -63,8 +68,5 @@ module.exports = function configureViews ({ arc, pragmas, inventory, errors }) {
63
68
  }
64
69
  }
65
70
 
66
- // De-dupe (in case multiple functions live at the same src path)
67
- views.views = [ ...new Set(views.views) ]
68
-
69
71
  return views
70
72
  }
@@ -2,21 +2,23 @@ let populate = require('./populate-lambda')
2
2
  let validate = require('./validate')
3
3
 
4
4
  module.exports = function configureWS ({ arc, inventory, errors }) {
5
- if (!arc.ws) return null
5
+ let wsPlugins = inventory.plugins?._methods?.set?.ws
6
+ if (!arc.ws && !wsPlugins?.length) return null
6
7
 
7
- let ws = [ ...arc.ws ]
8
+ let ws = [ ]
9
+ if (arc.ws) ws.push(...arc.ws)
8
10
 
9
11
  // Backfill required routes if not already present
10
12
  let defaults = [ 'disconnect', 'default', 'connect' ]
11
13
  defaults.forEach(route => {
12
- let found = arc.ws.find(item => {
14
+ let found = arc?.ws?.find(item => {
13
15
  if (item === route) return true
14
16
  if (item[route]) return true
15
17
  })
16
18
  if (!found) ws.unshift(route)
17
19
  })
18
20
 
19
- let websockets = populate.ws(ws, inventory, errors)
21
+ let websockets = populate.ws({ arc, inventory, errors, pragma: ws })
20
22
 
21
23
  // Forgive and normalize userland use of '$default', '$connect', '$disconnect'
22
24
  websockets.forEach(({ name }, i) => {
@@ -1,60 +1,76 @@
1
+ let { join } = require('path')
1
2
  let upsert = require('../_upsert')
2
3
  let prefs = require('./prefs')
3
- let is = require('../../lib/is')
4
4
  let plugins = require('./plugins')
5
+ let { is, mergeEnvVars } = require('../../lib')
5
6
 
6
7
  /**
7
8
  * Get the project-level configuration, overlaying arc.aws settings (if present)
8
9
  */
9
- module.exports = function getProjectConfig (params, errors) {
10
- let { arc, raw, filepath, inventory } = params
11
- let project = {
10
+ module.exports = function getProjectConfig (params) {
11
+ let { arc, errors, raw, filepath, inventory } = params
12
+ let _project = {
12
13
  ...inventory._project,
13
14
  arc,
14
15
  raw,
15
16
  }
16
17
 
17
18
  if (arc.aws) {
18
- project.defaultFunctionConfig = upsert(project.defaultFunctionConfig, arc.aws)
19
+ _project.defaultFunctionConfig = upsert(_project.defaultFunctionConfig, arc.aws)
19
20
  }
20
21
 
21
22
  if (filepath) {
22
- project.manifest = filepath
23
- // TODO add manifestCreated once we determine we can get birthtime reliably
23
+ _project.manifest = filepath
24
24
  }
25
25
 
26
- // require project plugin modules
27
- project.plugins = plugins(project, errors)
28
-
29
- // parse local and global arc preferences
26
+ // Parse local and global project preferences
30
27
  let scopes = [ 'global', 'local' ]
31
28
  for (let scope of scopes) {
32
29
  let p = prefs({ scope, inventory, errors })
33
30
  if (p) {
34
31
  // Set up the scoped metadata
35
- project[`${scope}Preferences`] = p.preferences
36
- project[`${scope}PreferencesFile`] = p.preferencesFile
32
+ _project[`${scope}Preferences`] = p.preferences
33
+ _project[`${scope}PreferencesFile`] = p.preferencesFile
37
34
 
38
35
  // Build out the final preferences
39
36
  /* istanbul ignore else: jic */
40
- if (!project.preferences) project.preferences = {}
37
+ if (!_project.preferences) _project.preferences = {}
41
38
  Object.keys(p.preferences).forEach(pragma => {
42
39
  // Ignore the raw data
43
40
  if (pragma === '_arc' || pragma === '_raw') return
44
41
  // Allow booleans, etc.
45
42
  if (!is.object(p.preferences[pragma])) {
46
- project.preferences[pragma] = p.preferences[pragma]
43
+ _project.preferences[pragma] = p.preferences[pragma]
47
44
  return
48
45
  }
49
46
  // Traverse and merge individual settings
50
47
  /* istanbul ignore else: jic */
51
- if (!project.preferences[pragma]) project.preferences[pragma] = {}
48
+ if (!_project.preferences[pragma]) _project.preferences[pragma] = {}
52
49
  Object.entries(p.preferences[pragma]).forEach(([ setting, value ]) => {
53
- project.preferences[pragma][setting] = value
50
+ _project.preferences[pragma][setting] = value
54
51
  })
55
52
  })
56
53
  }
57
54
  }
58
55
 
59
- return project
56
+ // Populate local env from preferences
57
+ if (_project.preferences?.env) {
58
+ _project.env.local = _project.preferences.env
59
+ }
60
+
61
+ if (inventory.plugins?._methods) {
62
+ _project.env.plugins = plugins.env(params, _project)
63
+ _project.env.local = mergeEnvVars({
64
+ name: 'Local',
65
+ source: _project.env.plugins,
66
+ target: _project.env.local,
67
+ errors,
68
+ })
69
+
70
+ let { build, runtimes } = plugins.runtimes(params, _project)
71
+ if (build) _project.build = join(_project.cwd, build)
72
+ if (runtimes) _project.customRuntimes = runtimes
73
+ }
74
+
75
+ return _project
60
76
  }
@@ -0,0 +1,33 @@
1
+ let { is } = require('../../../lib')
2
+
3
+ module.exports = function setEnvPlugins (params, project) {
4
+ let { errors, inventory } = params
5
+ let envPlugins = inventory.plugins?._methods?.set?.env
6
+ if (envPlugins?.length) {
7
+ let env = {}
8
+
9
+ // inventory._project is not yet built, so provide as much as we can to plugins for now
10
+ let inv = { ...inventory, _project: project }
11
+ envPlugins.forEach(fn => {
12
+ let errType = `plugin: ${fn.plugin}, method: set.env`
13
+ try {
14
+ let result = fn({ inventory: inv })
15
+ if (!is.object(result) || !Object.keys(result).length) {
16
+ return errors.push(`Env plugin returned invalid data, must return an Object with one or more keys + values: ${errType}`)
17
+ }
18
+ Object.entries(result).forEach(([ k, v ]) => {
19
+ if (env[k]) {
20
+ return errors.push(`Env var '${k}' already registered: ${errType}`)
21
+ }
22
+ if (is.object(v) || is.array(v)) env[k] = JSON.stringify(v)
23
+ else env[k] = String(v)
24
+ })
25
+ }
26
+ catch (err) {
27
+ errors.push(`Runtime plugin '${fn.plugin}' failed: ${err.message}`)
28
+ }
29
+ })
30
+ return { testing: env, staging: env, production: env }
31
+ }
32
+ return inventory._project.env.plugins
33
+ }
@@ -0,0 +1,7 @@
1
+ let env = require('./env')
2
+ let runtimes = require('./runtimes')
3
+
4
+ module.exports = {
5
+ env,
6
+ runtimes,
7
+ }
@@ -0,0 +1,56 @@
1
+ let { is } = require('../../../lib')
2
+ let { aliases, runtimeList } = require('lambda-runtimes')
3
+ let allRuntimes = runtimeList.concat([ 'deno', ...Object.keys(aliases) ])
4
+
5
+ module.exports = function setRuntimePlugins (params, project) {
6
+ let { errors, inventory } = params
7
+ let runtimePlugins = inventory.plugins?._methods?.set?.runtimes
8
+ if (runtimePlugins?.length) {
9
+ let runtimes = {
10
+ runtimes: [],
11
+ }
12
+ // inventory._project is not yet built, so provide as much as we can to plugins for now
13
+ let inv = { ...inventory, _project: project }
14
+ let build
15
+ runtimePlugins.forEach(fn => {
16
+ let errType = `plugin: ${fn.plugin}, method: set.runtimes`
17
+ try {
18
+ let result = fn({ inventory: inv })
19
+ result = is.array(result) ? result : [ result ]
20
+ result.forEach(runtime => {
21
+ // TODO add more validation
22
+ let { name } = runtime
23
+ if (!name) {
24
+ let msg = `Runtime plugin must provide a name: ${errType}`
25
+ return errors.push(msg)
26
+ }
27
+ if (allRuntimes.includes(name)) {
28
+ let msg = `Runtime name '${name}' is reserved: ${errType}`
29
+ return errors.push(msg)
30
+ }
31
+ if (runtimes[name]) {
32
+ let msg = `Runtime '${name}' already registered: ${errType}`
33
+ return errors.push(msg)
34
+ }
35
+ if (runtime.build) {
36
+ if (build && build !== runtime.build) {
37
+ errors.push(`Runtime '${name}' cannot set a build directory, as it is already configured to: ${build}`)
38
+ }
39
+ else if (is.bool(runtime.build) ||
40
+ !is.string(runtime.build)) {
41
+ build = 'build'
42
+ }
43
+ else build = runtime.build
44
+ }
45
+ runtimes.runtimes.push(name)
46
+ runtimes[name] = runtime
47
+ })
48
+ }
49
+ catch (err) {
50
+ errors.push(`Runtime plugin '${fn.plugin}' failed: ${err.message}`)
51
+ }
52
+ })
53
+ return { build, runtimes }
54
+ }
55
+ return {}
56
+ }
@@ -0,0 +1,73 @@
1
+ // Copyright (c) 2015, Scott Motte
2
+ // All rights reserved.
3
+
4
+ /* istanbul ignore file */
5
+ /* eslint-disable */
6
+ // node_modules/dotenv/lib/main.js
7
+ var fs = require("fs");
8
+ var path = require("path");
9
+ var os = require("os");
10
+ function log(message) {
11
+ console.log(`[dotenv][DEBUG] ${message}`);
12
+ }
13
+ var NEWLINE = "\n";
14
+ var RE_INI_KEY_VAL = /^\s*([\w.-]+)\s*=\s*(.*)?\s*$/;
15
+ var RE_NEWLINES = /\\n/g;
16
+ var NEWLINES_MATCH = /\r\n|\n|\r/;
17
+ function parse(src, options) {
18
+ const debug = Boolean(options && options.debug);
19
+ const obj = {};
20
+ src.toString().split(NEWLINES_MATCH).forEach(function(line, idx) {
21
+ const keyValueArr = line.match(RE_INI_KEY_VAL);
22
+ if (keyValueArr != null) {
23
+ const key = keyValueArr[1];
24
+ let val = keyValueArr[2] || "";
25
+ const end = val.length - 1;
26
+ const isDoubleQuoted = val[0] === '"' && val[end] === '"';
27
+ const isSingleQuoted = val[0] === "'" && val[end] === "'";
28
+ if (isSingleQuoted || isDoubleQuoted) {
29
+ val = val.substring(1, end);
30
+ if (isDoubleQuoted) {
31
+ val = val.replace(RE_NEWLINES, NEWLINE);
32
+ }
33
+ } else {
34
+ val = val.trim();
35
+ }
36
+ obj[key] = val;
37
+ } else if (debug) {
38
+ log(`did not match key and value when parsing line ${idx + 1}: ${line}`);
39
+ }
40
+ });
41
+ return obj;
42
+ }
43
+ function resolveHome(envPath) {
44
+ return envPath[0] === "~" ? path.join(os.homedir(), envPath.slice(1)) : envPath;
45
+ }
46
+ function config(options) {
47
+ let dotenvPath = path.resolve(process.cwd(), ".env");
48
+ let encoding = "utf8";
49
+ const debug = Boolean(options && options.debug);
50
+ if (options) {
51
+ if (options.path != null) {
52
+ dotenvPath = resolveHome(options.path);
53
+ }
54
+ if (options.encoding != null) {
55
+ encoding = options.encoding;
56
+ }
57
+ }
58
+ try {
59
+ const parsed = parse(fs.readFileSync(dotenvPath, { encoding }), { debug });
60
+ Object.keys(parsed).forEach(function(key) {
61
+ if (!Object.prototype.hasOwnProperty.call(process.env, key)) {
62
+ process.env[key] = parsed[key];
63
+ } else if (debug) {
64
+ log(`"${key}" is already defined in \`process.env\` and will not be overwritten`);
65
+ }
66
+ });
67
+ return { parsed };
68
+ } catch (e) {
69
+ return { error: e };
70
+ }
71
+ }
72
+ module.exports.config = config;
73
+ module.exports.parse = parse;
@@ -1,17 +1,26 @@
1
- let read = require('../../read')
2
- let validate = require('./validate')
3
- let is = require('../../lib/is')
1
+ let { join } = require('path')
2
+ let { existsSync, readFileSync } = require('fs')
3
+ let read = require('../../../read')
4
+ let validate = require('../validate')
5
+ let { is } = require('../../../lib')
6
+ let { parse } = require('./dotenv')
4
7
  let { homedir } = require('os')
5
8
 
6
9
  module.exports = function getPrefs ({ scope, inventory, errors }) {
7
10
  let cwd = scope === 'global'
8
11
  ? homedir()
9
- : inventory._project.src
12
+ : inventory._project.cwd
10
13
 
11
- // Populate preferences
14
+ let envFilepath = join(cwd, '.env')
15
+ let hasEnvFile = scope === 'local' && existsSync(envFilepath)
12
16
  let prefs = read({ type: 'preferences', cwd, errors })
17
+
18
+ if (!prefs.filepath && !hasEnvFile) return null
19
+
20
+ let preferences = {}
21
+
22
+ // Populate Architect preferences
13
23
  if (prefs.filepath) {
14
- let preferences = {}
15
24
  // Ok, this gets a bit hairy
16
25
  // Arc outputs an object of nested arrays
17
26
  // Basically, construct a pared-down intermediate prefs obj for consumers
@@ -45,6 +54,7 @@ module.exports = function getPrefs ({ scope, inventory, errors }) {
45
54
  if (is.array(val)) preferences.env[e][key] = val.join(' ')
46
55
  })
47
56
  }
57
+ else preferences.env[e] = null
48
58
  })
49
59
  }
50
60
  // Turn Sandbox scripts into commands
@@ -58,16 +68,24 @@ module.exports = function getPrefs ({ scope, inventory, errors }) {
58
68
  })
59
69
 
60
70
  validate(preferences, errors)
71
+ }
61
72
 
62
- return {
63
- preferences: {
64
- ...preferences,
65
- _arc: prefs.arc,
66
- _raw: prefs.raw,
67
- },
68
- preferencesFile: prefs.filepath
73
+ // Populate .env (testing environment only, disables other env vars)
74
+ if (hasEnvFile) {
75
+ let dotenv = parse(readFileSync(envFilepath))
76
+ preferences.env = {
77
+ testing: Object.keys(dotenv).length ? dotenv : null,
78
+ staging: null,
79
+ production: null,
69
80
  }
70
81
  }
71
82
 
72
- return null
83
+ return {
84
+ preferences: {
85
+ ...preferences,
86
+ _arc: prefs.arc,
87
+ _raw: prefs.raw,
88
+ },
89
+ preferencesFile: prefs.filepath
90
+ }
73
91
  }
@@ -1,4 +1,4 @@
1
- let is = require('./../../../lib/is')
1
+ let { is } = require('./../../../lib')
2
2
 
3
3
  module.exports = function validatePreferences (preferences, errors) {
4
4
  // Env checks
@@ -1,38 +1,45 @@
1
+ let { join } = require('path')
1
2
  let fnConfig = require('./function-config')
2
- let pragmas = require('../lib/pragmas')
3
+ let { pragmas } = require('../lib')
3
4
 
4
5
  /**
5
6
  * Returns a default stub inventory object
6
7
  * - Every possible officially supported value should be present
7
8
  */
8
9
  module.exports = function inventoryDefaults (params = {}) {
9
- let { cwd, region } = params
10
+ let { cwd = process.cwd(), deployStage = null, region } = params
10
11
  // Allow region env var override
11
- region = process.env.AWS_REGION || region || 'us-west-2'
12
+ region = region || process.env.AWS_REGION || 'us-west-2'
12
13
  let defaultFunctionConfig = fnConfig()
13
14
  return {
14
15
  // Meta
15
16
  _arc: {
16
17
  version: 'Unknown', // @architect/architect semver (if installed)
17
18
  defaultFunctionConfig, // Architect's default function config
18
- pragmas, // Registry of all + Lambda pragmas
19
+ pragmas, // Registry of all, Lambda, reserved, retired pragmas
20
+ deployStage, // Deploy stage of the running project (if specified)
19
21
  },
20
22
  _project: {
21
23
  type: 'aws',
22
- src: cwd,
24
+ cwd, // Project root dir
25
+ src: join(cwd, 'src'), // Default source tree dir
26
+ build: null, // Optional build artifact dir
23
27
  manifest: null, // Root project manifest filename
24
- // manifestCreated // TODO
25
- preferences: null, // Realized preferences obj, resolved from global > local
28
+ preferences: null, // Realized preferences obj, resolved from local > global
26
29
  localPreferences: null, // Local preferences obj
27
30
  localPreferencesFile: null, // Local preferences file path
28
31
  globalPreferences: null, // Global preferences obj
29
32
  globalPreferencesFile: null, // Global preferences file path
30
33
  defaultFunctionConfig, // Project-level function config
31
34
  rootHandler: null, // null | configured | arcStaticAssetProxy | proxy
32
- plugins: null, // `require`d plugin modules as a map of plugin name to module
35
+ env: { // Env vars pulled from:
36
+ local: null, // Local/global prefs or .env
37
+ plugins: null, // Plugins
38
+ aws: null, // SSM
39
+ },
40
+ customRuntimes: null, // Runtime plugins
33
41
  arc: [], // Raw arc obj
34
42
  raw: '', // Raw arc string
35
- env: null, // Env vars pulled from SSM (if enabled)
36
43
  },
37
44
  // App + vendor config
38
45
  app: '',
@@ -52,9 +59,7 @@ module.exports = function inventoryDefaults (params = {}) {
52
59
  cdn: null,
53
60
  events: null,
54
61
  http: null,
55
- indexes: null,
56
- macros: null,
57
- plugins: null, // These are the Lambdas created by plugins, not the plugin modules, which are in _project.plugins
62
+ plugins: null,
58
63
  proxy: null,
59
64
  queues: null,
60
65
  scheduled: null,
@@ -65,7 +70,9 @@ module.exports = function inventoryDefaults (params = {}) {
65
70
  'tables-streams': null,
66
71
  views: null,
67
72
  ws: null,
68
- // Collection of all Lambda paths
73
+ // Unclassified / non-pragma custom Lambdas created by plugins
74
+ customLambdas: null,
75
+ // Collection of all Lambda source paths
69
76
  lambdaSrcDirs: null,
70
77
  // Lambda lookup by source directory
71
78
  lambdasBySrcDir: null,