release-it 19.0.3 → 19.0.5

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.
package/README.md CHANGED
@@ -146,26 +146,32 @@ remote.
146
146
 
147
147
  → See [Git][29] for more details.
148
148
 
149
+ ## npmjs.com Releases
150
+
151
+ As of July 2025, GitHub and GitLab CI workflows can now use npm's [Trusted Publishing][30] OpenID Connect (OIDC)
152
+ integration for secure, token-free publishing from CI/CD. This eliminates long-lived tokens and automatically generates
153
+ provenance attestations. See [docs/npm.md][31] for details.
154
+
149
155
  ## GitHub Releases
150
156
 
151
157
  GitHub projects can have releases attached to Git tags, containing release notes and assets. There are two ways to add
152
- [GitHub releases][30] in your release-it flow:
158
+ [GitHub releases][32] in your release-it flow:
153
159
 
154
160
  1. Automated (requires a `GITHUB_TOKEN`)
155
161
  2. Manual (using the GitHub web interface with pre-populated fields)
156
162
 
157
- → See [GitHub Releases][31] for more details.
163
+ → See [GitHub Releases][33] for more details.
158
164
 
159
165
  ## GitLab Releases
160
166
 
161
167
  GitLab projects can have releases attached to Git tags, containing release notes and assets. To automate [GitLab
162
- releases][32]:
168
+ releases][34]:
163
169
 
164
170
  - Configure `gitlab.release: true`
165
- - Obtain a [personal access token][33] (release-it needs the `api` and `self_rotate` scopes).
166
- - Make sure the token is [available as an environment variable][34].
171
+ - Obtain a [personal access token][35] (release-it needs the `api` and `self_rotate` scopes).
172
+ - Make sure the token is [available as an environment variable][36].
167
173
 
168
- → See [GitLab Releases][35] for more details.
174
+ → See [GitLab Releases][37] for more details.
169
175
 
170
176
  ## Changelog
171
177
 
@@ -185,7 +191,7 @@ message conventions. Plugins are available for:
185
191
 
186
192
  To print the changelog without releasing anything, add the `--changelog` flag.
187
193
 
188
- → See [Changelog][36] for more details.
194
+ → See [Changelog][38] for more details.
189
195
 
190
196
  ## Publish to npm
191
197
 
@@ -200,7 +206,7 @@ With release-it, it's easy to create pre-releases: a version of your software th
200
206
  it's not in the stable semver range yet. Often "alpha", "beta", and "rc" (release candidate) are used as identifiers for
201
207
  pre-releases. An example pre-release version is `2.0.0-beta.0`.
202
208
 
203
- → See [Manage pre-releases][37] for more details.
209
+ → See [Manage pre-releases][39] for more details.
204
210
 
205
211
  ## Update or re-run existing releases
206
212
 
@@ -230,7 +236,7 @@ Use the optional `:plugin` part in the middle to hook into a life cycle method e
230
236
  The core plugins include `version`, `git`, `npm`, `github`, `gitlab`.
231
237
 
232
238
  Note that hooks like `after:git:release` will not run when either the `git push` failed, or when it is configured not to
233
- be executed (e.g. `git.push: false`). See [execution order][38] for more details on execution order of plugin lifecycle
239
+ be executed (e.g. `git.push: false`). See [execution order][40] for more details on execution order of plugin lifecycle
234
240
  methods.
235
241
 
236
242
  All commands can use configuration variables (like template strings). An array of commands can also be provided, they
