@fuman/build 0.0.14 → 0.0.16

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
@@ -16,12 +16,12 @@ this package works on some assumptions, allowing to abstract some of the complex
16
16
  - `.exports` and `.bin` fields in package.json are build entrypoints, e.g.:
17
17
  ```json
18
18
  {
19
- "exports": {
20
- ".": "./src/index.ts"
21
- },
22
- "bin": {
23
- "fuman-build": "./src/cli.ts"
24
- }
19
+ "exports": {
20
+ ".": "./src/index.ts"
21
+ },
22
+ "bin": {
23
+ "fuman-build": "./src/cli.ts"
24
+ }
25
25
  }
26
26
  - `.main`, `.module`, `.types`, `.browser` are explicitly **not** supported. for browser-specific code, you should make a secondary entrypoint/package instead of relying on bundle-time magic
27
27
  - package versioning is continous and semver-compliant (except "fixed version" releases, which all share the same version)
@@ -71,15 +71,15 @@ just put this in your `vite.config.js`:
71
71
  import { fumanBuild } from '@fuman/build/vite'
72
72
 
73
73
  export default {
74
- plugins: [
75
- fumanBuild({
76
- root: __dirname,
77
- // if you're using `vite-plugin-dts`, make sure to add this option,
78
- // otherwise additional entrypoints will not have proper types
79
- // (and DO NOT add this option to the dts plugin itself)
80
- insertTypesEntry: true,
81
- }),
82
- ],
74
+ plugins: [
75
+ fumanBuild({
76
+ root: __dirname,
77
+ // if you're using `vite-plugin-dts`, make sure to add this option,
78
+ // otherwise additional entrypoints will not have proper types
79
+ // (and DO NOT add this option to the dts plugin itself)
80
+ insertTypesEntry: true,
81
+ }),
82
+ ],
83
83
  }
84
84
  ```
85
85
 
