@langri-sha/projen-project 0.32.1 → 0.34.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.
- package/CHANGELOG.json +359 -1
- package/CHANGELOG.md +78 -2
- package/dist/index.d.ts +44 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +153 -31
- package/dist/index.js.map +1 -1
- package/package.json +25 -23
- package/project.d.ts +1 -1
- package/readme.md +65 -18
- package/src/index.ts +210 -49
package/src/index.ts
CHANGED
|
@@ -1,45 +1,6 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'
|
|
2
2
|
import * as path from 'node:path'
|
|
3
3
|
|
|
4
|
-
import { Babel, BabelOptions } from '@langri-sha/projen-babel'
|
|
5
|
-
import { Beachball, BeachballOptions } from '@langri-sha/projen-beachball'
|
|
6
|
-
import {
|
|
7
|
-
type CargoOptions,
|
|
8
|
-
CargoPackage,
|
|
9
|
-
CargoWorkspace,
|
|
10
|
-
} from '@langri-sha/projen-cargo'
|
|
11
|
-
import {
|
|
12
|
-
Codeowners,
|
|
13
|
-
type CodeownersOptions,
|
|
14
|
-
} from '@langri-sha/projen-codeowners'
|
|
15
|
-
import { Dagger, type DaggerOptions } from '@langri-sha/projen-dagger'
|
|
16
|
-
import {
|
|
17
|
-
EditorConfig,
|
|
18
|
-
type EditorConfigOptions,
|
|
19
|
-
} from '@langri-sha/projen-editorconfig'
|
|
20
|
-
import { ESLint, ESLintOptions } from '@langri-sha/projen-eslint'
|
|
21
|
-
import { Husky, type HuskyOptions } from '@langri-sha/projen-husky'
|
|
22
|
-
import { JestConfig, JestConfigOptions } from '@langri-sha/projen-jest-config'
|
|
23
|
-
import { License } from '@langri-sha/projen-license'
|
|
24
|
-
import { LintStaged, LintStagedOptions } from '@langri-sha/projen-lint-staged'
|
|
25
|
-
import {
|
|
26
|
-
LintSynthesized,
|
|
27
|
-
type LintSynthesizedOptions,
|
|
28
|
-
} from '@langri-sha/projen-lint-synthesized'
|
|
29
|
-
import {
|
|
30
|
-
PnpmWorkspace,
|
|
31
|
-
PnpmWorkspaceOptions,
|
|
32
|
-
} from '@langri-sha/projen-pnpm-workspace'
|
|
33
|
-
import { Prettier, PrettierOptions } from '@langri-sha/projen-prettier'
|
|
34
|
-
import { ReadmeFile, type ReadmeFileOptions } from '@langri-sha/projen-readme'
|
|
35
|
-
import { Renovate, type RenovateOptions } from '@langri-sha/projen-renovate'
|
|
36
|
-
import { SWCConfig, type SWCConfigOptions } from '@langri-sha/projen-swcrc'
|
|
37
|
-
import {
|
|
38
|
-
TypeScriptConfig,
|
|
39
|
-
type TypeScriptConfigOptions,
|
|
40
|
-
} from '@langri-sha/projen-typescript-config'
|
|
41
|
-
import { type UvOptions, UvPackage, UvWorkspace } from '@langri-sha/projen-uv'
|
|
42
|
-
import { Worktrunk, type WorktrunkOptions } from '@langri-sha/projen-worktrunk'
|
|
43
4
|
import {
|
|
44
5
|
Project as BaseProject,
|
|
45
6
|
type ProjectOptions as BaseProjectOptions,
|
|
@@ -49,13 +10,41 @@ import {
|
|
|
49
10
|
IgnoreFileOptions,
|
|
50
11
|
javascript,
|
|
51
12
|
} from 'projen'
|
|
13
|
+
import { Babel, BabelOptions } from 'projen-babel-config'
|
|
14
|
+
import { Beachball, BeachballOptions } from 'projen-beachball'
|
|
15
|
+
import { type CargoOptions, CargoPackage, CargoWorkspace } from 'projen-cargo'
|
|
16
|
+
import { Codeowners, type CodeownersOptions } from 'projen-codeowners'
|
|
17
|
+
import { Dagger, type DaggerOptions } from 'projen-dagger'
|
|
18
|
+
import { EditorConfig, type EditorConfigOptions } from 'projen-editorconfig'
|
|
19
|
+
import { ESLint, ESLintOptions } from 'projen-eslint'
|
|
20
|
+
import { Husky, type HuskyOptions } from 'projen-husky'
|
|
21
|
+
import { JestConfig, JestConfigOptions } from 'projen-jest-config'
|
|
22
|
+
import { License } from 'projen-license'
|
|
23
|
+
import { LintStaged, LintStagedOptions } from 'projen-lint-staged'
|
|
24
|
+
import {
|
|
25
|
+
LintSynthesized,
|
|
26
|
+
type LintSynthesizedOptions,
|
|
27
|
+
} from 'projen-lint-synthesized'
|
|
28
|
+
import { PnpmWorkspace, PnpmWorkspaceOptions } from 'projen-pnpm-workspace'
|
|
29
|
+
import { Prettier, PrettierOptions } from 'projen-prettier'
|
|
30
|
+
import { ReadmeFile, type ReadmeFileOptions } from 'projen-readme'
|
|
31
|
+
import { Renovate, type RenovateOptions } from 'projen-renovate'
|
|
32
|
+
import { Ruff, type RuffOptions } from 'projen-ruff'
|
|
33
|
+
import { SWCConfig, type SWCConfigOptions } from 'projen-swcrc'
|
|
34
|
+
import { type SupportedPythonVersion, Ty, type TyOptions } from 'projen-ty'
|
|
35
|
+
import {
|
|
36
|
+
TypeScriptConfig,
|
|
37
|
+
type TypeScriptConfigOptions,
|
|
38
|
+
} from 'projen-typescript-config'
|
|
39
|
+
import { type UvOptions, UvPackage, UvWorkspace } from 'projen-uv'
|
|
40
|
+
import { Worktrunk, type WorktrunkOptions, pipeline } from 'projen-worktrunk'
|
|
52
41
|
import * as R from 'ramda'
|
|
53
42
|
import { satisfies, valid } from 'semver'
|
|
54
43
|
|
|
55
44
|
import { GitAttributesFile } from './lib/gitattributes.js'
|
|
56
45
|
import { NodePackage, NodePackageOptions, ProjenrcFile } from './lib/index.js'
|
|
57
46
|
|
|
58
|
-
export * from '
|
|
47
|
+
export * from 'projen-typescript-config'
|
|
59
48
|
|
|
60
49
|
/**
|
|
61
50
|
* The package manager assumed when a project does not name one.
|
|
@@ -77,6 +66,38 @@ const PROJEN_COMMANDS: Record<javascript.NodePackageManager, string> = {
|
|
|
77
66
|
[javascript.NodePackageManager.YARN_CLASSIC]: 'yarn projen',
|
|
78
67
|
}
|
|
79
68
|
|
|
69
|
+
/**
|
|
70
|
+
* The name of the command that installs dependencies in a worktree hook, per
|
|
71
|
+
* package manager. The binary rather than the enum value, so that every yarn
|
|
72
|
+
* version is `yarn`.
|
|
73
|
+
*/
|
|
74
|
+
const PACKAGE_MANAGER_BINARIES: Record<javascript.NodePackageManager, string> =
|
|
75
|
+
{
|
|
76
|
+
[javascript.NodePackageManager.BUN]: 'bun',
|
|
77
|
+
[javascript.NodePackageManager.NPM]: 'npm',
|
|
78
|
+
[javascript.NodePackageManager.PNPM]: 'pnpm',
|
|
79
|
+
[javascript.NodePackageManager.YARN]: 'yarn',
|
|
80
|
+
[javascript.NodePackageManager.YARN2]: 'yarn',
|
|
81
|
+
[javascript.NodePackageManager.YARN_BERRY]: 'yarn',
|
|
82
|
+
[javascript.NodePackageManager.YARN_CLASSIC]: 'yarn',
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The `sync` command of the default `pre-start` pipeline. Worktrunk fails on
|
|
87
|
+
* undefined variables, and leaves `remote` undefined in a repository with no
|
|
88
|
+
* remote and `base` undefined for a worktree on an existing branch, so the
|
|
89
|
+
* command is skipped there. Worktrunk approves a command by its exact text, so
|
|
90
|
+
* editing it asks every teammate to approve it again.
|
|
91
|
+
*/
|
|
92
|
+
const WORKTRUNK_SYNC_COMMAND =
|
|
93
|
+
'{% if remote and base and base == default_branch %}git fetch {{ remote }} {{ default_branch }} && git merge --ff-only --quiet {{ remote }}/{{ default_branch }}{% endif %}'
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Copies each tracked `.env.example` to a `.env` that is missing.
|
|
97
|
+
*/
|
|
98
|
+
const WORKTRUNK_ENV_COMMAND =
|
|
99
|
+
'git ls-files -- ":(glob)**/.env.example" | while read -r example; do target=${example%.example}; [ -e "$target" ] || cp "$example" "$target"; done'
|
|
100
|
+
|
|
80
101
|
/**
|
|
81
102
|
* How long a release must have been published before Renovate proposes it.
|
|
82
103
|
*
|
|
@@ -204,11 +225,30 @@ export interface ProjectOptions extends Omit<
|
|
|
204
225
|
*/
|
|
205
226
|
renovate?: RenovateOptions
|
|
206
227
|
|
|
228
|
+
/**
|
|
229
|
+
* Pass in to configure Ruff. Root projects only: Ruff takes the nearest
|
|
230
|
+
* configuration, so one at the root covers the whole workspace.
|
|
231
|
+
*
|
|
232
|
+
* With `lintStaged`, staged Python files are fixed and formatted on commit,
|
|
233
|
+
* through `uv run --frozen` when `uv` is set, so ruff comes from `uv.lock`:
|
|
234
|
+
* declare it in the workspace's `dev` group, or `uv run` falls back to
|
|
235
|
+
* whatever ruff is on the `PATH`.
|
|
236
|
+
*/
|
|
237
|
+
ruff?: RuffOptions
|
|
238
|
+
|
|
207
239
|
/*
|
|
208
240
|
* Pass in to configure SWC.
|
|
209
241
|
*/
|
|
210
242
|
swcrc?: SWCConfigOptions
|
|
211
243
|
|
|
244
|
+
/**
|
|
245
|
+
* Pass in to configure ty. Root projects only, like `ruff`.
|
|
246
|
+
*
|
|
247
|
+
* With `uv.pythonVersion` set, `environment.python-version` follows it; set
|
|
248
|
+
* it to `null` to leave the version to ty.
|
|
249
|
+
*/
|
|
250
|
+
ty?: TyOptions
|
|
251
|
+
|
|
212
252
|
/**
|
|
213
253
|
* TypeScript configuration options.
|
|
214
254
|
*/
|
|
@@ -226,8 +266,8 @@ export interface ProjectOptions extends Omit<
|
|
|
226
266
|
withTerraform?: boolean
|
|
227
267
|
|
|
228
268
|
/**
|
|
229
|
-
* Configures Worktrunk, when provided.
|
|
230
|
-
*
|
|
269
|
+
* Configures Worktrunk, when provided. Supplies a default `pre-start`
|
|
270
|
+
* pipeline, which a `pre-start` in `config`, in any form, replaces whole.
|
|
231
271
|
*/
|
|
232
272
|
worktrunk?: WorktrunkOptions
|
|
233
273
|
}
|
|
@@ -252,7 +292,9 @@ export class Project extends BaseProject {
|
|
|
252
292
|
projenrc?: ProjenrcFile
|
|
253
293
|
readme?: ReadmeFile
|
|
254
294
|
renovate?: Renovate
|
|
295
|
+
ruff?: Ruff
|
|
255
296
|
swcrc?: SWCConfig
|
|
297
|
+
ty?: Ty
|
|
256
298
|
typeScriptConfig?: TypeScriptConfig
|
|
257
299
|
uv?: UvPackage | UvWorkspace
|
|
258
300
|
worktrunk?: Worktrunk
|
|
@@ -319,6 +361,8 @@ export class Project extends BaseProject {
|
|
|
319
361
|
this.#configureNpmIgnore(options)
|
|
320
362
|
this.#configurePnpmWorkspace(options)
|
|
321
363
|
this.#configureReadme(options)
|
|
364
|
+
this.#configureRuff(options)
|
|
365
|
+
this.#configureTy(options)
|
|
322
366
|
this.#configureUv(options)
|
|
323
367
|
this.#configureWorktrunk(options)
|
|
324
368
|
this.#configureRenovate(options)
|
|
@@ -599,6 +643,7 @@ export class Project extends BaseProject {
|
|
|
599
643
|
|
|
600
644
|
#configureEditorConfig({
|
|
601
645
|
editorConfig: editorConfigOptions,
|
|
646
|
+
uv,
|
|
602
647
|
}: ProjectOptions) {
|
|
603
648
|
if (!editorConfigOptions || this.parent) {
|
|
604
649
|
return
|
|
@@ -616,11 +661,19 @@ export class Project extends BaseProject {
|
|
|
616
661
|
Dockerfile: {
|
|
617
662
|
indent_style: 'tab',
|
|
618
663
|
},
|
|
664
|
+
// What ruff formats Python to. It ignores EditorConfig, so editors
|
|
665
|
+
// indenting at anything else are corrected on every format.
|
|
666
|
+
...(uv && {
|
|
667
|
+
'*.{py,pyi}': {
|
|
668
|
+
indent_style: 'space',
|
|
669
|
+
indent_size: 4,
|
|
670
|
+
},
|
|
671
|
+
}),
|
|
619
672
|
}
|
|
620
673
|
|
|
621
674
|
this.editorConfig = new EditorConfig(
|
|
622
675
|
this,
|
|
623
|
-
deepMerge(
|
|
676
|
+
deepMerge(defaults, editorConfigOptions),
|
|
624
677
|
)
|
|
625
678
|
|
|
626
679
|
this.prettier?.ignore.addPatterns('!.editorconfig')
|
|
@@ -704,7 +757,7 @@ export class Project extends BaseProject {
|
|
|
704
757
|
})
|
|
705
758
|
}
|
|
706
759
|
|
|
707
|
-
#configureLintStaged({ lintStaged, package: pkg }: ProjectOptions) {
|
|
760
|
+
#configureLintStaged({ lintStaged, package: pkg, ruff, uv }: ProjectOptions) {
|
|
708
761
|
if (!lintStaged) {
|
|
709
762
|
return
|
|
710
763
|
}
|
|
@@ -721,7 +774,34 @@ export class Project extends BaseProject {
|
|
|
721
774
|
this.#addDefaultDevDeps('lint-staged@17.6.0')
|
|
722
775
|
}
|
|
723
776
|
|
|
724
|
-
|
|
777
|
+
// ruff is configured at the root alone, but lint-staged runs the nearest
|
|
778
|
+
// configuration to each staged file, so a subproject's runs ruff as well.
|
|
779
|
+
const root = this.root instanceof Project ? this.root : undefined
|
|
780
|
+
const withRuff = this.parent ? root?.ruff : ruff
|
|
781
|
+
const withUv = uv ?? (this.parent ? root?.uv : undefined)
|
|
782
|
+
|
|
783
|
+
// ruff fixes before it formats, so that the formatter has the last word.
|
|
784
|
+
// lint-staged names the files, which ruff checks even where the project
|
|
785
|
+
// excludes them unless forced to exclude. Since 17.6 it also stages every
|
|
786
|
+
// file a task changes, so `uv run` must not re-lock the workspace.
|
|
787
|
+
const ruffCommand = withUv ? 'uv run --frozen ruff' : 'ruff'
|
|
788
|
+
const python = withRuff
|
|
789
|
+
? {
|
|
790
|
+
'*.{py,pyi}': [
|
|
791
|
+
`${ruffCommand} check --fix --force-exclude`,
|
|
792
|
+
`${ruffCommand} format --force-exclude`,
|
|
793
|
+
],
|
|
794
|
+
}
|
|
795
|
+
: {}
|
|
796
|
+
|
|
797
|
+
const { config, ...options } = deepMerge(defaults, lintStaged)
|
|
798
|
+
|
|
799
|
+
// Spread rather than merged, so that a project's own glob replaces these
|
|
800
|
+
// the way it replaces those of the configuration it extends.
|
|
801
|
+
this.lintStaged = new LintStaged(this, {
|
|
802
|
+
...options,
|
|
803
|
+
config: { ...python, ...config },
|
|
804
|
+
})
|
|
725
805
|
|
|
726
806
|
this.typeScriptConfig?.addFile(this.lintStaged!.path)
|
|
727
807
|
}
|
|
@@ -1085,6 +1165,26 @@ export class Project extends BaseProject {
|
|
|
1085
1165
|
},
|
|
1086
1166
|
]
|
|
1087
1167
|
: []),
|
|
1168
|
+
// `.python-version` is synthesized from the projenrc, so pyenv's update
|
|
1169
|
+
// to the file alone would be put back by the next synthesis. Read with
|
|
1170
|
+
// pyenv's depName, datasource and versioning, the declaration moves on
|
|
1171
|
+
// the same branch as the file. Held to the projenrc for the reason
|
|
1172
|
+
// spelled out under the `packageManager` manager, and because
|
|
1173
|
+
// `pythonVersion:` appears in this preset's tests and projen-uv's.
|
|
1174
|
+
...(uv?.pythonVersion
|
|
1175
|
+
? [
|
|
1176
|
+
{
|
|
1177
|
+
customType: 'regex' as const,
|
|
1178
|
+
datasourceTemplate: 'docker',
|
|
1179
|
+
depNameTemplate: 'python',
|
|
1180
|
+
versioningTemplate: 'docker',
|
|
1181
|
+
managerFilePatterns: [
|
|
1182
|
+
'/(^|/)\\.?projenrc\\.(js|cjs|mjs|ts|mts|cts)$/',
|
|
1183
|
+
],
|
|
1184
|
+
matchStrings: ["pythonVersion:\\s*'(?<currentValue>[^']+)'"],
|
|
1185
|
+
},
|
|
1186
|
+
]
|
|
1187
|
+
: []),
|
|
1088
1188
|
// The `packageManager` field is declared in a projenrc and only
|
|
1089
1189
|
// reaches the manifest through synthesis, so the npm manager reading
|
|
1090
1190
|
// the manifest cannot propose it. Both patterns are held to that one
|
|
@@ -1111,9 +1211,9 @@ export class Project extends BaseProject {
|
|
|
1111
1211
|
// `pnpm` offered pnpm's version for every other tool — and the version
|
|
1112
1212
|
// ends at the first space or quote.
|
|
1113
1213
|
//
|
|
1114
|
-
// Anchored to a projenrc for the reason the
|
|
1115
|
-
// pattern that merely contains `projen` reaches the sources of
|
|
1116
|
-
// package here, and this preset's own tests exercise this regex
|
|
1214
|
+
// Anchored to a projenrc for the reason the anchored managers above
|
|
1215
|
+
// are: a pattern that merely contains `projen` reaches the sources of
|
|
1216
|
+
// every package here, and this preset's own tests exercise this regex
|
|
1117
1217
|
// against a literal `pnpx name@version`. Renovate rewrote the fixture
|
|
1118
1218
|
// and left the assertion beside it, failing the suite over a package
|
|
1119
1219
|
// nothing depends on.
|
|
@@ -1140,6 +1240,14 @@ export class Project extends BaseProject {
|
|
|
1140
1240
|
this.renovate = new Renovate(this, deepMerge(defaults, renovateOptions))
|
|
1141
1241
|
}
|
|
1142
1242
|
|
|
1243
|
+
#configureRuff({ ruff }: ProjectOptions) {
|
|
1244
|
+
if (!ruff || this.parent) {
|
|
1245
|
+
return
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
this.ruff = new Ruff(this, ruff)
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1143
1251
|
#configureSWC({ swcrc, typeScriptConfig }: ProjectOptions) {
|
|
1144
1252
|
if (!swcrc) {
|
|
1145
1253
|
return
|
|
@@ -1170,6 +1278,29 @@ export class Project extends BaseProject {
|
|
|
1170
1278
|
this.swcrc = new SWCConfig(this, deepMerge(defaults, swcrc))
|
|
1171
1279
|
}
|
|
1172
1280
|
|
|
1281
|
+
#configureTy({ ty, uv }: ProjectOptions) {
|
|
1282
|
+
if (!ty || this.parent) {
|
|
1283
|
+
return
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
// ty takes `major.minor` alone, so a pinned patch release is cut back to
|
|
1287
|
+
// it and a pinned implementation is left to ty. The schema's type lists
|
|
1288
|
+
// only the versions ty knew when it was published; a newer one is ty's
|
|
1289
|
+
// to refuse.
|
|
1290
|
+
const pythonVersion = uv?.pythonVersion?.match(/^\d+\.\d+/)?.[0] as
|
|
1291
|
+
SupportedPythonVersion | undefined
|
|
1292
|
+
|
|
1293
|
+
const defaults: TyOptions = {
|
|
1294
|
+
...(pythonVersion && {
|
|
1295
|
+
environment: {
|
|
1296
|
+
'python-version': pythonVersion,
|
|
1297
|
+
},
|
|
1298
|
+
}),
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
this.ty = new Ty(this, deepMerge(defaults, ty))
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1173
1304
|
#configureTypeScript({ parent, typeScriptConfig }: ProjectOptions) {
|
|
1174
1305
|
if (!typeScriptConfig) {
|
|
1175
1306
|
return
|
|
@@ -1252,7 +1383,33 @@ export class Project extends BaseProject {
|
|
|
1252
1383
|
return
|
|
1253
1384
|
}
|
|
1254
1385
|
|
|
1255
|
-
|
|
1386
|
+
// Replaced whole per event, not deep-merged like the other defaults: the
|
|
1387
|
+
// three hook forms cannot be merged into one another.
|
|
1388
|
+
this.worktrunk = new Worktrunk(this, {
|
|
1389
|
+
...worktrunk,
|
|
1390
|
+
config: {
|
|
1391
|
+
...worktrunk.config,
|
|
1392
|
+
'pre-start': worktrunk.config?.['pre-start'] ?? this.#defaultPreStart(),
|
|
1393
|
+
},
|
|
1394
|
+
})
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
/**
|
|
1398
|
+
* The install commands are the components' own text, so an upgrade that
|
|
1399
|
+
* changes one asks every teammate to approve the hook again.
|
|
1400
|
+
*/
|
|
1401
|
+
#defaultPreStart() {
|
|
1402
|
+
const install = this.package && {
|
|
1403
|
+
[PACKAGE_MANAGER_BINARIES[this.package.packageManager]]:
|
|
1404
|
+
this.package.installCommand,
|
|
1405
|
+
}
|
|
1406
|
+
const cargo = this.cargo && { cargo: this.cargo.installCommand }
|
|
1407
|
+
const uv = this.uv && { uv: this.uv.installCommand }
|
|
1408
|
+
|
|
1409
|
+
return pipeline(
|
|
1410
|
+
{ sync: WORKTRUNK_SYNC_COMMAND },
|
|
1411
|
+
{ env: WORKTRUNK_ENV_COMMAND, ...install, ...cargo, ...uv },
|
|
1412
|
+
)
|
|
1256
1413
|
}
|
|
1257
1414
|
|
|
1258
1415
|
#populateTypeScriptProjectReferencesFromDependencies() {
|
|
@@ -1297,6 +1454,7 @@ const getGitIgnoreOptions = ({
|
|
|
1297
1454
|
parent,
|
|
1298
1455
|
typeScriptConfig: typeScriptConfigOptions,
|
|
1299
1456
|
withTerraform,
|
|
1457
|
+
worktrunk,
|
|
1300
1458
|
}: ProjectOptions): ProjectOptions['gitIgnoreOptions'] =>
|
|
1301
1459
|
parent
|
|
1302
1460
|
? gitIgnoreOptions
|
|
@@ -1307,6 +1465,7 @@ const getGitIgnoreOptions = ({
|
|
|
1307
1465
|
!.babelrc
|
|
1308
1466
|
!.dockerignore
|
|
1309
1467
|
!.editorconfig
|
|
1468
|
+
${worktrunk ? '!.env.example' : ''}
|
|
1310
1469
|
!.gitattributes
|
|
1311
1470
|
!.gitignore
|
|
1312
1471
|
!.gitkeep
|
|
@@ -1341,6 +1500,8 @@ const deepMerge = R.mergeDeepWith(
|
|
|
1341
1500
|
[R.allPass([R.is(String), R.is(String)]), R.nthArg(1)],
|
|
1342
1501
|
// Same for booleans, which cannot be concatenated at all.
|
|
1343
1502
|
[R.allPass([R.is(Boolean), R.is(Boolean)]), R.nthArg(1)],
|
|
1503
|
+
// And for numbers.
|
|
1504
|
+
[R.allPass([R.is(Number), R.is(Number)]), R.nthArg(1)],
|
|
1344
1505
|
// Otherwise, concatenate.
|
|
1345
1506
|
[R.T, R.concat],
|
|
1346
1507
|
]),
|