auklet 0.1.1 → 0.1.2

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
@@ -131,6 +131,7 @@ auk publish --version patch --dry-run
131
131
  auk publish --no-format
132
132
  auk publish --no-git
133
133
  auk publish --otp 123456
134
+ auk publish --token npm_xxx
134
135
  auk inspect publish --version patch
135
136
  auk inspect pack --filter @scope/ui
136
137
  auk inspect css --modules
@@ -161,8 +162,16 @@ Before writing versions, auklet checks npm authentication from each target
161
162
  package directory. Package-local `.npmrc` files and
162
163
  `package.json#publishConfig.registry` are respected.
163
164
  `--otp` is forwarded to `pnpm publish` for npm accounts or organizations that
164
- require publish 2FA, and to `pnpm owner add` for owner management 2FA. In CI,
165
- prefer an npm automation token.
165
+ require publish 2FA, and to `pnpm owner add` for owner management 2FA.
166
+ `--token` sets `NODE_AUTH_TOKEN` and `NPM_TOKEN` for publish subprocesses. The
167
+ token still needs npmrc auth config, for example:
168
+
169
+ ```ini
170
+ //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}
171
+ ```
172
+
173
+ When a package uses `package.json#publishConfig.registry`, the npmrc token entry
174
+ must target that registry. In CI, prefer an npm automation token over `--otp`.
166
175
 
167
176
  `auk inspect publish` accepts the same publish selection and version flags as
168
177
  `auk publish`. It resolves the publish plan, checks package entry/export files,
@@ -177,7 +186,9 @@ and declared `files` paths point to existing package files.
177
186
  `auk inspect css` accepts the same build override flags as `auk build`. It
178
187
  prints the normalized CSS plan, including output entries, theme files, and
179
188
  module entries. When run from a pnpm workspace root, it inspects workspace child
180
- packages instead of the root package. It does not write CSS output.
189
+ packages instead of the root package. It does not write CSS output, but
190
+ dependency CSS files must already exist when the plan relies on external package
191
+ style entries or component auto imports.
181
192
 
182
193
  ## Configuration
183
194
 
package/dist/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { AukletConfig, StyleDependencyGroup } from '#auklet/types';
1
+ import type { AukletConfig } from '#auklet/types';
2
2
  export declare const aukletConfigFiles: string[];
3
3
  export declare function isAukletConfigFile(file: string): boolean;
4
4
  export declare const aukletDefaultOptions: {
@@ -15,7 +15,6 @@ export declare const aukletDefaultOptions: {
15
15
  dependencies: {};
16
16
  };
17
17
  };
18
- export declare const aukletDefaultStyleDependencyConfig: StyleDependencyGroup;
19
18
  export declare function normalizeAukletConfig(config?: AukletConfig): {
20
19
  source: string;
21
20
  output: string;
package/dist/config.js CHANGED
@@ -16,14 +16,6 @@ export const aukletDefaultOptions = {
16
16
  dependencies: {},
17
17
  },
18
18
  };