@@ -39,7 +39,7 @@ const releaseCli = bc.command({
39
39
  dryRun: bc.boolean("dry-run").desc("whether to skip publishing and only print what is going to happen")
40
40
  },
41
41
  handler: async (args) => {
42
- const root = process.cwd();
42
+ const root = process.env.FUMAN_ROOT ?? process.cwd();
43
43
  const config = await loadConfig({
44
44
  workspaceRoot: root,
45
45
  require: false
@@ -81,7 +81,9 @@ const releaseCli = bc.command({
81
81
  const taggingSchema = config?.versioning?.taggingSchema ?? "semver";
82
82
  let tagName;
83
83
  if (taggingSchema === "semver") {
84
- const versions = sort(workspace.map((pkg) => asNonNull(pkg.json.version)));
84
+ const versions = sort(
85
+ workspace.filter((pkg) => !pkg.json.fuman?.ownVersioning && !pkg.json.fuman?.standalone).map((pkg) => asNonNull(pkg.json.version))
86
+ );
85
87
  tagName = `v${versions[versions.length - 1]}`;
86
88
  if (await gitTagExists(tagName, root)) {
87
89
  console.log(`❗ tag ${tagName} already exists. did the previous release complete successfully?`);
package/index.js CHANGED
@@ -12,7 +12,7 @@ import { NPM_PACKAGE_NAME_REGEX, npmCheckVersion } from "./npm/npm-api.js";
12
12
  import { collectPackageJsons, filterPackageJsonsForPublish } from "./package-json/collect-package-jsons.js";
13
13
  import { findPackageJson } from "./package-json/find-package-json.js";
14
14
  import { parsePackageJson, parsePackageJsonFile, parsePackageJsonFromDir, parseWorkspaceRootPackageJson } from "./package-json/parse.js";
15
- import { processPackageJson } from "./package-json/process-package-json.js";
15
+ import { processPackageJson, removeCommonjsExports } from "./package-json/process-package-json.js";
16
16
  import { PackageJsonSchema } from "./package-json/types.js";
17
17
  import { bumpVersion } from "./versioning/bump-version.js";
18
18
  import { findProjectChangedFiles, findProjectChangedPackages } from "./versioning/collect-files.js";
@@ -52,6 +52,7 @@ export {
52
52
  parsePackageJsonFromDir,
53
53
  parseWorkspaceRootPackageJson,
54
54
  processPackageJson,
55
+ removeCommonjsExports,
55
56
  sortWorkspaceByPublishOrder,
56
57
  validateWorkspaceDeps,
57
58
  writeGithubActionsOutput
@@ -0,0 +1 @@
1
+ export declare function applyDenoDirectives(code: string): string;
@@ -0,0 +1,23 @@
1
+ import { asNonNull } from "@fuman/utils";
2
+ function applyDenoDirectives(code) {
3
+ if (!code.match("<deno-(insert|remove|tsignore)>")) return code;
4
+ let insertContent = code.match(/\/\/\s*<deno-insert>(.*?)<\/deno-insert>/s);
5
+ while (insertContent) {
6
+ code = code.slice(0, insertContent.index) + insertContent[1].replace(/\/\/\s*/g, "") + code.slice(asNonNull(insertContent.index) + insertContent[0].length);
7
+ insertContent = code.match(/\/\/\s*<deno-insert>(.*?)<\/deno-insert>/s);
8
+ }
9
+ let removeContent = code.match(/\/\/\s*<deno-remove>(.*?)<\/deno-remove>/s);
10
+ while (removeContent) {
11
+ code = code.slice(0, removeContent.index) + code.slice(asNonNull(removeContent.index) + removeContent[0].length);
12
+ removeContent = code.match(/\/\/\s*<deno-remove>(.*?)<\/deno-remove>/s);
13
+ }
14
+ let tsIgnoreContent = code.match(/\/\/\s*<deno-tsignore>/);
15
+ while (tsIgnoreContent) {
16
+ code = `${code.slice(0, tsIgnoreContent.index)}/* @ts-ignore */${code.slice(asNonNull(tsIgnoreContent.index) + tsIgnoreContent[0].length)}`;
17
+ tsIgnoreContent = code.match(/\/\/\s*<deno-tsignore>/);
18
+ }
19
+ return code;
20
+ }
21
+ export {
22
+ applyDenoDirectives
23
+ };
package/jsr/config.d.ts CHANGED
@@ -45,4 +45,48 @@ export interface JsrConfig {
45
45
  transformAst?: (ast: ts.SourceFile) => boolean;
46
46
  /** similar to transformAst, but for the code itself (runs after transformAst) */
47
47
  transformCode?: (path: string, code: string) => string;
48
+ /**
49
+ * whether to enable pre-processor directives when processing typescript files.
50
+ * this is useful to provide deno-specific typings for stuff.
51
+ *
52
+ * **note**: this is run *before* the transformCode hook, but *after* the transformAst hook
53
+ *
54
+ * supported directives:
55
+ *
56
+ * `<deno-insert>`: inserts the given code at transform time. example:
57
+ * ```ts
58
+ * // <deno-insert>
59
+ * // declare type SharedWorker = never
60
+ * // </deno-insert>
61
+ * ```
62
+ * transforms to:
63
+ * ```ts
64
+ * declare type SharedWorker = never
65
+ * ```
66
+ *
67
+ * `<deno-remove>`: remove the given code at transform time. example:
68
+ * ```ts
69
+ * // <deno-remove>
70
+ * if (self instanceof SharedWorkerGlobalScope) {
71
+ * // do something
72
+ * }
73
+ * // </deno-remove>
74
+ * ```
75
+ * transforms to: (nothing)
76
+ *
77
+ * `<deno-tsignore>`: insert a `// @ts-ignore` comment when building for deno at the given position
78
+ * example:
79
+ * ```ts
80
+ * // <deno-tsignore>
81
+ * const foo: string = 123
82
+ * ```
83
+ * transforms to:
84
+ * ```ts
85
+ * // @ts-ignore
86
+ * const foo = 123
87
+ * ```
88
+ *
89
+ * @default false
90
+ */
91
+ enableDenoDirectives?: boolean;
48
92
  }
@@ -12,6 +12,7 @@ import { normalizeFilePath } from "../misc/path.js";
12
12
  import { collectPackageJsons, filterPackageJsonsForPublish } from "../package-json/collect-package-jsons.js";
13
13
  import { processPackageJson } from "../package-json/process-package-json.js";
14
14
  import { findRootPackage, collectVersions } from "../package-json/utils.js";
15
+ import { applyDenoDirectives } from "./_deno-directives.js";
15
16
  import { packageJsonToDeno } from "./deno-json.js";
16
17
  function mergeArrays(a, b, defaultValue = []) {
17
18
  if (!a) return b ?? defaultValue;
@@ -111,6 +112,9 @@ async function generateDenoWorkspace(params) {
111
112
  fileContent = printer.printFile(file);
112
113
  changed = true;
113
114
  }
115
+ if (rootConfig?.enableDenoDirectives) {
116
+ fileContent = applyDenoDirectives(fileContent);
117
+ }
114
118
  if (rootConfig?.transformCode || packageConfigJsr?.transformCode) {
115
119
  const origFileContent = fileContent;
116
120
  if (rootConfig?.transformCode) {
package/misc/_config.js CHANGED
@@ -1,8 +1,10 @@
1
1
  import { join } from "node:path";
2
+ import { pathToFileURL } from "node:url";
2
3
  const CONFIG_NAME = "build.config.js";
3
4
  async function loadBuildConfig(packageRoot) {
4
5
  try {
5
- const mod = (await import(join(packageRoot, CONFIG_NAME))).default;
6
+ const filePath = pathToFileURL(join(packageRoot, CONFIG_NAME)).href;
7
+ const mod = (await import(filePath)).default;
6
8
  if (typeof mod === "function") {
7
9
  return mod();
8
10
  } else {
@@ -12,3 +12,9 @@ export declare function processPackageJson(params: {
12
12
  packageJsonOrig: PackageJson;
13
13
  entrypoints: Record<string, string>;
14
14
  };
15
+ /**
16
+ * remove comonjs export definitions from package.json
17
+ *
18
+ * **note**: this function modifies the input object
19
+ */
20
+ export declare function removeCommonjsExports(exports: Record<string, unknown>): void;
@@ -138,6 +138,19 @@ function processPackageJson(params) {
138
138
  entrypoints
139
139
  };
140
140
  }
141
+ function removeCommonjsExports(exports) {
142
+ const keys = Object.keys(exports);
143
+ if (keys.includes("import")) {
144
+ delete exports.require;
145
+ return;
146
+ }
147
+ for (const key of keys) {
148
+ const value = exports[key];
149
+ if (value == null || typeof value !== "object") continue;
150
+ delete value.require;
151
+ }
152
+ }
141
153
  export {
142
- processPackageJson
154
+ processPackageJson,
155
+ removeCommonjsExports
143
156
  };
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@fuman/build",
3
3
  "type": "module",
4
- "version": "0.0.14",
4
+ "version": "0.0.16",
5
5
  "description": "utils for building packages and managing monorepos",
6
6
  "license": "MIT",
7
7
  "scripts": {},
8
8
  "dependencies": {
9
9
  "@drizzle-team/brocli": "^0.10.2",
10
10
  "@fuman/fetch": "0.0.13",
11
- "@fuman/io": "^0.0.14",
12
- "@fuman/node": "^0.0.14",
13
- "@fuman/utils": "^0.0.14",
11
+ "@fuman/io": "^0.0.16",
12
+ "@fuman/node": "^0.0.16",
13
+ "@fuman/utils": "^0.0.16",
14
14
  "cross-spawn": "^7.0.5",
15
15
  "detect-indent": "^7.0.1",
16
16
  "js-yaml": "^4.1.0",
@@ -30,30 +30,18 @@
30
30
  "import": {
31
31
  "types": "./index.d.ts",
32
32
  "default": "./index.js"
33
- },
34
- "require": {
35
- "types": "./index.d.cts",
36
- "default": "./index.cjs"
37
33
  }
38
34
  },
39
35
  "./vite": {
40
36
  "import": {
41
37
  "types": "./vite.d.ts",
42
38
  "default": "./vite.js"
43
- },
44
- "require": {
45
- "types": "./vite.d.cts",
46
- "default": "./vite.cjs"
47
39
  }
48
40
  },
49
41
  "./jsr": {
50
42
  "import": {
51
43
  "types": "./jsr.d.ts",
52
44
  "default": "./jsr.js"
53
- },
54
- "require": {
55
- "types": "./jsr.d.cts",
56
- "default": "./jsr.cjs"
57
45
  }
58
46
  }
59
47
  },
@@ -80,6 +80,7 @@ async function bumpVersion(params) {
80
80
  prevVersion: asNonNull(pkg.json.version)
81
81
  });
82
82
  }
83
+ const bumpWithDependants = params.params?.bumpWithDependants;
83
84
  for (const pkg of changedPackages) {
84
85
  if (pkg.json.fuman?.ownVersioning) continue;
85
86
  const pkgName = asNonNull(pkg.json.name);
@@ -94,7 +95,15 @@ async function bumpVersion(params) {
94
95
  }
95
96
  if (expandedVersion === "workspace:^") expandedVersion = `^${workspaceVersions[pkgName]}`;
96
97
  if (expandedVersion === "workspace:*") expandedVersion = workspaceVersions[pkgName];
97
- if (!satisfies(nextVersion, expandedVersion)) {
98
+ let shouldBump;
99
+ if (bumpWithDependants === true) {
100
+ shouldBump = true;
101
+ } else if (bumpWithDependants === "only-minor") {
102
+ shouldBump = !satisfies(nextVersion, expandedVersion) && type === "minor";
103
+ } else {
104
+ shouldBump = !satisfies(nextVersion, expandedVersion);
105
+ }
106
+ if (shouldBump) {
98
107
  if (otherPkg.json.fuman?.ownVersioning) {
99
108
  throw new Error(`package ${otherPkg.json.name}@${otherPkg.json.version} is marked as "own versioning", and will not be compatible with ${pkgName}@${expandedVersion} after bumping. please bump it manually`);
100
109
  }
@@ -1,5 +1,5 @@
1
- import { VersioningOptions } from './types.js';
2
1
  import { WorkspacePackage } from '../package-json/index.js';
2
+ import { VersioningOptions } from './types.js';
3
3
  export interface ProjectChangedFile {
4
4
  /** package to which the file belongs */
5
5
  package: WorkspacePackage;
@@ -39,6 +39,24 @@ export interface VersioningOptions {
39
39
  * @default `['**\/*.test.ts', '**\/*.md']`
40
40
  */
41
41
  exclude?: string[] | null;
42
+ /**
43
+ * whether to also bump dependant packages when bumping a package,
44
+ * even if this is a semver-compatible bump.
45
+ *
46
+ * example:
47
+ * - A depends on package B, and B depends on package C
48
+ * - A gets patch bump (e.g. `v1.2.3` -> `v1.2.4`)
49
+ * - when `false` or `'only-minor'`, B and C єlwill not be bumped
50
+ * - when `true`, B and C will be bumped to the same version as A (i.e. `v1.2.4`)
51
+ *
52
+ * `only-minor` will make fuman ignore patch bumps and only bump dependants
53
+ * when minor version is bumped.
54
+ *
55
+ * note that dependants are always bumped on a major bump.
56
+ *
57
+ * @default false
58
+ */
59
+ bumpWithDependants?: boolean | 'only-minor';
42
60
  /**
43
61
  * custom predicate for inclusion of files
44
62
  * (will be called in addition to the globs,
@@ -1,6 +1,6 @@
1
+ import { MaybeArray, MaybePromise } from '@fuman/utils';
1
2
  import { PluginOption } from 'vite';
2
3
  import { BuildHookContext } from '../config.js';
3
- import { MaybeArray, MaybePromise } from '@fuman/utils';
4
4
  export declare function fumanBuild(params: {
5
5
  root: URL | string;
6
6
  /**
@@ -7,7 +7,7 @@ import { loadBuildConfig } from "../misc/_config.js";
7
7
  import { tryCopy, fileExists, directoryExists } from "../misc/fs.js";
8
8
  import { normalizeFilePath } from "../misc/path.js";
9
9
  import { collectPackageJsons } from "../package-json/collect-package-jsons.js";
10
- import { processPackageJson } from "../package-json/process-package-json.js";
10
+ import { processPackageJson, removeCommonjsExports } from "../package-json/process-package-json.js";
11
11
  import { collectVersions } from "../package-json/utils.js";
12
12
  async function fumanBuild(params) {
13
13
  const {
@@ -113,6 +113,9 @@ async function fumanBuild(params) {
113
113
  },
114
114
  async closeBundle() {
115
115
  if (isNoop) return;
116
+ if (!buildCjs) {
117
+ removeCommonjsExports(packageJson.exports);
118
+ }
116
119
  await params.finalizePackageJson?.(hookContext);
117
120
  await packageConfig?.finalizePackageJson?.(hookContext);
118
121
  await fsp.writeFile(join(buildDir, "package.json"), JSON.stringify(packageJson, null, 4));