webpacker 3.0.2 → 3.1.0

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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintignore +1 -0
  3. data/.travis.yml +10 -0
  4. data/CHANGELOG.md +110 -0
  5. data/Gemfile.lock +69 -67
  6. data/MIT-LICENSE +1 -1
  7. data/README.md +86 -30
  8. data/docs/assets.md +4 -4
  9. data/docs/cloud9.md +310 -0
  10. data/docs/css.md +32 -3
  11. data/docs/deployment.md +42 -4
  12. data/docs/docker.md +49 -0
  13. data/docs/env.md +5 -5
  14. data/docs/folder-structure.md +2 -2
  15. data/docs/testing.md +14 -34
  16. data/docs/troubleshooting.md +40 -4
  17. data/docs/typescript.md +2 -2
  18. data/docs/webpack-dev-server.md +21 -4
  19. data/docs/webpack.md +103 -25
  20. data/gemfiles/Gemfile-rails-edge +13 -0
  21. data/gemfiles/Gemfile-rails.4.2.x +10 -0
  22. data/gemfiles/Gemfile-rails.5.0.x +10 -0
  23. data/gemfiles/Gemfile-rails.5.1.x +10 -0
  24. data/lib/install/angular.rb +5 -5
  25. data/lib/install/config/webpacker.yml +7 -0
  26. data/lib/install/elm.rb +7 -7
  27. data/lib/install/examples/vue/hello_vue.js +30 -4
  28. data/lib/install/react.rb +5 -5
  29. data/lib/install/template.rb +19 -9
  30. data/lib/install/vue.rb +4 -4
  31. data/lib/tasks/installers.rake +2 -2
  32. data/lib/tasks/webpacker.rake +7 -6
  33. data/lib/tasks/webpacker/check_binstubs.rake +3 -3
  34. data/lib/tasks/webpacker/compile.rake +15 -8
  35. data/lib/tasks/webpacker/install.rake +4 -4
  36. data/lib/tasks/webpacker/verify_install.rake +1 -1
  37. data/lib/webpacker/compiler.rb +6 -6
  38. data/lib/webpacker/dev_server.rb +2 -2
  39. data/lib/webpacker/dev_server_proxy.rb +2 -1
  40. data/lib/webpacker/dev_server_runner.rb +4 -4
  41. data/lib/webpacker/helper.rb +3 -3
  42. data/lib/webpacker/manifest.rb +2 -2
  43. data/lib/webpacker/railtie.rb +41 -2
  44. data/lib/webpacker/runner.rb +1 -1
  45. data/lib/webpacker/version.rb +1 -1
  46. data/package.json +29 -21
  47. data/package/asset_host.js +4 -5
  48. data/package/config.js +7 -1
  49. data/package/config_types/__tests__/config_list.js +123 -0
  50. data/package/config_types/__tests__/config_object.js +43 -0
  51. data/package/config_types/config_list.js +83 -0
  52. data/package/config_types/config_object.js +55 -0
  53. data/package/config_types/index.js +7 -0
  54. data/package/environment.js +64 -40
  55. data/package/environments/development.js +31 -34
  56. data/package/environments/production.js +14 -11
  57. data/package/index.js +7 -2
  58. data/package/{loaders → rules}/babel.js +6 -4
  59. data/package/{loaders → rules}/coffee.js +3 -1
  60. data/package/rules/css.js +39 -0
  61. data/package/rules/elm.js +23 -0
  62. data/package/rules/erb.js +11 -0
  63. data/package/{loaders → rules}/file.js +1 -1
  64. data/package/rules/index.js +23 -0
  65. data/package/rules/sass.js +15 -0
  66. data/package/{loaders → rules}/typescript.js +3 -1
  67. data/package/rules/url.js +13 -0
  68. data/package/rules/vue.js +13 -0
  69. data/package/utils/__tests__/deep_assign.js +11 -0
  70. data/package/utils/__tests__/deep_merge.js +10 -0
  71. data/package/utils/__tests__/objectify.js +9 -0
  72. data/package/utils/deep_assign.js +22 -0
  73. data/package/utils/deep_merge.js +23 -0
  74. data/package/utils/helpers.js +32 -0
  75. data/package/utils/objectify.js +4 -0
  76. data/test/command_test.rb +1 -1
  77. data/test/compiler_test.rb +5 -1
  78. data/test/configuration_test.rb +1 -1
  79. data/test/dev_server_test.rb +1 -1
  80. data/test/helper_test.rb +15 -10
  81. data/test/manifest_test.rb +1 -1
  82. data/test/rake_tasks_test.rb +29 -0
  83. data/test/test_app/Rakefile +3 -0
  84. data/test/test_app/config/application.rb +11 -0
  85. data/test/test_app/config/environment.rb +4 -0
  86. data/test/{webpacker_test_helper.rb → test_helper.rb} +3 -14
  87. data/webpacker.gemspec +1 -1
  88. data/yarn.lock +1552 -829
  89. metadata +43 -16
  90. data/package/loaders/elm.js +0 -19
  91. data/package/loaders/erb.js +0 -9
  92. data/package/loaders/style.js +0 -31
  93. data/package/loaders/vue.js +0 -12
  94. data/test/test_app/config/secrets.yml +0 -5
