auklet 0.1.3 → 0.1.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.
Files changed (72) hide show
  1. package/README.md +113 -412
  2. package/dist/build/tsdown/dependencies.js +2 -2
  3. package/dist/cli/build.d.ts +3 -5
  4. package/dist/cli/build.js +88 -17
  5. package/dist/cli/buildCss.d.ts +10 -3
  6. package/dist/cli/buildCss.js +40 -29
  7. package/dist/cli/buildWorkspace.d.ts +23 -0
  8. package/dist/cli/buildWorkspace.js +43 -0
  9. package/dist/cli/dev.d.ts +2 -1
  10. package/dist/cli/dev.js +131 -16
  11. package/dist/cli/main.js +36 -12
  12. package/dist/cli/parse/build.d.ts +62 -0
  13. package/dist/cli/parse/build.js +161 -0
  14. package/dist/cli/parse/core.d.ts +14 -0
  15. package/dist/cli/parse/core.js +68 -0
  16. package/dist/cli/parse/dev.d.ts +17 -0
  17. package/dist/cli/parse/dev.js +4 -0
  18. package/dist/cli/parse/owner.d.ts +11 -0
  19. package/dist/cli/parse/owner.js +25 -0
  20. package/dist/cli/parse/publish.d.ts +19 -0
  21. package/dist/cli/parse/publish.js +60 -0
  22. package/dist/cli/parse/values.d.ts +17 -0
  23. package/dist/cli/parse/values.js +14 -0
  24. package/dist/cli/parse/workspace.d.ts +12 -0
  25. package/dist/cli/parse/workspace.js +45 -0
  26. package/dist/css/core/style/dependencies.d.ts +0 -1
  27. package/dist/css/core/style/dependencies.js +0 -3
  28. package/dist/css/core/style/entries.js +2 -2
  29. package/dist/css/core/style/files.d.ts +0 -1
  30. package/dist/css/core/style/files.js +0 -3
  31. package/dist/css/core/stylePackageContext.js +3 -3
  32. package/dist/css/inspect.js +4 -3
  33. package/dist/css/vite/hmr.js +2 -2
  34. package/dist/css/vite/moduleGraph/packageSource/monorepo.d.ts +1 -1
  35. package/dist/css/vite/moduleGraph/packageSource/monorepo.js +2 -2
  36. package/dist/env.d.ts +22 -0
  37. package/dist/env.js +105 -0
  38. package/dist/logger.d.ts +0 -1
  39. package/dist/logger.js +0 -3
  40. package/dist/publish/api/npmrc.d.ts +1 -1
  41. package/dist/publish/api/npmrc.js +1 -4
  42. package/dist/publish/api/pnpmApi.d.ts +5 -13
  43. package/dist/publish/api/pnpmApi.js +5 -47
  44. package/dist/publish/api/pnpmPublishApi.d.ts +2 -2
  45. package/dist/publish/api/pnpmPublishApi.js +5 -3
  46. package/dist/publish/cli.d.ts +0 -12
  47. package/dist/publish/cli.js +27 -106
  48. package/dist/publish/inspect.js +19 -9
  49. package/dist/publish/inspectPack.js +6 -2
  50. package/dist/publish/inspectRegistry.d.ts +3 -2
  51. package/dist/publish/inspectRegistry.js +11 -4
  52. package/dist/publish/publishEnv.d.ts +13 -0
  53. package/dist/publish/publishEnv.js +21 -0
  54. package/dist/publish/publishRunner.d.ts +3 -2
  55. package/dist/publish/publishRunner.js +9 -7
  56. package/dist/publish/runner/packageBuilder.d.ts +2 -3
  57. package/dist/publish/runner/packageBuilder.js +5 -3
  58. package/dist/publish/runner/packagePublisher.d.ts +3 -2
  59. package/dist/publish/runner/packagePublisher.js +4 -2
  60. package/dist/publish/runner/publishPreflight.d.ts +3 -2
  61. package/dist/publish/runner/publishPreflight.js +13 -6
  62. package/dist/publish/runner/versionWriter.d.ts +1 -1
  63. package/dist/publish/targetResolver.d.ts +2 -2
  64. package/dist/publish/targetResolver.js +34 -75
  65. package/dist/publish/types.d.ts +6 -7
  66. package/dist/workspace/targets.d.ts +31 -0
  67. package/dist/workspace/targets.js +144 -0
  68. package/package.json +1 -1
  69. package/dist/cli/buildArgs.d.ts +0 -8
  70. package/dist/cli/buildArgs.js +0 -114
  71. package/dist/cli/publish.d.ts +0 -2
  72. package/dist/cli/publish.js +0 -9