@@ -280,7 +286,7 @@ Using Inquirer.js inside custom hook scripts might cause issues (since release-i
280
286
 
281
287
  Use `--dry-run` to show the interactivity and the commands it _would_ execute.
282
288
 
283
- → See [Dry Runs][39] for more details.
289
+ → See [Dry Runs][41] for more details.
284
290
 
285
291
  ## Troubleshooting & debugging
286
292
 
@@ -298,51 +304,51 @@ Since v11, release-it can be extended in many, many ways. Here are some plugins:
298
304
  | ----------------------------------------- | ------------------------------------------------------------------------------------------- |
299
305
  | [@release-it/bumper][26] | Read & write the version from/to any file |
300
306
  | [@release-it/conventional-changelog][27] | Provides recommended bump, conventional-changelog, and updates `CHANGELOG.md` |
301
- | [@release-it/keep-a-changelog][40] | Maintain CHANGELOG.md using the Keep a Changelog standards |
302
- | [@release-it-plugins/lerna-changelog][41] | Integrates lerna-changelog into the release-it pipeline |
303
- | [@jcamp-code/release-it-changelogen][42] | Use [@unjs/changelogen][43] for versioning and changelog |
304
- | [@release-it-plugins/workspaces][44] | Releases each of your projects configured workspaces |
307
+ | [@release-it/keep-a-changelog][42] | Maintain CHANGELOG.md using the Keep a Changelog standards |
308
+ | [@release-it-plugins/lerna-changelog][43] | Integrates lerna-changelog into the release-it pipeline |
309
+ | [@jcamp-code/release-it-changelogen][44] | Use [@unjs/changelogen][45] for versioning and changelog |
310
+ | [@release-it-plugins/workspaces][46] | Releases each of your projects configured workspaces |
305
311
  | [release-it-calver-plugin][28] | Enables Calendar Versioning (calver) with release-it |
306
- | [@grupoboticario/news-fragments][45] | An easy way to generate your changelog file |
307
- | [@j-ulrich/release-it-regex-bumper][46] | Regular expression based version read/write plugin for release-it |
308
- | [@jcamp-code/release-it-dotnet][47] | Use .csproj or .props file for versioning, automate NuGet publishing |
309
- | [release-it-pnpm][16] | Add basic support for pnpm workspaces, integrates with [bumpp][48] and [changelogithub][49] |
310
- | [changesets-release-it-plugin][50] | Combine [Changesets][51] changelog management with release-it |
312
+ | [@grupoboticario/news-fragments][47] | An easy way to generate your changelog file |
313
+ | [@j-ulrich/release-it-regex-bumper][48] | Regular expression based version read/write plugin for release-it |
314
+ | [@jcamp-code/release-it-dotnet][49] | Use .csproj or .props file for versioning, automate NuGet publishing |
315
+ | [release-it-pnpm][16] | Add basic support for pnpm workspaces, integrates with [bumpp][50] and [changelogithub][51] |
316
+ | [changesets-release-it-plugin][52] | Combine [Changesets][53] changelog management with release-it |
317
+ | [release-it-gitea][54] | Gitea plugin to create Gitea releases and upload attachments |
311
318
 
312
319
  Internally, release-it uses its own plugin architecture (for Git, GitHub, GitLab, npm).
313
320
 
314
- → See all [release-it plugins on npm][52].
321
+ → See all [release-it plugins on npm][55].
315
322
 
316
- → See [plugins][53] for documentation to write plugins.
323
+ → See [plugins][56] for documentation to write plugins.
317
324
 
318
325
  ## Use release-it programmatically
319
326
 
320
327
  While mostly used as a CLI tool, release-it can be used as a dependency to integrate in your own scripts. See [use
321
- release-it programmatically][54] for example code.
328
+ release-it programmatically][57] for example code.
322
329
 
323
330
  ## Projects using release-it
324
331
 
325
- - [AdonisJs][55]
326
- - [Axios][56]
327
- - [Cal.com][57]
328
- - [Ember CLI][58]
329
- - [Halo][59]
330
- - [hosts][60]
331
- - [js-cookie][61]
332
- - [jQuery][62]
333
- - [Madge][63]
334
- - [Metalsmith][64]
335
- - [Node-Redis][65]
336
- - [React Native Paper][66]
337
- - [Readability.js][67]
338
- - [Redux][68]
339
- - [Saleor][69]
340
- - [Semantic UI React][70]
341
- - [Shepherd][71]
342
- - [Tabler][72] + [tabler-icons][73]
343
- - Swagger ([swagger-ui][74] + [swagger-editor][75])
344
- - [Repositories that depend on release-it][76]
345
- - GitHub search for [path:\*\*/.release-it.json][77]
332
+ - [AdonisJs][58]
333
+ - [Axios][59]
334
+ - [Chakra UI][60]
335
+ - [Halo][61]
336
+ - [hosts][62]
337
+ - [js-cookie][63]
338
+ - [jQuery][64]
339
+ - [Madge][65]
340
+ - [Metalsmith][66]
341
+ - [n8n][67]
342
+ - [Node-Redis][68]
343
+ - [React Native Paper][69]
344
+ - [Readability.js][70]
345
+ - [Redux][71]
346
+ - [Saleor][72]
347
+ - [Semantic UI React][73]
348
+ - [tabler-icons][74]
349
+ - Swagger ([swagger-ui][75] + [swagger-editor][76])
350
+ - [Repositories that depend on release-it][77]
351
+ - GitHub search for [path:\*\*/.release-it.json][78]
346
352
 
