@ekanos/cli 0.22.0 → 0.23.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 +18 -4
- package/dist/commands/add.js +21 -10
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/contract.js +12 -2
- package/dist/commands/contract.js.map +1 -1
- package/dist/commands/dev.js +33 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/publish.d.ts +6 -0
- package/dist/commands/publish.js +80 -4
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/status.d.ts +44 -0
- package/dist/commands/status.js +79 -18
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/upgrade.js +287 -144
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/docs-links.js +5 -1
- package/dist/docs-links.js.map +1 -1
- package/dist/errors.d.ts +2 -0
- package/dist/errors.js +9 -0
- package/dist/errors.js.map +1 -1
- package/dist/exit-codes.d.ts +3 -0
- package/dist/exit-codes.js +3 -0
- package/dist/exit-codes.js.map +1 -1
- package/dist/experience/checks.js +2 -1
- package/dist/experience/checks.js.map +1 -1
- package/dist/experience/definition-checks.d.ts +7 -0
- package/dist/experience/definition-checks.js +36 -4
- package/dist/experience/definition-checks.js.map +1 -1
- package/dist/experience/init.js +10 -0
- package/dist/experience/init.js.map +1 -1
- package/dist/experience/load-experience.js +33 -2
- package/dist/experience/load-experience.js.map +1 -1
- package/dist/experience/pins.d.ts +10 -0
- package/dist/experience/pins.js +19 -1
- package/dist/experience/pins.js.map +1 -1
- package/dist/generated/phosphor-names.d.ts +3 -0
- package/dist/generated/phosphor-names.js +1541 -0
- package/dist/generated/phosphor-names.js.map +1 -0
- package/dist/harness-scaffold.d.ts +13 -0
- package/dist/harness-scaffold.js +19 -3
- package/dist/harness-scaffold.js.map +1 -1
- package/dist/icon-findings.d.ts +12 -17
- package/dist/icon-findings.js +49 -74
- package/dist/icon-findings.js.map +1 -1
- package/dist/index.js +28 -5
- package/dist/index.js.map +1 -1
- package/dist/lockfile-instances.d.ts +60 -0
- package/dist/lockfile-instances.js +177 -0
- package/dist/lockfile-instances.js.map +1 -0
- package/dist/pack-hygiene.d.ts +8 -0
- package/dist/pack-hygiene.js +57 -0
- package/dist/pack-hygiene.js.map +1 -0
- package/dist/package-manager.d.ts +34 -6
- package/dist/package-manager.js +130 -20
- package/dist/package-manager.js.map +1 -1
- package/dist/project.js +11 -0
- package/dist/project.js.map +1 -1
- package/dist/repo/scaffold.js +4 -0
- package/dist/repo/scaffold.js.map +1 -1
- package/dist/schema-skew.js.map +1 -1
- package/dist/validate-findings.js +10 -1
- package/dist/validate-findings.js.map +1 -1
- package/dist/workspace-root.d.ts +16 -0
- package/dist/workspace-root.js +50 -0
- package/dist/workspace-root.js.map +1 -0
- package/package.json +4 -4
- package/templates/AGENTS.md.tmpl +11 -15
- package/templates/experience/package.json.tmpl +8 -6
- package/templates/experience/src/widgets/hello-widget.test.tsx.tmpl +49 -0
- package/templates/experience/vitest.config.ts.tmpl +21 -0
- package/templates/harness/next.config.mjs.tmpl +7 -4
- package/templates/package.json.tmpl +5 -5
- package/templates/skills/build-integration/references/widget-design.md +2 -3
- package/templates/skills/polish-widgets/references/patterns.md +5 -5
- package/dist/generated/fa-free-names.d.ts +0 -9
- package/dist/generated/fa-free-names.js +0 -2599
- package/dist/generated/fa-free-names.js.map +0 -1
package/dist/icon-findings.js
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { PHOSPHOR_ICON_NAMES } from './generated/phosphor-names.js';
|
|
4
4
|
/**
|
|
5
|
-
* Flags
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* discovers it, if nobody was watching the console.
|
|
5
|
+
* Flags icon names in a project's widget source that `@ekanos/ui`'s `Icon`
|
|
6
|
+
* cannot draw. Icons are Phosphor (phosphoricons.com): a name that is not
|
|
7
|
+
* one draws the `shapes` fallback, which nobody notices until a screenshot
|
|
8
|
+
* review. A Font Awesome value from before the move (`fa-house`) still
|
|
9
|
+
* renders through a translation table, but new code should write the
|
|
10
|
+
* Phosphor name.
|
|
12
11
|
*
|
|
13
|
-
* `validate` has no live component tree
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* already-imported component. So this scans the project's own `src/**\/*.{ts,tsx}`
|
|
18
|
-
* on disk instead, the same fallback `collectProjectFindings` would use if it
|
|
19
|
-
* needed source text rather than a loaded value.
|
|
12
|
+
* `validate` has no live component tree, and by the time `loadDefinition`
|
|
13
|
+
* resolves a definition its `component`/`icon` fields are live values with
|
|
14
|
+
* no path back to source, so this scans the project's own
|
|
15
|
+
* `src/**\/*.{ts,tsx}` on disk.
|
|
20
16
|
*
|
|
21
|
-
* WARN, not error:
|
|
22
|
-
*
|
|
23
|
-
* where the exact same name renders correctly.
|
|
17
|
+
* WARN, not error: an unknown name is broken UX, not an unbuildable
|
|
18
|
+
* submission.
|
|
24
19
|
*/
|
|
25
20
|
export function collectIconFindings(projectDir) {
|
|
26
21
|
const srcDir = path.join(projectDir, 'src');
|
|
@@ -44,75 +39,55 @@ function* walkTsFiles(dir) {
|
|
|
44
39
|
}
|
|
45
40
|
}
|
|
46
41
|
/**
|
|
47
|
-
*
|
|
48
|
-
* `
|
|
49
|
-
*
|
|
50
|
-
* `FA_ICON_STYLES` — a style name is never itself an icon name, so it must
|
|
51
|
-
* not be treated as one, but that list lives in a browser package this one
|
|
52
|
-
* may not import.
|
|
42
|
+
* A quoted literal whose entire contents could be an icon value: a Phosphor
|
|
43
|
+
* name (`house`, `star:fill`) or a Font Awesome value (`fa-solid fa-house`).
|
|
44
|
+
* Parameterized on its backreference because it is spliced in twice.
|
|
53
45
|
*/
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
* A quoted string literal whose ENTIRE contents are a bare `fa-<name>` value
|
|
57
|
-
* or a two-token `fa-<style> fa-<name>` value — anchored to the quote
|
|
58
|
-
* boundaries (the backreference to the opening quote must follow the name
|
|
59
|
-
* pattern immediately) so this cannot match a `fa-`-prefixed SUBSTRING inside
|
|
60
|
-
* a longer, unrelated string.
|
|
61
|
-
*
|
|
62
|
-
* Parameterized on its own backreference number because it is spliced into
|
|
63
|
-
* `FA_ICON_CONTEXT_RE` twice — each copy opens its own capture group, so a
|
|
64
|
-
* hardcoded `\1` in the second copy would wrongly point at the FIRST copy's
|
|
65
|
-
* quote group instead of its own.
|
|
66
|
-
*/
|
|
67
|
-
function faIconLiteral(quoteGroup) {
|
|
68
|
-
return `(['"\`])(?:fa-${FA_STYLE_TOKEN}\\s+)?fa-([a-z][a-z0-9]*(?:-[a-z0-9]+)*)\\${quoteGroup}`;
|
|
46
|
+
function iconLiteral(quoteGroup) {
|
|
47
|
+
return `(['"\`])((?:fa-[a-z]+\\s+)?[a-z][a-z0-9]*(?:-[a-z0-9]+)*(?::fill)?)\\${quoteGroup}`;
|
|
69
48
|
}
|
|
70
49
|
/**
|
|
71
|
-
* Only literals in a position that plausibly
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* `
|
|
75
|
-
*
|
|
76
|
-
* This is a heuristic, not a parser — it will miss an icon name built up any
|
|
77
|
-
* other way (a variable, a template with interpolation, an indirect prop
|
|
78
|
-
* name), and in principle a `name`/`icon` key on some unrelated object could
|
|
79
|
-
* coincidentally hold an `fa-`-shaped string and get flagged. Both failure
|
|
80
|
-
* modes are accepted: a scan that required full TS type information to be
|
|
81
|
-
* exact is not worth the cost here, and this project's own convention names
|
|
82
|
-
* icon props/keys `name` or `icon` specifically to keep that collision rare.
|
|
83
|
-
* Group numbers: 1 = quote, 2 = name for the `name`/`icon` branch; 3 = quote,
|
|
84
|
-
* 4 = name for the `resolveIcon`/`renderIcon` branch.
|
|
50
|
+
* Only literals in a position that plausibly holds an icon name: the `icon`
|
|
51
|
+
* prop or key, an `<Icon name=…>`, or a direct argument to `resolveIcon` /
|
|
52
|
+
* `renderIcon`. A heuristic, not a parser: it misses names built any other
|
|
53
|
+
* way. Groups: 1 = quote, 2 = value for the `icon` key; 3/4 for `<Icon
|
|
54
|
+
* name>`; 5/6 for the helper calls.
|
|
85
55
|
*/
|
|
86
|
-
const
|
|
87
|
-
|
|
56
|
+
const ICON_CONTEXT_RE = new RegExp(`\\bicon\\s*[:=]\\s*\\{?\\s*${iconLiteral(1)}` +
|
|
57
|
+
`|<Icon\\b[^>]*?\\bname=\\{?\\s*${iconLiteral(3)}` +
|
|
58
|
+
`|\\b(?:resolveIcon|renderIcon)\\(\\s*${iconLiteral(5)}`, 'g');
|
|
88
59
|
function collectIconFindingsInFile(file) {
|
|
89
|
-
var _a;
|
|
60
|
+
var _a, _b;
|
|
90
61
|
const source = fs.readFileSync(file, 'utf8');
|
|
91
62
|
const findings = [];
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (!iconName || FA_FREE_ICON_NAMES.has(iconName))
|
|
63
|
+
for (const match of source.matchAll(ICON_CONTEXT_RE)) {
|
|
64
|
+
const value = (_b = (_a = match[2]) !== null && _a !== void 0 ? _a : match[4]) !== null && _b !== void 0 ? _b : match[6];
|
|
65
|
+
if (!value)
|
|
96
66
|
continue;
|
|
97
|
-
const dedupeKey = `${iconName}@${match.index}`;
|
|
98
|
-
if (seen.has(dedupeKey))
|
|
99
|
-
continue;
|
|
100
|
-
seen.add(dedupeKey);
|
|
101
67
|
const line = source.slice(0, match.index).split('\n').length;
|
|
102
|
-
|
|
68
|
+
if (value.startsWith('fa-')) {
|
|
69
|
+
findings.push({
|
|
70
|
+
check: 'icons/font-awesome',
|
|
71
|
+
severity: 'warn',
|
|
72
|
+
file,
|
|
73
|
+
line,
|
|
74
|
+
message: `"${value}" is a Font Awesome value. Ekanos draws Phosphor icons; ` +
|
|
75
|
+
'this one still renders through a translation table, but may not ' +
|
|
76
|
+
'be the glyph you meant.',
|
|
77
|
+
hint: 'Write the Phosphor name from phosphoricons.com (e.g. "house").',
|
|
78
|
+
});
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (PHOSPHOR_ICON_NAMES.has(value.replace(/:fill$/, '')))
|
|
82
|
+
continue;
|
|
103
83
|
findings.push({
|
|
104
|
-
check: 'icons/
|
|
84
|
+
check: 'icons/unknown',
|
|
105
85
|
severity: 'warn',
|
|
106
86
|
file,
|
|
107
87
|
line,
|
|
108
|
-
message: `"
|
|
109
|
-
'
|
|
110
|
-
|
|
111
|
-
'circle-question placeholder instead of the intended glyph.',
|
|
112
|
-
hint: alternative
|
|
113
|
-
? `Use "fa-${alternative}" instead — the nearest Free equivalent.`
|
|
114
|
-
: 'Pick a Free icon name — Pro names render as placeholder discs ' +
|
|
115
|
-
'outside Pro-licensed hosts.',
|
|
88
|
+
message: `"${value}" is not a Phosphor icon, so it draws the "shapes" ` +
|
|
89
|
+
'fallback instead of the glyph you meant.',
|
|
90
|
+
hint: 'Pick a name from phosphoricons.com (e.g. "house", "caret-down").',
|
|
116
91
|
});
|
|
117
92
|
}
|
|
118
93
|
return findings;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon-findings.js","sourceRoot":"","sources":["../src/icon-findings.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,
|
|
1
|
+
{"version":3,"file":"icon-findings.js","sourceRoot":"","sources":["../src/icon-findings.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Finding } from '@ekanos/integration-schema';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { PHOSPHOR_ICON_NAMES } from './generated/phosphor-names';\n\n/**\n * Flags icon names in a project's widget source that `@ekanos/ui`'s `Icon`\n * cannot draw. Icons are Phosphor (phosphoricons.com): a name that is not\n * one draws the `shapes` fallback, which nobody notices until a screenshot\n * review. A Font Awesome value from before the move (`fa-house`) still\n * renders through a translation table, but new code should write the\n * Phosphor name.\n *\n * `validate` has no live component tree, and by the time `loadDefinition`\n * resolves a definition its `component`/`icon` fields are live values with\n * no path back to source, so this scans the project's own\n * `src/**\\/*.{ts,tsx}` on disk.\n *\n * WARN, not error: an unknown name is broken UX, not an unbuildable\n * submission.\n */\nexport function collectIconFindings(projectDir: string): Finding[] {\n const srcDir = path.join(projectDir, 'src');\n if (!fs.existsSync(srcDir)) return [];\n\n const findings: Finding[] = [];\n for (const file of walkTsFiles(srcDir)) {\n findings.push(...collectIconFindingsInFile(file));\n }\n return findings;\n}\n\nfunction* walkTsFiles(dir: string): Generator<string> {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n yield* walkTsFiles(full);\n } else if (/\\.(ts|tsx)$/.test(entry.name)) {\n yield full;\n }\n }\n}\n\n/**\n * A quoted literal whose entire contents could be an icon value: a Phosphor\n * name (`house`, `star:fill`) or a Font Awesome value (`fa-solid fa-house`).\n * Parameterized on its backreference because it is spliced in twice.\n */\nfunction iconLiteral(quoteGroup: number): string {\n return `(['\"\\`])((?:fa-[a-z]+\\\\s+)?[a-z][a-z0-9]*(?:-[a-z0-9]+)*(?::fill)?)\\\\${quoteGroup}`;\n}\n\n/**\n * Only literals in a position that plausibly holds an icon name: the `icon`\n * prop or key, an `<Icon name=…>`, or a direct argument to `resolveIcon` /\n * `renderIcon`. A heuristic, not a parser: it misses names built any other\n * way. Groups: 1 = quote, 2 = value for the `icon` key; 3/4 for `<Icon\n * name>`; 5/6 for the helper calls.\n */\nconst ICON_CONTEXT_RE = new RegExp(\n `\\\\bicon\\\\s*[:=]\\\\s*\\\\{?\\\\s*${iconLiteral(1)}` +\n `|<Icon\\\\b[^>]*?\\\\bname=\\\\{?\\\\s*${iconLiteral(3)}` +\n `|\\\\b(?:resolveIcon|renderIcon)\\\\(\\\\s*${iconLiteral(5)}`,\n 'g',\n);\n\nfunction collectIconFindingsInFile(file: string): Finding[] {\n const source = fs.readFileSync(file, 'utf8');\n const findings: Finding[] = [];\n\n for (const match of source.matchAll(ICON_CONTEXT_RE)) {\n const value = match[2] ?? match[4] ?? match[6];\n if (!value) continue;\n const line = source.slice(0, match.index).split('\\n').length;\n\n if (value.startsWith('fa-')) {\n findings.push({\n check: 'icons/font-awesome',\n severity: 'warn',\n file,\n line,\n message:\n `\"${value}\" is a Font Awesome value. Ekanos draws Phosphor icons; ` +\n 'this one still renders through a translation table, but may not ' +\n 'be the glyph you meant.',\n hint: 'Write the Phosphor name from phosphoricons.com (e.g. \"house\").',\n });\n continue;\n }\n\n if (PHOSPHOR_ICON_NAMES.has(value.replace(/:fill$/, ''))) continue;\n\n findings.push({\n check: 'icons/unknown',\n severity: 'warn',\n file,\n line,\n message:\n `\"${value}\" is not a Phosphor icon, so it draws the \"shapes\" ` +\n 'fallback instead of the glyph you meant.',\n hint: 'Pick a name from phosphoricons.com (e.g. \"house\", \"caret-down\").',\n });\n }\n\n return findings;\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -30,7 +30,7 @@ import { runRoutes } from './commands/routes.js';
|
|
|
30
30
|
import { runApprovals, runRuns } from './commands/runs.js';
|
|
31
31
|
import { runSkills } from './commands/skills.js';
|
|
32
32
|
import { runSources } from './commands/sources.js';
|
|
33
|
-
import { runStatus } from './commands/status.js';
|
|
33
|
+
import { parseTimeoutMinutes, runStatus } from './commands/status.js';
|
|
34
34
|
import { TEAM_AGENT_AREAS, usageFor } from './commands/team-agents.js';
|
|
35
35
|
import { runTeams } from './commands/teams.js';
|
|
36
36
|
import { runTest } from './commands/test.js';
|
|
@@ -200,6 +200,14 @@ const COMMAND_SPECS = {
|
|
|
200
200
|
type: 'boolean',
|
|
201
201
|
description: "Wait until this project's current version reaches a gate verdict",
|
|
202
202
|
},
|
|
203
|
+
wait: {
|
|
204
|
+
type: 'boolean',
|
|
205
|
+
description: 'Same as --watch',
|
|
206
|
+
},
|
|
207
|
+
timeout: {
|
|
208
|
+
type: 'string',
|
|
209
|
+
description: 'With --watch/--wait: give up after this many minutes (default 30; exit 11)',
|
|
210
|
+
},
|
|
203
211
|
},
|
|
204
212
|
sources: {
|
|
205
213
|
host: HOST,
|
|
@@ -751,6 +759,14 @@ const COMMAND_SPECS = {
|
|
|
751
759
|
type: 'boolean',
|
|
752
760
|
description: 'In a repo: publish every package',
|
|
753
761
|
},
|
|
762
|
+
wait: {
|
|
763
|
+
type: 'boolean',
|
|
764
|
+
description: 'After submitting, wait for the gate verdict and print its findings (exit 10 if rejected)',
|
|
765
|
+
},
|
|
766
|
+
timeout: {
|
|
767
|
+
type: 'string',
|
|
768
|
+
description: 'With --wait: give up after this many minutes (default 30; exit 11)',
|
|
769
|
+
},
|
|
754
770
|
},
|
|
755
771
|
upgrade: {
|
|
756
772
|
dir: DIR,
|
|
@@ -843,8 +859,9 @@ const USAGE = [
|
|
|
843
859
|
' a compact list of the sources you hold a seat on',
|
|
844
860
|
" status Show login state and this project's submissions on the host",
|
|
845
861
|
' (--findings for full gate findings, --all to expand other',
|
|
846
|
-
' integrations in the source, --watch to block until
|
|
847
|
-
" project's current version reaches a gate verdict
|
|
862
|
+
' integrations in the source, --watch (or --wait) to block until',
|
|
863
|
+
" this project's current version reaches a gate verdict, up to",
|
|
864
|
+
' --timeout <minutes>, default 30)',
|
|
848
865
|
' sources List every source you hold a developer/source-admin seat on |',
|
|
849
866
|
' products [--source <slug>] (each product, Experience or',
|
|
850
867
|
' Integration, and whether it is enabled for the Source) |',
|
|
@@ -1105,7 +1122,9 @@ const USAGE = [
|
|
|
1105
1122
|
' <run-id> | runs cancel <run-id> [--yes] | approvals list |',
|
|
1106
1123
|
' approvals approve|reject <id> [--reason "…"]',
|
|
1107
1124
|
' use Set this project\'s publish target ("ekanos use <source-slug>")',
|
|
1108
|
-
' publish Validate, pack and submit the integration to an Ekanos host
|
|
1125
|
+
' publish Validate, pack and submit the integration to an Ekanos host',
|
|
1126
|
+
' (--dry-run gates and packs, sends nothing; --wait [--timeout',
|
|
1127
|
+
' <minutes>] then waits for the gate verdict).',
|
|
1109
1128
|
' In a repo: publish [<package>...] | --all [--dry-run] (integrations',
|
|
1110
1129
|
' first, each package gated, artifacts under .ekanos/publish/)',
|
|
1111
1130
|
' upgrade Move this toolchain to a coherent target version, with',
|
|
@@ -1268,7 +1287,8 @@ export async function run(argv, options = {}) {
|
|
|
1268
1287
|
env,
|
|
1269
1288
|
findings: parsed.flags.findings === true,
|
|
1270
1289
|
all: parsed.flags.all === true,
|
|
1271
|
-
watch: parsed.flags.watch === true,
|
|
1290
|
+
watch: parsed.flags.watch === true || parsed.flags.wait === true,
|
|
1291
|
+
timeoutMinutes: parseTimeoutMinutes(parsed.flags.timeout),
|
|
1272
1292
|
sleep: options.sleep,
|
|
1273
1293
|
now: options.now,
|
|
1274
1294
|
});
|
|
@@ -1506,6 +1526,9 @@ export async function run(argv, options = {}) {
|
|
|
1506
1526
|
dryRun: parsed.flags['dry-run'] === true,
|
|
1507
1527
|
packages: parsed.positionals,
|
|
1508
1528
|
all: parsed.flags.all === true,
|
|
1529
|
+
wait: parsed.flags.wait === true,
|
|
1530
|
+
timeoutMinutes: parseTimeoutMinutes(parsed.flags.timeout),
|
|
1531
|
+
sleep: options.sleep,
|
|
1509
1532
|
env,
|
|
1510
1533
|
stdinIsTTY: options.stdinIsTTY,
|
|
1511
1534
|
confirm: options.confirm,
|