auklet 0.0.20 → 0.0.22

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
@@ -24,17 +24,18 @@ Requirements:
24
24
 
25
25
  ## Quick Start
26
26
 
27
- `auklet.config.ts` is optional. Without it, auklet uses `src` as source,
28
- `dist` as output, no module output, and default JavaScript formats.
27
+ `auklet.config.js` or `auklet.config.mjs` is optional. Without it, auklet uses
28
+ `src` as source, `dist` as output, no module output, and default JavaScript
29
+ formats.
29
30
 
30
31
  For a component package, a minimal config usually looks like this:
31
32
 
32
- ```ts
33
- import type { AukletConfig } from 'auklet';
33
+ ```js
34
+ import { defineConfig } from 'auklet';
34
35
 
35
- export const config: AukletConfig = {
36
+ export const config = defineConfig({
36
37
  modules: true,
37
- };
38
+ });
38
39
  ```
39
40
 
40
41
  Build JavaScript and CSS output:
@@ -101,7 +102,7 @@ Supported build override flags:
101
102
  Config precedence:
102
103
 
103
104
  ```text
104
- CLI flags > auklet.config.ts > auklet defaults
105
+ CLI flags > auklet.config.js / auklet.config.mjs > auklet defaults
105
106
  ```
106
107
 
107
108
  `build-js` passes unknown flags through to tsdown. Auklet build override flags
@@ -115,8 +116,8 @@ auk build-js --modules --no-config
115
116
  ```
116
117
 
117
118
  When `--config`, `-c`, or `--no-config` is used, tsdown owns the full build
118
- config. Use `auklet.config.ts` or tsdown config code directly instead of auklet
119
- CLI overrides.
119
+ config. Use auklet config files or tsdown config code directly instead of
120
+ auklet CLI overrides.
120
121
 
121
122
  Publish controls stay on CLI flags:
122
123
 
@@ -131,12 +132,13 @@ configured in `package.json`.
131
132
 
132
133
  ## Configuration
133
134
 
134
- `auklet.config.ts` is loaded from the current package root:
135
+ `auklet.config.js` or `auklet.config.mjs` is loaded from the current package
136
+ root. Config files must export a named `config` binding:
135
137
 
136
- ```ts
137
- import type { AukletConfig } from 'auklet';
138
+ ```js
139
+ import { defineConfig } from 'auklet';
138
140
 
