├── .github
└── workflows
│ ├── release.yml
│ └── test.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── action.yml
├── dist
└── index.js
├── index.js
├── package-lock.json
└── package.json
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches:
4 | - master
5 | name: release
6 | jobs:
7 | release:
8 | name: release
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@master
12 | - uses: actions/setup-node@v1
13 | with:
14 | node-version: "12.x"
15 | - run: npm ci
16 | - run: npm run build
17 | - run: npx semantic-release
18 | env:
19 | GITHUB_TOKEN: ${{ secrets.GR2M_PAT_FOR_SEMANTIC_RELEASE }}
20 | - run: "git push https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git HEAD:refs/heads/v1.x"
21 | env:
22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches:
4 | - master
5 | - "greenkeeper/**"
6 | pull_request:
7 | types: [opened, synchronize]
8 | name: Test
9 | jobs:
10 | readmeExample:
11 | name: "[TEST] README example"
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@master
15 | - uses: actions/setup-node@v1
16 | with:
17 | node-version: "12.x"
18 | - run: "npm ci"
19 | - run: "npm run build"
20 | - id: action_with_json_output
21 | run: 'node -p "require(''@actions/core'').setOutput(''data'', JSON.stringify({foo: {bar: ''baz''}}))"'
22 | - id: result
23 | uses: ./
24 | with:
25 | json: ${{ steps.action_with_json_output.outputs.data }}
26 | bar: "foo.bar"
27 | - run: 'node -e "assert.equal(''baz'', ''${{ steps.result.outputs.bar }}'')"'
28 | readmeRequestActionExample:
29 | name: "[TEST] README octokit/request-action@v2.x example"
30 | runs-on: ubuntu-latest
31 | steps:
32 | - uses: actions/checkout@master
33 | - uses: actions/setup-node@v1
34 | with:
35 | node-version: "12.x"
36 | - run: "npm ci"
37 | - run: "npm run build"
38 | - id: request
39 | uses: octokit/request-action@v2.x
40 | with:
41 | route: GET /repos/:owner/:repo/releases/latest
42 | owner: gr2m
43 | repo: get-json-paths-action
44 | env:
45 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
46 | - id: result
47 | uses: ./
48 | with:
49 | json: ${{ steps.request.outputs.data }}
50 | name: "name"
51 | tag_name: "tag_name"
52 | created_by: "author.login"
53 | - run: 'node -e "assert.equal(''gr2m'', ''${{ steps.result.outputs.created_by }}'')"'
54 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | - Using welcoming and inclusive language
12 | - Being respectful of differing viewpoints and experiences
13 | - Gracefully accepting constructive criticism
14 | - Focusing on what is best for the community
15 | - Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | - The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | - Trolling, insulting/derogatory comments, and personal or political attacks
21 | - Public or private harassment
22 | - Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | - Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at coc@martynus.net. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Gregor Martynus
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 💁♂️ This action is now obsolete
2 |
3 | Use the built-in [`fromJSON(value)`](https://help.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#fromjson) function instead
4 |
5 | # Get JSON paths action
6 |
7 | > A GitHub Action to access deep values of JSON strings
8 |
9 | [](https://github.com/gr2m/get-json-paths-action/actions)
10 | [](https://greenkeeper.io/)
11 |
12 | ## Usage
13 |
14 | Minimal example
15 |
16 | ```yml
17 | Name: Minimal example
18 | on: [push]
19 |
20 | jobs:
21 | minimal_example:
22 | runs-on: ubuntu-latest
23 | steps:
24 | - id: action_with_json_output
25 | run: 'echo ::set-output name=data::{ "foo": { "bar":"baz" } }'
26 | - id: data
27 | uses: gr2m/get-json-paths-action@v1.x
28 | with:
29 | json: ${{ steps.action_with_json_output.outputs.data }}
30 | bar: "foo.bar"
31 | - run: "echo bar is ${{ steps.data.outputs.bar }}"
32 | ```
33 |
34 | Example with [`octokit/request-action`](https://github.com/octokit/request-action/)
35 |
36 | ```yml
37 | Name: Request example
38 | on:
39 | push:
40 | branches:
41 | - master
42 |
43 | jobs:
44 | request_example:
45 | runs-on: ubuntu-latest
46 | steps:
47 | - id: request
48 | uses: octokit/request-action@v2.x
49 | with:
50 | route: GET /repos/:owner/:repo/releases/latest
51 | owner: gr2m
52 | repo: get-json-paths-action
53 | env:
54 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55 | - id: result
56 | uses: gr2m/get-json-paths-action@v1.x
57 | with:
58 | json: ${{ steps.request.outputs.data }}
59 | name: "name"
60 | tag_name: "tag_name"
61 | created_by: "author.login"
62 | - run: "echo latest release: ${{ steps.result.outputs.name }} (${{ steps.result.outputs.tag_name }}) by ${{ ${{ steps.result.outputs.login }}"
63 | ```
64 |
65 | ## Debugging
66 |
67 | To see additional debug logs, create a secret with the name: `ACTIONS_STEP_DEBUG` and value `true`.
68 |
69 | ## How it works
70 |
71 | `get-json-paths-action` is using [`lodash.get`](https://lodash.com/docs/4.17.15#get) to access deep properties at the provided path. `json` is the only required `input`. All other inputs are turned into equally named outputs with the value at the given paths.
72 |
73 | ## License
74 |
75 | [MIT](LICENSE)
76 |
--------------------------------------------------------------------------------
/action.yml:
--------------------------------------------------------------------------------
1 | name: Get JSON paths
2 | description: "A GitHub Action to access deep values of JSON strings"
3 | branding:
4 | icon: "box"
5 | color: gray-dark
6 | inputs:
7 | json:
8 | description: "JSON string"
9 | required: true
10 | runs:
11 | using: "node12"
12 | main: "dist/index.js"
13 |
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | module.exports =
2 | /******/ (function(modules, runtime) { // webpackBootstrap
3 | /******/ "use strict";
4 | /******/ // The module cache
5 | /******/ var installedModules = {};
6 | /******/
7 | /******/ // The require function
8 | /******/ function __webpack_require__(moduleId) {
9 | /******/
10 | /******/ // Check if module is in cache
11 | /******/ if(installedModules[moduleId]) {
12 | /******/ return installedModules[moduleId].exports;
13 | /******/ }
14 | /******/ // Create a new module (and put it into the cache)
15 | /******/ var module = installedModules[moduleId] = {
16 | /******/ i: moduleId,
17 | /******/ l: false,
18 | /******/ exports: {}
19 | /******/ };
20 | /******/
21 | /******/ // Execute the module function
22 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
23 | /******/
24 | /******/ // Flag the module as loaded
25 | /******/ module.l = true;
26 | /******/
27 | /******/ // Return the exports of the module
28 | /******/ return module.exports;
29 | /******/ }
30 | /******/
31 | /******/
32 | /******/ __webpack_require__.ab = __dirname + "/";
33 | /******/
34 | /******/ // the startup function
35 | /******/ function startup() {
36 | /******/ // Load entry module and return exports
37 | /******/ return __webpack_require__(104);
38 | /******/ };
39 | /******/
40 | /******/ // run startup
41 | /******/ return startup();
42 | /******/ })
43 | /************************************************************************/
44 | /******/ ({
45 |
46 | /***/ 87:
47 | /***/ (function(module) {
48 |
49 | module.exports = require("os");
50 |
51 | /***/ }),
52 |
53 | /***/ 104:
54 | /***/ (function(__unusedmodule, __unusedexports, __webpack_require__) {
55 |
56 | const { inspect } = __webpack_require__(669);
57 |
58 | const get = __webpack_require__(854);
59 | const core = __webpack_require__(470);
60 |
61 | const { json, ...paths } = getAllInputs();
62 | const jsonParsed = JSON.parse(json);
63 |
64 | try {
65 | core.debug(`json input: ${inspect(jsonParsed)}`);
66 | core.debug(`paths inputs: ${inspect(paths)}`);
67 |
68 | for (const [name, path] of Object.entries(paths)) {
69 | const value = get(jsonParsed, path);
70 | core.debug(`setting output ${name} to ${value} using "${path}"`);
71 | core.setOutput(name, value);
72 | }
73 | } catch (error) {
74 | core.setFailed(error);
75 | process.exit(1);
76 | }
77 |
78 | function getAllInputs() {
79 | return Object.entries(process.env).reduce((result, [key, value]) => {
80 | if (!/^INPUT_/.test(key)) return result;
81 |
82 | const inputName = key.substr("INPUT_".length).toLowerCase();
83 | result[inputName] = value;
84 | return result;
85 | }, {});
86 | }
87 |
88 |
89 | /***/ }),
90 |
91 | /***/ 431:
92 | /***/ (function(__unusedmodule, exports, __webpack_require__) {
93 |
94 | "use strict";
95 |
96 | Object.defineProperty(exports, "__esModule", { value: true });
97 | const os = __webpack_require__(87);
98 | /**
99 | * Commands
100 | *
101 | * Command Format:
102 | * ##[name key=value;key=value]message
103 | *
104 | * Examples:
105 | * ##[warning]This is the user warning message
106 | * ##[set-secret name=mypassword]definitelyNotAPassword!
107 | */
108 | function issueCommand(command, properties, message) {
109 | const cmd = new Command(command, properties, message);
110 | process.stdout.write(cmd.toString() + os.EOL);
111 | }
112 | exports.issueCommand = issueCommand;
113 | function issue(name, message = '') {
114 | issueCommand(name, {}, message);
115 | }
116 | exports.issue = issue;
117 | const CMD_STRING = '::';
118 | class Command {
119 | constructor(command, properties, message) {
120 | if (!command) {
121 | command = 'missing.command';
122 | }
123 | this.command = command;
124 | this.properties = properties;
125 | this.message = message;
126 | }
127 | toString() {
128 | let cmdStr = CMD_STRING + this.command;
129 | if (this.properties && Object.keys(this.properties).length > 0) {
130 | cmdStr += ' ';
131 | for (const key in this.properties) {
132 | if (this.properties.hasOwnProperty(key)) {
133 | const val = this.properties[key];
134 | if (val) {
135 | // safely append the val - avoid blowing up when attempting to
136 | // call .replace() if message is not a string for some reason
137 | cmdStr += `${key}=${escape(`${val || ''}`)},`;
138 | }
139 | }
140 | }
141 | }
142 | cmdStr += CMD_STRING;
143 | // safely append the message - avoid blowing up when attempting to
144 | // call .replace() if message is not a string for some reason
145 | const message = `${this.message || ''}`;
146 | cmdStr += escapeData(message);
147 | return cmdStr;
148 | }
149 | }
150 | function escapeData(s) {
151 | return s.replace(/\r/g, '%0D').replace(/\n/g, '%0A');
152 | }
153 | function escape(s) {
154 | return s
155 | .replace(/\r/g, '%0D')
156 | .replace(/\n/g, '%0A')
157 | .replace(/]/g, '%5D')
158 | .replace(/;/g, '%3B');
159 | }
160 | //# sourceMappingURL=command.js.map
161 |
162 | /***/ }),
163 |
164 | /***/ 470:
165 | /***/ (function(__unusedmodule, exports, __webpack_require__) {
166 |
167 | "use strict";
168 |
169 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
170 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
171 | return new (P || (P = Promise))(function (resolve, reject) {
172 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
173 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
174 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
175 | step((generator = generator.apply(thisArg, _arguments || [])).next());
176 | });
177 | };
178 | Object.defineProperty(exports, "__esModule", { value: true });
179 | const command_1 = __webpack_require__(431);
180 | const os = __webpack_require__(87);
181 | const path = __webpack_require__(622);
182 | /**
183 | * The code to exit an action
184 | */
185 | var ExitCode;
186 | (function (ExitCode) {
187 | /**
188 | * A code indicating that the action was successful
189 | */
190 | ExitCode[ExitCode["Success"] = 0] = "Success";
191 | /**
192 | * A code indicating that the action was a failure
193 | */
194 | ExitCode[ExitCode["Failure"] = 1] = "Failure";
195 | })(ExitCode = exports.ExitCode || (exports.ExitCode = {}));
196 | //-----------------------------------------------------------------------
197 | // Variables
198 | //-----------------------------------------------------------------------
199 | /**
200 | * Sets env variable for this action and future actions in the job
201 | * @param name the name of the variable to set
202 | * @param val the value of the variable
203 | */
204 | function exportVariable(name, val) {
205 | process.env[name] = val;
206 | command_1.issueCommand('set-env', { name }, val);
207 | }
208 | exports.exportVariable = exportVariable;
209 | /**
210 | * Registers a secret which will get masked from logs
211 | * @param secret value of the secret
212 | */
213 | function setSecret(secret) {
214 | command_1.issueCommand('add-mask', {}, secret);
215 | }
216 | exports.setSecret = setSecret;
217 | /**
218 | * Prepends inputPath to the PATH (for this action and future actions)
219 | * @param inputPath
220 | */
221 | function addPath(inputPath) {
222 | command_1.issueCommand('add-path', {}, inputPath);
223 | process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;
224 | }
225 | exports.addPath = addPath;
226 | /**
227 | * Gets the value of an input. The value is also trimmed.
228 | *
229 | * @param name name of the input to get
230 | * @param options optional. See InputOptions.
231 | * @returns string
232 | */
233 | function getInput(name, options) {
234 | const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '';
235 | if (options && options.required && !val) {
236 | throw new Error(`Input required and not supplied: ${name}`);
237 | }
238 | return val.trim();
239 | }
240 | exports.getInput = getInput;
241 | /**
242 | * Sets the value of an output.
243 | *
244 | * @param name name of the output to set
245 | * @param value value to store
246 | */
247 | function setOutput(name, value) {
248 | command_1.issueCommand('set-output', { name }, value);
249 | }
250 | exports.setOutput = setOutput;
251 | //-----------------------------------------------------------------------
252 | // Results
253 | //-----------------------------------------------------------------------
254 | /**
255 | * Sets the action status to failed.
256 | * When the action exits it will be with an exit code of 1
257 | * @param message add error issue message
258 | */
259 | function setFailed(message) {
260 | process.exitCode = ExitCode.Failure;
261 | error(message);
262 | }
263 | exports.setFailed = setFailed;
264 | //-----------------------------------------------------------------------
265 | // Logging Commands
266 | //-----------------------------------------------------------------------
267 | /**
268 | * Writes debug message to user log
269 | * @param message debug message
270 | */
271 | function debug(message) {
272 | command_1.issueCommand('debug', {}, message);
273 | }
274 | exports.debug = debug;
275 | /**
276 | * Adds an error issue
277 | * @param message error issue message
278 | */
279 | function error(message) {
280 | command_1.issue('error', message);
281 | }
282 | exports.error = error;
283 | /**
284 | * Adds an warning issue
285 | * @param message warning issue message
286 | */
287 | function warning(message) {
288 | command_1.issue('warning', message);
289 | }
290 | exports.warning = warning;
291 | /**
292 | * Writes info to log with console.log.
293 | * @param message info message
294 | */
295 | function info(message) {
296 | process.stdout.write(message + os.EOL);
297 | }
298 | exports.info = info;
299 | /**
300 | * Begin an output group.
301 | *
302 | * Output until the next `groupEnd` will be foldable in this group
303 | *
304 | * @param name The name of the output group
305 | */
306 | function startGroup(name) {
307 | command_1.issue('group', name);
308 | }
309 | exports.startGroup = startGroup;
310 | /**
311 | * End an output group.
312 | */
313 | function endGroup() {
314 | command_1.issue('endgroup');
315 | }
316 | exports.endGroup = endGroup;
317 | /**
318 | * Wrap an asynchronous function call in a group.
319 | *
320 | * Returns the same type as the function itself.
321 | *
322 | * @param name The name of the group
323 | * @param fn The function to wrap in the group
324 | */
325 | function group(name, fn) {
326 | return __awaiter(this, void 0, void 0, function* () {
327 | startGroup(name);
328 | let result;
329 | try {
330 | result = yield fn();
331 | }
332 | finally {
333 | endGroup();
334 | }
335 | return result;
336 | });
337 | }
338 | exports.group = group;
339 | //# sourceMappingURL=core.js.map
340 |
341 | /***/ }),
342 |
343 | /***/ 622:
344 | /***/ (function(module) {
345 |
346 | module.exports = require("path");
347 |
348 | /***/ }),
349 |
350 | /***/ 669:
351 | /***/ (function(module) {
352 |
353 | module.exports = require("util");
354 |
355 | /***/ }),
356 |
357 | /***/ 854:
358 | /***/ (function(module) {
359 |
360 | /**
361 | * lodash (Custom Build)
362 | * Build: `lodash modularize exports="npm" -o ./`
363 | * Copyright jQuery Foundation and other contributors
364 | * Released under MIT license
365 | * Based on Underscore.js 1.8.3
366 | * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
367 | */
368 |
369 | /** Used as the `TypeError` message for "Functions" methods. */
370 | var FUNC_ERROR_TEXT = 'Expected a function';
371 |
372 | /** Used to stand-in for `undefined` hash values. */
373 | var HASH_UNDEFINED = '__lodash_hash_undefined__';
374 |
375 | /** Used as references for various `Number` constants. */
376 | var INFINITY = 1 / 0;
377 |
378 | /** `Object#toString` result references. */
379 | var funcTag = '[object Function]',
380 | genTag = '[object GeneratorFunction]',
381 | symbolTag = '[object Symbol]';
382 |
383 | /** Used to match property names within property paths. */
384 | var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
385 | reIsPlainProp = /^\w*$/,
386 | reLeadingDot = /^\./,
387 | rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
388 |
389 | /**
390 | * Used to match `RegExp`
391 | * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
392 | */
393 | var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
394 |
395 | /** Used to match backslashes in property paths. */
396 | var reEscapeChar = /\\(\\)?/g;
397 |
398 | /** Used to detect host constructors (Safari). */
399 | var reIsHostCtor = /^\[object .+?Constructor\]$/;
400 |
401 | /** Detect free variable `global` from Node.js. */
402 | var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
403 |
404 | /** Detect free variable `self`. */
405 | var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
406 |
407 | /** Used as a reference to the global object. */
408 | var root = freeGlobal || freeSelf || Function('return this')();
409 |
410 | /**
411 | * Gets the value at `key` of `object`.
412 | *
413 | * @private
414 | * @param {Object} [object] The object to query.
415 | * @param {string} key The key of the property to get.
416 | * @returns {*} Returns the property value.
417 | */
418 | function getValue(object, key) {
419 | return object == null ? undefined : object[key];
420 | }
421 |
422 | /**
423 | * Checks if `value` is a host object in IE < 9.
424 | *
425 | * @private
426 | * @param {*} value The value to check.
427 | * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
428 | */
429 | function isHostObject(value) {
430 | // Many host objects are `Object` objects that can coerce to strings
431 | // despite having improperly defined `toString` methods.
432 | var result = false;
433 | if (value != null && typeof value.toString != 'function') {
434 | try {
435 | result = !!(value + '');
436 | } catch (e) {}
437 | }
438 | return result;
439 | }
440 |
441 | /** Used for built-in method references. */
442 | var arrayProto = Array.prototype,
443 | funcProto = Function.prototype,
444 | objectProto = Object.prototype;
445 |
446 | /** Used to detect overreaching core-js shims. */
447 | var coreJsData = root['__core-js_shared__'];
448 |
449 | /** Used to detect methods masquerading as native. */
450 | var maskSrcKey = (function() {
451 | var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
452 | return uid ? ('Symbol(src)_1.' + uid) : '';
453 | }());
454 |
455 | /** Used to resolve the decompiled source of functions. */
456 | var funcToString = funcProto.toString;
457 |
458 | /** Used to check objects for own properties. */
459 | var hasOwnProperty = objectProto.hasOwnProperty;
460 |
461 | /**
462 | * Used to resolve the
463 | * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
464 | * of values.
465 | */
466 | var objectToString = objectProto.toString;
467 |
468 | /** Used to detect if a method is native. */
469 | var reIsNative = RegExp('^' +
470 | funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
471 | .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
472 | );
473 |
474 | /** Built-in value references. */
475 | var Symbol = root.Symbol,
476 | splice = arrayProto.splice;
477 |
478 | /* Built-in method references that are verified to be native. */
479 | var Map = getNative(root, 'Map'),
480 | nativeCreate = getNative(Object, 'create');
481 |
482 | /** Used to convert symbols to primitives and strings. */
483 | var symbolProto = Symbol ? Symbol.prototype : undefined,
484 | symbolToString = symbolProto ? symbolProto.toString : undefined;
485 |
486 | /**
487 | * Creates a hash object.
488 | *
489 | * @private
490 | * @constructor
491 | * @param {Array} [entries] The key-value pairs to cache.
492 | */
493 | function Hash(entries) {
494 | var index = -1,
495 | length = entries ? entries.length : 0;
496 |
497 | this.clear();
498 | while (++index < length) {
499 | var entry = entries[index];
500 | this.set(entry[0], entry[1]);
501 | }
502 | }
503 |
504 | /**
505 | * Removes all key-value entries from the hash.
506 | *
507 | * @private
508 | * @name clear
509 | * @memberOf Hash
510 | */
511 | function hashClear() {
512 | this.__data__ = nativeCreate ? nativeCreate(null) : {};
513 | }
514 |
515 | /**
516 | * Removes `key` and its value from the hash.
517 | *
518 | * @private
519 | * @name delete
520 | * @memberOf Hash
521 | * @param {Object} hash The hash to modify.
522 | * @param {string} key The key of the value to remove.
523 | * @returns {boolean} Returns `true` if the entry was removed, else `false`.
524 | */
525 | function hashDelete(key) {
526 | return this.has(key) && delete this.__data__[key];
527 | }
528 |
529 | /**
530 | * Gets the hash value for `key`.
531 | *
532 | * @private
533 | * @name get
534 | * @memberOf Hash
535 | * @param {string} key The key of the value to get.
536 | * @returns {*} Returns the entry value.
537 | */
538 | function hashGet(key) {
539 | var data = this.__data__;
540 | if (nativeCreate) {
541 | var result = data[key];
542 | return result === HASH_UNDEFINED ? undefined : result;
543 | }
544 | return hasOwnProperty.call(data, key) ? data[key] : undefined;
545 | }
546 |
547 | /**
548 | * Checks if a hash value for `key` exists.
549 | *
550 | * @private
551 | * @name has
552 | * @memberOf Hash
553 | * @param {string} key The key of the entry to check.
554 | * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
555 | */
556 | function hashHas(key) {
557 | var data = this.__data__;
558 | return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
559 | }
560 |
561 | /**
562 | * Sets the hash `key` to `value`.
563 | *
564 | * @private
565 | * @name set
566 | * @memberOf Hash
567 | * @param {string} key The key of the value to set.
568 | * @param {*} value The value to set.
569 | * @returns {Object} Returns the hash instance.
570 | */
571 | function hashSet(key, value) {
572 | var data = this.__data__;
573 | data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
574 | return this;
575 | }
576 |
577 | // Add methods to `Hash`.
578 | Hash.prototype.clear = hashClear;
579 | Hash.prototype['delete'] = hashDelete;
580 | Hash.prototype.get = hashGet;
581 | Hash.prototype.has = hashHas;
582 | Hash.prototype.set = hashSet;
583 |
584 | /**
585 | * Creates an list cache object.
586 | *
587 | * @private
588 | * @constructor
589 | * @param {Array} [entries] The key-value pairs to cache.
590 | */
591 | function ListCache(entries) {
592 | var index = -1,
593 | length = entries ? entries.length : 0;
594 |
595 | this.clear();
596 | while (++index < length) {
597 | var entry = entries[index];
598 | this.set(entry[0], entry[1]);
599 | }
600 | }
601 |
602 | /**
603 | * Removes all key-value entries from the list cache.
604 | *
605 | * @private
606 | * @name clear
607 | * @memberOf ListCache
608 | */
609 | function listCacheClear() {
610 | this.__data__ = [];
611 | }
612 |
613 | /**
614 | * Removes `key` and its value from the list cache.
615 | *
616 | * @private
617 | * @name delete
618 | * @memberOf ListCache
619 | * @param {string} key The key of the value to remove.
620 | * @returns {boolean} Returns `true` if the entry was removed, else `false`.
621 | */
622 | function listCacheDelete(key) {
623 | var data = this.__data__,
624 | index = assocIndexOf(data, key);
625 |
626 | if (index < 0) {
627 | return false;
628 | }
629 | var lastIndex = data.length - 1;
630 | if (index == lastIndex) {
631 | data.pop();
632 | } else {
633 | splice.call(data, index, 1);
634 | }
635 | return true;
636 | }
637 |
638 | /**
639 | * Gets the list cache value for `key`.
640 | *
641 | * @private
642 | * @name get
643 | * @memberOf ListCache
644 | * @param {string} key The key of the value to get.
645 | * @returns {*} Returns the entry value.
646 | */
647 | function listCacheGet(key) {
648 | var data = this.__data__,
649 | index = assocIndexOf(data, key);
650 |
651 | return index < 0 ? undefined : data[index][1];
652 | }
653 |
654 | /**
655 | * Checks if a list cache value for `key` exists.
656 | *
657 | * @private
658 | * @name has
659 | * @memberOf ListCache
660 | * @param {string} key The key of the entry to check.
661 | * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
662 | */
663 | function listCacheHas(key) {
664 | return assocIndexOf(this.__data__, key) > -1;
665 | }
666 |
667 | /**
668 | * Sets the list cache `key` to `value`.
669 | *
670 | * @private
671 | * @name set
672 | * @memberOf ListCache
673 | * @param {string} key The key of the value to set.
674 | * @param {*} value The value to set.
675 | * @returns {Object} Returns the list cache instance.
676 | */
677 | function listCacheSet(key, value) {
678 | var data = this.__data__,
679 | index = assocIndexOf(data, key);
680 |
681 | if (index < 0) {
682 | data.push([key, value]);
683 | } else {
684 | data[index][1] = value;
685 | }
686 | return this;
687 | }
688 |
689 | // Add methods to `ListCache`.
690 | ListCache.prototype.clear = listCacheClear;
691 | ListCache.prototype['delete'] = listCacheDelete;
692 | ListCache.prototype.get = listCacheGet;
693 | ListCache.prototype.has = listCacheHas;
694 | ListCache.prototype.set = listCacheSet;
695 |
696 | /**
697 | * Creates a map cache object to store key-value pairs.
698 | *
699 | * @private
700 | * @constructor
701 | * @param {Array} [entries] The key-value pairs to cache.
702 | */
703 | function MapCache(entries) {
704 | var index = -1,
705 | length = entries ? entries.length : 0;
706 |
707 | this.clear();
708 | while (++index < length) {
709 | var entry = entries[index];
710 | this.set(entry[0], entry[1]);
711 | }
712 | }
713 |
714 | /**
715 | * Removes all key-value entries from the map.
716 | *
717 | * @private
718 | * @name clear
719 | * @memberOf MapCache
720 | */
721 | function mapCacheClear() {
722 | this.__data__ = {
723 | 'hash': new Hash,
724 | 'map': new (Map || ListCache),
725 | 'string': new Hash
726 | };
727 | }
728 |
729 | /**
730 | * Removes `key` and its value from the map.
731 | *
732 | * @private
733 | * @name delete
734 | * @memberOf MapCache
735 | * @param {string} key The key of the value to remove.
736 | * @returns {boolean} Returns `true` if the entry was removed, else `false`.
737 | */
738 | function mapCacheDelete(key) {
739 | return getMapData(this, key)['delete'](key);
740 | }
741 |
742 | /**
743 | * Gets the map value for `key`.
744 | *
745 | * @private
746 | * @name get
747 | * @memberOf MapCache
748 | * @param {string} key The key of the value to get.
749 | * @returns {*} Returns the entry value.
750 | */
751 | function mapCacheGet(key) {
752 | return getMapData(this, key).get(key);
753 | }
754 |
755 | /**
756 | * Checks if a map value for `key` exists.
757 | *
758 | * @private
759 | * @name has
760 | * @memberOf MapCache
761 | * @param {string} key The key of the entry to check.
762 | * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
763 | */
764 | function mapCacheHas(key) {
765 | return getMapData(this, key).has(key);
766 | }
767 |
768 | /**
769 | * Sets the map `key` to `value`.
770 | *
771 | * @private
772 | * @name set
773 | * @memberOf MapCache
774 | * @param {string} key The key of the value to set.
775 | * @param {*} value The value to set.
776 | * @returns {Object} Returns the map cache instance.
777 | */
778 | function mapCacheSet(key, value) {
779 | getMapData(this, key).set(key, value);
780 | return this;
781 | }
782 |
783 | // Add methods to `MapCache`.
784 | MapCache.prototype.clear = mapCacheClear;
785 | MapCache.prototype['delete'] = mapCacheDelete;
786 | MapCache.prototype.get = mapCacheGet;
787 | MapCache.prototype.has = mapCacheHas;
788 | MapCache.prototype.set = mapCacheSet;
789 |
790 | /**
791 | * Gets the index at which the `key` is found in `array` of key-value pairs.
792 | *
793 | * @private
794 | * @param {Array} array The array to inspect.
795 | * @param {*} key The key to search for.
796 | * @returns {number} Returns the index of the matched value, else `-1`.
797 | */
798 | function assocIndexOf(array, key) {
799 | var length = array.length;
800 | while (length--) {
801 | if (eq(array[length][0], key)) {
802 | return length;
803 | }
804 | }
805 | return -1;
806 | }
807 |
808 | /**
809 | * The base implementation of `_.get` without support for default values.
810 | *
811 | * @private
812 | * @param {Object} object The object to query.
813 | * @param {Array|string} path The path of the property to get.
814 | * @returns {*} Returns the resolved value.
815 | */
816 | function baseGet(object, path) {
817 | path = isKey(path, object) ? [path] : castPath(path);
818 |
819 | var index = 0,
820 | length = path.length;
821 |
822 | while (object != null && index < length) {
823 | object = object[toKey(path[index++])];
824 | }
825 | return (index && index == length) ? object : undefined;
826 | }
827 |
828 | /**
829 | * The base implementation of `_.isNative` without bad shim checks.
830 | *
831 | * @private
832 | * @param {*} value The value to check.
833 | * @returns {boolean} Returns `true` if `value` is a native function,
834 | * else `false`.
835 | */
836 | function baseIsNative(value) {
837 | if (!isObject(value) || isMasked(value)) {
838 | return false;
839 | }
840 | var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
841 | return pattern.test(toSource(value));
842 | }
843 |
844 | /**
845 | * The base implementation of `_.toString` which doesn't convert nullish
846 | * values to empty strings.
847 | *
848 | * @private
849 | * @param {*} value The value to process.
850 | * @returns {string} Returns the string.
851 | */
852 | function baseToString(value) {
853 | // Exit early for strings to avoid a performance hit in some environments.
854 | if (typeof value == 'string') {
855 | return value;
856 | }
857 | if (isSymbol(value)) {
858 | return symbolToString ? symbolToString.call(value) : '';
859 | }
860 | var result = (value + '');
861 | return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
862 | }
863 |
864 | /**
865 | * Casts `value` to a path array if it's not one.
866 | *
867 | * @private
868 | * @param {*} value The value to inspect.
869 | * @returns {Array} Returns the cast property path array.
870 | */
871 | function castPath(value) {
872 | return isArray(value) ? value : stringToPath(value);
873 | }
874 |
875 | /**
876 | * Gets the data for `map`.
877 | *
878 | * @private
879 | * @param {Object} map The map to query.
880 | * @param {string} key The reference key.
881 | * @returns {*} Returns the map data.
882 | */
883 | function getMapData(map, key) {
884 | var data = map.__data__;
885 | return isKeyable(key)
886 | ? data[typeof key == 'string' ? 'string' : 'hash']
887 | : data.map;
888 | }
889 |
890 | /**
891 | * Gets the native function at `key` of `object`.
892 | *
893 | * @private
894 | * @param {Object} object The object to query.
895 | * @param {string} key The key of the method to get.
896 | * @returns {*} Returns the function if it's native, else `undefined`.
897 | */
898 | function getNative(object, key) {
899 | var value = getValue(object, key);
900 | return baseIsNative(value) ? value : undefined;
901 | }
902 |
903 | /**
904 | * Checks if `value` is a property name and not a property path.
905 | *
906 | * @private
907 | * @param {*} value The value to check.
908 | * @param {Object} [object] The object to query keys on.
909 | * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
910 | */
911 | function isKey(value, object) {
912 | if (isArray(value)) {
913 | return false;
914 | }
915 | var type = typeof value;
916 | if (type == 'number' || type == 'symbol' || type == 'boolean' ||
917 | value == null || isSymbol(value)) {
918 | return true;
919 | }
920 | return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
921 | (object != null && value in Object(object));
922 | }
923 |
924 | /**
925 | * Checks if `value` is suitable for use as unique object key.
926 | *
927 | * @private
928 | * @param {*} value The value to check.
929 | * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
930 | */
931 | function isKeyable(value) {
932 | var type = typeof value;
933 | return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
934 | ? (value !== '__proto__')
935 | : (value === null);
936 | }
937 |
938 | /**
939 | * Checks if `func` has its source masked.
940 | *
941 | * @private
942 | * @param {Function} func The function to check.
943 | * @returns {boolean} Returns `true` if `func` is masked, else `false`.
944 | */
945 | function isMasked(func) {
946 | return !!maskSrcKey && (maskSrcKey in func);
947 | }
948 |
949 | /**
950 | * Converts `string` to a property path array.
951 | *
952 | * @private
953 | * @param {string} string The string to convert.
954 | * @returns {Array} Returns the property path array.
955 | */
956 | var stringToPath = memoize(function(string) {
957 | string = toString(string);
958 |
959 | var result = [];
960 | if (reLeadingDot.test(string)) {
961 | result.push('');
962 | }
963 | string.replace(rePropName, function(match, number, quote, string) {
964 | result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
965 | });
966 | return result;
967 | });
968 |
969 | /**
970 | * Converts `value` to a string key if it's not a string or symbol.
971 | *
972 | * @private
973 | * @param {*} value The value to inspect.
974 | * @returns {string|symbol} Returns the key.
975 | */
976 | function toKey(value) {
977 | if (typeof value == 'string' || isSymbol(value)) {
978 | return value;
979 | }
980 | var result = (value + '');
981 | return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
982 | }
983 |
984 | /**
985 | * Converts `func` to its source code.
986 | *
987 | * @private
988 | * @param {Function} func The function to process.
989 | * @returns {string} Returns the source code.
990 | */
991 | function toSource(func) {
992 | if (func != null) {
993 | try {
994 | return funcToString.call(func);
995 | } catch (e) {}
996 | try {
997 | return (func + '');
998 | } catch (e) {}
999 | }
1000 | return '';
1001 | }
1002 |
1003 | /**
1004 | * Creates a function that memoizes the result of `func`. If `resolver` is
1005 | * provided, it determines the cache key for storing the result based on the
1006 | * arguments provided to the memoized function. By default, the first argument
1007 | * provided to the memoized function is used as the map cache key. The `func`
1008 | * is invoked with the `this` binding of the memoized function.
1009 | *
1010 | * **Note:** The cache is exposed as the `cache` property on the memoized
1011 | * function. Its creation may be customized by replacing the `_.memoize.Cache`
1012 | * constructor with one whose instances implement the
1013 | * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
1014 | * method interface of `delete`, `get`, `has`, and `set`.
1015 | *
1016 | * @static
1017 | * @memberOf _
1018 | * @since 0.1.0
1019 | * @category Function
1020 | * @param {Function} func The function to have its output memoized.
1021 | * @param {Function} [resolver] The function to resolve the cache key.
1022 | * @returns {Function} Returns the new memoized function.
1023 | * @example
1024 | *
1025 | * var object = { 'a': 1, 'b': 2 };
1026 | * var other = { 'c': 3, 'd': 4 };
1027 | *
1028 | * var values = _.memoize(_.values);
1029 | * values(object);
1030 | * // => [1, 2]
1031 | *
1032 | * values(other);
1033 | * // => [3, 4]
1034 | *
1035 | * object.a = 2;
1036 | * values(object);
1037 | * // => [1, 2]
1038 | *
1039 | * // Modify the result cache.
1040 | * values.cache.set(object, ['a', 'b']);
1041 | * values(object);
1042 | * // => ['a', 'b']
1043 | *
1044 | * // Replace `_.memoize.Cache`.
1045 | * _.memoize.Cache = WeakMap;
1046 | */
1047 | function memoize(func, resolver) {
1048 | if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
1049 | throw new TypeError(FUNC_ERROR_TEXT);
1050 | }
1051 | var memoized = function() {
1052 | var args = arguments,
1053 | key = resolver ? resolver.apply(this, args) : args[0],
1054 | cache = memoized.cache;
1055 |
1056 | if (cache.has(key)) {
1057 | return cache.get(key);
1058 | }
1059 | var result = func.apply(this, args);
1060 | memoized.cache = cache.set(key, result);
1061 | return result;
1062 | };
1063 | memoized.cache = new (memoize.Cache || MapCache);
1064 | return memoized;
1065 | }
1066 |
1067 | // Assign cache to `_.memoize`.
1068 | memoize.Cache = MapCache;
1069 |
1070 | /**
1071 | * Performs a
1072 | * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
1073 | * comparison between two values to determine if they are equivalent.
1074 | *
1075 | * @static
1076 | * @memberOf _
1077 | * @since 4.0.0
1078 | * @category Lang
1079 | * @param {*} value The value to compare.
1080 | * @param {*} other The other value to compare.
1081 | * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
1082 | * @example
1083 | *
1084 | * var object = { 'a': 1 };
1085 | * var other = { 'a': 1 };
1086 | *
1087 | * _.eq(object, object);
1088 | * // => true
1089 | *
1090 | * _.eq(object, other);
1091 | * // => false
1092 | *
1093 | * _.eq('a', 'a');
1094 | * // => true
1095 | *
1096 | * _.eq('a', Object('a'));
1097 | * // => false
1098 | *
1099 | * _.eq(NaN, NaN);
1100 | * // => true
1101 | */
1102 | function eq(value, other) {
1103 | return value === other || (value !== value && other !== other);
1104 | }
1105 |
1106 | /**
1107 | * Checks if `value` is classified as an `Array` object.
1108 | *
1109 | * @static
1110 | * @memberOf _
1111 | * @since 0.1.0
1112 | * @category Lang
1113 | * @param {*} value The value to check.
1114 | * @returns {boolean} Returns `true` if `value` is an array, else `false`.
1115 | * @example
1116 | *
1117 | * _.isArray([1, 2, 3]);
1118 | * // => true
1119 | *
1120 | * _.isArray(document.body.children);
1121 | * // => false
1122 | *
1123 | * _.isArray('abc');
1124 | * // => false
1125 | *
1126 | * _.isArray(_.noop);
1127 | * // => false
1128 | */
1129 | var isArray = Array.isArray;
1130 |
1131 | /**
1132 | * Checks if `value` is classified as a `Function` object.
1133 | *
1134 | * @static
1135 | * @memberOf _
1136 | * @since 0.1.0
1137 | * @category Lang
1138 | * @param {*} value The value to check.
1139 | * @returns {boolean} Returns `true` if `value` is a function, else `false`.
1140 | * @example
1141 | *
1142 | * _.isFunction(_);
1143 | * // => true
1144 | *
1145 | * _.isFunction(/abc/);
1146 | * // => false
1147 | */
1148 | function isFunction(value) {
1149 | // The use of `Object#toString` avoids issues with the `typeof` operator
1150 | // in Safari 8-9 which returns 'object' for typed array and other constructors.
1151 | var tag = isObject(value) ? objectToString.call(value) : '';
1152 | return tag == funcTag || tag == genTag;
1153 | }
1154 |
1155 | /**
1156 | * Checks if `value` is the
1157 | * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
1158 | * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
1159 | *
1160 | * @static
1161 | * @memberOf _
1162 | * @since 0.1.0
1163 | * @category Lang
1164 | * @param {*} value The value to check.
1165 | * @returns {boolean} Returns `true` if `value` is an object, else `false`.
1166 | * @example
1167 | *
1168 | * _.isObject({});
1169 | * // => true
1170 | *
1171 | * _.isObject([1, 2, 3]);
1172 | * // => true
1173 | *
1174 | * _.isObject(_.noop);
1175 | * // => true
1176 | *
1177 | * _.isObject(null);
1178 | * // => false
1179 | */
1180 | function isObject(value) {
1181 | var type = typeof value;
1182 | return !!value && (type == 'object' || type == 'function');
1183 | }
1184 |
1185 | /**
1186 | * Checks if `value` is object-like. A value is object-like if it's not `null`
1187 | * and has a `typeof` result of "object".
1188 | *
1189 | * @static
1190 | * @memberOf _
1191 | * @since 4.0.0
1192 | * @category Lang
1193 | * @param {*} value The value to check.
1194 | * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
1195 | * @example
1196 | *
1197 | * _.isObjectLike({});
1198 | * // => true
1199 | *
1200 | * _.isObjectLike([1, 2, 3]);
1201 | * // => true
1202 | *
1203 | * _.isObjectLike(_.noop);
1204 | * // => false
1205 | *
1206 | * _.isObjectLike(null);
1207 | * // => false
1208 | */
1209 | function isObjectLike(value) {
1210 | return !!value && typeof value == 'object';
1211 | }
1212 |
1213 | /**
1214 | * Checks if `value` is classified as a `Symbol` primitive or object.
1215 | *
1216 | * @static
1217 | * @memberOf _
1218 | * @since 4.0.0
1219 | * @category Lang
1220 | * @param {*} value The value to check.
1221 | * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
1222 | * @example
1223 | *
1224 | * _.isSymbol(Symbol.iterator);
1225 | * // => true
1226 | *
1227 | * _.isSymbol('abc');
1228 | * // => false
1229 | */
1230 | function isSymbol(value) {
1231 | return typeof value == 'symbol' ||
1232 | (isObjectLike(value) && objectToString.call(value) == symbolTag);
1233 | }
1234 |
1235 | /**
1236 | * Converts `value` to a string. An empty string is returned for `null`
1237 | * and `undefined` values. The sign of `-0` is preserved.
1238 | *
1239 | * @static
1240 | * @memberOf _
1241 | * @since 4.0.0
1242 | * @category Lang
1243 | * @param {*} value The value to process.
1244 | * @returns {string} Returns the string.
1245 | * @example
1246 | *
1247 | * _.toString(null);
1248 | * // => ''
1249 | *
1250 | * _.toString(-0);
1251 | * // => '-0'
1252 | *
1253 | * _.toString([1, 2, 3]);
1254 | * // => '1,2,3'
1255 | */
1256 | function toString(value) {
1257 | return value == null ? '' : baseToString(value);
1258 | }
1259 |
1260 | /**
1261 | * Gets the value at `path` of `object`. If the resolved value is
1262 | * `undefined`, the `defaultValue` is returned in its place.
1263 | *
1264 | * @static
1265 | * @memberOf _
1266 | * @since 3.7.0
1267 | * @category Object
1268 | * @param {Object} object The object to query.
1269 | * @param {Array|string} path The path of the property to get.
1270 | * @param {*} [defaultValue] The value returned for `undefined` resolved values.
1271 | * @returns {*} Returns the resolved value.
1272 | * @example
1273 | *
1274 | * var object = { 'a': [{ 'b': { 'c': 3 } }] };
1275 | *
1276 | * _.get(object, 'a[0].b.c');
1277 | * // => 3
1278 | *
1279 | * _.get(object, ['a', '0', 'b', 'c']);
1280 | * // => 3
1281 | *
1282 | * _.get(object, 'a.b.c', 'default');
1283 | * // => 'default'
1284 | */
1285 | function get(object, path, defaultValue) {
1286 | var result = object == null ? undefined : baseGet(object, path);
1287 | return result === undefined ? defaultValue : result;
1288 | }
1289 |
1290 | module.exports = get;
1291 |
1292 |
1293 | /***/ })
1294 |
1295 | /******/ });
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const { inspect } = require("util");
2 |
3 | const get = require("lodash.get");
4 | const core = require("@actions/core");
5 |
6 | const { json, ...paths } = getAllInputs();
7 | const jsonParsed = JSON.parse(json);
8 |
9 | try {
10 | core.debug(`json input: ${inspect(jsonParsed)}`);
11 | core.debug(`paths inputs: ${inspect(paths)}`);
12 |
13 | for (const [name, path] of Object.entries(paths)) {
14 | const value = get(jsonParsed, path);
15 | core.debug(`setting output ${name} to ${value} using "${path}"`);
16 | core.setOutput(name, value);
17 | }
18 | } catch (error) {
19 | core.setFailed(error);
20 | process.exit(1);
21 | }
22 |
23 | function getAllInputs() {
24 | return Object.entries(process.env).reduce((result, [key, value]) => {
25 | if (!/^INPUT_/.test(key)) return result;
26 |
27 | const inputName = key.substr("INPUT_".length).toLowerCase();
28 | result[inputName] = value;
29 | return result;
30 | }, {});
31 | }
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "get-json-paths-action",
3 | "private": true,
4 | "version": "0.0.0-development",
5 | "description": "A GitHub Action to access deep values of a JSON output",
6 | "main": "dist/index.js",
7 | "scripts": {
8 | "build": "ncc build index.js -o dist"
9 | },
10 | "repository": "https://github.com/gr2m/get-json-paths-action",
11 | "keywords": [
12 | "github-action"
13 | ],
14 | "author": "Gregor Martynus (https://twitter.com/gr2m)",
15 | "license": "MIT",
16 | "dependencies": {
17 | "@actions/core": "^1.1.3",
18 | "lodash.get": "^4.4.2"
19 | },
20 | "devDependencies": {
21 | "@semantic-release/git": "^9.0.0",
22 | "@zeit/ncc": "^0.22.0",
23 | "semantic-release": "^17.0.0"
24 | },
25 | "release": {
26 | "plugins": [
27 | "@semantic-release/commit-analyzer",
28 | "@semantic-release/release-notes-generator",
29 | [
30 | "@semantic-release/git",
31 | {
32 | "assets": [
33 | "dist/index.js"
34 | ],
35 | "message": "build(release): compiled action for ${nextRelease.version}\n\n[skip ci]"
36 | }
37 | ],
38 | "@semantic-release/github"
39 | ]
40 | }
41 | }
42 |
--------------------------------------------------------------------------------