@produck/agent-toolkit 0.8.1 → 0.9.0
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 +22 -22
- package/bin/agent-toolkit.mjs +33 -8
- package/bin/build-publish-assets.mjs +132 -24
- package/bin/command/enforce-node-baseline/index.mjs +18 -5
- package/bin/command/preflight/index.mjs +20 -4
- package/bin/command/run-capture/index.mjs +7 -1
- package/bin/command/shared/workspace-validation.mjs +9 -3
- package/bin/command/sync-coverage/index.mjs +103 -48
- package/bin/command/sync-coverage/required-c8-config.json +15 -0
- package/bin/command/sync-editorconfig/index.mjs +2 -1
- package/bin/command/sync-format/index.mjs +92 -37
- package/bin/command/sync-git/help.txt +1 -0
- package/bin/command/sync-git/index.mjs +110 -33
- package/bin/command/sync-install/index.mjs +10 -3
- package/bin/command/sync-instructions/index.mjs +35 -10
- package/bin/command/sync-lint/eslint.config.template.mjs +32 -0
- package/bin/command/sync-lint/index.mjs +63 -32
- package/bin/command/sync-publish/help.txt +4 -2
- package/bin/command/sync-publish/index.mjs +126 -35
- package/bin/command/validate-commit-msg/index.mjs +46 -25
- package/package.json +5 -3
- package/publish-assets/eslint.config.template.mjs +32 -0
- package/publish-assets/gitignore +3 -0
- package/publish-assets/instructions/produck/20-produck-commit.instructions.md +3 -3
- package/publish-assets/instructions/produck/stale.instructions.md +1 -0
- package/publish-assets/instructions/produck/tooling-version-baseline.json +36 -1
- package/publish-assets/lerna.json +14 -0
- package/publish-assets/prettierrc +11 -0
|
@@ -7,23 +7,21 @@ import { printTextResource } from '../shared/text-resource.mjs';
|
|
|
7
7
|
|
|
8
8
|
const COMMAND_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
9
9
|
const HELP_FILE = path.resolve(COMMAND_DIR, 'help.txt');
|
|
10
|
+
const PACKAGE_ROOT = path.resolve(COMMAND_DIR, '../../..');
|
|
11
|
+
const REPO_ROOT = path.resolve(PACKAGE_ROOT, '../..');
|
|
10
12
|
const LERNA_CONFIG_FILE = 'lerna.json';
|
|
13
|
+
const LERNA_TEMPLATE_CANDIDATE_PATHS = [
|
|
14
|
+
path.resolve(REPO_ROOT, LERNA_CONFIG_FILE),
|
|
15
|
+
path.resolve(PACKAGE_ROOT, 'publish-assets', LERNA_CONFIG_FILE),
|
|
16
|
+
];
|
|
11
17
|
|
|
12
18
|
const REQUIRED_PUBLISH_CHECK_SCRIPT_KEY = 'produck:publish:check';
|
|
13
19
|
const REQUIRED_PUBLISH_CHECK_SCRIPT_VALUE =
|
|
14
|
-
'npm run produck:install && npm run produck:
|
|
15
|
-
const USER_PUBLISH_SCRIPT_KEY = 'publish';
|
|
20
|
+
'npm run produck:install && npm run produck:coverage && npm run produck:commit:check';
|
|
16
21
|
const REQUIRED_PUBLISH_SCRIPT_KEY = 'produck:publish';
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
{
|
|
21
|
-
$schema: 'node_modules/lerna/schemas/lerna-schema.json',
|
|
22
|
-
version: 'independent',
|
|
23
|
-
},
|
|
24
|
-
null,
|
|
25
|
-
2,
|
|
26
|
-
)}\n`;
|
|
22
|
+
const REQUIRED_PUBLISH_SCRIPT_VALUE =
|
|
23
|
+
'npm run produck:publish:check && npm run publish --';
|
|
24
|
+
const REQUIRED_LERNA_VERSION_COMMIT_HOOKS = false;
|
|
27
25
|
|
|
28
26
|
export function printSyncPublishHelp() {
|
|
29
27
|
printTextResource(HELP_FILE);
|
|
@@ -38,12 +36,51 @@ function parseJsonFile(filePath, label) {
|
|
|
38
36
|
}
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
function
|
|
42
|
-
|
|
43
|
-
return
|
|
39
|
+
function loadRequiredLernaTemplate() {
|
|
40
|
+
const templatePath = LERNA_TEMPLATE_CANDIDATE_PATHS.find((candidatePath) => {
|
|
41
|
+
return fs.existsSync(candidatePath);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (!templatePath) {
|
|
45
|
+
console.error('lerna template does not exist in expected locations:');
|
|
46
|
+
for (const candidatePath of LERNA_TEMPLATE_CANDIDATE_PATHS) {
|
|
47
|
+
console.error(`- ${candidatePath}`);
|
|
48
|
+
}
|
|
49
|
+
process.exit(2);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const template = parseJsonFile(templatePath, 'lerna template');
|
|
53
|
+
if (typeof template.version !== 'string') {
|
|
54
|
+
console.error(
|
|
55
|
+
`lerna template must have a "version" field: ${templatePath}`,
|
|
56
|
+
);
|
|
57
|
+
process.exit(2);
|
|
44
58
|
}
|
|
45
59
|
|
|
46
|
-
|
|
60
|
+
// The {} fallbacks below guard against templates that omit 'command' or
|
|
61
|
+
// 'command.version'; the canonical lerna template always provides both.
|
|
62
|
+
const normalizedTemplate = {
|
|
63
|
+
...template,
|
|
64
|
+
command: {
|
|
65
|
+
...(template.command && typeof template.command === 'object'
|
|
66
|
+
? template.command
|
|
67
|
+
: /* c8 ignore next */
|
|
68
|
+
{}),
|
|
69
|
+
version: {
|
|
70
|
+
...(template?.command?.version &&
|
|
71
|
+
typeof template.command.version === 'object'
|
|
72
|
+
? template.command.version
|
|
73
|
+
: /* c8 ignore next */
|
|
74
|
+
{}),
|
|
75
|
+
commitHooks: REQUIRED_LERNA_VERSION_COMMIT_HOOKS,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
templatePath,
|
|
82
|
+
content: `${JSON.stringify(normalizedTemplate, null, 2)}\n`,
|
|
83
|
+
};
|
|
47
84
|
}
|
|
48
85
|
|
|
49
86
|
export function runSyncPublish(options) {
|
|
@@ -52,6 +89,7 @@ export function runSyncPublish(options) {
|
|
|
52
89
|
const dryRun = hasFlag(options, '--dry-run') && !check;
|
|
53
90
|
const jsonFile = getSingle(options, '--json', '');
|
|
54
91
|
const mode = check ? 'check' : dryRun ? 'dry-run' : 'sync';
|
|
92
|
+
const requiredLernaTemplate = loadRequiredLernaTemplate();
|
|
55
93
|
|
|
56
94
|
if (!fs.existsSync(cwd)) {
|
|
57
95
|
console.error(`CWD does not exist: ${cwd}`);
|
|
@@ -61,19 +99,53 @@ export function runSyncPublish(options) {
|
|
|
61
99
|
const lernaConfigPath = path.resolve(cwd, LERNA_CONFIG_FILE);
|
|
62
100
|
const lernaExistedBefore = fs.existsSync(lernaConfigPath);
|
|
63
101
|
let lernaDefaultCreated = false;
|
|
102
|
+
let matchesRequiredLernaCommitHooks = false;
|
|
103
|
+
let matchesRequiredLernaCommitHooksBefore = false;
|
|
64
104
|
|
|
65
105
|
if (!lernaExistedBefore) {
|
|
66
106
|
if (mode === 'sync') {
|
|
67
|
-
fs.writeFileSync(lernaConfigPath,
|
|
107
|
+
fs.writeFileSync(lernaConfigPath, requiredLernaTemplate.content, 'utf8');
|
|
68
108
|
lernaDefaultCreated = true;
|
|
109
|
+
matchesRequiredLernaCommitHooks = true;
|
|
69
110
|
}
|
|
70
111
|
} else {
|
|
71
112
|
const lernaConfig = parseJsonFile(lernaConfigPath, 'lerna.json');
|
|
72
113
|
|
|
73
114
|
if (typeof lernaConfig.version !== 'string') {
|
|
74
|
-
console.error(
|
|
115
|
+
console.error(
|
|
116
|
+
`lerna.json must have a "version" field: ${lernaConfigPath}`,
|
|
117
|
+
);
|
|
75
118
|
process.exit(2);
|
|
76
119
|
}
|
|
120
|
+
|
|
121
|
+
const currentCommitHooks = lernaConfig?.command?.version?.commitHooks;
|
|
122
|
+
matchesRequiredLernaCommitHooks =
|
|
123
|
+
currentCommitHooks === REQUIRED_LERNA_VERSION_COMMIT_HOOKS;
|
|
124
|
+
matchesRequiredLernaCommitHooksBefore = matchesRequiredLernaCommitHooks;
|
|
125
|
+
|
|
126
|
+
if (mode === 'sync' && !matchesRequiredLernaCommitHooks) {
|
|
127
|
+
const nextLernaConfig = {
|
|
128
|
+
...lernaConfig,
|
|
129
|
+
command: {
|
|
130
|
+
...(lernaConfig.command && typeof lernaConfig.command === 'object'
|
|
131
|
+
? lernaConfig.command
|
|
132
|
+
: {}),
|
|
133
|
+
version: {
|
|
134
|
+
...(lernaConfig?.command?.version &&
|
|
135
|
+
typeof lernaConfig.command.version === 'object'
|
|
136
|
+
? lernaConfig.command.version
|
|
137
|
+
: {}),
|
|
138
|
+
commitHooks: REQUIRED_LERNA_VERSION_COMMIT_HOOKS,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
fs.writeFileSync(
|
|
143
|
+
lernaConfigPath,
|
|
144
|
+
`${JSON.stringify(nextLernaConfig, null, 2)}\n`,
|
|
145
|
+
'utf8',
|
|
146
|
+
);
|
|
147
|
+
matchesRequiredLernaCommitHooks = true;
|
|
148
|
+
}
|
|
77
149
|
}
|
|
78
150
|
|
|
79
151
|
const rootPackageJsonPath = path.resolve(cwd, 'package.json');
|
|
@@ -84,13 +156,11 @@ export function runSyncPublish(options) {
|
|
|
84
156
|
|
|
85
157
|
const pkg = parseJsonFile(rootPackageJsonPath, 'Root package.json');
|
|
86
158
|
const scripts =
|
|
87
|
-
pkg.scripts &&
|
|
159
|
+
pkg.scripts &&
|
|
160
|
+
typeof pkg.scripts === 'object' &&
|
|
161
|
+
!Array.isArray(pkg.scripts)
|
|
88
162
|
? { ...pkg.scripts }
|
|
89
163
|
: {};
|
|
90
|
-
const hasUserPublishScript =
|
|
91
|
-
typeof scripts[USER_PUBLISH_SCRIPT_KEY] === 'string' &&
|
|
92
|
-
scripts[USER_PUBLISH_SCRIPT_KEY].trim() !== '';
|
|
93
|
-
const requiredPublishScriptValue = buildRequiredPublishScriptValue(hasUserPublishScript);
|
|
94
164
|
|
|
95
165
|
const previousPublishCheck =
|
|
96
166
|
typeof scripts[REQUIRED_PUBLISH_CHECK_SCRIPT_KEY] === 'string'
|
|
@@ -101,17 +171,30 @@ export function runSyncPublish(options) {
|
|
|
101
171
|
? scripts[REQUIRED_PUBLISH_SCRIPT_KEY]
|
|
102
172
|
: null;
|
|
103
173
|
|
|
104
|
-
const matchesRequiredPublishCheck =
|
|
105
|
-
|
|
174
|
+
const matchesRequiredPublishCheck =
|
|
175
|
+
previousPublishCheck === REQUIRED_PUBLISH_CHECK_SCRIPT_VALUE;
|
|
176
|
+
const matchesRequiredPublish =
|
|
177
|
+
previousPublish === REQUIRED_PUBLISH_SCRIPT_VALUE;
|
|
106
178
|
const lernaRequiresCreation = !lernaExistedBefore && !lernaDefaultCreated;
|
|
107
179
|
const requiresUpdate =
|
|
108
|
-
!matchesRequiredPublishCheck ||
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
180
|
+
!matchesRequiredPublishCheck ||
|
|
181
|
+
!matchesRequiredPublish ||
|
|
182
|
+
lernaRequiresCreation ||
|
|
183
|
+
!matchesRequiredLernaCommitHooks;
|
|
184
|
+
|
|
185
|
+
if (
|
|
186
|
+
mode === 'sync' &&
|
|
187
|
+
(!matchesRequiredPublishCheck || !matchesRequiredPublish)
|
|
188
|
+
) {
|
|
189
|
+
scripts[REQUIRED_PUBLISH_CHECK_SCRIPT_KEY] =
|
|
190
|
+
REQUIRED_PUBLISH_CHECK_SCRIPT_VALUE;
|
|
191
|
+
scripts[REQUIRED_PUBLISH_SCRIPT_KEY] = REQUIRED_PUBLISH_SCRIPT_VALUE;
|
|
113
192
|
pkg.scripts = scripts;
|
|
114
|
-
fs.writeFileSync(
|
|
193
|
+
fs.writeFileSync(
|
|
194
|
+
rootPackageJsonPath,
|
|
195
|
+
`${JSON.stringify(pkg, null, 2)}\n`,
|
|
196
|
+
'utf8',
|
|
197
|
+
);
|
|
115
198
|
}
|
|
116
199
|
|
|
117
200
|
const report = {
|
|
@@ -121,21 +204,29 @@ export function runSyncPublish(options) {
|
|
|
121
204
|
lernaConfigPath,
|
|
122
205
|
rootPackageJsonPath,
|
|
123
206
|
required: {
|
|
207
|
+
lernaTemplatePath: requiredLernaTemplate.templatePath,
|
|
124
208
|
publishCheckScriptKey: REQUIRED_PUBLISH_CHECK_SCRIPT_KEY,
|
|
125
209
|
publishCheckScriptValue: REQUIRED_PUBLISH_CHECK_SCRIPT_VALUE,
|
|
126
210
|
publishScriptKey: REQUIRED_PUBLISH_SCRIPT_KEY,
|
|
127
|
-
publishScriptValue:
|
|
211
|
+
publishScriptValue: REQUIRED_PUBLISH_SCRIPT_VALUE,
|
|
212
|
+
lernaVersionCommitHooks: REQUIRED_LERNA_VERSION_COMMIT_HOOKS,
|
|
128
213
|
},
|
|
129
214
|
status: {
|
|
130
|
-
hasUserPublishScript,
|
|
131
215
|
lernaExistedBefore,
|
|
132
216
|
lernaDefaultCreated,
|
|
217
|
+
matchesRequiredLernaCommitHooksBefore:
|
|
218
|
+
matchesRequiredLernaCommitHooksBefore,
|
|
219
|
+
matchesRequiredLernaCommitHooksAfter: matchesRequiredLernaCommitHooks,
|
|
133
220
|
matchesRequiredPublishCheckBefore: matchesRequiredPublishCheck,
|
|
134
221
|
matchesRequiredPublishCheckAfter:
|
|
135
|
-
!matchesRequiredPublishCheck && mode === 'sync'
|
|
222
|
+
!matchesRequiredPublishCheck && mode === 'sync'
|
|
223
|
+
? true
|
|
224
|
+
: matchesRequiredPublishCheck,
|
|
136
225
|
matchesRequiredPublishBefore: matchesRequiredPublish,
|
|
137
226
|
matchesRequiredPublishAfter:
|
|
138
|
-
!matchesRequiredPublish && mode === 'sync'
|
|
227
|
+
!matchesRequiredPublish && mode === 'sync'
|
|
228
|
+
? true
|
|
229
|
+
: matchesRequiredPublish,
|
|
139
230
|
updated: requiresUpdate && mode === 'sync',
|
|
140
231
|
},
|
|
141
232
|
};
|
|
@@ -5,12 +5,31 @@ import { fileURLToPath } from 'node:url';
|
|
|
5
5
|
import { getSingle } from '../shared/args.mjs';
|
|
6
6
|
import { printTextResource } from '../shared/text-resource.mjs';
|
|
7
7
|
|
|
8
|
-
const ALLOWED_TAGS = [
|
|
9
|
-
|
|
8
|
+
const ALLOWED_TAGS = [
|
|
9
|
+
'INIT',
|
|
10
|
+
'ADD',
|
|
11
|
+
'REMOVE',
|
|
12
|
+
'FIX',
|
|
13
|
+
'REFACTOR',
|
|
14
|
+
'UPGRADE',
|
|
15
|
+
'PUBLISH',
|
|
16
|
+
];
|
|
17
|
+
const ALLOWED_TARGETS = [
|
|
18
|
+
'docs',
|
|
19
|
+
'test',
|
|
20
|
+
'ci',
|
|
21
|
+
'deps',
|
|
22
|
+
'api',
|
|
23
|
+
'schema',
|
|
24
|
+
'infra',
|
|
25
|
+
'fmt',
|
|
26
|
+
];
|
|
10
27
|
const SECTION_HEADER_RE = /^(?:\*|(?:@[\w.-]+\/)?[\w.-]+):$/;
|
|
11
28
|
const COMMAND_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
12
29
|
const HELP_FILE = path.resolve(COMMAND_DIR, 'help.txt');
|
|
13
|
-
const ROOT_PACKAGE_FILE =
|
|
30
|
+
const ROOT_PACKAGE_FILE =
|
|
31
|
+
process.env._AGENT_TOOLKIT_TEST_ROOT_PKG ||
|
|
32
|
+
path.resolve(COMMAND_DIR, '../../../../../package.json');
|
|
14
33
|
const WORKSPACE_SCOPE = 'workspace';
|
|
15
34
|
const WILDCARD_SCOPE = '*';
|
|
16
35
|
const DEFAULT_COMMENT_CHAR = '#';
|
|
@@ -65,42 +84,38 @@ function isMonorepoRoot() {
|
|
|
65
84
|
|
|
66
85
|
try {
|
|
67
86
|
const rootPackage = JSON.parse(fs.readFileSync(ROOT_PACKAGE_FILE, 'utf8'));
|
|
68
|
-
return
|
|
87
|
+
return (
|
|
88
|
+
Array.isArray(rootPackage.workspaces) && rootPackage.workspaces.length > 0
|
|
89
|
+
);
|
|
69
90
|
} catch {
|
|
70
91
|
return false;
|
|
71
92
|
}
|
|
72
93
|
}
|
|
73
94
|
|
|
74
95
|
function getMonorepoAllowedSectionScopes() {
|
|
75
|
-
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
let rootPackage;
|
|
80
|
-
try {
|
|
81
|
-
rootPackage = JSON.parse(fs.readFileSync(ROOT_PACKAGE_FILE, 'utf8'));
|
|
82
|
-
} catch {
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (!Array.isArray(rootPackage.workspaces) || rootPackage.workspaces.length === 0) {
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
|
|
96
|
+
const rootPackage = JSON.parse(fs.readFileSync(ROOT_PACKAGE_FILE, 'utf8'));
|
|
90
97
|
const rootDir = path.dirname(ROOT_PACKAGE_FILE);
|
|
91
98
|
const allowedScopes = new Set([WORKSPACE_SCOPE, WILDCARD_SCOPE]);
|
|
92
99
|
|
|
93
100
|
for (const workspaceEntry of rootPackage.workspaces) {
|
|
94
101
|
const workspacePath = path.resolve(rootDir, String(workspaceEntry));
|
|
95
|
-
const workspacePackageJsonPath = path.resolve(
|
|
102
|
+
const workspacePackageJsonPath = path.resolve(
|
|
103
|
+
workspacePath,
|
|
104
|
+
'package.json',
|
|
105
|
+
);
|
|
96
106
|
|
|
97
107
|
if (!fs.existsSync(workspacePackageJsonPath)) {
|
|
98
108
|
continue;
|
|
99
109
|
}
|
|
100
110
|
|
|
101
111
|
try {
|
|
102
|
-
const workspacePackage = JSON.parse(
|
|
103
|
-
|
|
112
|
+
const workspacePackage = JSON.parse(
|
|
113
|
+
fs.readFileSync(workspacePackageJsonPath, 'utf8'),
|
|
114
|
+
);
|
|
115
|
+
if (
|
|
116
|
+
typeof workspacePackage.name === 'string' &&
|
|
117
|
+
workspacePackage.name.trim() !== ''
|
|
118
|
+
) {
|
|
104
119
|
allowedScopes.add(workspacePackage.name.trim());
|
|
105
120
|
}
|
|
106
121
|
} catch {
|
|
@@ -220,7 +235,9 @@ export function runValidateCommitMsg(options) {
|
|
|
220
235
|
}
|
|
221
236
|
|
|
222
237
|
const mustUseSectionHeaders = isMonorepoRoot();
|
|
223
|
-
const allowedSectionScopes = mustUseSectionHeaders
|
|
238
|
+
const allowedSectionScopes = mustUseSectionHeaders
|
|
239
|
+
? getMonorepoAllowedSectionScopes()
|
|
240
|
+
: null;
|
|
224
241
|
const hasSectionHeaders = lines.some((line) => isSectionHeaderLine(line));
|
|
225
242
|
|
|
226
243
|
// [PUBLISH] is generated by lerna and is always a repo-wide tag.
|
|
@@ -235,11 +252,15 @@ export function runValidateCommitMsg(options) {
|
|
|
235
252
|
|
|
236
253
|
if (mustUseSectionHeaders && !hasSectionHeaders) {
|
|
237
254
|
console.error('Commit message validation failed:');
|
|
238
|
-
console.error(
|
|
255
|
+
console.error(
|
|
256
|
+
'- Line 1: section header is required before tagged lines in monorepo mode',
|
|
257
|
+
);
|
|
239
258
|
process.exit(1);
|
|
240
259
|
}
|
|
241
260
|
|
|
242
|
-
const errors = hasSectionHeaders
|
|
261
|
+
const errors = hasSectionHeaders
|
|
262
|
+
? validateSectionFormat(lines, allowedSectionScopes)
|
|
263
|
+
: [];
|
|
243
264
|
if (!hasSectionHeaders) {
|
|
244
265
|
for (let i = 0; i < lines.length; i += 1) {
|
|
245
266
|
const err = validateCommitLine(lines[i], i + 1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@produck/agent-toolkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Central CLI toolkit for organization AI execution workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"scripts": {
|
|
15
15
|
"prepack": "node ./bin/build-publish-assets.mjs",
|
|
16
16
|
"test": "node test/index.mjs",
|
|
17
|
-
"produck:coverage": "c8 --reporter=lcov --reporter=html --reporter=text-summary npm test"
|
|
17
|
+
"produck:coverage": "c8 --reporter=lcov --reporter=html --reporter=text-summary npm test",
|
|
18
|
+
"produck:lint": "eslint --fix . --max-warnings=0"
|
|
18
19
|
},
|
|
19
20
|
"files": [
|
|
20
21
|
"bin",
|
|
@@ -28,7 +29,8 @@
|
|
|
28
29
|
},
|
|
29
30
|
"license": "MIT",
|
|
30
31
|
"devDependencies": {
|
|
32
|
+
"@produck/eslint-rules": "^0.3.6",
|
|
31
33
|
"c8": "11.0.0"
|
|
32
34
|
},
|
|
33
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "d13162976bfbf23756e678027aaffe464b7c8177"
|
|
34
36
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import js from '@eslint/js';
|
|
2
|
+
import globals from 'globals';
|
|
3
|
+
import tseslint from 'typescript-eslint';
|
|
4
|
+
import json from '@eslint/json';
|
|
5
|
+
import markdown from '@eslint/markdown';
|
|
6
|
+
import { defineConfig } from 'eslint/config';
|
|
7
|
+
import * as ProduckRule from '@produck/eslint-rules';
|
|
8
|
+
|
|
9
|
+
export default defineConfig([
|
|
10
|
+
{
|
|
11
|
+
files: ['**/*.{js,mjs,cjs,ts,mts,cts}'],
|
|
12
|
+
plugins: { js },
|
|
13
|
+
extends: ['js/recommended'],
|
|
14
|
+
languageOptions: { globals: { ...globals.browser, ...globals.node } },
|
|
15
|
+
},
|
|
16
|
+
tseslint.configs.recommended,
|
|
17
|
+
{
|
|
18
|
+
files: ['**/*.json'],
|
|
19
|
+
ignores: ['**/package-lock.json'],
|
|
20
|
+
plugins: { json },
|
|
21
|
+
language: 'json/json',
|
|
22
|
+
extends: ['json/recommended'],
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
files: ['**/*.md'],
|
|
26
|
+
plugins: { markdown },
|
|
27
|
+
language: 'markdown/gfm',
|
|
28
|
+
extends: ['markdown/recommended'],
|
|
29
|
+
},
|
|
30
|
+
ProduckRule.config,
|
|
31
|
+
ProduckRule.excludeGitIgnore(import.meta.url),
|
|
32
|
+
]);
|
package/publish-assets/gitignore
CHANGED
|
@@ -40,7 +40,7 @@ Monorepo format (required for multi-package repositories):
|
|
|
40
40
|
|
|
41
41
|
Example monorepo format:
|
|
42
42
|
|
|
43
|
-
```
|
|
43
|
+
```text
|
|
44
44
|
foo:
|
|
45
45
|
[FIX] race condition in auth handler
|
|
46
46
|
[ADD] <test>: cover edge case for concurrent login
|
|
@@ -121,14 +121,14 @@ integration test)`
|
|
|
121
121
|
|
|
122
122
|
Monorepo examples:
|
|
123
123
|
|
|
124
|
-
```
|
|
124
|
+
```text
|
|
125
125
|
foo:
|
|
126
126
|
[FIX] a
|
|
127
127
|
[FIX] b
|
|
128
128
|
[FIX] c
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
-
```
|
|
131
|
+
```text
|
|
132
132
|
core:
|
|
133
133
|
[ADD] <api>: new user authentication endpoint
|
|
134
134
|
[REFACTOR] <test>: restructure session management tests
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
user owned content
|
|
@@ -22,8 +22,43 @@
|
|
|
22
22
|
"policy": "pinned",
|
|
23
23
|
"allowLatest": false
|
|
24
24
|
},
|
|
25
|
+
"eslint": {
|
|
26
|
+
"version": "10.4.0",
|
|
27
|
+
"policy": "pinned",
|
|
28
|
+
"allowLatest": false
|
|
29
|
+
},
|
|
30
|
+
"@eslint/js": {
|
|
31
|
+
"version": "10.0.1",
|
|
32
|
+
"policy": "pinned",
|
|
33
|
+
"allowLatest": false
|
|
34
|
+
},
|
|
35
|
+
"@eslint/json": {
|
|
36
|
+
"version": "1.2.0",
|
|
37
|
+
"policy": "pinned",
|
|
38
|
+
"allowLatest": false
|
|
39
|
+
},
|
|
40
|
+
"@eslint/markdown": {
|
|
41
|
+
"version": "8.0.1",
|
|
42
|
+
"policy": "pinned",
|
|
43
|
+
"allowLatest": false
|
|
44
|
+
},
|
|
45
|
+
"@eslint/config-helpers": {
|
|
46
|
+
"version": "0.6.0",
|
|
47
|
+
"policy": "pinned",
|
|
48
|
+
"allowLatest": false
|
|
49
|
+
},
|
|
50
|
+
"typescript-eslint": {
|
|
51
|
+
"version": "8.59.4",
|
|
52
|
+
"policy": "pinned",
|
|
53
|
+
"allowLatest": false
|
|
54
|
+
},
|
|
55
|
+
"globals": {
|
|
56
|
+
"version": "17.6.0",
|
|
57
|
+
"policy": "pinned",
|
|
58
|
+
"allowLatest": false
|
|
59
|
+
},
|
|
25
60
|
"@produck/eslint-rules": {
|
|
26
|
-
"version": "0.3.
|
|
61
|
+
"version": "0.3.6",
|
|
27
62
|
"policy": "pinned",
|
|
28
63
|
"allowLatest": false
|
|
29
64
|
}
|