@aidc-toolkit/dev 0.9.17-beta → 0.9.19-beta
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 +12 -23
- package/config/publish.json +20 -23
- package/dist/eslint-config-template.d.ts +1 -1
- package/dist/eslint-config-template.d.ts.map +1 -1
- package/dist/eslint-config-template.js +107 -89
- package/dist/eslint-config-template.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/package.json +18 -18
- package/src/eslint-config-template.ts +23 -13
- package/src/index.ts +0 -1
- package/src/publish/logger.ts +34 -0
- package/src/publish/publish-alpha.ts +144 -0
- package/src/publish/publish-beta.ts +293 -0
- package/src/publish/publish.ts +903 -0
- package/src/publish/type-helper.ts +51 -0
- package/tsconfig.json +2 -2
- package/typedoc.json +1 -0
- package/dist/utility.d.ts +0 -22
- package/dist/utility.d.ts.map +0 -1
- package/dist/utility.js +0 -57
- package/dist/utility.js.map +0 -1
- package/src/publish-external.ts +0 -332
- package/src/publish-internal.ts +0 -111
- package/src/publish.ts +0 -273
- package/src/utility.ts +0 -59
package/src/publish.ts
DELETED
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
import configurationJSON from "../config/publish.json";
|
|
4
|
-
import secureConfigurationJSON from "../config/publish.secure.json";
|
|
5
|
-
import { logger, run } from "./utility";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Repository.
|
|
9
|
-
*/
|
|
10
|
-
export interface Repository {
|
|
11
|
-
/**
|
|
12
|
-
* Directory in which repository resides, if different from repository name.
|
|
13
|
-
*/
|
|
14
|
-
directory?: string;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Dependency type, dictating how it is published.
|
|
18
|
-
*/
|
|
19
|
-
dependencyType: string;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Files excluded from consideration when checking for changes.
|
|
23
|
-
*/
|
|
24
|
-
excludeFiles?: string[];
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Date/time the package was last published internally in ISO format.
|
|
28
|
-
*/
|
|
29
|
-
lastInternalPublished?: string;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Date/time the package was last published externally in ISO format.
|
|
33
|
-
*/
|
|
34
|
-
lastExternalPublished?: string;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Last external published version.
|
|
38
|
-
*/
|
|
39
|
-
lastExternalVersion?: string;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Current step in external publication; used to resume after failure recovery.
|
|
43
|
-
*/
|
|
44
|
-
publishExternalStep?: string | undefined;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Configuration layout of publish.json.
|
|
49
|
-
*/
|
|
50
|
-
export interface Configuration {
|
|
51
|
-
/**
|
|
52
|
-
* Organization that owns the repositories.
|
|
53
|
-
*/
|
|
54
|
-
organization: string;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Repositories.
|
|
58
|
-
*/
|
|
59
|
-
repositories: Record<string, Repository>;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Configuration layout of publish.secure.json.
|
|
64
|
-
*/
|
|
65
|
-
interface SecureConfiguration {
|
|
66
|
-
token: string;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Configuration layout of package.json (relevant attributes only).
|
|
71
|
-
*/
|
|
72
|
-
export interface PackageConfiguration {
|
|
73
|
-
/**
|
|
74
|
-
* Name.
|
|
75
|
-
*/
|
|
76
|
-
name: string;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Version.
|
|
80
|
-
*/
|
|
81
|
-
version: string;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Development dependencies.
|
|
85
|
-
*/
|
|
86
|
-
devDependencies?: Record<string, string>;
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Dependencies.
|
|
90
|
-
*/
|
|
91
|
-
dependencies?: Record<string, string>;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export const configuration: Configuration = configurationJSON;
|
|
95
|
-
export const secureConfiguration: SecureConfiguration = secureConfigurationJSON;
|
|
96
|
-
|
|
97
|
-
const atOrganization = `@${configuration.organization}`;
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Get the organization repository name or a dependency if it belongs to the organization or null if not.
|
|
101
|
-
*
|
|
102
|
-
* @param dependency
|
|
103
|
-
* Dependency.
|
|
104
|
-
*
|
|
105
|
-
* @returns
|
|
106
|
-
* Organization repository name or null.
|
|
107
|
-
*/
|
|
108
|
-
export function organizationRepository(dependency: string): string | null {
|
|
109
|
-
const [dependencyAtOrganization, dependencyRepositoryName] = dependency.split("/");
|
|
110
|
-
|
|
111
|
-
return dependencyAtOrganization === atOrganization ? dependencyRepositoryName : null;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Determine if there have been any changes to a repository.
|
|
116
|
-
*
|
|
117
|
-
* @param repository
|
|
118
|
-
* Repository configuration.
|
|
119
|
-
*
|
|
120
|
-
* @param external
|
|
121
|
-
* False if comparing to the last internal published date/time, true if comparing to the last external published
|
|
122
|
-
* date/time.
|
|
123
|
-
*
|
|
124
|
-
* @returns
|
|
125
|
-
* True if there is no last published date/time or if there have been any changes since then.
|
|
126
|
-
*/
|
|
127
|
-
export function anyChanges(repository: Repository, external: boolean): boolean {
|
|
128
|
-
let anyChanges: boolean;
|
|
129
|
-
|
|
130
|
-
const lastPublishedString = !external ? repository.lastInternalPublished : repository.lastExternalPublished;
|
|
131
|
-
|
|
132
|
-
const changedFilesSet = new Set<string>();
|
|
133
|
-
|
|
134
|
-
if (lastPublishedString !== undefined) {
|
|
135
|
-
for (const line of run(true, "git", "log", `--since="${lastPublishedString}"`, "--name-status", "--pretty=oneline")) {
|
|
136
|
-
// Header starts with 40-character SHA.
|
|
137
|
-
if (!/^[0-9a-f]{40} /.test(line)) {
|
|
138
|
-
const [status, file] = line.split("\t");
|
|
139
|
-
|
|
140
|
-
// Ignore deleted files; anything that depends on a deleted file will have been modified.
|
|
141
|
-
if (status !== "D") {
|
|
142
|
-
logger.debug(`+File: ${file}`);
|
|
143
|
-
|
|
144
|
-
changedFilesSet.add(file);
|
|
145
|
-
}
|
|
146
|
-
} else {
|
|
147
|
-
logger.debug(`Commit SHA ${line.substring(0, 40)}`);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (lastPublishedString !== undefined || external) {
|
|
153
|
-
const output = run(true, "git", "status", "--porcelain");
|
|
154
|
-
|
|
155
|
-
if (output.length !== 0) {
|
|
156
|
-
if (external) {
|
|
157
|
-
throw new Error("Repository has uncommitted changes");
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
logger.debug("Uncommitted");
|
|
161
|
-
|
|
162
|
-
for (const line of output) {
|
|
163
|
-
// Line is two-character status, space, and detail.
|
|
164
|
-
const status = line.substring(0, 2);
|
|
165
|
-
const detail = line.substring(3);
|
|
166
|
-
|
|
167
|
-
// Ignore deleted files; anything that depends on a deleted file will have been modified.
|
|
168
|
-
if (status !== "D ") {
|
|
169
|
-
let file: string;
|
|
170
|
-
|
|
171
|
-
if (status.startsWith("R")) {
|
|
172
|
-
// File has been renamed; get old and new file names.
|
|
173
|
-
const [oldFile, newFile] = detail.split(" -> ");
|
|
174
|
-
|
|
175
|
-
logger.debug(`-File: ${oldFile}`);
|
|
176
|
-
|
|
177
|
-
changedFilesSet.delete(oldFile);
|
|
178
|
-
|
|
179
|
-
file = newFile;
|
|
180
|
-
} else {
|
|
181
|
-
file = detail;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
logger.debug(`+File: ${file}`);
|
|
185
|
-
|
|
186
|
-
changedFilesSet.add(file);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (lastPublishedString !== undefined) {
|
|
193
|
-
logger.debug("Excluded");
|
|
194
|
-
|
|
195
|
-
const hiddenFiles = [];
|
|
196
|
-
|
|
197
|
-
// Get list of hidden files and directories.
|
|
198
|
-
for (const changedFile of changedFilesSet) {
|
|
199
|
-
if (changedFile.startsWith(".") || changedFile.includes("/.")) {
|
|
200
|
-
hiddenFiles.push(changedFile);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Exclude hidden files and directories.
|
|
205
|
-
for (const hiddenFile of hiddenFiles) {
|
|
206
|
-
logger.debug(`-File: ${hiddenFile}`);
|
|
207
|
-
|
|
208
|
-
changedFilesSet.delete(hiddenFile);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (repository.excludeFiles !== undefined) {
|
|
212
|
-
for (const excludeFile of repository.excludeFiles) {
|
|
213
|
-
if (changedFilesSet.delete(excludeFile)) {
|
|
214
|
-
logger.debug(`-File: ${excludeFile}`);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
logger.info("Changed");
|
|
220
|
-
|
|
221
|
-
const lastPublished = new Date(lastPublishedString);
|
|
222
|
-
|
|
223
|
-
anyChanges = false;
|
|
224
|
-
|
|
225
|
-
for (const changedFile of changedFilesSet) {
|
|
226
|
-
if (fs.lstatSync(changedFile).mtime > lastPublished) {
|
|
227
|
-
logger.info(`File: ${changedFile}`);
|
|
228
|
-
|
|
229
|
-
anyChanges = true;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
} else {
|
|
233
|
-
// No last published, so there must have been changes.
|
|
234
|
-
anyChanges = true;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (!anyChanges) {
|
|
238
|
-
logger.debug("No changes");
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
return anyChanges;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Configuration may be written from any directory so full path is required.
|
|
245
|
-
const configurationPath = path.resolve("config/publish.json");
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Save the current configuration.
|
|
249
|
-
*/
|
|
250
|
-
export function saveConfiguration(): void {
|
|
251
|
-
fs.writeFileSync(configurationPath, `${JSON.stringify(configuration, null, 2)}\n`);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Publish all repositories.
|
|
256
|
-
*
|
|
257
|
-
* @param callback
|
|
258
|
-
* Callback taking the name and properties of the repository to publish.
|
|
259
|
-
*/
|
|
260
|
-
export async function publishRepositories(callback: (name: string, repository: Repository) => void | Promise<void>): Promise<void> {
|
|
261
|
-
logger.settings.minLevel = 2;
|
|
262
|
-
|
|
263
|
-
for (const [name, repository] of Object.entries(configuration.repositories)) {
|
|
264
|
-
logger.info(`Repository ${name}...`);
|
|
265
|
-
|
|
266
|
-
// All repositories are expected to be children of the parent of this repository.
|
|
267
|
-
process.chdir(`../${repository.directory ?? name}`);
|
|
268
|
-
|
|
269
|
-
await callback(name, repository);
|
|
270
|
-
|
|
271
|
-
saveConfiguration();
|
|
272
|
-
}
|
|
273
|
-
}
|
package/src/utility.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from "child_process";
|
|
2
|
-
import { Logger } from "tslog";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Log level.
|
|
6
|
-
*/
|
|
7
|
-
enum LogLevel {
|
|
8
|
-
Silly, Trace, Debug, Info, Warn, Error, Fatal
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Logger with a default minimum level of Info.
|
|
13
|
-
*/
|
|
14
|
-
export const logger = new Logger({
|
|
15
|
-
minLevel: LogLevel.Info
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Run a command and optionally capture its output.
|
|
20
|
-
*
|
|
21
|
-
* @param captureOutput
|
|
22
|
-
* If true, output is captured and returned.
|
|
23
|
-
*
|
|
24
|
-
* @param command
|
|
25
|
-
* Command to run.
|
|
26
|
-
*
|
|
27
|
-
* @param args
|
|
28
|
-
* Arguments to command.
|
|
29
|
-
*
|
|
30
|
-
* @returns
|
|
31
|
-
* Output if captured or empty array if not.
|
|
32
|
-
*/
|
|
33
|
-
export function run(captureOutput: boolean, command: string, ...args: string[]): string[] {
|
|
34
|
-
logger.debug(`Running command "${command}" with arguments ${JSON.stringify(args)}.`);
|
|
35
|
-
|
|
36
|
-
const spawnResult = spawnSync(command, args, {
|
|
37
|
-
stdio: ["inherit", captureOutput ? "pipe" : "inherit", "inherit"]
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
if (spawnResult.error !== undefined) {
|
|
41
|
-
throw spawnResult.error;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (spawnResult.status === null) {
|
|
45
|
-
throw new Error(`Terminated by signal ${spawnResult.signal}`);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (spawnResult.status !== 0) {
|
|
49
|
-
throw new Error(`Failed with status ${spawnResult.status}`);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const output = captureOutput ? spawnResult.stdout.toString().split("\n").slice(0, -1) : [];
|
|
53
|
-
|
|
54
|
-
if (captureOutput) {
|
|
55
|
-
logger.debug(`Output is ${JSON.stringify(output)}.`);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return output;
|
|
59
|
-
}
|