19
- export const aukletDefaultStyleDependencyConfig = {
20
- entry: '/style.css',
21
- components: ['/pages/**.css', '/components/**.css'],
22
- themes: {
23
- dark: '/themes/dark.css',
24
- light: '/themes/light.css',
25
- },
26
- };
27
19
  const normalizeStyleDependency = (dependency) => ({
28
20
  entry: dependency.entry,
29
21
  themes: dependency.themes,
@@ -0,0 +1,4 @@
1
+ export declare function findNpmrcWithAuthToken(packageRoot: string, root: string, registry?: string): string | undefined;
2
+ export declare function findNpmrcFiles(packageRoot: string, root: string): string[];
3
+ export declare function hasAuthToken(content: string, registry?: string): boolean;
4
+ export declare function toNpmrcRegistryKey(registry: string): string;
@@ -0,0 +1,52 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ export function findNpmrcWithAuthToken(packageRoot, root, registry) {
4
+ const npmrcFiles = findNpmrcFiles(packageRoot, root);
5
+ return npmrcFiles.find((file) => {
6
+ return hasAuthToken(fs.readFileSync(file, 'utf8'), registry);
7
+ });
8
+ }
9
+ export function findNpmrcFiles(packageRoot, root) {
10
+ const files = [];
11
+ let current = path.resolve(packageRoot);
12
+ const boundary = path.resolve(root);
13
+ while (true) {
14
+ const file = path.join(current, '.npmrc');
15
+ if (fs.existsSync(file))
16
+ files.push(file);
17
+ if (current === boundary)
18
+ break;
19
+ const parent = path.dirname(current);
20
+ if (parent === current)
21
+ break;
22
+ current = parent;
23
+ }
24
+ return files;
25
+ }
26
+ export function hasAuthToken(content, registry) {
27
+ const lines = content
28
+ .split(/\r?\n/)
29
+ .map((line) => line.trim())
30
+ .filter((line) => line && !line.startsWith('#') && !line.startsWith(';'));
31
+ if (!registry)
32
+ return lines.some((line) => line.includes('_authToken'));
33
+ const authKey = `${toNpmrcRegistryKey(registry)}:_authToken`;
34
+ return lines.some((line) => line.startsWith(authKey));
35
+ }
36
+ export function toNpmrcRegistryKey(registry) {
37
+ const url = parseRegistryUrl(registry);
38
+ const pathname = url.pathname.endsWith('/')
39
+ ? url.pathname
40
+ : `${url.pathname}/`;
41
+ return `//${url.host}${pathname}`;
42
+ }
43
+ const parseRegistryUrl = (registry) => {
44
+ try {
45
+ return new URL(registry);
46
+ }
47
+ catch (error) {
48
+ throw new Error(`[publish] invalid publishConfig.registry: ${registry}`, {
49
+ cause: error,
50
+ });
51
+ }
52
+ };
@@ -11,20 +11,28 @@ export declare function withPnpmTimeout(subprocess: ReturnType<typeof execa>, ti
11
11
  export declare function ensurePnpm(): Promise<string>;
12
12
  export declare function readPnpmWorkspacePackages(root: string): Promise<WorkspacePackage[]>;
13
13
  export declare function runPnpmBuild(packageRoot: string): Promise<void>;
14
- export declare function runPnpmPublish(packageRoot: string, args: Array<string>): Promise<void>;
14
+ export declare function runPnpmPublish(packageRoot: string, args: Array<string>, options?: {
15
+ token?: string;
16
+ }): Promise<void>;
15
17
  export declare function runPnpmWhoami(packageRoot: string, options?: {
16
18
  packageName?: string;
17
19
  registry?: string;
18
20
  timeout?: number;
21
+ token?: string;
19
22
  }): Promise<string>;
20
23
  export declare function hasPublishedPackageVersion(packageRoot: string, packageName: string, version: string, options?: {
21
24
  registry?: string;
22
25
  timeout?: number;
26
+ token?: string;
23
27
  }): Promise<boolean>;
24
28
  export declare function runPnpmOwnerAdd(packageName: string, user: string, options: {
25
29
  cwd: string;
26
30
  otp?: string;
27
31
  }): Promise<void>;
32
+ export declare function createPnpmAuthEnv(token?: string): {
33
+ NODE_AUTH_TOKEN: string;
34
+ NPM_TOKEN: string;
35
+ } | undefined;
28
36
  export declare function hasNpmAuthChallenge(result: {
29
37
  stdout?: unknown;
30
38
  stderr?: unknown;
@@ -89,10 +89,11 @@ export async function runPnpmBuild(packageRoot) {
89
89
  throw new Error(`[publish] build failed at ${packageRoot}.`);
90
90
  }
91
91
  }
92
- export async function runPnpmPublish(packageRoot, args) {
92
+ export async function runPnpmPublish(packageRoot, args, options = {}) {
93
93
  const isDryRun = args.includes('--dry-run');
94
94
  const result = await runPnpm(['publish', ...args], {
95
95
  cwd: packageRoot,
96
+ env: createPnpmAuthEnv(options.token),
96
97
  stdio: isDryRun ? 'pipe' : 'inherit',
97
98
  });
98
99
  if (isDryRun)
@@ -110,6 +111,7 @@ export async function runPnpmWhoami(packageRoot, options = {}) {
110
111
  args.push('--registry', options.registry);
111
112
  const result = await runPnpm(args, {
112
113
  cwd: packageRoot,
114
+ env: createPnpmAuthEnv(options.token),
113
115
  timeout: options.timeout,
114
116
  });
115
117
  if (hasFailedPnpmResult(result)) {
@@ -128,6 +130,7 @@ export async function hasPublishedPackageVersion(packageRoot, packageName, versi
128
130
  args.push('--registry', options.registry);
129
131
  const result = await runPnpm(args, {
130
132
  cwd: packageRoot,
133
+ env: createPnpmAuthEnv(options.token),
131
134
  timeout: options.timeout,
132
135
  });
133
136
  if (!hasFailedPnpmResult(result)) {
@@ -151,6 +154,14 @@ export async function runPnpmOwnerAdd(packageName, user, options) {
151
154
  throw new Error(`[publish] pnpm owner add failed for ${user} -> ${packageName}.`);
152
155
  }
153
156
  }
157
+ export function createPnpmAuthEnv(token) {
158
+ if (!token)
159
+ return undefined;
160
+ return {
161
+ NODE_AUTH_TOKEN: token,
162
+ NPM_TOKEN: token,
163
+ };
164
+ }
154
165
  const isWorkspacePackage = (value) => {
155
166
  if (!isPlainObject(value)) {
156
167
  return false;
@@ -2,6 +2,11 @@ import { runPnpmPublish } from '#auklet/publish/api/pnpmApi';
2
2
  import { createPublishArgs } from '#auklet/publish/api/publishArgs';
3
3
  export class PnpmPublishApi {
4
4
  async publish(target, options) {
5
- await runPnpmPublish(target.packageRoot, createPublishArgs(target, options));
5
+ const args = createPublishArgs(target, options);
6
+ if (options.token) {
7
+ await runPnpmPublish(target.packageRoot, args, { token: options.token });
8
+ return;
9
+ }
10
+ await runPnpmPublish(target.packageRoot, args);
6
11
  }
7
12
  }
@@ -9,5 +9,6 @@ export declare function resolvePublishCliOptions(args: Array<string>, cwd?: stri
9
9
  dryRun: boolean;
10
10
  allowDirty: boolean;
11
11
  ignoreScripts: boolean;
12
+ token: string | undefined;
12
13
  };
13
14
  export declare function runOwnerCli(args: Array<string>): Promise<void>;
@@ -11,6 +11,7 @@ const publishFlags = new Set([
11
11
  'format',
12
12
  'git',
13
13
  'otp',
14
+ 'token',
14
15
  'ignore-scripts',
15
16
  'allow-dirty',
16
17
  ]);
@@ -34,13 +35,14 @@ export function resolvePublishCliOptions(args, cwd = process.cwd()) {
34
35
  dryRun: argv['dry-run'] === true,
35
36
  allowDirty: argv['allow-dirty'] === true,
36
37
  ignoreScripts: argv['ignore-scripts'] === true,
38
+ token: stringOption(argv.token),
37
39
  };
38
40
  }
39
41
  const parsePublishArgs = (args) => {
40
42
  const cliArgs = stripLeadingArgsSeparator(args);
41
43
  validateNoPrefixedFlags(cliArgs, new Set(['--no-format', '--no-git']));
42
44
  const argv = minimist(cliArgs, {
43
- string: ['filter', 'version', 'otp'],
45
+ string: ['filter', 'version', 'otp', 'token'],
44
46
  boolean: ['dry-run', 'format', 'git', 'ignore-scripts', 'allow-dirty'],
45
47
  default: {
46
48
  git: true,
@@ -22,6 +22,7 @@ export async function runInspectPublishCli(args) {
22
22
  const spinner = logger.spinner('Checking publish registry');
23
23
  spinner.start();
24
24
  const registryChecks = await inspectPublishRegistry(plan, {
25
+ token: options.token,
25
26
  onCheck: (info) => {
26
27
  spinner.text([
27
28
  'Checking registry ',
@@ -1,4 +1,4 @@
1
- import type { PublishPlan } from '#auklet/publish/types';
1
+ import type { PublishOptions, PublishPlan } from '#auklet/publish/types';
2
2
  export type PublishRegistryCheckStatus = 'success' | 'error';
3
3
  export type PublishRegistryCheck = {
4
4
  packageName: string;
@@ -17,6 +17,7 @@ export type PublishRegistryRetryInfo = {
17
17
  };
18
18
  export type PublishRegistryCheckInfo = Pick<PublishRegistryRetryInfo, 'packageName' | 'registry' | 'check'>;
19
19
  export type InspectPublishRegistryOptions = {
20
+ token?: PublishOptions['token'];
20
21
  onCheck?: (info: PublishRegistryCheckInfo) => void;
21
22
  onRetry?: (info: PublishRegistryRetryInfo) => void;
22
23
  };
@@ -35,6 +35,7 @@ const checkAuth = async (authResults, authKey, packageRoot, packageName, registr
35
35
  await retryWithLog(() => runPnpmWhoami(packageRoot, {
36
36
  packageName,
37
37
  registry,
38
+ token: options.token,
38
39
  timeout: registryCheckTimeout,
39
40
  }), {
40
41
  check: 'auth',
@@ -60,6 +61,7 @@ const checkVersion = async (packageRoot, packageName, version, registry, options
60
61
  });
61
62
  const exists = await retryWithLog(() => hasPublishedPackageVersion(packageRoot, packageName, version, {
62
63
  registry,
64
+ token: options.token,
63
65
  timeout: registryCheckTimeout,
64
66
  }), {
65
67
  check: 'version',
@@ -7,6 +7,7 @@ export declare class PublishPreflight {
7
7
  constructor(options: PublishOptions, logger: AukletLogger);
8
8
  run(plan: PublishPlan): Promise<void>;
9
9
  verifyBeforeBuild(plan: PublishPlan): Promise<void>;
10
+ private verifyTokenConfig;
10
11
  private verifyAuthentication;
11
12
  private verifyPnpmPublishDryRun;
12
13
  private verifyPackageVersions;
@@ -1,5 +1,6 @@
1
1
  import { PnpmPublishApi } from '#auklet/publish/api/pnpmPublishApi';
2
2
  import { hasPublishedPackageVersion, NpmPackageVersionExistsError, runPnpmWhoami, } from '#auklet/publish/api/pnpmApi';
3
+ import { findNpmrcFiles, findNpmrcWithAuthToken, toNpmrcRegistryKey, } from '#auklet/publish/api/npmrc';
3
4
  import { getPublishRegistry } from '#auklet/publish/api/registry';
4
5
  import { logAuthenticationError } from '#auklet/publish/runner/packagePublisher';
5
6
  import { PublishTargetError } from '#auklet/publish/runner/publishTargetError';
@@ -15,11 +16,23 @@ export class PublishPreflight {
15
16
  await this.verifyPnpmPublishDryRun(plan);
16
17
  }
17
18
  async verifyBeforeBuild(plan) {
19
+ this.verifyTokenConfig(plan);
18
20
  if (plan.dryRun)
19
21
  return;
20
22
  await this.verifyAuthentication(plan);
21
23
  await this.verifyPackageVersions(plan);
22
24
  }
25
+ verifyTokenConfig(plan) {
26
+ if (!this.options.token)
27
+ return;
28
+ for (const target of plan.targets) {
29
+ const registry = getPublishRegistry(target.packageJson.publishConfig);
30
+ const npmrc = findNpmrcWithAuthToken(target.packageRoot, plan.root, registry);
31
+ if (npmrc)
32
+ continue;
33
+ throw new PublishTargetError(target, 'preflight', new Error(createMissingNpmrcAuthMessage(target, plan.root, registry)), []);
34
+ }
35
+ }
23
36
  async verifyAuthentication(plan) {
24
37
  const checked = new Set();
25
38
  for (const target of plan.targets) {
@@ -30,6 +43,7 @@ export class PublishPreflight {
30
43
  await runPnpmWhoami(target.packageRoot, {
31
44
  packageName: target.packageName,
32
45
  registry,
46
+ token: this.options.token,
33
47
  });
34
48
  checked.add(key);
35
49
  }
@@ -52,7 +66,7 @@ export class PublishPreflight {
52
66
  async verifyPackageVersions(plan) {
53
67
  for (const target of plan.targets) {
54
68
  const registry = getPublishRegistry(target.packageJson.publishConfig);
55
- const exists = await hasPublishedPackageVersion(target.packageRoot, target.packageName, target.publishVersion, { registry });
69
+ const exists = await hasPublishedPackageVersion(target.packageRoot, target.packageName, target.publishVersion, { registry, token: this.options.token });
56
70
  if (!exists)
57
71
  continue;
58
72
  this.logExistingVersion(target, registry);
@@ -66,3 +80,20 @@ export class PublishPreflight {
66
80
  }
67
81
  }
68
82
  }
83
+ function createMissingNpmrcAuthMessage(target, root, registry) {
84
+ const npmrcFiles = findNpmrcFiles(target.packageRoot, root);
85
+ const authTarget = registry
86
+ ? `${toNpmrcRegistryKey(registry)}:_authToken`
87
+ : '_authToken';
88
+ const registryHint = registry
89
+ ? `[publish] ${target.packageName} uses publishConfig.registry: ${registry}.\n`
90
+ : '';
91
+ const location = npmrcFiles.length
92
+ ? 'found npmrc files, but none declares'
93
+ : 'could not find an npmrc file declaring';
94
+ return (`[publish] --token requires npmrc auth config for ${target.packageName}.\n` +
95
+ registryHint +
96
+ `[publish] ${location} ${authTarget}.\n` +
97
+ '[publish] Add an npmrc entry such as:\n' +
98
+ ` ${authTarget}=\${NODE_AUTH_TOKEN}`);
99
+ }
@@ -50,6 +50,7 @@ export type PublishOptions = {
50
50
  filters: Array<string>;
51
51
  git?: boolean;
52
52
  otp?: string;
53
+ token?: string;
53
54
  version?: string;
54
55
  };
55
56
  export type OwnerOptions = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auklet",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "author": "chentao.arthur",
6
6
  "description": "Build utilities for TypeScript packages and module CSS output.",