347
353
  ## Node.js version support
348
354
 
@@ -356,17 +362,17 @@ The latest major version is v19, supporting Node.js 20 and up:
356
362
  | v16 | v16 |
357
363
  | v15 | v14 |
358
364
 
359
- Also see [CHANGELOG.md][78] for dates and details.
365
+ Also see [CHANGELOG.md][79] for dates and details.
360
366
 
361
367
  ## Links
362
368
 
363
- - See [CHANGELOG.md][78] for major/breaking updates, and [releases][79] for a detailed version history.
364
- - To **contribute**, please read [CONTRIBUTING.md][80] first.
365
- - Please [open an issue][81] if anything is missing or unclear in this documentation.
369
+ - See [CHANGELOG.md][79] for major/breaking updates, and [releases][80] for a detailed version history.
370
+ - To **contribute**, please read [CONTRIBUTING.md][81] first.
371
+ - Please [open an issue][82] if anything is missing or unclear in this documentation.
366
372
 
367
373
  ## License
368
374
 
369
- [MIT][82]
375
+ [MIT][83]
370
376
 
371
377
  Are you using release-it at work? Please consider [sponsoring me][14]!
372
378
 
@@ -399,56 +405,57 @@ Are you using release-it at work? Please consider [sponsoring me][14]!
399
405
  [27]: https://github.com/release-it/conventional-changelog
400
406
  [28]: https://github.com/casmith/release-it-calver-plugin
401
407
  [29]: ./docs/git.md
