@jsenv/core 41.5.3 → 41.5.4

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.
@@ -6023,6 +6023,8 @@ const createNodeEsmResolver = ({
6023
6023
  packageDirectory,
6024
6024
  runtimeCompat,
6025
6025
  rootDirectoryUrl,
6026
+ dev,
6027
+ build,
6026
6028
  packageConditions = {},
6027
6029
  packageConditionsConfig,
6028
6030
  preservesSymlink,
@@ -6040,6 +6042,8 @@ const createNodeEsmResolver = ({
6040
6042
  packageConditionsConfig,
6041
6043
  rootDirectoryUrl,
6042
6044
  runtimeCompat,
6045
+ dev,
6046
+ build,
6043
6047
  preservesSymlink,
6044
6048
  },
6045
6049
  );
@@ -6201,6 +6205,8 @@ const createBuildPackageConditions = (
6201
6205
  packageConditionsConfig,
6202
6206
  rootDirectoryUrl,
6203
6207
  runtimeCompat,
6208
+ dev,
6209
+ build,
6204
6210
  preservesSymlink,
6205
6211
  },
6206
6212
  ) => {
@@ -6290,8 +6296,19 @@ const createBuildPackageConditions = (
6290
6296
  };
6291
6297
 
6292
6298
  const conditionDefaultResolvers = {
6299
+ // "dev:*" conditions target packages under active development: they
6300
+ // apply to files resolved outside node_modules (sources, workspace
6301
+ // symlinks), never to installed packages.
6293
6302
  "dev:*": devResolver,
6294
- "development": devResolver,
6303
+ // "development"/"production" follow the ecosystem semantics
6304
+ // (Vite, webpack): they describe how the app runs, not where the
6305
+ // package lives, so they apply to every package, node_modules
6306
+ // included. Dev server resolves "development"; build resolves
6307
+ // "production", unless the build is dev-flavored
6308
+ // (build({ entryPoints: { "./file.js": { dev: true } } }))
6309
+ // in which case it resolves "development" too.
6310
+ "development": Boolean(dev),
6311
+ "production": Boolean(build) && !dev,
6295
6312
  "node": nodeRuntimeEnabled,
6296
6313
  "browser": !nodeRuntimeEnabled,
6297
6314
  "import": true,
@@ -6505,6 +6522,7 @@ const jsenvPluginNodeEsmResolution = ({
6505
6522
  resolutionConfig = {},
6506
6523
  packageConditions,
6507
6524
  packageConditionsConfig = {},
6525
+ dev,
6508
6526
  }) => {
6509
6527
  let nodeEsmResolverDefault;
6510
6528
  const resolverMap = new Map();
@@ -6526,6 +6544,8 @@ const jsenvPluginNodeEsmResolution = ({
6526
6544
  packageDirectory,
6527
6545
  runtimeCompat: kitchenContext.runtimeCompat,
6528
6546
  rootDirectoryUrl: kitchenContext.rootDirectoryUrl,
6547
+ dev: dev === undefined ? kitchenContext.dev : dev,
6548
+ build: kitchenContext.build,
6529
6549
  packageConditions,
6530
6550
  packageConditionsConfig: {
6531
6551
  ...kitchenContext.packageConditionsConfig,
@@ -6543,6 +6563,8 @@ const jsenvPluginNodeEsmResolution = ({
6543
6563
  packageDirectory,
6544
6564
  runtimeCompat: kitchenContext.runtimeCompat,
6545
6565
  rootDirectoryUrl: kitchenContext.rootDirectoryUrl,
6566
+ dev: dev === undefined ? kitchenContext.dev : dev,
6567
+ build: kitchenContext.build,
6546
6568
  // preservesSymlink: true,
6547
6569
  packageConditions,
6548
6570
  packageConditionsConfig: {
@@ -8189,11 +8211,16 @@ const babelPluginMetadataExpressionPaths = (
8189
8211
  * - left as is to be evaluated to undefined (import.meta.build but it's the dev server)
8190
8212
  * - replaced by undefined (import.meta.dev but it's build; the goal is to ensure it's tree-shaked)
8191
8213
  *
8214
+ * A build can also be dev-flavored (build({ entryPoints: { "./file.js": { dev: true } } })):
8215
+ * import.meta.dev is then replaced by true, so a package can publish a build
8216
+ * that keeps its dev-only code, exposed to consumers via the "development"
8217
+ * package export condition.
8218
+ *
8192
8219
  * TODO: ideally during dev we would keep import.meta.dev and ensure we set it to true rather than replacing it with true?
8193
8220
  */
8194
8221
 
8195
8222
 
8196
- const jsenvPluginImportMetaScenarios = () => {
8223
+ const jsenvPluginImportMetaScenarios = ({ dev } = {}) => {
8197
8224
  return {
8198
8225
  name: "jsenv:import_meta_scenario",
8199
8226
  appliesDuring: "*",
@@ -8223,17 +8250,19 @@ const jsenvPluginImportMetaScenarios = () => {
8223
8250
  }
8224
8251
  },
8225
8252
  });
8226
- const { dev, build } = importMetaScenarioNodes;
8253
+ const devNodes = importMetaScenarioNodes.dev;
8254
+ const buildNodes = importMetaScenarioNodes.build;
8227
8255
  const replacements = [];
8228
8256
  const replace = (node, value) => {
8229
8257
  replacements.push({ node, value });
8230
8258
  };
8231
8259
  if (urlInfo.context.build) {
8232
8260
  // during build ensure replacement for tree-shaking
8233
- dev.forEach((node) => {
8234
- replace(node, "undefined");
8261
+ // (or for keeping dev code when the build is dev-flavored)
8262
+ devNodes.forEach((node) => {
8263
+ replace(node, dev ? "true" : "undefined");
8235
8264
  });
8236
- build.forEach((node) => {
8265
+ buildNodes.forEach((node) => {
8237
8266
  replace(node, "true");
8238
8267
  });
8239
8268
  } else {
@@ -8241,7 +8270,7 @@ const jsenvPluginImportMetaScenarios = () => {
8241
8270
  // it will be evaluated to undefined.
8242
8271
  // Moreover it can be surprising to see some "undefined"
8243
8272
  // when source file contains "import.meta.build"
8244
- dev.forEach((node) => {
8273
+ devNodes.forEach((node) => {
8245
8274
  replace(node, "true");
8246
8275
  });
8247
8276
  }
@@ -10119,6 +10148,9 @@ const getCorePlugins = ({
10119
10148
  runtimeCompat,
10120
10149
  packageDirectory,
10121
10150
  sourceFilesConfig,
10151
+ // during build, a dev-flavored entry point sets dev: true
10152
+ // (during dev the kitchen context already says so, no need to pass it)
10153
+ dev,
10122
10154
 
10123
10155
  referenceAnalysis = {},
10124
10156
  nodeEsmResolution = {},
@@ -10215,6 +10247,7 @@ const getCorePlugins = ({
10215
10247
  resolutionConfig: nodeEsmResolution,
10216
10248
  packageConditions,
10217
10249
  packageConditionsConfig,
10250
+ dev,
10218
10251
  }),
10219
10252
  ]
10220
10253
  : []),
@@ -10232,7 +10265,7 @@ const getCorePlugins = ({
10232
10265
 
10233
10266
  jsenvPluginImportMetaCss(),
10234
10267
  jsenvPluginCommonJsGlobals(),
10235
- jsenvPluginImportMetaScenarios(),
10268
+ jsenvPluginImportMetaScenarios({ dev }),
10236
10269
  ...(scenarioPlaceholders ? [jsenvPluginGlobalScenarios()] : []),
10237
10270
  jsenvPluginNodeRuntime({ runtimeCompat }),
10238
10271
 
@@ -12413,6 +12446,12 @@ const jsenvPluginMappings = (mappings) => {
12413
12446
  * Relative URL where this entry point will be written in the build directory
12414
12447
  * @param {object} [entryPoint.runtimeCompat]
12415
12448
  * Runtime compatibility configuration for this entry point
12449
+ * @param {boolean} [entryPoint.dev=false]
12450
+ * Produce a dev-flavored build: import.meta.dev is replaced by true
12451
+ * (instead of undefined) and dependencies resolve their "development"
12452
+ * package export condition (instead of "production"). Meant for packages
12453
+ * publishing two flavors, the dev one exposed to consumers via the
12454
+ * "development" condition in their package.json "exports"
12416
12455
  * @param {string} [entryPoint.assetsDirectory]
12417
12456
  * Directory where asset files will be written for this entry point
12418
12457
  * @param {string|url} [entryPoint.base]
@@ -12536,12 +12575,10 @@ entryPoints: {
12536
12575
  let runtimeType;
12537
12576
  {
12538
12577
  if (isBareSpecifier(key)) {
12539
- const packageConditions = [
12540
- "development",
12541
- "dev:*",
12542
- "node",
12543
- "import",
12544
- ];
12578
+ // "development" is not resolved here on purpose: it points at a
12579
+ // package's dev-flavored dist, which is not a build input;
12580
+ // "dev:*" points at sources, which are.
12581
+ const packageConditions = ["dev:*", "node", "import"];
12545
12582
  try {
12546
12583
  const { url, type } = applyNodeEsmResolution({
12547
12584
  conditions: packageConditions,
@@ -13273,6 +13310,7 @@ entryPoints: {
13273
13310
  const entryPointDefaultParams = {
13274
13311
  buildRelativeUrl: undefined,
13275
13312
  mode: undefined,
13313
+ dev: false,
13276
13314
  runtimeCompat: undefined,
13277
13315
  plugins: [],
13278
13316
  mappings: undefined,
@@ -13328,6 +13366,7 @@ const prepareEntryPointBuild = async (
13328
13366
  let {
13329
13367
  buildRelativeUrl,
13330
13368
  mode,
13369
+ dev,
13331
13370
  runtimeCompat,
13332
13371
  plugins,
13333
13372
  mappings,
@@ -13508,6 +13547,7 @@ const prepareEntryPointBuild = async (
13508
13547
  packageDirectory,
13509
13548
  rootDirectoryUrl: sourceDirectoryUrl,
13510
13549
  runtimeCompat,
13550
+ dev,
13511
13551
  referenceAnalysis,
13512
13552
  nodeEsmResolution,
13513
13553
  packageConditions,
@@ -2689,6 +2689,8 @@ const createNodeEsmResolver = ({
2689
2689
  packageDirectory,
2690
2690
  runtimeCompat,
2691
2691
  rootDirectoryUrl,
2692
+ dev,
2693
+ build,
2692
2694
  packageConditions = {},
2693
2695
  packageConditionsConfig,
2694
2696
  preservesSymlink,
@@ -2706,6 +2708,8 @@ const createNodeEsmResolver = ({
2706
2708
  packageConditionsConfig,
2707
2709
  rootDirectoryUrl,
2708
2710
  runtimeCompat,
2711
+ dev,
2712
+ build,
2709
2713
  preservesSymlink,
2710
2714
  },
2711
2715
  );
@@ -2867,6 +2871,8 @@ const createBuildPackageConditions = (
2867
2871
  packageConditionsConfig,
2868
2872
  rootDirectoryUrl,
2869
2873
  runtimeCompat,
2874
+ dev,
2875
+ build,
2870
2876
  preservesSymlink,
2871
2877
  },
2872
2878
  ) => {
@@ -2956,8 +2962,19 @@ const createBuildPackageConditions = (
2956
2962
  };
2957
2963
 
2958
2964
  const conditionDefaultResolvers = {
2965
+ // "dev:*" conditions target packages under active development: they
2966
+ // apply to files resolved outside node_modules (sources, workspace
2967
+ // symlinks), never to installed packages.
2959
2968
  "dev:*": devResolver,
2960
- "development": devResolver,
2969
+ // "development"/"production" follow the ecosystem semantics
2970
+ // (Vite, webpack): they describe how the app runs, not where the
2971
+ // package lives, so they apply to every package, node_modules
2972
+ // included. Dev server resolves "development"; build resolves
2973
+ // "production", unless the build is dev-flavored
2974
+ // (build({ entryPoints: { "./file.js": { dev: true } } }))
2975
+ // in which case it resolves "development" too.
2976
+ "development": Boolean(dev),
2977
+ "production": Boolean(build) && !dev,
2961
2978
  "node": nodeRuntimeEnabled,
2962
2979
  "browser": !nodeRuntimeEnabled,
2963
2980
  "import": true,
@@ -3171,6 +3188,7 @@ const jsenvPluginNodeEsmResolution = ({
3171
3188
  resolutionConfig = {},
3172
3189
  packageConditions,
3173
3190
  packageConditionsConfig = {},
3191
+ dev,
3174
3192
  }) => {
3175
3193
  let nodeEsmResolverDefault;
3176
3194
  const resolverMap = new Map();
@@ -3192,6 +3210,8 @@ const jsenvPluginNodeEsmResolution = ({
3192
3210
  packageDirectory,
3193
3211
  runtimeCompat: kitchenContext.runtimeCompat,
3194
3212
  rootDirectoryUrl: kitchenContext.rootDirectoryUrl,
3213
+ dev: dev === undefined ? kitchenContext.dev : dev,
3214
+ build: kitchenContext.build,
3195
3215
  packageConditions,
3196
3216
  packageConditionsConfig: {
3197
3217
  ...kitchenContext.packageConditionsConfig,
@@ -3209,6 +3229,8 @@ const jsenvPluginNodeEsmResolution = ({
3209
3229
  packageDirectory,
3210
3230
  runtimeCompat: kitchenContext.runtimeCompat,
3211
3231
  rootDirectoryUrl: kitchenContext.rootDirectoryUrl,
3232
+ dev: dev === undefined ? kitchenContext.dev : dev,
3233
+ build: kitchenContext.build,
3212
3234
  // preservesSymlink: true,
3213
3235
  packageConditions,
3214
3236
  packageConditionsConfig: {
@@ -5994,11 +6016,16 @@ const babelPluginMetadataExpressionPaths = (
5994
6016
  * - left as is to be evaluated to undefined (import.meta.build but it's the dev server)
5995
6017
  * - replaced by undefined (import.meta.dev but it's build; the goal is to ensure it's tree-shaked)
5996
6018
  *
6019
+ * A build can also be dev-flavored (build({ entryPoints: { "./file.js": { dev: true } } })):
6020
+ * import.meta.dev is then replaced by true, so a package can publish a build
6021
+ * that keeps its dev-only code, exposed to consumers via the "development"
6022
+ * package export condition.
6023
+ *
5997
6024
  * TODO: ideally during dev we would keep import.meta.dev and ensure we set it to true rather than replacing it with true?
5998
6025
  */
5999
6026
 
6000
6027
 
6001
- const jsenvPluginImportMetaScenarios = () => {
6028
+ const jsenvPluginImportMetaScenarios = ({ dev } = {}) => {
6002
6029
  return {
6003
6030
  name: "jsenv:import_meta_scenario",
6004
6031
  appliesDuring: "*",
@@ -6028,17 +6055,19 @@ const jsenvPluginImportMetaScenarios = () => {
6028
6055
  }
6029
6056
  },
6030
6057
  });
6031
- const { dev, build } = importMetaScenarioNodes;
6058
+ const devNodes = importMetaScenarioNodes.dev;
6059
+ const buildNodes = importMetaScenarioNodes.build;
6032
6060
  const replacements = [];
6033
6061
  const replace = (node, value) => {
6034
6062
  replacements.push({ node, value });
6035
6063
  };
6036
6064
  if (urlInfo.context.build) {
6037
6065
  // during build ensure replacement for tree-shaking
6038
- dev.forEach((node) => {
6039
- replace(node, "undefined");
6066
+ // (or for keeping dev code when the build is dev-flavored)
6067
+ devNodes.forEach((node) => {
6068
+ replace(node, dev ? "true" : "undefined");
6040
6069
  });
6041
- build.forEach((node) => {
6070
+ buildNodes.forEach((node) => {
6042
6071
  replace(node, "true");
6043
6072
  });
6044
6073
  } else {
@@ -6046,7 +6075,7 @@ const jsenvPluginImportMetaScenarios = () => {
6046
6075
  // it will be evaluated to undefined.
6047
6076
  // Moreover it can be surprising to see some "undefined"
6048
6077
  // when source file contains "import.meta.build"
6049
- dev.forEach((node) => {
6078
+ devNodes.forEach((node) => {
6050
6079
  replace(node, "true");
6051
6080
  });
6052
6081
  }
@@ -7984,6 +8013,9 @@ const getCorePlugins = ({
7984
8013
  runtimeCompat,
7985
8014
  packageDirectory,
7986
8015
  sourceFilesConfig,
8016
+ // during build, a dev-flavored entry point sets dev: true
8017
+ // (during dev the kitchen context already says so, no need to pass it)
8018
+ dev,
7987
8019
 
7988
8020
  referenceAnalysis = {},
7989
8021
  nodeEsmResolution = {},
@@ -8080,6 +8112,7 @@ const getCorePlugins = ({
8080
8112
  resolutionConfig: nodeEsmResolution,
8081
8113
  packageConditions,
8082
8114
  packageConditionsConfig,
8115
+ dev,
8083
8116
  }),
8084
8117
  ]
8085
8118
  : []),
@@ -8097,7 +8130,7 @@ const getCorePlugins = ({
8097
8130
 
8098
8131
  jsenvPluginImportMetaCss(),
8099
8132
  jsenvPluginCommonJsGlobals(),
8100
- jsenvPluginImportMetaScenarios(),
8133
+ jsenvPluginImportMetaScenarios({ dev }),
8101
8134
  ...(scenarioPlaceholders ? [jsenvPluginGlobalScenarios()] : []),
8102
8135
  jsenvPluginNodeRuntime({ runtimeCompat }),
8103
8136
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "41.5.3",
3
+ "version": "41.5.4",
4
4
  "type": "module",
5
5
  "description": "Tool to develop, test and build js projects",
6
6
  "repository": {
@@ -117,6 +117,12 @@ import { jsenvPluginMappings } from "./jsenv_plugin_mappings.js";
117
117
  * Relative URL where this entry point will be written in the build directory
118
118
  * @param {object} [entryPoint.runtimeCompat]
119
119
  * Runtime compatibility configuration for this entry point
120
+ * @param {boolean} [entryPoint.dev=false]
121
+ * Produce a dev-flavored build: import.meta.dev is replaced by true
122
+ * (instead of undefined) and dependencies resolve their "development"
123
+ * package export condition (instead of "production"). Meant for packages
124
+ * publishing two flavors, the dev one exposed to consumers via the
125
+ * "development" condition in their package.json "exports"
120
126
  * @param {string} [entryPoint.assetsDirectory]
121
127
  * Directory where asset files will be written for this entry point
122
128
  * @param {string|url} [entryPoint.base]
@@ -240,12 +246,10 @@ entryPoints: {
240
246
  let runtimeType;
241
247
  {
242
248
  if (isBareSpecifier(key)) {
243
- const packageConditions = [
244
- "development",
245
- "dev:*",
246
- "node",
247
- "import",
248
- ];
249
+ // "development" is not resolved here on purpose: it points at a
250
+ // package's dev-flavored dist, which is not a build input;
251
+ // "dev:*" points at sources, which are.
252
+ const packageConditions = ["dev:*", "node", "import"];
249
253
  try {
250
254
  const { url, type } = applyNodeEsmResolution({
251
255
  conditions: packageConditions,
@@ -979,6 +983,7 @@ entryPoints: {
979
983
  const entryPointDefaultParams = {
980
984
  buildRelativeUrl: undefined,
981
985
  mode: undefined,
986
+ dev: false,
982
987
  runtimeCompat: undefined,
983
988
  plugins: [],
984
989
  mappings: undefined,
@@ -1034,6 +1039,7 @@ const prepareEntryPointBuild = async (
1034
1039
  let {
1035
1040
  buildRelativeUrl,
1036
1041
  mode,
1042
+ dev,
1037
1043
  runtimeCompat,
1038
1044
  plugins,
1039
1045
  mappings,
@@ -1214,6 +1220,7 @@ const prepareEntryPointBuild = async (
1214
1220
  packageDirectory,
1215
1221
  rootDirectoryUrl: sourceDirectoryUrl,
1216
1222
  runtimeCompat,
1223
+ dev,
1217
1224
  referenceAnalysis,
1218
1225
  nodeEsmResolution,
1219
1226
  packageConditions,
@@ -7,13 +7,18 @@
7
7
  * - left as is to be evaluated to undefined (import.meta.build but it's the dev server)
8
8
  * - replaced by undefined (import.meta.dev but it's build; the goal is to ensure it's tree-shaked)
9
9
  *
10
+ * A build can also be dev-flavored (build({ entryPoints: { "./file.js": { dev: true } } })):
11
+ * import.meta.dev is then replaced by true, so a package can publish a build
12
+ * that keeps its dev-only code, exposed to consumers via the "development"
13
+ * package export condition.
14
+ *
10
15
  * TODO: ideally during dev we would keep import.meta.dev and ensure we set it to true rather than replacing it with true?
11
16
  */
12
17
 
13
18
  import { getImportMetaPropertyName, visitJsAst } from "@jsenv/ast";
14
19
  import { createMagicSource } from "@jsenv/sourcemap";
15
20
 
16
- export const jsenvPluginImportMetaScenarios = () => {
21
+ export const jsenvPluginImportMetaScenarios = ({ dev } = {}) => {
17
22
  return {
18
23
  name: "jsenv:import_meta_scenario",
19
24
  appliesDuring: "*",
@@ -43,17 +48,19 @@ export const jsenvPluginImportMetaScenarios = () => {
43
48
  }
44
49
  },
45
50
  });
46
- const { dev, build } = importMetaScenarioNodes;
51
+ const devNodes = importMetaScenarioNodes.dev;
52
+ const buildNodes = importMetaScenarioNodes.build;
47
53
  const replacements = [];
48
54
  const replace = (node, value) => {
49
55
  replacements.push({ node, value });
50
56
  };
51
57
  if (urlInfo.context.build) {
52
58
  // during build ensure replacement for tree-shaking
53
- dev.forEach((node) => {
54
- replace(node, "undefined");
59
+ // (or for keeping dev code when the build is dev-flavored)
60
+ devNodes.forEach((node) => {
61
+ replace(node, dev ? "true" : "undefined");
55
62
  });
56
- build.forEach((node) => {
63
+ buildNodes.forEach((node) => {
57
64
  replace(node, "true");
58
65
  });
59
66
  } else {
@@ -61,7 +68,7 @@ export const jsenvPluginImportMetaScenarios = () => {
61
68
  // it will be evaluated to undefined.
62
69
  // Moreover it can be surprising to see some "undefined"
63
70
  // when source file contains "import.meta.build"
64
- dev.forEach((node) => {
71
+ devNodes.forEach((node) => {
65
72
  replace(node, "true");
66
73
  });
67
74
  }
@@ -38,6 +38,9 @@ export const getCorePlugins = ({
38
38
  runtimeCompat,
39
39
  packageDirectory,
40
40
  sourceFilesConfig,
41
+ // during build, a dev-flavored entry point sets dev: true
42
+ // (during dev the kitchen context already says so, no need to pass it)
43
+ dev,
41
44
 
42
45
  referenceAnalysis = {},
43
46
  nodeEsmResolution = {},
@@ -134,6 +137,7 @@ export const getCorePlugins = ({
134
137
  resolutionConfig: nodeEsmResolution,
135
138
  packageConditions,
136
139
  packageConditionsConfig,
140
+ dev,
137
141
  }),
138
142
  ]
139
143
  : []),
@@ -151,7 +155,7 @@ export const getCorePlugins = ({
151
155
 
152
156
  jsenvPluginImportMetaCss(),
153
157
  jsenvPluginCommonJsGlobals(),
154
- jsenvPluginImportMetaScenarios(),
158
+ jsenvPluginImportMetaScenarios({ dev }),
155
159
  ...(scenarioPlaceholders ? [jsenvPluginGlobalScenarios()] : []),
156
160
  jsenvPluginNodeRuntime({ runtimeCompat }),
157
161
 
@@ -5,6 +5,7 @@ export const jsenvPluginNodeEsmResolution = ({
5
5
  resolutionConfig = {},
6
6
  packageConditions,
7
7
  packageConditionsConfig = {},
8
+ dev,
8
9
  }) => {
9
10
  let nodeEsmResolverDefault;
10
11
  const resolverMap = new Map();
@@ -26,6 +27,8 @@ export const jsenvPluginNodeEsmResolution = ({
26
27
  packageDirectory,
27
28
  runtimeCompat: kitchenContext.runtimeCompat,
28
29
  rootDirectoryUrl: kitchenContext.rootDirectoryUrl,
30
+ dev: dev === undefined ? kitchenContext.dev : dev,
31
+ build: kitchenContext.build,
29
32
  packageConditions,
30
33
  packageConditionsConfig: {
31
34
  ...kitchenContext.packageConditionsConfig,
@@ -43,6 +46,8 @@ export const jsenvPluginNodeEsmResolution = ({
43
46
  packageDirectory,
44
47
  runtimeCompat: kitchenContext.runtimeCompat,
45
48
  rootDirectoryUrl: kitchenContext.rootDirectoryUrl,
49
+ dev: dev === undefined ? kitchenContext.dev : dev,
50
+ build: kitchenContext.build,
46
51
  // preservesSymlink: true,
47
52
  packageConditions,
48
53
  packageConditionsConfig: {
@@ -20,6 +20,8 @@ export const createNodeEsmResolver = ({
20
20
  packageDirectory,
21
21
  runtimeCompat,
22
22
  rootDirectoryUrl,
23
+ dev,
24
+ build,
23
25
  packageConditions = {},
24
26
  packageConditionsConfig,
25
27
  preservesSymlink,
@@ -37,6 +39,8 @@ export const createNodeEsmResolver = ({
37
39
  packageConditionsConfig,
38
40
  rootDirectoryUrl,
39
41
  runtimeCompat,
42
+ dev,
43
+ build,
40
44
  preservesSymlink,
41
45
  },
42
46
  );
@@ -198,6 +202,8 @@ const createBuildPackageConditions = (
198
202
  packageConditionsConfig,
199
203
  rootDirectoryUrl,
200
204
  runtimeCompat,
205
+ dev,
206
+ build,
201
207
  preservesSymlink,
202
208
  },
203
209
  ) => {
@@ -287,8 +293,19 @@ const createBuildPackageConditions = (
287
293
  };
288
294
 
289
295
  const conditionDefaultResolvers = {
296
+ // "dev:*" conditions target packages under active development: they
297
+ // apply to files resolved outside node_modules (sources, workspace
298
+ // symlinks), never to installed packages.
290
299
  "dev:*": devResolver,
291
- "development": devResolver,
300
+ // "development"/"production" follow the ecosystem semantics
301
+ // (Vite, webpack): they describe how the app runs, not where the
302
+ // package lives, so they apply to every package, node_modules
303
+ // included. Dev server resolves "development"; build resolves
304
+ // "production", unless the build is dev-flavored
305
+ // (build({ entryPoints: { "./file.js": { dev: true } } }))
306
+ // in which case it resolves "development" too.
307
+ "development": Boolean(dev),
308
+ "production": Boolean(build) && !dev,
292
309
  "node": nodeRuntimeEnabled,
293
310
  "browser": !nodeRuntimeEnabled,
294
311
  "import": true,