@@ -9,8 +9,9 @@ class Webpacker::DevServerProxy < Rack::Proxy
9
9
  end
10
10
 
11
11
  def perform_request(env)
12
- if env["PATH_INFO"] =~ /#{public_output_uri_path}/ && Webpacker.dev_server.running?
12
+ if env["PATH_INFO"].start_with?("/#{public_output_uri_path}") && Webpacker.dev_server.running?
13
13
  env["HTTP_HOST"] = env["HTTP_X_FORWARDED_HOST"] = env["HTTP_X_FORWARDED_SERVER"] = Webpacker.dev_server.host_with_port
14
+ env["SCRIPT_NAME"] = ""
14
15
 
15
16
  super(env)
16
17
  else
@@ -18,10 +18,11 @@ module Webpacker
18
18
 
19
19
  @hostname = dev_server["host"]
20
20
  @port = dev_server["port"]
21
+ @pretty = dev_server.fetch("pretty", true)
21
22
 
22
23
  rescue Errno::ENOENT, NoMethodError
23
- $stdout.puts "Webpack dev_server configuration not found in #{@config_file}."
24
- $stdout.puts "Please run bundle exec rails webpacker:install to install webpacker"
24
+ $stdout.puts "webpack dev_server configuration not found in #{@config_file}."
25
+ $stdout.puts "Please run bundle exec rails webpacker:install to install Webpacker"
25
26
  exit!
26
27
  end
27
28
 
@@ -38,10 +39,9 @@ module Webpacker
38
39
  env = { "NODE_PATH" => @node_modules_path.shellescape }
39
40
  cmd = [
40
41
  "#{@node_modules_path}/.bin/webpack-dev-server",
41
- "--progress",
42
- "--color",
43
42
  "--config", @webpack_config
44
43
  ]
44
+ cmd += ["--progress", "--color"] if @pretty
45
45
 
46
46
  Dir.chdir(@app_path) do
47
47
  exec env, *cmd
@@ -1,5 +1,5 @@
1
1
  module Webpacker::Helper
2
- # Computes the full path for a given webpacker asset.
2
+ # Computes the full path for a given Webpacker asset.
3
3
  # Return relative path using manifest.json and passes it to asset_url helper
4
4
  # This will use asset_path internally, so most of their behaviors will be the same.
5
5
  #
@@ -9,7 +9,7 @@ module Webpacker::Helper
9
9
  def asset_pack_path(name, **options)
10
10
  asset_path(Webpacker.manifest.lookup!(name), **options)
11
11
  end
12
- # Creates a script tag that references the named pack file, as compiled by Webpack per the entries list
12
+ # Creates a script tag that references the named pack file, as compiled by webpack per the entries list
13
13
  # in config/webpack/shared.js. By default, this list is auto-generated to match everything in