@@ -1,4 +1,4 @@
1
- import type { PublishOptions } from '#auklet/publish/types';
1
+ import type { PublishOptions, PublishRuntime } from '#auklet/publish/types';
2
2
  export declare class PublishRunner {
3
3
  private readonly git;
4
4
  private readonly publisher;
@@ -6,7 +6,8 @@ export declare class PublishRunner {
6
6
  private readonly versions;
7
7
  private readonly logger;
8
8
  private readonly options;
9
- constructor(options: PublishOptions);
9
+ private readonly runtime;
10
+ constructor(options: PublishOptions, runtime: PublishRuntime);
10
11
  run(): Promise<void>;
11
12
  private publishWithPlan;
12
13
  private handleFailure;
@@ -1,4 +1,4 @@
1
- import { createScopedAukletLogger } from '#auklet/logger';
1
+ import { createAukletLogger } from '#auklet/logger';
2
2
  import { runPublishHook } from '#auklet/publish/api/publishHookApi';
3
3
  import { runPackageBuilds, validateBuildScript, } from '#auklet/publish/runner/packageBuilder';
4
4
  import { formatPublishOutputs } from '#auklet/publish/runner/publishOutputFormatter';
@@ -17,16 +17,18 @@ export class PublishRunner {
17
17
  versions;
18
18
  logger;
19
19
  options;
20
- constructor(options) {
20
+ runtime;
21
+ constructor(options, runtime) {
21
22
  this.options = options;
22
- this.logger = createScopedAukletLogger('publish');
23
+ this.runtime = runtime;
24
+ this.logger = createAukletLogger({ scope: 'publish' });
23
25
  this.git = new ReleaseGitController(this.options, this.logger);
24
- this.publisher = new PackagePublisher(this.options, this.logger);
25
- this.preflight = new PublishPreflight(this.options, this.logger);
26
+ this.publisher = new PackagePublisher(this.options, this.runtime, this.logger);
27
+ this.preflight = new PublishPreflight(this.options, this.runtime, this.logger);
26
28
  this.versions = new VersionWriter(this.options, this.logger);
27
29
  }
28
30
  async run() {
29
- const plan = await resolvePublishPlan(this.options, this.logger);
31
+ const plan = await resolvePublishPlan(this.options, this.runtime, this.logger);
30
32
  let failureHookEnabled = false;
31
33
  try {
32
34
  validateBuildScript(plan.targets);
@@ -36,7 +38,7 @@ export class PublishRunner {
36
38
  await runPublishHook({ status: 'beforeBuild', plan });
37
39
  failureHookEnabled = true;
38
40
  this.versions.writeBeforeBuild(plan);
39
- await runPackageBuilds(plan.targets, this.logger, this.options);
41
+ await runPackageBuilds(plan.targets, this.logger, this.options, this.runtime);
40
42
  await runPublishHook({ status: 'afterBuild', plan });
41
43
  await formatPublishOutputs(plan.targets, this.options.format);
42
44
  await runPublishHook({ status: 'beforePublish', plan });
@@ -1,5 +1,4 @@
1
- import type { PublishTarget } from '#auklet/publish/types';
2
1
  import type { AukletLogger } from '#auklet/logger';
3
- import type { PublishOptions } from '#auklet/publish/types';
2
+ import type { PublishTarget, PublishOptions, PublishRuntime } from '#auklet/publish/types';
4
3
  export declare function validateBuildScript(targets: Array<PublishTarget>): void;
5
- export declare function runPackageBuilds(targets: Array<PublishTarget>, logger: AukletLogger, options?: Pick<PublishOptions, 'token'>): Promise<void>;
4
+ export declare function runPackageBuilds(targets: Array<PublishTarget>, logger: AukletLogger, options: Pick<PublishOptions, 'token'>, runtime: PublishRuntime): Promise<void>;
@@ -1,5 +1,6 @@
1
1
  import { isString } from 'aidly';
2
2
  import { runPnpmBuild } from '#auklet/publish/api/pnpmApi';
3
+ import { createPublishTargetEnv } from '#auklet/publish/publishEnv';
3
4
  export function validateBuildScript(targets) {
4
5
  for (const target of targets) {
5
6
  const buildScript = target.packageJson.scripts?.build;
@@ -8,11 +9,12 @@ export function validateBuildScript(targets) {
8
9
  }
9
10
  }
10
11
  }
11
- export async function runPackageBuilds(targets, logger, options = {}) {
12
+ export async function runPackageBuilds(targets, logger, options, runtime) {
12
13
  for (const target of targets) {
13
14
  logger.step('build ', logger.package(target.packageName));
14
- if (options.token) {
15
- await runPnpmBuild(target.packageRoot, { token: options.token });
15
+ const { env } = createPublishTargetEnv(options, runtime, target);
16
+ if (env) {
17
+ await runPnpmBuild(target.packageRoot, { env });
16
18
  continue;
17
19
  }
18
20
  await runPnpmBuild(target.packageRoot);
@@ -1,10 +1,11 @@
1
1
  import type { AukletLogger } from '#auklet/logger';
2
- import type { PublishOptions, PublishPlan } from '#auklet/publish/types';
2
+ import type { PublishOptions, PublishPlan, PublishRuntime } from '#auklet/publish/types';
3
3
  export declare class PackagePublisher {
4
4
  private readonly options;
5
+ private readonly runtime;
5
6
  private readonly logger;
6
7
  private readonly pnpm;
7
- constructor(options: PublishOptions, logger: AukletLogger);
8
+ constructor(options: PublishOptions, runtime: PublishRuntime, logger: AukletLogger);
8
9
  run(plan: PublishPlan): Promise<void>;
9
10
  }
10
11
  export declare function logAuthenticationError(logger: AukletLogger, error: unknown): void;
@@ -3,17 +3,19 @@ import { NpmPublishAuthenticationError } from '#auklet/publish/api/pnpmApi';
3
3
  import { PublishTargetError } from '#auklet/publish/runner/publishTargetError';
4
4
  export class PackagePublisher {
5
5
  options;
6
+ runtime;
6
7
  logger;
7
8
  pnpm = new PnpmPublishApi();
8
- constructor(options, logger) {
9
+ constructor(options, runtime, logger) {
9
10
  this.options = options;
11
+ this.runtime = runtime;
10
12
  this.logger = logger;
11
13
  }
12
14
  async run(plan) {
13
15
  const publishedTargets = [];
14
16
  for (const target of plan.targets) {
15
17
  try {
16
- await this.pnpm.publish(target, this.options);
18
+ await this.pnpm.publish(target, this.options, this.runtime);
17
19
  publishedTargets.push(target);
18
20
  }
19
21
  catch (error) {
@@ -1,10 +1,11 @@
1
1
  import type { AukletLogger } from '#auklet/logger';
2
- import type { PublishOptions, PublishPlan } from '#auklet/publish/types';
2
+ import type { PublishOptions, PublishPlan, PublishRuntime } from '#auklet/publish/types';
3
3
  export declare class PublishPreflight {
4
4
  private readonly options;
5
+ private readonly runtime;
5
6
  private readonly logger;
6
7
  private readonly pnpm;
7
- constructor(options: PublishOptions, logger: AukletLogger);
8
+ constructor(options: PublishOptions, runtime: PublishRuntime, logger: AukletLogger);
8
9
  run(plan: PublishPlan): Promise<void>;
9
10
  verifyBeforeBuild(plan: PublishPlan): Promise<void>;
10
11
  private verifyNpmrcAuthEnv;
@@ -1,15 +1,18 @@
1
1
  import { PnpmPublishApi } from '#auklet/publish/api/pnpmPublishApi';
2
- import { hasPublishedPackageVersion, NpmPackageVersionExistsError, runPnpmWhoami, } from '#auklet/publish/api/pnpmApi';
2
+ import { runPnpmWhoami, hasPublishedPackageVersion, NpmPackageVersionExistsError, } from '#auklet/publish/api/pnpmApi';
3
3
  import { findNpmrcFiles, findNpmrcWithAuthToken, toNpmrcRegistryKey, validateNpmrcAuthEnv, } from '#auklet/publish/api/npmrc';
4
4
  import { getPublishRegistry } from '#auklet/publish/api/registry';
5
+ import { createPublishTargetEnv } from '#auklet/publish/publishEnv';
5
6
  import { logAuthenticationError } from '#auklet/publish/runner/packagePublisher';
6
7
  import { PublishTargetError } from '#auklet/publish/runner/publishTargetError';
7
8
  export class PublishPreflight {
8
9
  options;
10
+ runtime;
9
11
  logger;
10
12
  pnpm = new PnpmPublishApi();
11
- constructor(options, logger) {
13
+ constructor(options, runtime, logger) {
12
14
  this.options = options;
15
+ this.runtime = runtime;
13
16
  this.logger = logger;
14
17
  }
15
18
  async run(plan) {
@@ -25,8 +28,9 @@ export class PublishPreflight {
25
28
  }
26
29
  verifyNpmrcAuthEnv(plan) {
27
30
  for (const target of plan.targets) {
31
+ const { env } = createPublishTargetEnv(this.options, this.runtime, target);
28
32
  validateNpmrcAuthEnv(target.packageRoot, plan.root, {
29
- token: this.options.token,
33
+ env,
30
34
  });
31
35
  }
32
36
  }
@@ -51,7 +55,7 @@ export class PublishPreflight {
51
55
  await runPnpmWhoami(target.packageRoot, {
52
56
  packageName: target.packageName,
53
57
  registry,
54
- token: this.options.token,
58
+ ...createPublishTargetEnv(this.options, this.runtime, target),
55
59
  });
56
60
  checked.add(key);
57
61
  }
@@ -63,7 +67,7 @@ export class PublishPreflight {
63
67
  };
64
68
  for (const target of plan.targets) {
65
69
  try {
66
- await this.pnpm.publish(target, options);
70
+ await this.pnpm.publish(target, options, this.runtime);
67
71
  }
68
72
  catch (error) {
69
73
  logAuthenticationError(this.logger, error);
@@ -74,7 +78,10 @@ export class PublishPreflight {
74
78
  async verifyPackageVersions(plan) {
75
79
  for (const target of plan.targets) {
76
80
  const registry = getPublishRegistry(target.packageJson.publishConfig);
77
- const exists = await hasPublishedPackageVersion(target.packageRoot, target.packageName, target.publishVersion, { registry, token: this.options.token });
81
+ const exists = await hasPublishedPackageVersion(target.packageRoot, target.packageName, target.publishVersion, {
82
+ registry,
83
+ ...createPublishTargetEnv(this.options, this.runtime, target),
84
+ });
78
85
  if (!exists)
79
86
  continue;
80
87
  this.logExistingVersion(target, registry);
@@ -1,5 +1,5 @@
1
+ import { type AukletLogger } from '#auklet/logger';
1
2
  import type { PublishOptions, PublishPlan } from '#auklet/publish/types';
2
- import type { AukletLogger } from '#auklet/logger';
3
3
  export declare class VersionWriter {
4
4
  private readonly options;
5
5
  private readonly logger;
@@ -1,7 +1,7 @@
1
1
  import { type AukletLogger } from '#auklet/logger';
2
- import type { OwnerOptions, PublishOptions, PublishPlan } from '#auklet/publish/types';
2
+ import type { OwnerOptions, PublishOptions, PublishPlan, PublishRuntime } from '#auklet/publish/types';
3
3
  type ResolvePublishTargetsOptions = Pick<PublishOptions, 'cwd' | 'filters' | 'version' | 'dryRun' | 'token'>;
4
4
  type ResolveOwnerTargetsOptions = Pick<OwnerOptions, 'cwd' | 'filters' | 'packages'>;
5
- export declare function resolvePublishPlan(options: ResolvePublishTargetsOptions, logger?: AukletLogger): Promise<PublishPlan>;
5
+ export declare function resolvePublishPlan(options: ResolvePublishTargetsOptions, runtime: PublishRuntime, logger?: AukletLogger): Promise<PublishPlan>;
6
6
  export declare function resolveOwnerPackageNames(options: ResolveOwnerTargetsOptions): Promise<string[]>;
7
7
  export {};
@@ -1,13 +1,14 @@
1
1
  import path from 'node:path';
2
2
  import semver from 'semver';
3
- import { createScopedAukletLogger } from '#auklet/logger';
4
3
  import { findWorkspaceRoot } from '#auklet/workspace/root';
4
+ import { createPublishRootEnv } from '#auklet/publish/publishEnv';
5
+ import { createAukletLogger } from '#auklet/logger';
6
+ import { resolveWorkspacePackageInfos, resolveWorkspaceTargets, } from '#auklet/workspace/targets';
5
7
  import { getPublishConfig, readPackageJson, requirePackageName, requirePackageVersion, } from '#auklet/publish/api/packageJsonApi';
6
- import { readPnpmWorkspacePackages } from '#auklet/publish/api/pnpmApi';
7
8
  import { resolvePublishVersion, validateVersionConsistency, } from '#auklet/publish/version';
8
- export async function resolvePublishPlan(options, logger = createScopedAukletLogger('publish')) {
9
+ export async function resolvePublishPlan(options, runtime, logger = createAukletLogger({ scope: 'publish' })) {
9
10
  if (options.filters.length) {
10
- return resolveMonorepoPublishPlan(options, logger);
11
+ return resolveMonorepoPublishPlan(options, runtime, logger);
11
12
  }
12
13
  return resolveCurrentPackagePublishPlan(options);
13
14
  }
@@ -17,10 +18,11 @@ export async function resolveOwnerPackageNames(options) {
17
18
  }
18
19
  if (options.filters.length) {
19
20
  const root = requireWorkspaceRoot(options.cwd);
20
- const packages = await readPnpmWorkspacePackages(root);
21
- return filterWorkspacePackages(packages, options.filters)
22
- .filter((item) => !item.private)
23
- .map((item) => item.name);
21
+ const packages = await resolveWorkspacePackageInfos(root, options.filters, {
22
+ scope: 'publish',
23
+ readErrorMessage: publishWorkspaceReadErrorMessage,
24
+ });
25
+ return packages.filter((item) => !item.private).map((item) => item.name);
24
26
  }
25
27
  if (options.packages.length)
26
28
  return [...new Set(options.packages)];
@@ -55,31 +57,33 @@ const resolveCurrentPackagePublishPlan = async (options) => {
55
57
  workspaceMode: 'single',
56
58
  };
57
59
  };
58
- const resolveMonorepoPublishPlan = async (options, logger) => {
60
+ const resolveMonorepoPublishPlan = async (options, runtime, logger) => {
59
61
  const root = requireWorkspaceRoot(options.cwd);
60
62
  const rootPackageJson = readPackageJson(root);
61
63
  const rootVersion = requirePackageVersion(root, rootPackageJson);
62
- const workspacePackages = await readPnpmWorkspacePackages(root, {
64
+ const { env } = createPublishRootEnv({
63
65
  token: options.token,
64
- });
65
- const selectedPackages = filterWorkspacePackages(workspacePackages, options.filters);
66
- const targets = selectedPackages
67
- .filter((item) => {
68
- if (!item.private)
69
- return true;
70
- if (isExactlyMatchedByFilter(item.name, options.filters)) {
71
- logger.warnOnce('package ', logger.package(item.name), ' is private, skipping.');
72
- }
73
- return false;
74
- })
75
- .map((item) => {
76
- const packageJson = readPackageJson(item.path);
77
- return createPublishTarget({
66
+ }, runtime);
67
+ const targets = await resolveWorkspaceTargets({
68
+ env,
69
+ cwd: root,
70
+ scope: 'publish',
71
+ readErrorMessage: publishWorkspaceReadErrorMessage,
72
+ readPackageJson,
73
+ filters: options.filters,
74
+ getDependencies: getWorkspaceDependencies,
75
+ emptyTargetMessage: '[publish] no publishable package found.',
76
+ createTarget: (item, packageJson) => createPublishTarget({
78
77
  packageRoot: item.path,
79
78
  packageJson,
80
79
  publishVersion: '',
81
80
  workspaceMode: 'monorepo',
82
- });
81
+ }),
82
+ onPrivatePackage: (item, context) => {
83
+ if (context.exact) {
84
+ logger.warnOnce('package ', logger.package(item.name), ' is private, skipping.');
85
+ }
86
+ },
83
87
  });
84
88
  const versionBase = getMonorepoVersionBase(rootVersion, targets);
85
89
  const publishVersion = await resolvePublishVersion(versionBase, options.version, root);
@@ -96,7 +100,7 @@ const resolveMonorepoPublishPlan = async (options, logger) => {
96
100
  root,
97
101
  version: publishVersion,
98
102
  dryRun: options.dryRun,
99
- targets: sortTargetsByWorkspaceDependencies(publishTargets),
103
+ targets: publishTargets,
100
104
  config: getPublishConfig(rootPackageJson),
101
105
  workspaceMode: 'monorepo',
102
106
  };
@@ -118,23 +122,6 @@ const requireWorkspaceRoot = (cwd) => {
118
122
  }
119
123
  return root;
120
124
  };
121
- const filterWorkspacePackages = (packages, filters) => {
122
- const matched = packages.filter((item) => filters.some((filter) => matchesFilter(item.name, filter)));
123
- if (!matched.length) {
124
- throw new Error(`[publish] no workspace package matched filter: ${filters.join(', ')}`);
125
- }
126
- return matched;
127
- };
128
- const matchesFilter = (packageName, filter) => {
129
- if (filter.endsWith('/*')) {
130
- const scope = filter.slice(0, -2);
131
- return packageName.startsWith(`${scope}/`);
132
- }
133
- return packageName === filter;
134
- };
135
- const isExactlyMatchedByFilter = (packageName, filters) => {
136
- return filters.some((filter) => filter === packageName);
137
- };
138
125
  const createPublishTarget = (options) => {
139
126
  const packageName = requirePackageName(options.packageRoot, options.packageJson);
140
127
  const version = requirePackageVersion(options.packageRoot, options.packageJson);
@@ -155,39 +142,10 @@ const validatePublishTargets = (targets) => {
155
142
  throw new Error('[publish] no publishable package found.');
156
143
  }
157
144
  };
158
- const sortTargetsByWorkspaceDependencies = (targets) => {
159
- const targetNames = new Set(targets.map((target) => target.packageName));
160
- const visited = new Set();
161
- const visiting = new Set();
162
- const sorted = [];
163
- const targetMap = new Map(targets.map((target) => [target.packageName, target]));
164
- const visit = (target) => {
165
- if (visited.has(target.packageName))
166
- return;
167
- if (visiting.has(target.packageName)) {
168
- throw new Error(`[publish] circular workspace dependency detected at ${target.packageName}.`);
169
- }
170
- visiting.add(target.packageName);
171
- for (const dependency of getWorkspaceDependencies(target.packageJson)) {
172
- if (!targetNames.has(dependency))
173
- continue;
174
- const dependencyTarget = targetMap.get(dependency);
175
- if (dependencyTarget)
176
- visit(dependencyTarget);
177
- }
178
- visiting.delete(target.packageName);
179
- visited.add(target.packageName);
180
- sorted.push(target);
181
- };
182
- for (const target of targets) {
183
- visit(target);
184
- }
185
- return sorted;
186
- };
187
- const getWorkspaceDependencies = (packageJson) => {
145
+ const getWorkspaceDependencies = (target) => {
188
146
  return Object.entries({
189
- ...packageJson.dependencies,
190
- ...packageJson.optionalDependencies,
147
+ ...target.packageJson.dependencies,
148
+ ...target.packageJson.optionalDependencies,
191
149
  })
192
150
  .filter(([, version]) => version === 'workspace:*')
193
151
  .map(([packageName]) => packageName);
@@ -211,3 +169,4 @@ const workspaceDependencyGroups = [
211
169
  'optionalDependencies',
212
170
  'peerDependencies',
213
171
  ];
172
+ const publishWorkspaceReadErrorMessage = '[publish] failed to read pnpm workspace packages.';
@@ -1,3 +1,5 @@
1
+ import type { AukletEnvContext } from '#auklet/env';
2
+ import type { DeferredCliValue } from '#auklet/cli/parse/values';
1
3
  export type PackageJson = {
2
4
  name?: string;
3
5
  version?: string;
@@ -35,12 +37,6 @@ export type PublishTarget = {
35
37
  workspaceMode: 'single' | 'monorepo';
36
38
  packageJson: PackageJson;
37
39
  };
38
- export type WorkspacePackage = {
39
- name: string;
40
- path: string;
41
- version: string;
42
- private?: boolean;
43
- };
44
40
  export type PublishOptions = {
45
41
  cwd: string;
46
42
  dryRun: boolean;
@@ -50,9 +46,12 @@ export type PublishOptions = {
50
46
  filters: Array<string>;
51
47
  git?: boolean;
52
48
  otp?: string;
53
- token?: string;
49
+ token?: DeferredCliValue;
54
50
  version?: string;
55
51
  };
52
+ export type PublishRuntime = {
53
+ envContext: AukletEnvContext;
54
+ };
56
55
  export type OwnerOptions = {
57
56
  cwd: string;
58
57
  users: Array<string>;
@@ -0,0 +1,31 @@
1
+ import type { WorkspacePackageInfo } from '#auklet/workspace/packages';
2
+ type WorkspaceTargetBase<T> = {
3
+ private?: boolean;
4
+ packageJson: T;
5
+ packageName: string;
6
+ };
7
+ type ResolveWorkspaceTargetsOptions<T, TTarget> = {
8
+ cwd: string;
9
+ scope: string;
10
+ filters: Array<string>;
11
+ emptyTargetMessage: string;
12
+ excludeRoot?: boolean;
13
+ includePrivate?: boolean;
14
+ readErrorMessage?: string;
15
+ includeDependencies?: boolean;
16
+ env?: Record<string, string | undefined>;
17
+ readPackageJson: (packageRoot: string) => T;
18
+ getDependencies: (target: TTarget) => Array<string>;
19
+ createTarget: (item: WorkspacePackageInfo, packageJson: T) => TTarget;
20
+ onPrivatePackage?: (item: WorkspacePackageInfo, context: {
21
+ exact: boolean;
22
+ }) => void;
23
+ };
24
+ export declare function resolveWorkspacePackageInfos(cwd: string, filters: Array<string>, options: {
25
+ env?: Record<string, string | undefined>;
26
+ scope: string;
27
+ readErrorMessage?: string;
28
+ }): Promise<WorkspacePackageInfo[]>;
29
+ export declare function resolveWorkspaceTargets<T, K extends WorkspaceTargetBase<T>>(options: ResolveWorkspaceTargetsOptions<T, K>): Promise<K[]>;
30
+ export declare function getWorkspaceDependencyNames(value: unknown): string[];
31
+ export {};
@@ -0,0 +1,144 @@
1
+ import path from 'node:path';
2
+ import { isPlainObject } from 'aidly';
3
+ import { findWorkspaceRoot } from '#auklet/workspace/root';
4
+ import { readPnpmWorkspacePackageInfo } from '#auklet/workspace/packages';
5
+ export async function resolveWorkspacePackageInfos(cwd, filters, options) {
6
+ const root = requireWorkspaceRoot(cwd, options.scope);
7
+ const packages = await readWorkspacePackageInfo(root, options);
8
+ return filterWorkspacePackages(packages, filters, options.scope);
9
+ }
10
+ export async function resolveWorkspaceTargets(options) {
11
+ const root = requireWorkspaceRoot(options.cwd, options.scope);
12
+ const packages = filterWorkspaceRootPackage(await readWorkspacePackageInfo(root, options), root, options);
13
+ const matchedPackages = filterWorkspacePackages(packages, options.filters, options.scope);
14
+ const targetFactory = createWorkspaceTargetFactory(options);
15
+ const targets = options.includeDependencies
16
+ ? includeWorkspaceDependencies(matchedPackages, packages, targetFactory, options)
17
+ : matchedPackages
18
+ .map((item) => targetFactory.create(item))
19
+ .filter(isWorkspaceTarget);
20
+ if (!targets.length) {
21
+ throw new Error(options.emptyTargetMessage);
22
+ }
23
+ return sortWorkspaceTargets(targets, {
24
+ getDependencies: options.getDependencies,
25
+ scope: options.scope,
26
+ });
27
+ }
28
+ export function getWorkspaceDependencyNames(value) {
29
+ return isPlainObject(value) ? Object.keys(value) : [];
30
+ }
31
+ const filterWorkspaceRootPackage = (packages, root, options) => {
32
+ if (!options.excludeRoot)
33
+ return packages;
34
+ const normalizedRoot = path.resolve(root);
35
+ return packages.filter((item) => path.resolve(item.path) !== normalizedRoot);
36
+ };
37
+ const isWorkspaceTarget = (target) => {
38
+ return target !== null;
39
+ };
40
+ const createWorkspaceTargetFactory = (options) => {
41
+ const cache = new Map();
42
+ const create = (item) => {
43
+ const cached = cache.get(item.name);
44
+ if (cached !== undefined)
45
+ return cached;
46
+ if (!options.includePrivate && item.private) {
47
+ options.onPrivatePackage?.(item, {
48
+ exact: options.filters.includes(item.name),
49
+ });
50
+ cache.set(item.name, null);
51
+ return null;
52
+ }
53
+ const packageJson = options.readPackageJson(item.path);
54
+ const target = options.createTarget(item, packageJson);
55
+ cache.set(item.name, target);
56
+ return target;
57
+ };
58
+ return { create };
59
+ };
60
+ const includeWorkspaceDependencies = (matchedPackages, packages, targetFactory, options) => {
61
+ const packageMap = new Map(packages.map((item) => [item.name, item]));
62
+ const included = new Map();
63
+ const include = (item) => {
64
+ const target = targetFactory.create(item);
65
+ if (!target || included.has(target.packageName))
66
+ return;
67
+ included.set(target.packageName, target);
68
+ for (const dependency of options.getDependencies(target)) {
69
+ const dependencyItem = packageMap.get(dependency);
70
+ if (dependencyItem)
71
+ include(dependencyItem);
72
+ }
73
+ };
74
+ for (const item of matchedPackages) {
75
+ include(item);
76
+ }
77
+ return [...included.values()];
78
+ };
79
+ const requireWorkspaceRoot = (cwd, scope) => {
80
+ const root = findWorkspaceRoot(cwd);
81
+ if (!root) {
82
+ throw new Error(`[${scope}] --filter requires a pnpm workspace root.`);
83
+ }
84
+ return root;
85
+ };
86
+ const readWorkspacePackageInfo = async (root, options) => {
87
+ try {
88
+ return await readPnpmWorkspacePackageInfo(root, {
89
+ env: options.env,
90
+ });
91
+ }
92
+ catch (error) {
93
+ if (!options.readErrorMessage)
94
+ throw error;
95
+ throw new Error(options.readErrorMessage, {
96
+ cause: error,
97
+ });
98
+ }
99
+ };
100
+ const filterWorkspacePackages = (packages, filters, scope) => {
101
+ const matched = packages.filter((item) => filters.some((filter) => matchesWorkspacePackageFilter(item.name, filter)));
102
+ if (!matched.length) {
103
+ throw new Error(`[${scope}] no workspace package matched filter: ${filters.join(', ')}`);
104
+ }
105
+ return matched;
106
+ };
107
+ const matchesWorkspacePackageFilter = (packageName, filter) => {
108
+ if (filter === '*')
109
+ return true;
110
+ if (filter.endsWith('/*')) {
111
+ const scope = filter.slice(0, -2);
112
+ return packageName.startsWith(`${scope}/`);
113
+ }
114
+ return packageName === filter;
115
+ };
116
+ const sortWorkspaceTargets = (targets, options) => {
117
+ const targetNames = new Set(targets.map((target) => target.packageName));
118
+ const targetMap = new Map(targets.map((target) => [target.packageName, target]));
119
+ const sorted = [];
120
+ const visited = new Set();
121
+ const visiting = new Set();
122
+ const visit = (target) => {
123
+ if (visited.has(target.packageName))
124
+ return;
125
+ if (visiting.has(target.packageName)) {
126
+ throw new Error(`[${options.scope}] circular workspace dependency detected at ${target.packageName}.`);
127
+ }
128
+ visiting.add(target.packageName);
129
+ for (const dependency of options.getDependencies(target)) {
130
+ if (!targetNames.has(dependency))
131
+ continue;
132
+ const dependencyTarget = targetMap.get(dependency);
133
+ if (dependencyTarget)
134
+ visit(dependencyTarget);
135
+ }
136
+ visiting.delete(target.packageName);
137
+ visited.add(target.packageName);
138
+ sorted.push(target);
139
+ };
140
+ for (const target of targets) {
141
+ visit(target);
142
+ }
143
+ return sorted;
144
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auklet",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
5
  "author": "chentao.arthur",
6
6
  "description": "Build utilities for TypeScript packages and module CSS output.",
@@ -1,8 +0,0 @@
1
- import type { AukletConfig } from '#auklet/types';
2
- export declare function resolveBuildCliArgs(args: Array<string>): {
3
- args: string[];
4
- config: AukletConfig;
5
- };
6
- export declare function createBuildEnv(config: AukletConfig): {
7
- AUKLET_CONFIG_OVERRIDES: string;
8
- } | undefined;