402
- [30]: https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases
403
- [31]: ./docs/github-releases.md
404
- [32]: https://docs.gitlab.com/api/releases/
405
- [33]: https://gitlab.com/profile/personal_access_tokens
406
- [34]: ./docs/environment-variables.md
407
- [35]: ./docs/gitlab-releases.md
408
- [36]: ./docs/changelog.md
409
- [37]: ./docs/pre-releases.md
410
- [38]: ./docs/plugins.md#execution-order
411
- [39]: ./docs/dry-runs.md
412
- [40]: https://github.com/release-it/keep-a-changelog
413
- [41]: https://github.com/release-it-plugins/lerna-changelog
414
- [42]: https://github.com/jcamp-code/release-it-changelogen
415
- [43]: https://github.com/unjs/changelogen
416
- [44]: https://github.com/release-it-plugins/workspaces
417
- [45]: https://github.com/grupoboticario/news-fragments
418
- [46]: https://github.com/j-ulrich/release-it-regex-bumper
419
- [47]: https://github.com/jcamp-code/release-it-dotnet
420
- [48]: https://github.com/antfu/bumpp
421
- [49]: https://github.com/antfu/changelogithub
422
- [50]: https://www.npmjs.com/package/changesets-release-it-plugin
423
- [51]: https://github.com/changesets/changesets
424
- [52]: https://www.npmjs.com/search?q=keywords:release-it-plugin
425
- [53]: ./docs/plugins.md
426
- [54]: ./docs/recipes/programmatic.md
427
- [55]: https://github.com/adonisjs/core
428
- [56]: https://github.com/axios/axios
429
- [57]: https://github.com/calcom/cal.com
430
- [58]: https://github.com/ember-cli/ember-cli
431
- [59]: https://github.com/halo-dev/halo
432
- [60]: https://github.com/StevenBlack/hosts
433
- [61]: https://github.com/js-cookie/js-cookie
434
- [62]: https://github.com/jquery/jquery
435
- [63]: https://github.com/pahen/madge
436
- [64]: https://github.com/metalsmith/metalsmith
437
- [65]: https://github.com/redis/node-redis
438
- [66]: https://github.com/callstack/react-native-paper
439
- [67]: https://github.com/mozilla/readability
440
- [68]: https://github.com/reduxjs/redux
441
- [69]: https://github.com/saleor/saleor
442
- [70]: https://github.com/Semantic-Org/Semantic-UI-React
443
- [71]: https://github.com/shipshapecode/shepherd
444
- [72]: https://github.com/tabler/tabler
445
- [73]: https://github.com/tabler/tabler-icons
446
- [74]: https://github.com/swagger-api/swagger-ui
447
- [75]: https://github.com/swagger-api/swagger-editor
448
- [76]: https://github.com/release-it/release-it/network/dependents
449
- [77]: https://github.com/search?q=path%3A**%2F.release-it.json&type=code
450
- [78]: ./CHANGELOG.md
451
- [79]: https://github.com/release-it/release-it/releases
452
- [80]: ./.github/CONTRIBUTING.md
453
- [81]: https://github.com/release-it/release-it/issues/new
454
- [82]: ./LICENSE
408
+ [30]: https://docs.npmjs.com/trusted-publishers
409
+ [31]: ./docs/npm.md#trusted-publishing-oidc
410
+ [32]: https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases
411
+ [33]: ./docs/github-releases.md
412
+ [34]: https://docs.gitlab.com/api/releases/
413
+ [35]: https://gitlab.com/profile/personal_access_tokens
414
+ [36]: ./docs/environment-variables.md
415
+ [37]: ./docs/gitlab-releases.md
416
+ [38]: ./docs/changelog.md
417
+ [39]: ./docs/pre-releases.md
418
+ [40]: ./docs/plugins.md#execution-order
419
+ [41]: ./docs/dry-runs.md
420
+ [42]: https://github.com/release-it/keep-a-changelog
421
+ [43]: https://github.com/release-it-plugins/lerna-changelog
422
+ [44]: https://github.com/jcamp-code/release-it-changelogen
423
+ [45]: https://github.com/unjs/changelogen
424
+ [46]: https://github.com/release-it-plugins/workspaces
425
+ [47]: https://github.com/grupoboticario/news-fragments
426
+ [48]: https://github.com/j-ulrich/release-it-regex-bumper
427
+ [49]: https://github.com/jcamp-code/release-it-dotnet
428
+ [50]: https://github.com/antfu/bumpp
429
+ [51]: https://github.com/antfu/changelogithub
430
+ [52]: https://www.npmjs.com/package/changesets-release-it-plugin
431
+ [53]: https://github.com/changesets/changesets
432
+ [54]: https://github.com/lib-pack/release-it-gitea
433
+ [55]: https://www.npmjs.com/search?q=keywords:release-it-plugin
434
+ [56]: ./docs/plugins.md
435
+ [57]: ./docs/recipes/programmatic.md
436
+ [58]: https://github.com/adonisjs/core
437
+ [59]: https://github.com/axios/axios
438
+ [60]: https://github.com/chakra-ui/chakra-ui
439
+ [61]: https://github.com/halo-dev/halo
440
+ [62]: https://github.com/StevenBlack/hosts
441
+ [63]: https://github.com/js-cookie/js-cookie
442
+ [64]: https://github.com/jquery/jquery
443
+ [65]: https://github.com/pahen/madge
444
+ [66]: https://github.com/metalsmith/metalsmith
445
+ [67]: https://github.com/n8n-io/n8n
446
+ [68]: https://github.com/redis/node-redis
447
+ [69]: https://github.com/callstack/react-native-paper
448
+ [70]: https://github.com/mozilla/readability
449
+ [71]: https://github.com/reduxjs/redux
450
+ [72]: https://github.com/saleor/saleor
451
+ [73]: https://github.com/Semantic-Org/Semantic-UI-React
452
+ [74]: https://github.com/tabler/tabler-icons
453
+ [75]: https://github.com/swagger-api/swagger-ui
454
+ [76]: https://github.com/swagger-api/swagger-editor
455
+ [77]: https://github.com/release-it/release-it/network/dependents
456
+ [78]: https://github.com/search?q=path%3A**%2F.release-it.json&type=code
457
+ [79]: ./CHANGELOG.md
458
+ [80]: https://github.com/release-it/release-it/releases
459
+ [81]: ./.github/CONTRIBUTING.md
460
+ [82]: https://github.com/release-it/release-it/issues/new
461
+ [83]: ./LICENSE
package/lib/config.js CHANGED
@@ -4,9 +4,8 @@ import { isCI } from 'ci-info';
4
4
  import defaultsDeep from '@nodeutils/defaults-deep';