14
14
  # app/javascript/packs/*.js. In production mode, the digested reference is automatically looked up.
15
15
  #
@@ -21,7 +21,7 @@ module Webpacker::Helper
21
21
  javascript_include_tag(*sources_from_pack_manifest(names, type: :javascript), **options)
22
22
  end
23
23
 
24
- # Creates a link tag that references the named pack file, as compiled by Webpack per the entries list
24
+ # Creates a link tag that references the named pack file, as compiled by webpack per the entries list
25
25
  # in config/webpack/shared.js. By default, this list is auto-generated to match everything in
26
26
  # app/javascript/packs/*.js. In production mode, the digested reference is automatically looked up.
27
27
  #
@@ -49,9 +49,9 @@ class Webpacker::Manifest
49
49
  Webpacker can't find #{bundle_name} in #{config.public_manifest_path}. Possible causes:
50
50
  1. You want to set webpacker.yml value of compile to true for your environment
51
51
  unless you are using the `webpack -w` or the webpack-dev-server.
52
- 2. Webpack has not yet re-run to reflect updates.
52
+ 2. webpack has not yet re-run to reflect updates.
53
53
  3. You have misconfigured Webpacker's config/webpacker.yml file.
54
- 4. Your Webpack configuration is not creating a manifest.
54
+ 4. Your webpack configuration is not creating a manifest.
55
55
  Your manifest contains:
56
56
  #{JSON.pretty_generate(@data)}
57
57
  MSG
@@ -4,6 +4,45 @@ require "webpacker/helper"
4
4
  require "webpacker/dev_server_proxy"
5
5
 
6
6
  class Webpacker::Engine < ::Rails::Engine
7
+ # Allows Webpacker config values to be set via Rails env config files
8
+ config.webpacker = ActiveSupport::OrderedOptions.new
9
+ config.webpacker.check_yarn_integrity = false
10
+
11
+ # ================================
12
+ # Check Yarn Integrity Initializer
13
+ # ================================
14
+ #
15
+ # development (on by default):
16
+ #
17
+ # to turn off:
18
+ # - edit config/environments/development.rb
19
+ # - add `config.webpacker.check_yarn_integrity = false`
20
+ #
21
+ # production (off by default):
22
+ #
23
+ # to turn on:
24
+ # - edit config/environments/production.rb
25
+ # - add `config.webpacker.check_yarn_integrity = false`
26
+ initializer "webpacker.yarn_check" do |app|
27
+ if File.exist?("yarn.lock") && app.config.webpacker.check_yarn_integrity
28
+ ok = system("yarn check --integrity")
29
+
30
+ if !ok
31
+ warn "\n\n"
32
+ warn "========================================"
33
+ warn " Your Yarn packages are out of date!"
34
+ warn " Please run `yarn install` to update."
35
+ warn "========================================"
36
+ warn "\n\n"
37
+ warn "To disable this check, please add `config.webpacker.check_yarn_integrity = false`"
38
+ warn "to your Rails development config file (config/environments/development.rb)."
39
+ warn "\n\n"
40
+
41
+ exit(1)
42
+ end
43
+ end
44
+ end
45
+
7
46
  initializer "webpacker.proxy" do |app|
8
47
  if Rails.env.development?
9
48
  app.middleware.insert_before 0,
@@ -12,7 +51,7 @@ class Webpacker::Engine < ::Rails::Engine
12
51
  end
13
52
  end
14
53
 
15
- initializer "webpacker.helper" do |app|
54
+ initializer "webpacker.helper" do
16
55
  ActiveSupport.on_load :action_controller do
17
56
  ActionController::Base.helper Webpacker::Helper
18
57
  end
@@ -23,7 +62,7 @@ class Webpacker::Engine < ::Rails::Engine
23
62
  end
24
63
 
25
64
  initializer "webpacker.logger" do