139
- export const config: AukletConfig = {
141
+ export const config = defineConfig({
140
142
  source: 'src',
141
143
  output: 'dist',
142
144
  modules: true,
@@ -155,7 +157,7 @@ export const config: AukletConfig = {
155
157
  },
156
158
  },
157
159
  },
158
- };
160
+ });
159
161
  ```
160
162
 
161
163
  Configuration reference:
@@ -1,3 +1,4 @@
1
+ import { isArray } from 'aidly';
1
2
  import { getBundleEntry } from '#auklet/build/tsdown/entries';
2
3
  import { getIifeAlwaysBundle, getIifeGlobals, } from '#auklet/build/tsdown/dependencies';
3
4
  import { configureTsdown, createCommonConfig, } from '#auklet/build/tsdown/common';
@@ -26,7 +27,7 @@ export function createBundleConfigs(context, formats) {
26
27
  let hasDtsConfig = false;
27
28
  for (const format of formats) {
28
29
  const extnames = formatMap[format];
29
- for (const extname of Array.isArray(extnames) ? extnames : [extnames]) {
30
+ for (const extname of isArray(extnames) ? extnames : [extnames]) {
30
31
  const emitDts = !hasDtsConfig;
31
32
  outputConfigs.push({ format, extname, dts: emitDts });
32
33
  hasDtsConfig ||= emitDts;
@@ -13,10 +13,19 @@ export function hasTsdownConfigArg(args) {
13
13
  args[index - 1] === '-c' ||
14
14
  args[index - 1] === '--config');
15
15
  }
16
+ const hasTsdownConfigLoaderArg = (args) => {
17
+ return args.some((arg, index) => arg === '--config-loader' ||
18
+ arg.startsWith('--config-loader=') ||
19
+ args[index - 1] === '--config-loader');
20
+ };
16
21
  export function createTsdownArgs(args) {
17
- const tsdownArgs = hasTsdownConfigArg(args)
18
- ? args
19
- : ['--config', defaultConfigFile, ...args];
22
+ if (hasTsdownConfigArg(args)) {
23
+ return [tsdownRunFile, ...args];
24
+ }
25
+ const loaderArgs = hasTsdownConfigLoaderArg(args)
26
+ ? []
27
+ : ['--config-loader', 'native'];
28
+ const tsdownArgs = ['--config', defaultConfigFile, ...loaderArgs, ...args];
20
29
  return [tsdownRunFile, ...tsdownArgs];
21
30
  }
22
31
  export async function runTsdown(args, options = {}) {
package/dist/config.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { AukletConfig, StyleDependencyGroup } from '#auklet/types';
2
- export declare const aukletConfigFile = "auklet.config.ts";
2
+ export declare const aukletConfigFiles: string[];
3
+ export declare function isAukletConfigFile(file: string): boolean;
3
4
  export declare const aukletDefaultOptions: {
4
5
  source: string;
5
6
  output: string;
@@ -42,3 +43,4 @@ export declare function normalizeAukletConfig(config?: AukletConfig): {
42
43
  };
43
44
  };
44
45
  };
46
+ export declare function defineConfig(config: AukletConfig): AukletConfig;
package/dist/config.js CHANGED
@@ -1,4 +1,7 @@
1
- export const aukletConfigFile = 'auklet.config.ts';
1
+ export const aukletConfigFiles = ['auklet.config.js', 'auklet.config.mjs'];
2
+ export function isAukletConfigFile(file) {
3
+ return aukletConfigFiles.includes(file);
4
+ }
2
5
  export const aukletDefaultOptions = {
3
6
  source: 'src',
4
7
  output: 'dist',
@@ -45,3 +48,6 @@ export function normalizeAukletConfig(config = {}) {
45
48
  },
46
49
  };
47
50
  }
51
+ export function defineConfig(config) {
52
+ return config;
53
+ }
@@ -1,3 +1,4 @@
1
1
  import type { AukletConfig, LoadAukletConfigOptions } from '#auklet/types';
2
+ export declare function resolveAukletConfigPath(packageRoot: string, configFile?: string): string | null;
2
3
  export declare function resolveAukletConfigModule(module: Record<string, unknown>): AukletConfig;
3
4
  export declare function loadAukletConfig(packageRoot: string, options?: LoadAukletConfigOptions): Promise<AukletConfig>;
@@ -1,79 +1,60 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { fileURLToPath, pathToFileURL } from 'node:url';
4
- import ts from 'typescript';
5
- import { aukletConfigFile } from '#auklet/config';
6
- const importAukletConfigModule = async (configPath, href) => {
7
- try {
8
- return (await import(href));
9
- }
10
- catch (error) {
11
- if (!isUnknownTsExtensionError(error) || !configPath.endsWith('.ts')) {
12
- throw error;
13
- }
14
- return importTsOptionsModule(href);
15
- }
16
- };
17
- const importTsOptionsModule = async (href) => {
18
- const configPath = fileURLToPath(href);
19
- const source = fs.readFileSync(configPath, 'utf8');
20
- const output = ts.transpileModule(source, {
21
- compilerOptions: {
22
- esModuleInterop: true,
23
- module: ts.ModuleKind.ESNext,
24
- target: ts.ScriptTarget.ES2020,
25
- },
26
- fileName: configPath,
27
- });
28
- const tempFile = path.join(path.dirname(configPath), `.auklet.config.${process.pid}.${Date.now()}.mjs`);
29
- fs.writeFileSync(tempFile, output.outputText);
30
- try {
31
- return (await import(pathToFileURL(tempFile).href));
32
- }
33
- finally {
34
- fs.rmSync(tempFile, { force: true });
35
- }
3
+ import { pathToFileURL } from 'node:url';
4
+ import { isPlainObject } from 'aidly';
5
+ import { aukletConfigFiles, isAukletConfigFile } from '#auklet/config';
6
+ const asRecord = (value) => {
7
+ return isPlainObject(value) ? value : null;
36
8
  };
37
- const isUnknownTsExtensionError = (error) => {
38
- return (error instanceof TypeError &&
39
- 'code' in error &&
40
- error.code === 'ERR_UNKNOWN_FILE_EXTENSION');
9
+ const assertSupportedConfigFile = (configFile) => {
10
+ const basename = path.basename(configFile);
11
+ if (isAukletConfigFile(basename))
12
+ return;
13
+ throw new Error('[auklet] unsupported config file: ' +
14
+ basename +
15
+ '. Use auklet.config.js or auklet.config.mjs and export `config`.');
41
16
  };
42
- const asRecord = (value) => {
43
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
17
+ export function resolveAukletConfigPath(packageRoot, configFile) {
18
+ if (!fs.existsSync(packageRoot))
44
19
  return null;
20
+ if (configFile) {
21
+ assertSupportedConfigFile(configFile);
22
+ const configPath = path.join(packageRoot, configFile);
23
+ return fs.existsSync(configPath) ? configPath : null;
24
+ }
25
+ const configPaths = aukletConfigFiles
26
+ .map((file) => path.join(packageRoot, file))
27
+ .filter((file) => fs.existsSync(file));
28
+ if (configPaths.length > 1) {
29
+ throw new Error('[auklet] found multiple config files: ' +
30
+ configPaths.map((file) => path.basename(file)).join(', ') +
31
+ '. Keep only one auklet config file.');
32
+ }
33
+ if (configPaths[0])
34
+ return configPaths[0];
35
+ for (const file of fs.readdirSync(packageRoot)) {
36
+ if (file.startsWith('auklet.config.') && !isAukletConfigFile(file)) {
37
+ assertSupportedConfigFile(file);
38
+ }
45
39
  }
46
- return value;
47
- };
40
+ return null;
41
+ }
48
42
  export function resolveAukletConfigModule(module) {
49
- const candidates = [
50
- module,
51
- asRecord(module.default),
52
- asRecord(module['module.exports']),
53
- ];
54
- for (const candidate of candidates) {
55
- if (!candidate)
56
- continue;
57
- const config = asRecord(candidate.config);
58
- if (config) {
59
- return config;
60
- }
43
+ const config = asRecord(module.config);
44
+ if (!config) {
45
+ throw new Error('[auklet] config file must export `config`.');
61
46
  }
62
- return {};
47
+ return config;
63
48
  }
64
49
  export async function loadAukletConfig(packageRoot, options = {}) {
65
- const configPath = path.join(packageRoot, options.configFile ?? aukletConfigFile);
66
- if (!fs.existsSync(configPath)) {
50
+ const configPath = resolveAukletConfigPath(packageRoot, options.configFile);
51
+ if (!configPath) {
67
52
  return {};
68
53
  }
69
54
  const url = pathToFileURL(configPath);
70
55
  if (options.cacheBust) {
71
56
  url.searchParams.set('t', Date.now().toString());
72
57
  }
73
- if (configPath.endsWith('.ts')) {
74
- const module = await importTsOptionsModule(url.href);
75
- return resolveAukletConfigModule(module);
76
- }
77
- const module = await importAukletConfigModule(configPath, url.href);
58
+ const module = (await import(url.href));
78
59
  return resolveAukletConfigModule(module);
79
60
  }
@@ -1,4 +1,5 @@
1
1
  import path from 'node:path';
2
+ import { isString } from 'aidly';
2
3
  import { normalizeFileKey } from '#auklet/utils';
3
4
  import { createScopedAukletLogger } from '#auklet/logger';
4
5
  // package CSS 的 HMR 不能直接走 Vite 原生 CSS 文件链路:
@@ -59,13 +60,13 @@ export class AukletStyleHmr {
59
60
  installFullReloadGuard(server) {
60
61
  const send = server.ws.send.bind(server.ws);
61
62
  server.ws.send = ((payload, data) => {
62
- if (typeof payload !== 'string' &&
63
+ if (!isString(payload) &&
63
64
  payload.type === 'full-reload' &&
64
65
  this.shouldSuppressFullReload()) {
65
66
  logger.info('suppressed package css full-reload');
66
67
  return;
67
68
  }
68
- if (typeof payload === 'string') {
69
+ if (isString(payload)) {
69
70
  send(payload, data);
70
71
  return;
71
72
  }
@@ -1,5 +1,5 @@
1
1
  import path from 'node:path';
2
- import { aukletConfigFile } from '#auklet/config';
2
+ import { isAukletConfigFile } from '#auklet/config';
3
3
  import { loadAukletConfig } from '#auklet/configLoader';
4
4
  import { moduleStyleBuildConfig } from '#auklet/css/config';
5
5
  import { parsePackageStyleId } from '#auklet/css/vite/moduleGraph/styleId';
@@ -37,7 +37,7 @@ export class ModuleStyleGraph {
37
37
  return this.packageSource.isSourceGraphFile(file);
38
38
  }
39
39
  isStyleConfigFile(file) {
40
- return normalizeFileKey(file).endsWith(aukletConfigFile);
40
+ return isAukletConfigFile(path.basename(normalizeFileKey(file)));
41
41
  }
42
42
  isStyleFile(file) {
43
43
  return this.config.styleExtensions.includes(path.extname(file));
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { aukletConfigFile } from '#auklet/config';
3
+ import { aukletConfigFiles, isAukletConfigFile } from '#auklet/config';
4
4
  import { SOURCE_MODULE_RE } from '#auklet/css/constants';
5
5
  import { normalizeFileKey, toPosixPath, toWatchPath } from '#auklet/utils';
6
6
  import { readPnpmWorkspacePackageInfoSync } from '#auklet/workspace/packages';
@@ -34,7 +34,7 @@ export class MonorepoPackageSource {
34
34
  if (!packages.some((item) => isPackageFile(item, normalizedFile))) {
35
35
  return false;
36
36
  }
37
- if (normalizedFile.endsWith(aukletConfigFile))
37
+ if (isAukletConfigFile(path.basename(normalizedFile)))
38
38
  return true;
39
39
  if (SOURCE_MODULE_RE.test(normalizedFile))
40
40
  return true;
@@ -43,7 +43,7 @@ export class MonorepoPackageSource {
43
43
  async getWatchRoots() {
44
44
  return this.getPackages().flatMap((item) => [
45
45
  toWatchPath(item.packageRoot, 'src'),
46
- toWatchPath(item.packageRoot, aukletConfigFile),
46
+ ...aukletConfigFiles.map((file) => toWatchPath(item.packageRoot, file)),
47
47
  ]);
48
48
  }
49
49
  getWorkspacePackages() {
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { aukletConfigFile, normalizeAukletConfig } from '#auklet/config';
3
+ import { aukletConfigFiles, isAukletConfigFile, normalizeAukletConfig, } from '#auklet/config';
4
4
  import { loadAukletConfig } from '#auklet/configLoader';
5
5
  import { SOURCE_MODULE_RE } from '#auklet/css/constants';
6
6
  import { normalizeFileKey, toWatchPath } from '#auklet/utils';
@@ -27,7 +27,7 @@ export class SinglePackageSource {
27
27
  const normalizedFile = normalizeFileKey(file);
28
28
  if (!this.isInsidePackage(normalizedFile))
29
29
  return false;
30
- if (normalizedFile.endsWith(aukletConfigFile))
30
+ if (isAukletConfigFile(path.basename(normalizedFile)))
31
31
  return true;
32
32
  if (SOURCE_MODULE_RE.test(normalizedFile))
33
33
  return true;
@@ -37,7 +37,7 @@ export class SinglePackageSource {
37
37
  const normalizedConfig = normalizeAukletConfig(await this.loadAukletConfig(this.root, { cacheBust: true }));
38
38
  return [
39
39
  toWatchPath(this.root, normalizedConfig.source),
40
- toWatchPath(this.root, aukletConfigFile),
40
+ ...aukletConfigFiles.map((file) => toWatchPath(this.root, file)),
41
41
  ];
42
42
  }
43
43
  getPackageInfo() {
@@ -9,7 +9,7 @@ export type PackageStyleContext = {
9
9
  context: ResolvedModuleStyleBuildContext;
10
10
  packageContext: StylePackageContext;
11
11
  packageName: string;
12
- configPath: string;
12
+ configPaths: Array<string>;
13
13
  resolver: WorkspaceStyleResolver;
14
14
  sourceRoot: string;
15
15
  styleProcessor: StyleProcessor;
@@ -27,6 +27,9 @@ export declare class ModuleStyleGraphRequestCache {
27
27
  getPackageNames(): string[];
28
28
  isKnownPackageName(packageName: string): boolean;
29
29
  getContext(parsed: PackageStyleId): Promise<PackageStyleContext | {
30
+ context: ResolvedModuleStyleBuildContext;
31
+ configPaths: string[];
32
+ packageContext: StylePackageContext;
30
33
  normalizedConfig: {
31
34
  source: string;
32
35
  output: string;
@@ -54,10 +57,7 @@ export declare class ModuleStyleGraphRequestCache {
54
57
  };
55
58
  };
56
59
  };
57
- context: ResolvedModuleStyleBuildContext;
58
- packageContext: StylePackageContext;
59
60
  packageName: string;
60
- configPath: string;
61
61
  resolver: WorkspaceStyleResolver;
62
62
  sourceRoot: string;
63
63
  styleProcessor: StyleProcessor;
@@ -1,6 +1,6 @@
1
1
  import path from 'node:path';
2
- import { aukletConfigFile, normalizeAukletConfig } from '#auklet/config';
3
- import { loadAukletConfig } from '#auklet/configLoader';
2
+ import { loadAukletConfig, resolveAukletConfigPath, } from '#auklet/configLoader';
3
+ import { aukletConfigFiles, normalizeAukletConfig } from '#auklet/config';
4
4
  import { StylePackageContext } from '#auklet/css/core/stylePackageContext';
5
5
  export class ModuleStyleGraphRequestCache {
6
6
  options;
@@ -31,6 +31,10 @@ export class ModuleStyleGraphRequestCache {
31
31
  if (!stylePackage)
32
32
  return null;
33
33
  const packageRoot = stylePackage.packageRoot;
34
+ const configPath = resolveAukletConfigPath(packageRoot);
35
+ const configPaths = configPath
36
+ ? [configPath]
37
+ : aukletConfigFiles.map((file) => path.join(packageRoot, file));
34
38
  const rawConfig = await this.loadAukletConfig(packageRoot, {
35
39
  cacheBust: true,
36
40
  });
@@ -46,11 +50,11 @@ export class ModuleStyleGraphRequestCache {
46
50
  normalizedConfig,
47
51
  });
48
52
  return {
49
- normalizedConfig,
50
53
  context,
54
+ configPaths,
51
55
  packageContext,
56
+ normalizedConfig,
52
57
  packageName: parsed.packageName,
53
- configPath: path.join(packageRoot, aukletConfigFile),
54
58
  resolver: packageContext.resolver,
55
59
  sourceRoot: packageContext.sourceRoot,
56
60
  styleProcessor: packageContext.styleProcessor,
@@ -53,7 +53,7 @@ export class StyleCodeFactory {
53
53
  async createDependencyStyleCode(context, cache, specifiers, mapSpecifier = (specifier) => specifier) {
54
54
  const results = [];
55
55
  const imports = [];
56
- const watchFiles = [context.configPath];
56
+ const watchFiles = [...context.configPaths];
57
57
  for (const specifier of specifiers) {
58
58
  const outputSpecifier = mapSpecifier(specifier);
59
59
  const parsed = this.parsePackageStyleIdInRequest(outputSpecifier, cache);
@@ -83,7 +83,7 @@ export class StyleCodeFactory {
83
83
  const { themeFiles } = context.packageContext;
84
84
  const targetThemeNames = themeNames ?? context.packageContext.themeNames;
85
85
  const root = context.styleProcessor.createRoot();
86
- const watchFiles = [context.configPath, ...themeFiles.values()];
86
+ const watchFiles = [...context.configPaths, ...themeFiles.values()];
87
87
  const dependencyResults = [];
88
88
  for (const themeName of targetThemeNames) {
89
89
  for (const part of createThemeEntryParts(context.normalizedConfig, themeName, {
@@ -122,7 +122,7 @@ export class StyleCodeFactory {
122
122
  }
123
123
  return {
124
124
  code: root.nodes?.length ? context.styleProcessor.stringify(root) : '',
125
- watchFiles: [context.configPath, ...styleFiles],
125
+ watchFiles: [...context.configPaths, ...styleFiles],
126
126
  };
127
127
  }
128
128
  async createSourceModuleStyleCode(context, cache, stylePath) {
@@ -162,7 +162,7 @@ export class StyleCodeFactory {
162
162
  .filter((code) => code.trim())
163
163
  .join('\n'),
164
164
  watchFiles: [
165
- context.configPath,
165
+ ...context.configPaths,
166
166
  ...styleFiles,
167
167
  ...moduleStyleWatchFiles,
168
168
  ...sourceFiles.filter((file) => /\.(ts|tsx)$/.test(file)),
@@ -1,7 +1,8 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import chokidar from 'chokidar';
4
- import { aukletConfigFile, aukletDefaultOptions } from '#auklet/config';
4
+ import { isString } from 'aidly';
5
+ import { aukletConfigFiles, aukletDefaultOptions, isAukletConfigFile, } from '#auklet/config';
5
6
  import { moduleStyleBuildConfig } from '#auklet/css/config';
6
7
  import { SOURCE_MODULE_RE } from '#auklet/css/constants';
7
8
  import { ModuleStyleBuilder } from '#auklet/css/production/builder';
@@ -48,8 +49,8 @@ export class ModuleStyleWatcher {
48
49
  const aukletConfig = this.context.aukletConfig ?? {};
49
50
  const sourceDir = this.context.source ?? aukletConfig.source ?? aukletDefaultOptions.source;
50
51
  const sourceRoot = path.join(this.context.packageRoot, sourceDir);
51
- const configPath = path.join(this.context.packageRoot, aukletConfigFile);
52
- const watchPaths = [sourceRoot, configPath].filter((file) => fs.existsSync(file));
52
+ const configPaths = aukletConfigFiles.map((file) => path.join(this.context.packageRoot, file));
53
+ const watchPaths = [sourceRoot, ...configPaths].filter((file) => fs.existsSync(file));
53
54
  await this.watcher?.close();
54
55
  this.watcher = chokidar.watch(watchPaths, {
55
56
  ignoreInitial: true,
@@ -57,7 +58,7 @@ export class ModuleStyleWatcher {
57
58
  usePolling: true,
58
59
  });
59
60
  this.watcher.on('all', (_event, file) => {
60
- if (typeof file === 'string' && !this.shouldRebuildForFile(file)) {
61
+ if (isString(file) && !this.shouldRebuildForFile(file)) {
61
62
  return;
62
63
  }
63
64
  this.scheduleBuild();
@@ -73,7 +74,7 @@ export class ModuleStyleWatcher {
73
74
  }, 80);
74
75
  }
75
76
  shouldRebuildForFile(file) {
76
- if (path.basename(file) === aukletConfigFile)
77
+ if (isAukletConfigFile(path.basename(file)))
77
78
  return true;
78
79
  if (SOURCE_MODULE_RE.test(file))
79
80
  return true;
package/dist/index.d.ts CHANGED
@@ -3,5 +3,6 @@ export type { AukletStylePluginOptions } from '#auklet/css/vite/vitePlugin';
3
3
  export { runAukletCli } from '#auklet/cli/main';
4
4
  export { runTsdown } from '#auklet/build/runTsdown';
5
5
  export { loadAukletConfig } from '#auklet/configLoader';
6
+ export { defineConfig } from '#auklet/config';
6
7
  export { aukletStylePlugin } from '#auklet/css/vite/vitePlugin';
7
8
  export { defineKernelPackageConfigFromFile, defineKernelPackageConfigFromOptions, } from '#auklet/build/tsdownConfig';
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { runAukletCli } from '#auklet/cli/main';
2
2
  export { runTsdown } from '#auklet/build/runTsdown';
3
3
  export { loadAukletConfig } from '#auklet/configLoader';
4
+ export { defineConfig } from '#auklet/config';
4
5
  export { aukletStylePlugin } from '#auklet/css/vite/vitePlugin';
5
6
  export { defineKernelPackageConfigFromFile, defineKernelPackageConfigFromOptions, } from '#auklet/build/tsdownConfig';
@@ -1,5 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
+ import { isString } from 'aidly';
3
4
  const packageJsonFile = 'package.json';
4
5
  export function getPackageJsonPath(packageRoot) {
5
6
  return path.join(packageRoot, packageJsonFile);
@@ -18,13 +19,13 @@ export function writePackageJson(packageRoot, packageJson) {
18
19
  fs.writeFileSync(filePath, `${JSON.stringify(packageJson, null, 2)}\n`);
19
20
  }
20
21
  export function requirePackageName(packageRoot, packageJson) {
21
- if (typeof packageJson.name === 'string' && packageJson.name) {
22
+ if (isString(packageJson.name) && packageJson.name) {
22
23
  return packageJson.name;
23
24
  }
24
25
  throw new Error(`[auklet:publish] package.json#name is required at ${packageRoot}.`);