5
5
  import { isObjectStrict } from '@phun-ky/typeof';
6
6
  import merge from 'lodash.merge';
7
- import get from 'lodash.get';
8
7
  import { loadConfig as loadC12 } from 'c12';
9
- import { getSystemInfo, readJSON } from './util.js';
8
+ import { get, getSystemInfo, readJSON } from './util.js';
10
9
 
11
10
  const debug = util.debug('release-it:config');
12
11
  const defaultConfig = readJSON(new URL('../config/release-it.json', import.meta.url));
@@ -1,6 +1,6 @@
1
1
  import { debug } from 'node:util';
2
2
  import merge from 'lodash.merge';
3
- import get from 'lodash.get';
3
+ import { get } from '../util.js';
4
4
 
5
5
  class Plugin {
6
6
  static isEnabled() {
@@ -178,7 +178,7 @@ class GitHub extends Release {
178
178
  baseUrl,
179
179
  auth: `token ${this.token}`,
180
180
  userAgent: `release-it/${pkg.version}`,
181
- log: this.config.isDebug ? console : null,
181
+ log: this.config.isDebug ? console : {},
182
182
  request: {
183
183
  timeout
184
184
  }
package/lib/util.js CHANGED
@@ -179,3 +179,28 @@ export const pick = (object, keys) => {
179
179
  return obj;
180
180
  }, {});
181
181
  };
182
+
183
+ const parsePath = path => {
184
+ const result = [];
185
+ const regex = /[^.[\]]+|\[(?:(\d+)|["'](.+?)["'])\]/g;
186
+ let match;
187
+
188
+ while ((match = regex.exec(path)) !== null) {
189
+ result.push(match[1] ?? match[2] ?? match[0]);
190
+ }
191
+
192
+ return result;
193
+ };
194
+
195
+ export const get = (obj, path, defaultValue = undefined) => {
196
+ if (!path || typeof path !== 'string') {
197
+ return defaultValue;
198
+ }
199
+
200
+ try {
201
+ const keys = parsePath(path);
202
+ return keys.reduce((acc, key) => acc?.[key], obj) ?? defaultValue;
203
+ } catch {
204
+ return defaultValue;
205
+ }
206
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-it",
3
- "version": "19.0.3",
3
+ "version": "19.0.5",
4
4
  "description": "Generic CLI tool to automate versioning and package publishing-related tasks.",
5
5
  "keywords": [
6
6
  "build",
@@ -79,48 +79,47 @@
79
79
  "license": "MIT",
80
80
  "dependencies": {
81
81
  "@nodeutils/defaults-deep": "1.1.0",
82
- "@octokit/rest": "21.1.1",
83
- "@phun-ky/typeof": "1.2.8",
82
+ "@octokit/rest": "22.0.0",
83
+ "@phun-ky/typeof": "2.0.3",
84
84
  "async-retry": "1.3.3",
85
- "c12": "3.0.4",
86
- "ci-info": "^4.2.0",
87
- "eta": "3.5.0",
85
+ "c12": "3.3.0",
86
+ "ci-info": "^4.3.0",
87
+ "eta": "4.0.1",
88
88
  "git-url-parse": "16.1.0",
89
- "inquirer": "12.6.3",
89
+ "inquirer": "12.9.6",
90
90
  "issue-parser": "7.0.1",
91
- "lodash.get": "4.4.2",
92
91
  "lodash.merge": "4.6.2",
93
92
  "mime-types": "3.0.1",
94
93
  "new-github-release-url": "2.0.0",
95
- "open": "10.1.2",
96
- "ora": "8.2.0",
94
+ "open": "10.2.0",
95
+ "ora": "9.0.0",
97
96
  "os-name": "6.1.0",
98
97
  "proxy-agent": "6.5.0",
99
98
  "semver": "7.7.2",
100
- "tinyglobby": "0.2.14",
101
- "undici": "6.21.2",
99
+ "tinyglobby": "0.2.15",
100
+ "undici": "6.21.3",
102
101
  "url-join": "5.0.0",
103
102
  "wildcard-match": "5.1.4",
104
103
  "yargs-parser": "21.1.1"
105
104
  },
106
105
  "devDependencies": {
107
- "@eslint/compat": "1.2.9",
106
+ "@eslint/compat": "1.3.2",
108
107
  "@eslint/eslintrc": "3.3.1",
109
- "@eslint/js": "9.27.0",
110
- "@octokit/request-error": "6.1.8",
111
- "@types/node": "20.17.32",
112
- "eslint": "9.27.0",
113
- "eslint-plugin-import-x": "4.13.3",
114
- "globals": "16.2.0",
108
+ "@eslint/js": "9.35.0",
109
+ "@octokit/request-error": "7.0.0",
110
+ "@types/node": "24.5.2",
111
+ "eslint": "9.35.0",
112
+ "eslint-plugin-import-x": "4.16.1",
113
+ "globals": "16.4.0",
115
114
  "installed-check": "9.3.0",
116
- "knip": "5.59.1",
115
+ "knip": "5.63.1",
117
116
  "mentoss": "0.11.0",
118
117
  "mock-stdio": "1.0.3",
119
- "prettier": "3.5.3",
118
+ "prettier": "3.6.2",
120
119
  "remark-cli": "12.0.1",
121
120
  "remark-preset-webpro": "1.1.1",
122
121
  "tar": "7.4.3",
123
- "typescript": "5.8.3"
122
+ "typescript": "5.9.2"
124
123
  },
125
124
  "overrides": {
126
125
  "pac-resolver": "7.0.1",
package/test/utils.js CHANGED
@@ -3,7 +3,7 @@ import test from 'node:test';
3
3
  import assert from 'node:assert/strict';
4
4
  import { stripVTControlCharacters } from 'node:util';
5
5
  import mockStdIo from 'mock-stdio';
6
- import { format, truncateLines, parseGitUrl, parseVersion } from '../lib/util.js';
6
+ import { format, truncateLines, parseGitUrl, parseVersion, get } from '../lib/util.js';
7
7
 
8
8
  test('format', () => {
9
9
  assert.equal(format('release v${version}', { version: '1.0.0' }), 'release v1.0.0');
@@ -96,3 +96,50 @@ test('parseVersion', () => {
96
96
  assert.deepEqual(parseVersion('1.0.0-next.1'), { version: '1.0.0-next.1', isPreRelease: true, preReleaseId: 'next' });
97
97
  assert.deepEqual(parseVersion('21.04.1'), { version: '21.04.1', isPreRelease: false, preReleaseId: null });
98
98
  });
99
+
100
+ const sample = {
101
+ root: {
102
+ level1: {
103
+ level2: {
104
+ value: 'nested'
105
+ },
106
+ array: [
107
+ { id: 1, data: 'first' },
108
+ { id: 2, data: 'second' }
109
+ ],
110
+ 'key.with.dot': {
111
+ special: true
112
+ }
113
+ },
114
+ mixed: [{ deep: { value: 100 } }, { deep: { value: 200 } }]
115
+ }
116
+ };
117
+
118
+ test('get: accesses a simple nested property', () => {
119
+ assert.equal(get(sample, 'root.level1.level2.value'), 'nested');
120
+ });
121
+
122
+ test('get: accesses array elements by index', () => {
123
+ assert.equal(get(sample, 'root.level1.array[0].data'), 'first');
124
+ assert.equal(get(sample, 'root.level1.array[1].id'), 2);
125
+ });
126
+
127
+ test('get: accesses keys with dots using bracket notation', () => {
128
+ assert.equal(get(sample, 'root.level1["key.with.dot"].special'), true);
129
+ });
130
+
131
+ test('get: navigates mixed objects and arrays', () => {
132
+ assert.equal(get(sample, 'root.mixed[0].deep.value'), 100);
133
+ assert.equal(get(sample, 'root.mixed[1].deep.value'), 200);
134
+ });
135
+
136
+ test('get: returns default value for non-existent properties', () => {
137
+ assert.equal(get(sample, 'root.level1.unknown', 'default'), 'default');
138
+ assert.equal(get(sample, 'root.level1.array[10].id', null), null);
139
+ });
140
+
141
+ test('get: handles empty path and null/undefined objects', () => {
142
+ assert.equal(get(sample, '', 'default'), 'default');
143
+ assert.equal(get(null, 'any.path', 'default'), 'default');
144
+ assert.equal(get(undefined, 'any.path', 'default'), 'default');
145
+ });