26
- config.after_initialize do |app|
65
+ config.after_initialize do
27
66
  if ::Rails.logger.respond_to?(:tagged)
28
67
  Webpacker.logger = ::Rails.logger
29
68
  else
@@ -14,7 +14,7 @@ module Webpacker
14
14
  @webpack_config = File.join(@app_path, "config/webpack/#{ENV["NODE_ENV"]}.js")
15
15
 
16
16
  unless File.exist?(@webpack_config)
17
- puts "Webpack config #{@webpack_config} not found, please run 'bundle exec rails webpacker:install' to install webpacker with default configs or add the missing config file for your custom environment."
17
+ $stderr.puts "webpack config #{@webpack_config} not found, please run 'bundle exec rails webpacker:install' to install Webpacker with default configs or add the missing config file for your custom environment."
18
18
  exit!
19
19
  end
20
20
  end
@@ -1,4 +1,4 @@
1
1
  module Webpacker
2
2
  # Change the version in package.json too, please!
3
- VERSION = "3.0.2".freeze
3
+ VERSION = "3.1.0".freeze
4
4
  end
data/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rails/webpacker",
3
- "version": "3.0.2",
4
- "description": "Use Webpack to manage app-like JavaScript modules in Rails",
3
+ "version": "3.1.0",
4
+ "description": "Use webpack to manage app-like JavaScript modules in Rails",
5
5
  "main": "package/index.js",
6
6
  "files": [
7
7
  "package"
@@ -17,38 +17,46 @@
17
17
  "babel-plugin-transform-class-properties": "^6.24.1",
18
18
  "babel-plugin-transform-object-rest-spread": "^6.26.0",
19
19
  "babel-polyfill": "^6.26.0",
20
- "babel-preset-env": "^1.6.0",
21
- "coffee-loader": "^0.8.0",
22
- "compression-webpack-plugin": "^1.0.0",
23
- "css-loader": "^0.28.5",
24
- "extract-text-webpack-plugin": "^3.0.0",
25
- "file-loader": "^0.11.2",
20
+ "babel-preset-env": "^1.6.1",
21
+ "case-sensitive-paths-webpack-plugin": "^2.1.1",
22
+ "coffee-loader": "^0.9.0",
23
+ "compression-webpack-plugin": "^1.0.1",
24
+ "css-loader": "^0.28.7",
25
+ "extract-text-webpack-plugin": "^3.0.2",
26
+ "file-loader": "^1.1.5",
26
27
  "glob": "^7.1.2",
27
- "js-yaml": "^3.9.1",
28
- "node-sass": "^4.5.3",
28
+ "js-yaml": "^3.10.0",
29
+ "node-sass": "^4.7.2",
29
30
  "path-complete-extname": "^0.1.0",
30
31
  "postcss-cssnext": "^3.0.2",
31
- "postcss-loader": "^2.0.6",
32
+ "postcss-loader": "^2.0.9",
32
33
  "postcss-smart-import": "^0.7.5",
33
34
  "rails-erb-loader": "^5.2.1",
34
- "resolve-url-loader": "^2.1.0",
35
35
  "sass-loader": "^6.0.6",
36
- "style-loader": "^0.18.2",
37
- "webpack": "^3.5.5",
38
- "webpack-manifest-plugin": "^1.3.1"
36
+ "style-loader": "^0.19.0",
37
+ "url-loader": "^0.6.2",
38
+ "webpack": "^3.8.1",
39
+ "webpack-manifest-plugin": "^1.3.2"
39
40
  },
40
41
  "devDependencies": {
41
- "eslint": "^3.16.1",
42
- "eslint-config-airbnb": "^14.1.0",
43
- "eslint-plugin-import": "^2.2.0",
44
- "eslint-plugin-jsx-a11y": "^4.0.0",
45
- "eslint-plugin-react": "^6.10.0"
42
+ "eslint": "^4.11.0",
43
+ "eslint-config-airbnb": "^16.1.0",
44
+ "eslint-plugin-import": "^2.8.0",
45
+ "eslint-plugin-jsx-a11y": "^6.0.2",
46
+ "eslint-plugin-react": "^7.5.1",
47
+ "jest": "^21.2.1"
48
+ },
49
+ "jest": {
50
+ "testRegex": "(/__tests__/.*|(\\.|/))\\.jsx?$",
51
+ "roots": [
52
+ "<rootDir>/package"
53
+ ]
46
54
  },