25
26
  }
26
27
  export function requirePackageVersion(packageRoot, packageJson) {
27
- if (typeof packageJson.version === 'string' && packageJson.version) {
28
+ if (isString(packageJson.version) && packageJson.version) {
28
29
  return packageJson.version;
29
30
  }
30
31
  throw new Error(`[auklet:publish] package.json#version is required at ${packageRoot}.`);
@@ -3,6 +3,7 @@ export declare function ensurePnpm(): Promise<string>;
3
3
  export declare function readPnpmWorkspacePackages(root: string): Promise<WorkspacePackage[]>;
4
4
  export declare function runPnpmBuild(packageRoot: string): Promise<void>;
5
5
  export declare function runPnpmPublish(packageRoot: string, args: Array<string>): Promise<void>;
6
+ export declare function runPnpmWhoami(root: string): Promise<string>;
6
7
  export declare function runPnpmOwnerAdd(packageName: string, user: string, options: {
7
8
  cwd: string;
8
9
  otp?: string;
@@ -1,3 +1,4 @@
1
+ import { isPlainObject, isString } from 'aidly';
1
2
  import { execa } from 'execa';
2
3
  import semver from 'semver';
3
4
  import { readPnpmWorkspacePackageInfo } from '#auklet/workspace/packages';
@@ -54,6 +55,16 @@ export async function runPnpmPublish(packageRoot, args) {
54
55
  throw new Error(`[auklet:publish] pnpm publish failed at ${packageRoot}.`);
55
56
  }
56
57
  }
58
+ export async function runPnpmWhoami(root) {
59
+ const result = await runPnpm(['whoami'], {
60
+ cwd: root,
61
+ });
62
+ if (result.exitCode) {
63
+ throw new Error('[auklet:publish] npm authentication is required before publishing.\n' +
64
+ '[auklet:publish] Run `pnpm login` or configure an npm token before retrying.');
65
+ }
66
+ return String(result.stdout ?? '').trim();
67
+ }
57
68
  export async function runPnpmOwnerAdd(packageName, user, options) {
58
69
  const args = ['owner', 'add', user, packageName];
59
70
  if (options.otp)
@@ -67,17 +78,16 @@ export async function runPnpmOwnerAdd(packageName, user, options) {
67
78
  }
68
79
  }
69
80
  const isWorkspacePackage = (value) => {
70
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
81
+ if (!isPlainObject(value)) {
71
82
  return false;
72
83
  }
73
- const item = value;
74
- return (typeof item.name === 'string' &&
75
- item.name.length > 0 &&
76
- typeof item.path === 'string' &&
77
- item.path.length > 0 &&
78
- typeof item.version === 'string' &&
79
- item.version.length > 0 &&
80
- (item.private === undefined || typeof item.private === 'boolean'));
84
+ return (isString(value.name) &&
85
+ value.name.length > 0 &&
86
+ isString(value.path) &&
87
+ value.path.length > 0 &&
88
+ isString(value.version) &&
89
+ value.version.length > 0 &&
90
+ (value.private === undefined || typeof value.private === 'boolean'));
81
91
  };
82
92
  function throwInvalidWorkspacePackages() {
83
93
  throw new Error('[auklet:publish] failed to read pnpm workspace packages.\n' +
@@ -1,9 +1,10 @@
1
+ import { isArray } from 'aidly';
1
2
  import { execa } from 'execa';
2
3
  export async function runPublishHook(options) {
3
4
  const hook = getHook(options.plan.config, options.status);
4
5
  if (!hook)
5
6
  return;
6
- const commands = Array.isArray(hook) ? hook : [hook];
7
+ const commands = isArray(hook) ? hook : [hook];
7
8
  for (const command of commands) {
8
9
  const result = await execa(command, {
9
10
  cwd: options.plan.root,
@@ -1,4 +1,5 @@
1
1
  import minimist from 'minimist';
2
+ import { isArray } from 'aidly';
2
3
  import { OwnerRunner } from '#auklet/publish/ownerRunner';
3
4
  import { PublishRunner } from '#auklet/publish/publishRunner';
4
5
  import { ensurePnpm } from '#auklet/publish/api/pnpmApi';
@@ -81,14 +82,14 @@ const stripLeadingArgsSeparator = (args) => {
81
82
  const toArray = (value) => {
82
83
  if (value === undefined)
83
84
  return [];
84
- return Array.isArray(value)
85
+ return isArray(value)
85
86
  ? value.map(String).filter(Boolean)
86
87
  : [String(value)].filter(Boolean);
87
88
  };
88
89
  const stringOption = (value) => {
89
90
  if (value === undefined)
90
91
  return undefined;
91
- if (Array.isArray(value))
92
+ if (isArray(value))
92
93
  return String(value.at(-1));
93
94
  return String(value);
94
95
  };
@@ -57,6 +57,7 @@ export class PublishRunner {
57
57
  const plan = await resolvePublishPlan(this.options, this.logger);
58
58
  validateBuildScript(plan.targets);
59
59
  await this.git.checkBeforePublish(plan);
60
+ await this.preflight.verifyAuthentication(plan);
60
61
  this.versions.logDryRunPlan(plan);
61
62
  return plan;
62
63
  }
@@ -1,8 +1,9 @@
1
+ import { isString } from 'aidly';
1
2
  import { runPnpmBuild } from '#auklet/publish/api/pnpmApi';
2
3
  export function validateBuildScript(targets) {
3
4
  for (const target of targets) {
4
5
  const buildScript = target.packageJson.scripts?.build;
5
- if (typeof buildScript !== 'string' || !buildScript) {
6
+ if (!isString(buildScript) || !buildScript) {
6
7
  throw new Error(`[auklet:publish] package ${target.packageName} must define package.json#scripts.build before publishing.`);
7
8
  }
8
9
  }
@@ -4,5 +4,6 @@ export declare class PublishPreflight {
4
4
  private readonly pnpm;
5
5
  constructor(options: PublishOptions);
6
6
  run(plan: PublishPlan): Promise<void>;
7
+ verifyAuthentication(plan: PublishPlan): Promise<void>;
7
8
  private verifyPnpmPublishDryRun;
8
9
  }
@@ -1,4 +1,5 @@
1
1
  import { PnpmPublishApi } from '#auklet/publish/api/pnpmPublishApi';
2
+ import { runPnpmWhoami } from '#auklet/publish/api/pnpmApi';
2
3
  import { PublishTargetError } from '#auklet/publish/runner/publishTargetError';
3
4
  export class PublishPreflight {
4
5
  options;
@@ -9,6 +10,11 @@ export class PublishPreflight {
9
10
  async run(plan) {
10
11
  await this.verifyPnpmPublishDryRun(plan);
11
12
  }
13
+ async verifyAuthentication(plan) {
14
+ if (plan.dryRun)
15
+ return;
16
+ await runPnpmWhoami(plan.root);
17
+ }
12
18
  async verifyPnpmPublishDryRun(plan) {
13
19
  const options = {
14
20
  ...this.options,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auklet",
3
- "version": "0.0.20",
3
+ "version": "0.0.22",
4
4
  "type": "module",
5
5
  "author": "chentao.arthur",
6
6
  "description": "Build utilities for TypeScript packages and module CSS output.",
@@ -52,7 +52,6 @@
52
52
  ],
53
53
  "dependencies": {
54
54
  "cac": "7.0.0",
55
- "unrun": "0.3.0",
56
55
  "tsdown": "0.22.0",
57
56
  "aidly": "1.37.0",
58
57
  "execa": "9.6.1",