47
55
  "peerDependencies": {
48
56
  "coffeescript": ">= 1.12.7 || >= 2.x"
49
57
  },
50
58
  "scripts": {
51
- "test": "echo \"Error: no test specified\" && exit 1",
59
+ "test": "jest",
52
60
  "lint": "eslint {package,lib}/"
53
61
  },
54
62
  "repository": {
@@ -1,11 +1,10 @@
1
1
  const config = require('./config')
2
2
  const { resolve } = require('path')
3
3
 
4
- function removeOuterSlashes(string) {
5
- return string.replace(/^\/*/, '').replace(/\/*$/, '')
6
- }
4
+ const removeOuterSlashes = string =>
5
+ string.replace(/^\/*/, '').replace(/\/*$/, '')
7
6
 
8
- function formatPublicPath(host = '', path = '') {
7
+ const formatPublicPath = (host = '', path = '') => {
9
8
  let formattedHost = removeOuterSlashes(host)
10
9
  if (formattedHost && !/^http/i.test(formattedHost)) {
11
10
  formattedHost = `//${formattedHost}`
@@ -17,5 +16,5 @@ function formatPublicPath(host = '', path = '') {
17
16
  module.exports = {
18
17
  path: resolve('public', config.public_output_path),
19
18
  publicPath: `/${config.public_output_path}/`.replace(/([^:]\/)\/+/g, '$1'),
20
- publicPathWithHost: formatPublicPath(process.env.ASSET_HOST, config.public_output_path)
19
+ publicPathWithHost: formatPublicPath(process.env.WEBPACKER_ASSET_HOST, config.public_output_path)
21
20
  }
data/package/config.js CHANGED
@@ -1,9 +1,15 @@
1
1
  const { resolve } = require('path')
2
2
  const { safeLoad } = require('js-yaml')
3
3
  const { readFileSync } = require('fs')
4
+ const deepMerge = require('./utils/deep_merge')
4
5
 
6
+ const defaultFilePath = require.resolve('../lib/install/config/webpacker.yml')
5
7
  const filePath = resolve('config', 'webpacker.yml')
6
- const config = safeLoad(readFileSync(filePath), 'utf8')[process.env.NODE_ENV]
8
+
9
+ const environment = process.env.NODE_ENV || 'development'
10
+ const defaultConfig = safeLoad(readFileSync(defaultFilePath), 'utf8')[environment]
11
+ const appConfig = safeLoad(readFileSync(filePath), 'utf8')[environment]
12
+ const config = deepMerge(defaultConfig, appConfig)
7
13
 
8
14
  const isBoolean = str => /^true/.test(str) || /^false/.test(str)
9
15
 
@@ -0,0 +1,123 @@
1
+ /* global test expect */
2
+
3
+ const ConfigList = require('../config_list')
4
+
5
+ test('new', () => {
6
+ const list = new ConfigList()
7
+ expect(list).toBeInstanceOf(ConfigList)
8
+ expect(list).toBeInstanceOf(Array)
9
+ })
10
+
11
+ test('set', () => {
12
+ const list = new ConfigList()
13
+ expect(list.set('key', 'value')).toEqual([{ key: 'key', value: 'value' }])
14
+ })
15
+
16
+ test('get', () => {
17
+ const list = new ConfigList()
18
+ list.append('key', 'value')
19
+ expect(list.get('key')).toEqual('value')
20
+ })
21
+
22
+ test('append', () => {
23
+ const list = new ConfigList()
24
+ list.append('key', 'value')
25
+ expect(list.append('key1', 'value1')).toEqual([
26
+ { key: 'key', value: 'value' },
27
+ { key: 'key1', value: 'value1' }
28
+ ])
29
+ })
30
+
31
+ test('prepend', () => {
32
+ const list = new ConfigList()
33
+ list.append('key', 'value')
34
+ expect(list.prepend('key1', 'value1')).toEqual([
35
+ { key: 'key1', value: 'value1' },
36
+ { key: 'key', value: 'value' }
37
+ ])
38
+ })
39
+
40
+ test('insert without position', () => {
41
+ const list = new ConfigList()
42
+ list.append('key', 'value')
43
+
44
+ expect(list.insert('key1', 'value1')).toEqual([
45
+ { key: 'key', value: 'value' },
46
+ { key: 'key1', value: 'value1' }
47
+ ])
48
+
49
+ expect(list.insert('key2', 'value2')).toEqual([
50
+ { key: 'key', value: 'value' },
51
+ { key: 'key1', value: 'value1' },
52
+ { key: 'key2', value: 'value2' }
53
+ ])
54
+ })
55
+
56
+ test('insert before an item', () => {
57
+ const list = new ConfigList()
58
+ list.append('key', 'value')
59
+ list.append('key1', 'value1')
60
+
61
+ expect(list.insert('key2', 'value2', { before: 'key' })).toEqual([
62
+ { key: 'key2', value: 'value2' },
63
+ { key: 'key', value: 'value' },
64
+ { key: 'key1', value: 'value1' }
65
+ ])
66
+
67
+ expect(list.insert('key3', 'value3', { before: 'key2' })).toEqual([
68
+ { key: 'key3', value: 'value3' },
69
+ { key: 'key2', value: 'value2' },
70
+ { key: 'key', value: 'value' },
71
+ { key: 'key1', value: 'value1' }
72
+ ])
73
+ })
74
+
75
+ test('insert after an item', () => {
76
+ const list = new ConfigList()
77
+ list.append('key', 'value')
78
+ list.append('key1', 'value1')
79
+
80
+ expect(list.insert('key2', 'value2', { after: 'key' })).toEqual([
81
+ { key: 'key', value: 'value' },
82
+ { key: 'key2', value: 'value2' },
83
+ { key: 'key1', value: 'value1' }
84
+ ])
85
+
86
+ expect(list.insert('key3', 'value3', { after: 'key2' })).toEqual([
87
+ { key: 'key', value: 'value' },
88
+ { key: 'key2', value: 'value2' },
89
+ { key: 'key3', value: 'value3' },
90
+ { key: 'key1', value: 'value1' }
91
+ ])
92
+ })
93
+
94
+ test('delete', () => {
95
+ const list = new ConfigList()
96
+ list.append('key', 'value')
97
+ list.append('key1', 'value1')
98
+ expect(list.delete('key')).toEqual([{ key: 'key1', value: 'value1' }])
99
+ expect(list.delete('key1')).toEqual([])
100
+ })
101
+
102
+ test('getIndex', () => {
103
+ const list = new ConfigList()
104
+ list.append('key', 'value')
105
+ list.append('key1', 'value1')
106
+ expect(list.getIndex('key')).toEqual(0)
107
+ expect(list.getIndex('key2')).toEqual(-1)
108
+ expect(() => list.getIndex('key2', true)).toThrow('Item key2 not found')
109
+ })
110
+
111
+ test('values', () => {
112
+ const list = new ConfigList()
113
+ list.append('key', 'value')
114
+ list.append('key1', 'value1')
115
+ expect(list.values()).toEqual(['value', 'value1'])
116
+ })
117
+
118
+ test('keys', () => {
119
+ const list = new ConfigList()
120
+ list.append('key', 'value')
121
+ list.append('key1', 'value1')
122
+ expect(list.keys()).toEqual(['key', 'key1'])
123
+ })
@@ -0,0 +1,43 @@
1
+ /* global test expect */
2
+
3
+ const ConfigObject = require('../config_object')
4
+
5
+ test('new', () => {
6
+ const object = new ConfigObject()
7
+ expect(object).toBeInstanceOf(ConfigObject)
8
+ expect(object).toBeInstanceOf(Object)
9
+ })
10
+
11
+ test('set', () => {
12
+ const object = new ConfigObject()
13
+ expect(object.set('key', 'value')).toEqual({ key: 'value' })
14
+ })
15
+
16
+ test('get', () => {
17
+ const object = new ConfigObject()
18
+ object.set('key', 'value')
19
+ object.set('key1', 'value1')
20
+ expect(object.get('key')).toEqual('value')
21
+ })
22
+
23
+ test('delete', () => {
24
+ const object = new ConfigObject()
25
+ object.set('key', { key1: 'value' })
26
+ expect(object.delete('key.key1')).toEqual({ key: {} })
27
+ expect(object.delete('key')).toEqual({})
28
+ })
29
+
30
+ test('toObject', () => {
31
+ const object = new ConfigObject()
32
+ object.set('key', 'value')
33
+ object.set('key1', 'value1')
34
+ expect(object.toObject()).toEqual({ key: 'value', key1: 'value1' })
35
+ })
36
+
37
+ test('merge', () => {
38
+ const object = new ConfigObject()
39
+ object.set('foo', {})
40
+ expect(object.merge({ key: 'foo', value: 'bar' })).toEqual(
41
+ { foo: {}, key: 'foo', value: 'bar' }
42
+ )
43
+ })
@@ -0,0 +1,83 @@
1
+ /**
2
+ * @class
3
+ * @extends { Array }
4
+ */
5
+ class ConfigList extends Array {
6
+ get(key) {
7
+ const index = this.getIndex(key, true)
8
+ return this[index].value
9
+ }
10
+
11
+ /**
12
+ * @deprecated after the 3.0.2 release and will be removed in the next major release
13
+ */
14
+ set(key, value) {
15
+ /* eslint no-console: 0 */
16
+ console.warn('set is deprecated! Use append instead')
17
+ return this.append(key, value)
18
+ }
19
+
20
+ append(key, value) {
21
+ return this.add({ key, value })
22
+ }
23
+
24
+ prepend(key, value) {
25
+ return this.add({ key, value }, 'prepend')
26
+ }
27
+
28
+ insert(key, value, pos = {}) {
29
+ if (!(pos.before || pos.after)) return this.append(key, value)
30
+
31
+ const currentIndex = this.getIndex(key)
32
+ if (currentIndex >= 0) this.splice(currentIndex, 1)
33
+
34
+ let newIndex = this.getIndex(pos.before || pos.after)
35
+ if (pos.after) newIndex += 1
36
+
37
+ this.splice(newIndex, 0, { key, value })
38
+ return this
39
+ }
40
+
41
+ delete(key) {
42
+ const index = this.getIndex(key, true)
43
+ this.splice(index, 1)
44
+ return this
45
+ }
46
+
47
+ getIndex(key, shouldThrow = false) {
48
+ const index = this.findIndex(entry =>
49
+ (
50
+ entry === key ||
51
+ entry.key === key ||
52
+ (entry.constructor && entry.constructor.name === key)
53
+ ))
54
+
55
+ if (shouldThrow && index < 0) throw new Error(`Item ${key} not found`)
56
+ return index
57
+ }
58
+
59
+ add({ key, value }, strategy = 'append') {
60
+ const index = this.getIndex(key)
61
+ if (index >= 0) this.delete(key)
62
+
63
+ switch (strategy) {
64
+ case 'prepend':
65
+ this.unshift({ key, value })
66
+ break
67
+ default:
68
+ this.push({ key, value })
69
+ }
70
+
71
+ return this
72
+ }
73
+
74
+ values() {
75
+ return this.map(item => item.value)
76
+ }
77
+
78
+ keys() {
79
+ return this.map(item => item.key)
80
+ }
81
+ }
82
+
83
+ module.exports = ConfigList