@pie-element/cli 0.1.1 → 0.1.2-next.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 +48 -10
- package/dist/commands/dev/demo/index.d.ts +1 -1
- package/dist/commands/dev/demo/index.js +21 -0
- package/dist/commands/dev/demo/index.js.map +1 -1
- package/dist/commands/dev/test-bundler.d.ts +0 -1
- package/dist/commands/dev/test-bundler.js +2 -10
- package/dist/commands/dev/test-bundler.js.map +1 -1
- package/dist/commands/docs/generate.d.ts +16 -0
- package/dist/commands/docs/generate.js +150 -0
- package/dist/commands/docs/generate.js.map +1 -0
- package/dist/commands/docs/verify.d.ts +12 -0
- package/dist/commands/docs/verify.js +40 -0
- package/dist/commands/docs/verify.js.map +1 -0
- package/dist/commands/packages/create-controllers.d.ts +0 -1
- package/dist/commands/packages/create-controllers.js.map +1 -1
- package/dist/commands/packages/create-lib-react.d.ts +0 -1
- package/dist/commands/packages/create-lib-react.js +1 -3
- package/dist/commands/packages/create-lib-react.js.map +1 -1
- package/dist/commands/packages/create-react-elements.d.ts +0 -1
- package/dist/commands/packages/create-react-elements.js +2 -3
- package/dist/commands/packages/create-react-elements.js.map +1 -1
- package/dist/commands/packages/enable-publishing.d.ts +0 -1
- package/dist/commands/packages/enable-publishing.js +26 -23
- package/dist/commands/packages/enable-publishing.js.map +1 -1
- package/dist/commands/packages/init-synced-elements.d.ts +0 -1
- package/dist/commands/packages/init-synced-elements.js +1 -1
- package/dist/commands/packages/init-synced-elements.js.map +1 -1
- package/dist/commands/upstream/analyze-esm.d.ts +0 -1
- package/dist/commands/upstream/analyze-esm.js +5 -1
- package/dist/commands/upstream/analyze-esm.js.map +1 -1
- package/dist/commands/upstream/check.d.ts +0 -1
- package/dist/commands/upstream/check.js.map +1 -1
- package/dist/commands/upstream/deps.d.ts +0 -1
- package/dist/commands/upstream/deps.js.map +1 -1
- package/dist/commands/upstream/sync.d.ts +11 -2
- package/dist/commands/upstream/sync.js +364 -25
- package/dist/commands/upstream/sync.js.map +1 -1
- package/dist/commands/upstream/track.d.ts +0 -1
- package/dist/commands/upstream/track.js.map +1 -1
- package/dist/commands/upstream/update.d.ts +0 -1
- package/dist/commands/upstream/update.js +37 -7
- package/dist/commands/upstream/update.js.map +1 -1
- package/dist/commands/verify/controllers.d.ts +0 -1
- package/dist/commands/verify/controllers.js +213 -59
- package/dist/commands/verify/controllers.js.map +1 -1
- package/dist/commands/verify/dependency-integrity.d.ts +18 -0
- package/dist/commands/verify/dependency-integrity.js +147 -0
- package/dist/commands/verify/dependency-integrity.js.map +1 -0
- package/dist/commands/verify/react-build.d.ts +0 -1
- package/dist/commands/verify/react-build.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/docs/contract-validator.d.ts +12 -0
- package/dist/lib/docs/contract-validator.js +38 -0
- package/dist/lib/docs/contract-validator.js.map +1 -0
- package/dist/lib/docs/contracts.d.ts +11 -0
- package/dist/lib/docs/contracts.js +241 -0
- package/dist/lib/docs/contracts.js.map +1 -0
- package/dist/lib/docs/discovery.d.ts +10 -0
- package/dist/lib/docs/discovery.js +91 -0
- package/dist/lib/docs/discovery.js.map +1 -0
- package/dist/lib/docs/generator.d.ts +14 -0
- package/dist/lib/docs/generator.js +450 -0
- package/dist/lib/docs/generator.js.map +1 -0
- package/dist/lib/docs/source-extractor.d.ts +2 -0
- package/dist/lib/docs/source-extractor.js +209 -0
- package/dist/lib/docs/source-extractor.js.map +1 -0
- package/dist/lib/docs/types.d.ts +77 -0
- package/dist/lib/docs/types.js +2 -0
- package/dist/lib/docs/types.js.map +1 -0
- package/dist/lib/upstream/repo-utils.d.ts +0 -1
- package/dist/lib/upstream/repo-utils.js.map +1 -1
- package/dist/lib/upstream/sync-compatibility.d.ts +0 -1
- package/dist/lib/upstream/sync-compatibility.js.map +1 -1
- package/dist/lib/upstream/sync-constants.d.ts +35 -7
- package/dist/lib/upstream/sync-constants.js +40 -11
- package/dist/lib/upstream/sync-constants.js.map +1 -1
- package/dist/lib/upstream/sync-controllers-strategy.d.ts +0 -1
- package/dist/lib/upstream/sync-controllers-strategy.js +14 -4
- package/dist/lib/upstream/sync-controllers-strategy.js.map +1 -1
- package/dist/lib/upstream/sync-demo-metadata.d.ts +0 -1
- package/dist/lib/upstream/sync-demo-metadata.js +1 -1
- package/dist/lib/upstream/sync-demo-metadata.js.map +1 -1
- package/dist/lib/upstream/sync-entry-discovery.d.ts +3 -0
- package/dist/lib/upstream/sync-entry-discovery.js +23 -0
- package/dist/lib/upstream/sync-entry-discovery.js.map +1 -0
- package/dist/lib/upstream/sync-externals.d.ts +7 -7
- package/dist/lib/upstream/sync-externals.js +51 -35
- package/dist/lib/upstream/sync-externals.js.map +1 -1
- package/dist/lib/upstream/sync-filesystem.d.ts +0 -1
- package/dist/lib/upstream/sync-filesystem.js.map +1 -1
- package/dist/lib/upstream/sync-imports.d.ts +82 -62
- package/dist/lib/upstream/sync-imports.js +658 -185
- package/dist/lib/upstream/sync-imports.js.map +1 -1
- package/dist/lib/upstream/sync-package-json.d.ts +0 -1
- package/dist/lib/upstream/sync-package-json.js +7 -0
- package/dist/lib/upstream/sync-package-json.js.map +1 -1
- package/dist/lib/upstream/sync-package-manager.d.ts +14 -4
- package/dist/lib/upstream/sync-package-manager.js +405 -72
- package/dist/lib/upstream/sync-package-manager.js.map +1 -1
- package/dist/lib/upstream/sync-pielib-strategy.d.ts +2 -1
- package/dist/lib/upstream/sync-pielib-strategy.js +228 -110
- package/dist/lib/upstream/sync-pielib-strategy.js.map +1 -1
- package/dist/lib/upstream/sync-presets.d.ts +52 -0
- package/dist/lib/upstream/sync-presets.js +175 -0
- package/dist/lib/upstream/sync-presets.js.map +1 -0
- package/dist/lib/upstream/sync-react-strategy.d.ts +6 -1
- package/dist/lib/upstream/sync-react-strategy.js +342 -134
- package/dist/lib/upstream/sync-react-strategy.js.map +1 -1
- package/dist/lib/upstream/sync-source-edit.d.ts +14 -0
- package/dist/lib/upstream/sync-source-edit.js +89 -0
- package/dist/lib/upstream/sync-source-edit.js.map +1 -0
- package/dist/lib/upstream/sync-source-tree.d.ts +22 -0
- package/dist/lib/upstream/sync-source-tree.js +99 -0
- package/dist/lib/upstream/sync-source-tree.js.map +1 -0
- package/dist/lib/upstream/sync-strategy.d.ts +1 -1
- package/dist/lib/upstream/sync-strategy.js.map +1 -1
- package/dist/lib/upstream/sync-summary.d.ts +0 -1
- package/dist/lib/upstream/sync-summary.js.map +1 -1
- package/dist/lib/upstream/sync-transforms.d.ts +13 -11
- package/dist/lib/upstream/sync-transforms.js +23 -17
- package/dist/lib/upstream/sync-transforms.js.map +1 -1
- package/dist/lib/upstream/sync-vite-config.d.ts +13 -1
- package/dist/lib/upstream/sync-vite-config.js +65 -46
- package/dist/lib/upstream/sync-vite-config.js.map +1 -1
- package/dist/utils/compatibility.d.ts +13 -1
- package/dist/utils/compatibility.js +143 -2
- package/dist/utils/compatibility.js.map +1 -1
- package/dist/utils/conversion.d.ts +0 -1
- package/dist/utils/conversion.js.map +1 -1
- package/dist/utils/dependency-integrity.d.ts +37 -0
- package/dist/utils/dependency-integrity.js +557 -0
- package/dist/utils/dependency-integrity.js.map +1 -0
- package/dist/utils/git.d.ts +0 -1
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/logger.d.ts +0 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/package-json.d.ts +0 -1
- package/dist/utils/package-json.js.map +1 -1
- package/package.json +25 -8
- package/.compatibility/report.json +0 -2491
- package/.turbo/turbo-build.log +0 -1
- package/CHANGELOG.md +0 -8
- package/REFACTORING.md +0 -131
- package/bin/dev.js +0 -5
- package/dist/commands/dev/demo/index.d.ts.map +0 -1
- package/dist/commands/dev/test-bundler.d.ts.map +0 -1
- package/dist/commands/mathquill/migrate.d.ts +0 -20
- package/dist/commands/mathquill/migrate.d.ts.map +0 -1
- package/dist/commands/mathquill/migrate.js +0 -240
- package/dist/commands/mathquill/migrate.js.map +0 -1
- package/dist/commands/mathquill/status.d.ts +0 -20
- package/dist/commands/mathquill/status.d.ts.map +0 -1
- package/dist/commands/mathquill/status.js +0 -231
- package/dist/commands/mathquill/status.js.map +0 -1
- package/dist/commands/packages/create-controllers.d.ts.map +0 -1
- package/dist/commands/packages/create-lib-react.d.ts.map +0 -1
- package/dist/commands/packages/create-react-elements.d.ts.map +0 -1
- package/dist/commands/packages/enable-publishing.d.ts.map +0 -1
- package/dist/commands/packages/init-synced-elements.d.ts.map +0 -1
- package/dist/commands/upstream/analyze-esm.d.ts.map +0 -1
- package/dist/commands/upstream/check.d.ts.map +0 -1
- package/dist/commands/upstream/deps.d.ts.map +0 -1
- package/dist/commands/upstream/sync-mathquill.d.ts +0 -12
- package/dist/commands/upstream/sync-mathquill.d.ts.map +0 -1
- package/dist/commands/upstream/sync-mathquill.js +0 -97
- package/dist/commands/upstream/sync-mathquill.js.map +0 -1
- package/dist/commands/upstream/sync.d.ts.map +0 -1
- package/dist/commands/upstream/track.d.ts.map +0 -1
- package/dist/commands/upstream/update.d.ts.map +0 -1
- package/dist/commands/verify/controllers.d.ts.map +0 -1
- package/dist/commands/verify/react-build.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/lib/mathquill/extension-generator.d.ts +0 -9
- package/dist/lib/mathquill/extension-generator.d.ts.map +0 -1
- package/dist/lib/mathquill/extension-generator.js +0 -107
- package/dist/lib/mathquill/extension-generator.js.map +0 -1
- package/dist/lib/mathquill/khan-extractor.d.ts +0 -16
- package/dist/lib/mathquill/khan-extractor.d.ts.map +0 -1
- package/dist/lib/mathquill/khan-extractor.js +0 -148
- package/dist/lib/mathquill/khan-extractor.js.map +0 -1
- package/dist/lib/mathquill/learnosity-extractor.d.ts +0 -15
- package/dist/lib/mathquill/learnosity-extractor.d.ts.map +0 -1
- package/dist/lib/mathquill/learnosity-extractor.js +0 -170
- package/dist/lib/mathquill/learnosity-extractor.js.map +0 -1
- package/dist/lib/mathquill/migration-orchestrator.d.ts +0 -77
- package/dist/lib/mathquill/migration-orchestrator.d.ts.map +0 -1
- package/dist/lib/mathquill/migration-orchestrator.js +0 -391
- package/dist/lib/mathquill/migration-orchestrator.js.map +0 -1
- package/dist/lib/mathquill/package-updater.d.ts +0 -9
- package/dist/lib/mathquill/package-updater.d.ts.map +0 -1
- package/dist/lib/mathquill/package-updater.js +0 -103
- package/dist/lib/mathquill/package-updater.js.map +0 -1
- package/dist/lib/mathquill/pie-extractor.d.ts +0 -14
- package/dist/lib/mathquill/pie-extractor.d.ts.map +0 -1
- package/dist/lib/mathquill/pie-extractor.js +0 -167
- package/dist/lib/mathquill/pie-extractor.js.map +0 -1
- package/dist/lib/upstream/repo-utils.d.ts.map +0 -1
- package/dist/lib/upstream/sync-compatibility.d.ts.map +0 -1
- package/dist/lib/upstream/sync-constants.d.ts.map +0 -1
- package/dist/lib/upstream/sync-controllers-strategy.d.ts.map +0 -1
- package/dist/lib/upstream/sync-demo-metadata.d.ts.map +0 -1
- package/dist/lib/upstream/sync-dev-exports.d.ts +0 -13
- package/dist/lib/upstream/sync-dev-exports.d.ts.map +0 -1
- package/dist/lib/upstream/sync-dev-exports.js +0 -115
- package/dist/lib/upstream/sync-dev-exports.js.map +0 -1
- package/dist/lib/upstream/sync-externals.d.ts.map +0 -1
- package/dist/lib/upstream/sync-filesystem.d.ts.map +0 -1
- package/dist/lib/upstream/sync-imports.d.ts.map +0 -1
- package/dist/lib/upstream/sync-mathquill.d.ts +0 -19
- package/dist/lib/upstream/sync-mathquill.d.ts.map +0 -1
- package/dist/lib/upstream/sync-mathquill.js +0 -160
- package/dist/lib/upstream/sync-mathquill.js.map +0 -1
- package/dist/lib/upstream/sync-package-json.d.ts.map +0 -1
- package/dist/lib/upstream/sync-package-manager.d.ts.map +0 -1
- package/dist/lib/upstream/sync-pielib-strategy.d.ts.map +0 -1
- package/dist/lib/upstream/sync-react-strategy.d.ts.map +0 -1
- package/dist/lib/upstream/sync-strategy.d.ts.map +0 -1
- package/dist/lib/upstream/sync-summary.d.ts.map +0 -1
- package/dist/lib/upstream/sync-transforms.d.ts.map +0 -1
- package/dist/lib/upstream/sync-vite-config.d.ts.map +0 -1
- package/dist/utils/compatibility.d.ts.map +0 -1
- package/dist/utils/conversion.d.ts.map +0 -1
- package/dist/utils/git.d.ts.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/package-json.d.ts.map +0 -1
- package/packages/cli/bin/dev.js +0 -5
- package/packages/cli/bin/run.js +0 -5
- package/src/commands/dev/demo/index.ts +0 -313
- package/src/commands/dev/test-bundler.ts +0 -345
- package/src/commands/mathquill/migrate.ts +0 -269
- package/src/commands/mathquill/status.ts +0 -267
- package/src/commands/packages/create-controllers.ts +0 -127
- package/src/commands/packages/create-lib-react.ts +0 -279
- package/src/commands/packages/create-react-elements.ts +0 -306
- package/src/commands/packages/enable-publishing.ts +0 -161
- package/src/commands/packages/init-synced-elements.ts +0 -259
- package/src/commands/upstream/README.md +0 -444
- package/src/commands/upstream/analyze-esm.ts +0 -1973
- package/src/commands/upstream/check.ts +0 -228
- package/src/commands/upstream/deps.ts +0 -222
- package/src/commands/upstream/sync-mathquill.ts +0 -108
- package/src/commands/upstream/sync.ts +0 -687
- package/src/commands/upstream/track.ts +0 -145
- package/src/commands/upstream/update.ts +0 -110
- package/src/commands/verify/controllers.ts +0 -166
- package/src/commands/verify/react-build.ts +0 -171
- package/src/index.ts +0 -1
- package/src/lib/mathquill/extension-generator.ts +0 -111
- package/src/lib/mathquill/khan-extractor.ts +0 -175
- package/src/lib/mathquill/learnosity-extractor.ts +0 -198
- package/src/lib/mathquill/migration-orchestrator.ts +0 -513
- package/src/lib/mathquill/package-updater.ts +0 -120
- package/src/lib/mathquill/pie-extractor.ts +0 -194
- package/src/lib/upstream/repo-utils.ts +0 -18
- package/src/lib/upstream/sync-compatibility.ts +0 -89
- package/src/lib/upstream/sync-constants.ts +0 -77
- package/src/lib/upstream/sync-controllers-strategy.ts +0 -291
- package/src/lib/upstream/sync-demo-metadata.ts +0 -199
- package/src/lib/upstream/sync-dev-exports.ts +0 -151
- package/src/lib/upstream/sync-externals.ts +0 -159
- package/src/lib/upstream/sync-filesystem.ts +0 -87
- package/src/lib/upstream/sync-imports.ts +0 -992
- package/src/lib/upstream/sync-mathquill.ts +0 -194
- package/src/lib/upstream/sync-package-json.ts +0 -86
- package/src/lib/upstream/sync-package-manager.ts +0 -694
- package/src/lib/upstream/sync-pielib-strategy.ts +0 -441
- package/src/lib/upstream/sync-react-strategy.ts +0 -945
- package/src/lib/upstream/sync-strategy.ts +0 -61
- package/src/lib/upstream/sync-summary.ts +0 -194
- package/src/lib/upstream/sync-transforms.ts +0 -154
- package/src/lib/upstream/sync-vite-config.ts +0 -243
- package/src/types/es-module-lexer.d.ts +0 -4
- package/src/utils/compatibility.ts +0 -182
- package/src/utils/conversion.ts +0 -153
- package/src/utils/git.ts +0 -63
- package/src/utils/logger.ts +0 -69
- package/src/utils/package-json.ts +0 -43
- package/tests/sync-package-manager.test.ts +0 -112
- package/tests/transform-assign-props.test.ts +0 -101
- package/tsconfig.json +0 -15
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC","sourcesContent":["export { run } from '@oclif/core';\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PieDocsContract } from './types.js';
|
|
2
|
+
export interface ContractValidationIssue {
|
|
3
|
+
elementName: string;
|
|
4
|
+
message: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ContractValidationResult {
|
|
7
|
+
issues: ContractValidationIssue[];
|
|
8
|
+
}
|
|
9
|
+
export declare const validateContracts: (contracts: Array<{
|
|
10
|
+
packageDir: string;
|
|
11
|
+
contract: PieDocsContract;
|
|
12
|
+
}>) => ContractValidationResult;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
export const validateContracts = (contracts) => {
|
|
4
|
+
const issues = [];
|
|
5
|
+
const seenElementNames = new Set();
|
|
6
|
+
for (const entry of contracts) {
|
|
7
|
+
const { contract, packageDir } = entry;
|
|
8
|
+
if (seenElementNames.has(contract.elementName)) {
|
|
9
|
+
issues.push({
|
|
10
|
+
elementName: contract.elementName,
|
|
11
|
+
message: `Duplicate elementName detected: ${contract.elementName}`,
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
seenElementNames.add(contract.elementName);
|
|
16
|
+
}
|
|
17
|
+
if (!contract.views.length) {
|
|
18
|
+
issues.push({
|
|
19
|
+
elementName: contract.elementName,
|
|
20
|
+
message: 'No views declared in contract',
|
|
21
|
+
});
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
for (const view of contract.views) {
|
|
25
|
+
for (const pointer of [view.pie, view.config]) {
|
|
26
|
+
const filePath = join(packageDir, pointer.file);
|
|
27
|
+
if (!existsSync(filePath)) {
|
|
28
|
+
issues.push({
|
|
29
|
+
elementName: contract.elementName,
|
|
30
|
+
message: `Missing source file for view "${view.view}": ${pointer.file}`,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return { issues };
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=contract-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-validator.js","sourceRoot":"","sources":["../../../src/lib/docs/contract-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAYjC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,SAAmE,EACzC,EAAE;IAC5B,MAAM,MAAM,GAA8B,EAAE,CAAC;IAC7C,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;IAE3C,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;QAC9B,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;QACvC,IAAI,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC;gBACV,WAAW,EAAE,QAAQ,CAAC,WAAW;gBACjC,OAAO,EAAE,mCAAmC,QAAQ,CAAC,WAAW,EAAE;aACnE,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC;gBACV,WAAW,EAAE,QAAQ,CAAC,WAAW;gBACjC,OAAO,EAAE,+BAA+B;aACzC,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YAClC,KAAK,MAAM,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;gBAChD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC1B,MAAM,CAAC,IAAI,CAAC;wBACV,WAAW,EAAE,QAAQ,CAAC,WAAW;wBACjC,OAAO,EAAE,iCAAiC,IAAI,CAAC,IAAI,MAAM,OAAO,CAAC,IAAI,EAAE;qBACxE,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC,CAAC","sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { PieDocsContract } from './types.js';\n\nexport interface ContractValidationIssue {\n elementName: string;\n message: string;\n}\n\nexport interface ContractValidationResult {\n issues: ContractValidationIssue[];\n}\n\nexport const validateContracts = (\n contracts: Array<{ packageDir: string; contract: PieDocsContract }>\n): ContractValidationResult => {\n const issues: ContractValidationIssue[] = [];\n const seenElementNames = new Set<string>();\n\n for (const entry of contracts) {\n const { contract, packageDir } = entry;\n if (seenElementNames.has(contract.elementName)) {\n issues.push({\n elementName: contract.elementName,\n message: `Duplicate elementName detected: ${contract.elementName}`,\n });\n } else {\n seenElementNames.add(contract.elementName);\n }\n\n if (!contract.views.length) {\n issues.push({\n elementName: contract.elementName,\n message: 'No views declared in contract',\n });\n continue;\n }\n\n for (const view of contract.views) {\n for (const pointer of [view.pie, view.config]) {\n const filePath = join(packageDir, pointer.file);\n if (!existsSync(filePath)) {\n issues.push({\n elementName: contract.elementName,\n message: `Missing source file for view \"${view.view}\": ${pointer.file}`,\n });\n }\n }\n }\n }\n\n return { issues };\n};\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ElementPackageInfo, PieDocsContract } from './types.js';
|
|
2
|
+
export declare const parseContract: (raw: unknown, location: string) => PieDocsContract;
|
|
3
|
+
export declare const loadContract: (packageDir: string) => Promise<PieDocsContract | null>;
|
|
4
|
+
export declare const writeContract: (packageDir: string, contract: PieDocsContract) => Promise<void>;
|
|
5
|
+
export declare const seedContractForElement: (element: ElementPackageInfo, rootDir: string, options?: {
|
|
6
|
+
refresh?: boolean;
|
|
7
|
+
}) => Promise<{
|
|
8
|
+
wrote: boolean;
|
|
9
|
+
contractPath: string;
|
|
10
|
+
contract: PieDocsContract;
|
|
11
|
+
}>;
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { join, relative } from 'node:path';
|
|
4
|
+
import { CONTRACT_FILENAME, inferViewsFromPackageExports } from './discovery.js';
|
|
5
|
+
const MODES = ['gather', 'view', 'evaluate'];
|
|
6
|
+
const isObject = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
7
|
+
const isSourcePointer = (value) => isObject(value) &&
|
|
8
|
+
typeof value.file === 'string' &&
|
|
9
|
+
(value.exportName === undefined || typeof value.exportName === 'string') &&
|
|
10
|
+
(value.path === undefined || typeof value.path === 'string');
|
|
11
|
+
const isPrimitiveEnumValue = (value) => value === null || ['string', 'number', 'boolean'].includes(typeof value);
|
|
12
|
+
const isPropertyMetadata = (value) => {
|
|
13
|
+
if (!isObject(value)) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
const allowed = [
|
|
17
|
+
'title',
|
|
18
|
+
'description',
|
|
19
|
+
'notes',
|
|
20
|
+
'type',
|
|
21
|
+
'required',
|
|
22
|
+
'enum',
|
|
23
|
+
'minimum',
|
|
24
|
+
'maximum',
|
|
25
|
+
'minLength',
|
|
26
|
+
'maxLength',
|
|
27
|
+
'pattern',
|
|
28
|
+
'itemType',
|
|
29
|
+
'examples',
|
|
30
|
+
];
|
|
31
|
+
for (const key of Object.keys(value)) {
|
|
32
|
+
if (!allowed.includes(key)) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (value.title !== undefined && typeof value.title !== 'string')
|
|
37
|
+
return false;
|
|
38
|
+
if (value.description !== undefined && typeof value.description !== 'string')
|
|
39
|
+
return false;
|
|
40
|
+
if (value.notes !== undefined && typeof value.notes !== 'string')
|
|
41
|
+
return false;
|
|
42
|
+
if (value.type !== undefined && typeof value.type !== 'string')
|
|
43
|
+
return false;
|
|
44
|
+
if (value.required !== undefined && typeof value.required !== 'boolean')
|
|
45
|
+
return false;
|
|
46
|
+
if (value.enum !== undefined) {
|
|
47
|
+
if (!Array.isArray(value.enum) || value.enum.some((entry) => !isPrimitiveEnumValue(entry))) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
for (const key of ['minimum', 'maximum', 'minLength', 'maxLength']) {
|
|
52
|
+
if (value[key] !== undefined && typeof value[key] !== 'number')
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
if (value.pattern !== undefined && typeof value.pattern !== 'string')
|
|
56
|
+
return false;
|
|
57
|
+
if (value.itemType !== undefined && typeof value.itemType !== 'string')
|
|
58
|
+
return false;
|
|
59
|
+
if (value.examples !== undefined && !Array.isArray(value.examples))
|
|
60
|
+
return false;
|
|
61
|
+
return true;
|
|
62
|
+
};
|
|
63
|
+
const normalizeMetadataMap = (map) => {
|
|
64
|
+
if (!map) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
return Object.fromEntries(Object.entries(map)
|
|
68
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
69
|
+
.map(([path, metadata]) => [path, { ...metadata }]));
|
|
70
|
+
};
|
|
71
|
+
const isViewMetadata = (value) => {
|
|
72
|
+
if (!isObject(value)) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
for (const key of Object.keys(value)) {
|
|
76
|
+
if (!['pie', 'config'].includes(key)) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
const map = value[key];
|
|
80
|
+
if (map === undefined)
|
|
81
|
+
continue;
|
|
82
|
+
if (!isObject(map))
|
|
83
|
+
return false;
|
|
84
|
+
for (const entry of Object.values(map)) {
|
|
85
|
+
if (!isPropertyMetadata(entry))
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
};
|
|
91
|
+
const normalizePointer = (pointer) => ({
|
|
92
|
+
file: pointer.file,
|
|
93
|
+
...(pointer.exportName ? { exportName: pointer.exportName } : {}),
|
|
94
|
+
...(pointer.path ? { path: pointer.path } : {}),
|
|
95
|
+
});
|
|
96
|
+
const normalizeContract = (contract) => ({
|
|
97
|
+
elementName: contract.elementName,
|
|
98
|
+
packageName: contract.packageName,
|
|
99
|
+
framework: contract.framework,
|
|
100
|
+
...(contract.summary ? { summary: contract.summary } : {}),
|
|
101
|
+
supportedModes: contract.supportedModes?.length ? [...contract.supportedModes] : MODES,
|
|
102
|
+
views: [...contract.views]
|
|
103
|
+
.sort((a, b) => a.view.localeCompare(b.view))
|
|
104
|
+
.map((view) => ({
|
|
105
|
+
view: view.view,
|
|
106
|
+
pie: normalizePointer(view.pie),
|
|
107
|
+
config: normalizePointer(view.config),
|
|
108
|
+
...(view.description ? { description: view.description } : {}),
|
|
109
|
+
...(view.metadata
|
|
110
|
+
? {
|
|
111
|
+
metadata: {
|
|
112
|
+
...(view.metadata.pie ? { pie: normalizeMetadataMap(view.metadata.pie) } : {}),
|
|
113
|
+
...(view.metadata.config
|
|
114
|
+
? { config: normalizeMetadataMap(view.metadata.config) }
|
|
115
|
+
: {}),
|
|
116
|
+
},
|
|
117
|
+
}
|
|
118
|
+
: {}),
|
|
119
|
+
})),
|
|
120
|
+
});
|
|
121
|
+
const inferPiePointer = (packageDir) => {
|
|
122
|
+
const candidates = [
|
|
123
|
+
{ file: 'src/author/defaultConfiguration.ts', path: 'model' },
|
|
124
|
+
{ file: 'src/author/defaults.ts', path: 'model' },
|
|
125
|
+
{ file: 'src/controller/defaults.ts' },
|
|
126
|
+
];
|
|
127
|
+
for (const candidate of candidates) {
|
|
128
|
+
if (existsSync(join(packageDir, candidate.file))) {
|
|
129
|
+
return candidate;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return { file: 'src/controller/defaults.ts' };
|
|
133
|
+
};
|
|
134
|
+
const inferConfigPointer = (packageDir) => {
|
|
135
|
+
const candidates = [
|
|
136
|
+
{ file: 'src/author/defaultConfiguration.ts', path: 'configuration' },
|
|
137
|
+
{ file: 'src/author/defaults.ts', path: 'configuration' },
|
|
138
|
+
{ file: 'src/controller/defaults.ts' },
|
|
139
|
+
];
|
|
140
|
+
for (const candidate of candidates) {
|
|
141
|
+
if (existsSync(join(packageDir, candidate.file))) {
|
|
142
|
+
return candidate;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return { file: 'src/controller/defaults.ts', path: 'configuration' };
|
|
146
|
+
};
|
|
147
|
+
export const parseContract = (raw, location) => {
|
|
148
|
+
if (!isObject(raw)) {
|
|
149
|
+
throw new Error(`Invalid docs contract in ${location}: expected object`);
|
|
150
|
+
}
|
|
151
|
+
if (typeof raw.elementName !== 'string' || !raw.elementName.trim()) {
|
|
152
|
+
throw new Error(`Invalid docs contract in ${location}: elementName is required`);
|
|
153
|
+
}
|
|
154
|
+
if (typeof raw.packageName !== 'string' || !raw.packageName.startsWith('@pie-element/')) {
|
|
155
|
+
throw new Error(`Invalid docs contract in ${location}: packageName is invalid`);
|
|
156
|
+
}
|
|
157
|
+
if (raw.framework !== 'react' && raw.framework !== 'svelte') {
|
|
158
|
+
throw new Error(`Invalid docs contract in ${location}: framework must be react|svelte`);
|
|
159
|
+
}
|
|
160
|
+
if (!Array.isArray(raw.views) || raw.views.length === 0) {
|
|
161
|
+
throw new Error(`Invalid docs contract in ${location}: at least one view is required`);
|
|
162
|
+
}
|
|
163
|
+
const views = raw.views.map((view, index) => {
|
|
164
|
+
if (!isObject(view)) {
|
|
165
|
+
throw new Error(`Invalid docs contract in ${location}: views[${index}] must be an object`);
|
|
166
|
+
}
|
|
167
|
+
if (typeof view.view !== 'string' || !view.view.trim()) {
|
|
168
|
+
throw new Error(`Invalid docs contract in ${location}: views[${index}].view is required`);
|
|
169
|
+
}
|
|
170
|
+
if (!isSourcePointer(view.pie)) {
|
|
171
|
+
throw new Error(`Invalid docs contract in ${location}: views[${index}].pie is invalid`);
|
|
172
|
+
}
|
|
173
|
+
if (!isSourcePointer(view.config)) {
|
|
174
|
+
throw new Error(`Invalid docs contract in ${location}: views[${index}].config is invalid`);
|
|
175
|
+
}
|
|
176
|
+
if (view.metadata !== undefined && !isViewMetadata(view.metadata)) {
|
|
177
|
+
throw new Error(`Invalid docs contract in ${location}: views[${index}].metadata is invalid`);
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
view: view.view,
|
|
181
|
+
pie: view.pie,
|
|
182
|
+
config: view.config,
|
|
183
|
+
...(typeof view.description === 'string' ? { description: view.description } : {}),
|
|
184
|
+
...(view.metadata ? { metadata: view.metadata } : {}),
|
|
185
|
+
};
|
|
186
|
+
});
|
|
187
|
+
const supportedModes = Array.isArray(raw.supportedModes)
|
|
188
|
+
? raw.supportedModes.filter((mode) => typeof mode === 'string')
|
|
189
|
+
: undefined;
|
|
190
|
+
return normalizeContract({
|
|
191
|
+
elementName: raw.elementName,
|
|
192
|
+
packageName: raw.packageName,
|
|
193
|
+
framework: raw.framework,
|
|
194
|
+
summary: typeof raw.summary === 'string' ? raw.summary : undefined,
|
|
195
|
+
supportedModes: supportedModes?.length ? supportedModes : MODES,
|
|
196
|
+
views,
|
|
197
|
+
});
|
|
198
|
+
};
|
|
199
|
+
export const loadContract = async (packageDir) => {
|
|
200
|
+
const contractPath = join(packageDir, CONTRACT_FILENAME);
|
|
201
|
+
if (!existsSync(contractPath)) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
const raw = JSON.parse(await readFile(contractPath, 'utf-8'));
|
|
205
|
+
return parseContract(raw, contractPath);
|
|
206
|
+
};
|
|
207
|
+
export const writeContract = async (packageDir, contract) => {
|
|
208
|
+
const contractPath = join(packageDir, CONTRACT_FILENAME);
|
|
209
|
+
const normalized = normalizeContract(contract);
|
|
210
|
+
await mkdir(packageDir, { recursive: true });
|
|
211
|
+
await writeFile(contractPath, `${JSON.stringify(normalized, null, 2)}\n`, 'utf-8');
|
|
212
|
+
};
|
|
213
|
+
export const seedContractForElement = async (element, rootDir, options) => {
|
|
214
|
+
const contractPath = join(element.packageDir, CONTRACT_FILENAME);
|
|
215
|
+
const existing = await loadContract(element.packageDir);
|
|
216
|
+
if (existing && !options?.refresh) {
|
|
217
|
+
return { wrote: false, contractPath, contract: existing };
|
|
218
|
+
}
|
|
219
|
+
const piePointer = inferPiePointer(element.packageDir);
|
|
220
|
+
const configPointer = inferConfigPointer(element.packageDir);
|
|
221
|
+
const views = inferViewsFromPackageExports(element.exportsMap).map((view) => ({
|
|
222
|
+
view,
|
|
223
|
+
pie: piePointer,
|
|
224
|
+
config: configPointer,
|
|
225
|
+
}));
|
|
226
|
+
const contract = normalizeContract({
|
|
227
|
+
elementName: element.elementName,
|
|
228
|
+
packageName: element.packageName,
|
|
229
|
+
framework: element.framework,
|
|
230
|
+
summary: existing?.summary || element.packageDescription,
|
|
231
|
+
supportedModes: existing?.supportedModes?.length ? existing.supportedModes : MODES,
|
|
232
|
+
views,
|
|
233
|
+
});
|
|
234
|
+
await writeContract(element.packageDir, contract);
|
|
235
|
+
return {
|
|
236
|
+
wrote: true,
|
|
237
|
+
contractPath: relative(rootDir, contractPath),
|
|
238
|
+
contract,
|
|
239
|
+
};
|
|
240
|
+
};
|
|
241
|
+
//# sourceMappingURL=contracts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../../src/lib/docs/contracts.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport { CONTRACT_FILENAME, inferViewsFromPackageExports } from './discovery.js';\nimport type {\n ElementPackageInfo,\n PieDocsContract,\n PieDocsPropertyMetadata,\n PieDocsSourcePointer,\n PieDocsViewMetadata,\n} from './types.js';\n\nconst MODES = ['gather', 'view', 'evaluate'];\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n !!value && typeof value === 'object' && !Array.isArray(value);\n\nconst isSourcePointer = (value: unknown): value is PieDocsSourcePointer =>\n isObject(value) &&\n typeof value.file === 'string' &&\n (value.exportName === undefined || typeof value.exportName === 'string') &&\n (value.path === undefined || typeof value.path === 'string');\n\nconst isPrimitiveEnumValue = (value: unknown): value is string | number | boolean | null =>\n value === null || ['string', 'number', 'boolean'].includes(typeof value);\n\nconst isPropertyMetadata = (value: unknown): value is PieDocsPropertyMetadata => {\n if (!isObject(value)) {\n return false;\n }\n const allowed = [\n 'title',\n 'description',\n 'notes',\n 'type',\n 'required',\n 'enum',\n 'minimum',\n 'maximum',\n 'minLength',\n 'maxLength',\n 'pattern',\n 'itemType',\n 'examples',\n ];\n for (const key of Object.keys(value)) {\n if (!allowed.includes(key)) {\n return false;\n }\n }\n if (value.title !== undefined && typeof value.title !== 'string') return false;\n if (value.description !== undefined && typeof value.description !== 'string') return false;\n if (value.notes !== undefined && typeof value.notes !== 'string') return false;\n if (value.type !== undefined && typeof value.type !== 'string') return false;\n if (value.required !== undefined && typeof value.required !== 'boolean') return false;\n if (value.enum !== undefined) {\n if (!Array.isArray(value.enum) || value.enum.some((entry) => !isPrimitiveEnumValue(entry))) {\n return false;\n }\n }\n for (const key of ['minimum', 'maximum', 'minLength', 'maxLength'] as const) {\n if (value[key] !== undefined && typeof value[key] !== 'number') return false;\n }\n if (value.pattern !== undefined && typeof value.pattern !== 'string') return false;\n if (value.itemType !== undefined && typeof value.itemType !== 'string') return false;\n if (value.examples !== undefined && !Array.isArray(value.examples)) return false;\n return true;\n};\n\nconst normalizeMetadataMap = (\n map?: Record<string, PieDocsPropertyMetadata>\n): Record<string, PieDocsPropertyMetadata> | undefined => {\n if (!map) {\n return undefined;\n }\n return Object.fromEntries(\n Object.entries(map)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([path, metadata]) => [path, { ...metadata }])\n );\n};\n\nconst isViewMetadata = (value: unknown): value is PieDocsViewMetadata => {\n if (!isObject(value)) {\n return false;\n }\n for (const key of Object.keys(value)) {\n if (!['pie', 'config'].includes(key)) {\n return false;\n }\n const map = value[key];\n if (map === undefined) continue;\n if (!isObject(map)) return false;\n for (const entry of Object.values(map)) {\n if (!isPropertyMetadata(entry)) return false;\n }\n }\n return true;\n};\n\nconst normalizePointer = (pointer: PieDocsSourcePointer): PieDocsSourcePointer => ({\n file: pointer.file,\n ...(pointer.exportName ? { exportName: pointer.exportName } : {}),\n ...(pointer.path ? { path: pointer.path } : {}),\n});\n\nconst normalizeContract = (contract: PieDocsContract): PieDocsContract => ({\n elementName: contract.elementName,\n packageName: contract.packageName,\n framework: contract.framework,\n ...(contract.summary ? { summary: contract.summary } : {}),\n supportedModes: contract.supportedModes?.length ? [...contract.supportedModes] : MODES,\n views: [...contract.views]\n .sort((a, b) => a.view.localeCompare(b.view))\n .map((view) => ({\n view: view.view,\n pie: normalizePointer(view.pie),\n config: normalizePointer(view.config),\n ...(view.description ? { description: view.description } : {}),\n ...(view.metadata\n ? {\n metadata: {\n ...(view.metadata.pie ? { pie: normalizeMetadataMap(view.metadata.pie) } : {}),\n ...(view.metadata.config\n ? { config: normalizeMetadataMap(view.metadata.config) }\n : {}),\n },\n }\n : {}),\n })),\n});\n\nconst inferPiePointer = (packageDir: string): PieDocsSourcePointer => {\n const candidates: PieDocsSourcePointer[] = [\n { file: 'src/author/defaultConfiguration.ts', path: 'model' },\n { file: 'src/author/defaults.ts', path: 'model' },\n { file: 'src/controller/defaults.ts' },\n ];\n\n for (const candidate of candidates) {\n if (existsSync(join(packageDir, candidate.file))) {\n return candidate;\n }\n }\n\n return { file: 'src/controller/defaults.ts' };\n};\n\nconst inferConfigPointer = (packageDir: string): PieDocsSourcePointer => {\n const candidates: PieDocsSourcePointer[] = [\n { file: 'src/author/defaultConfiguration.ts', path: 'configuration' },\n { file: 'src/author/defaults.ts', path: 'configuration' },\n { file: 'src/controller/defaults.ts' },\n ];\n\n for (const candidate of candidates) {\n if (existsSync(join(packageDir, candidate.file))) {\n return candidate;\n }\n }\n\n return { file: 'src/controller/defaults.ts', path: 'configuration' };\n};\n\nexport const parseContract = (raw: unknown, location: string): PieDocsContract => {\n if (!isObject(raw)) {\n throw new Error(`Invalid docs contract in ${location}: expected object`);\n }\n if (typeof raw.elementName !== 'string' || !raw.elementName.trim()) {\n throw new Error(`Invalid docs contract in ${location}: elementName is required`);\n }\n if (typeof raw.packageName !== 'string' || !raw.packageName.startsWith('@pie-element/')) {\n throw new Error(`Invalid docs contract in ${location}: packageName is invalid`);\n }\n if (raw.framework !== 'react' && raw.framework !== 'svelte') {\n throw new Error(`Invalid docs contract in ${location}: framework must be react|svelte`);\n }\n if (!Array.isArray(raw.views) || raw.views.length === 0) {\n throw new Error(`Invalid docs contract in ${location}: at least one view is required`);\n }\n\n const views = raw.views.map((view, index) => {\n if (!isObject(view)) {\n throw new Error(`Invalid docs contract in ${location}: views[${index}] must be an object`);\n }\n if (typeof view.view !== 'string' || !view.view.trim()) {\n throw new Error(`Invalid docs contract in ${location}: views[${index}].view is required`);\n }\n if (!isSourcePointer(view.pie)) {\n throw new Error(`Invalid docs contract in ${location}: views[${index}].pie is invalid`);\n }\n if (!isSourcePointer(view.config)) {\n throw new Error(`Invalid docs contract in ${location}: views[${index}].config is invalid`);\n }\n if (view.metadata !== undefined && !isViewMetadata(view.metadata)) {\n throw new Error(`Invalid docs contract in ${location}: views[${index}].metadata is invalid`);\n }\n\n return {\n view: view.view,\n pie: view.pie,\n config: view.config,\n ...(typeof view.description === 'string' ? { description: view.description } : {}),\n ...(view.metadata ? { metadata: view.metadata } : {}),\n };\n });\n\n const supportedModes = Array.isArray(raw.supportedModes)\n ? raw.supportedModes.filter((mode): mode is string => typeof mode === 'string')\n : undefined;\n\n return normalizeContract({\n elementName: raw.elementName,\n packageName: raw.packageName,\n framework: raw.framework,\n summary: typeof raw.summary === 'string' ? raw.summary : undefined,\n supportedModes: supportedModes?.length ? supportedModes : MODES,\n views,\n });\n};\n\nexport const loadContract = async (packageDir: string): Promise<PieDocsContract | null> => {\n const contractPath = join(packageDir, CONTRACT_FILENAME);\n if (!existsSync(contractPath)) {\n return null;\n }\n const raw = JSON.parse(await readFile(contractPath, 'utf-8')) as unknown;\n return parseContract(raw, contractPath);\n};\n\nexport const writeContract = async (\n packageDir: string,\n contract: PieDocsContract\n): Promise<void> => {\n const contractPath = join(packageDir, CONTRACT_FILENAME);\n const normalized = normalizeContract(contract);\n await mkdir(packageDir, { recursive: true });\n await writeFile(contractPath, `${JSON.stringify(normalized, null, 2)}\\n`, 'utf-8');\n};\n\nexport const seedContractForElement = async (\n element: ElementPackageInfo,\n rootDir: string,\n options?: { refresh?: boolean }\n): Promise<{ wrote: boolean; contractPath: string; contract: PieDocsContract }> => {\n const contractPath = join(element.packageDir, CONTRACT_FILENAME);\n const existing = await loadContract(element.packageDir);\n if (existing && !options?.refresh) {\n return { wrote: false, contractPath, contract: existing };\n }\n\n const piePointer = inferPiePointer(element.packageDir);\n const configPointer = inferConfigPointer(element.packageDir);\n const views = inferViewsFromPackageExports(element.exportsMap).map((view) => ({\n view,\n pie: piePointer,\n config: configPointer,\n }));\n\n const contract: PieDocsContract = normalizeContract({\n elementName: element.elementName,\n packageName: element.packageName,\n framework: element.framework,\n summary: existing?.summary || element.packageDescription,\n supportedModes: existing?.supportedModes?.length ? existing.supportedModes : MODES,\n views,\n });\n\n await writeContract(element.packageDir, contract);\n\n return {\n wrote: true,\n contractPath: relative(rootDir, contractPath),\n contract,\n };\n};\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ElementPackageInfo, PieElementFramework } from './types.js';
|
|
2
|
+
interface DiscoverOptions {
|
|
3
|
+
rootDir: string;
|
|
4
|
+
frameworkFilter: PieElementFramework | 'all';
|
|
5
|
+
elementFilter?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const CONTRACT_FILENAME = "docs.contract.json";
|
|
8
|
+
export declare const discoverElementPackages: (options: DiscoverOptions) => Promise<ElementPackageInfo[]>;
|
|
9
|
+
export declare const inferViewsFromPackageExports: (exportsMap?: Record<string, unknown>) => string[];
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
const ELEMENT_PREFIX = '@pie-element/';
|
|
5
|
+
const FRAMEWORK_DIRS = {
|
|
6
|
+
react: 'packages/elements-react',
|
|
7
|
+
svelte: 'packages/elements-svelte',
|
|
8
|
+
};
|
|
9
|
+
export const CONTRACT_FILENAME = 'docs.contract.json';
|
|
10
|
+
const safeReadPackageJson = async (packageJsonPath) => {
|
|
11
|
+
try {
|
|
12
|
+
const content = await readFile(packageJsonPath, 'utf-8');
|
|
13
|
+
return JSON.parse(content);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const coerceRecord = (value) => value && typeof value === 'object' && !Array.isArray(value)
|
|
20
|
+
? value
|
|
21
|
+
: undefined;
|
|
22
|
+
export const discoverElementPackages = async (options) => {
|
|
23
|
+
const frameworks = options.frameworkFilter === 'all'
|
|
24
|
+
? Object.keys(FRAMEWORK_DIRS)
|
|
25
|
+
: [options.frameworkFilter];
|
|
26
|
+
const results = [];
|
|
27
|
+
for (const framework of frameworks) {
|
|
28
|
+
const frameworkDir = join(options.rootDir, FRAMEWORK_DIRS[framework]);
|
|
29
|
+
if (!existsSync(frameworkDir)) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const packageDirs = await readdir(frameworkDir);
|
|
33
|
+
for (const dirName of packageDirs) {
|
|
34
|
+
const packageDir = join(frameworkDir, dirName);
|
|
35
|
+
const packageJsonPath = join(packageDir, 'package.json');
|
|
36
|
+
if (!existsSync(packageJsonPath)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const pkg = await safeReadPackageJson(packageJsonPath);
|
|
40
|
+
if (!pkg) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
const packageName = typeof pkg.name === 'string' ? pkg.name : '';
|
|
44
|
+
if (!packageName.startsWith(ELEMENT_PREFIX)) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const elementName = packageName.slice(ELEMENT_PREFIX.length).trim();
|
|
48
|
+
if (!elementName) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (options.elementFilter && options.elementFilter !== elementName) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
results.push({
|
|
55
|
+
elementName,
|
|
56
|
+
packageName,
|
|
57
|
+
framework,
|
|
58
|
+
packageDir,
|
|
59
|
+
packageDescription: typeof pkg.description === 'string' ? pkg.description : undefined,
|
|
60
|
+
exportsMap: coerceRecord(pkg.exports),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return results.sort((a, b) => a.elementName.localeCompare(b.elementName));
|
|
65
|
+
};
|
|
66
|
+
export const inferViewsFromPackageExports = (exportsMap) => {
|
|
67
|
+
if (!exportsMap) {
|
|
68
|
+
return ['delivery'];
|
|
69
|
+
}
|
|
70
|
+
const views = new Set(['delivery']);
|
|
71
|
+
for (const key of Object.keys(exportsMap)) {
|
|
72
|
+
if (!key.startsWith('./')) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const view = key.replace('./', '').trim();
|
|
76
|
+
if (!view ||
|
|
77
|
+
view === 'delivery' ||
|
|
78
|
+
view === 'configure' ||
|
|
79
|
+
view === 'controller' ||
|
|
80
|
+
view === 'controller.js' ||
|
|
81
|
+
view === 'runtime-support' ||
|
|
82
|
+
view.startsWith('browser/')) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (view === 'author' || view === 'print' || view.startsWith('delivery-')) {
|
|
86
|
+
views.add(view);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return Array.from(views).sort();
|
|
90
|
+
};
|
|
91
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../../src/lib/docs/discovery.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { ElementPackageInfo, PieElementFramework } from './types.js';\n\ninterface DiscoverOptions {\n rootDir: string;\n frameworkFilter: PieElementFramework | 'all';\n elementFilter?: string;\n}\n\nconst ELEMENT_PREFIX = '@pie-element/';\n\nconst FRAMEWORK_DIRS: Record<PieElementFramework, string> = {\n react: 'packages/elements-react',\n svelte: 'packages/elements-svelte',\n};\n\nexport const CONTRACT_FILENAME = 'docs.contract.json';\n\nconst safeReadPackageJson = async (\n packageJsonPath: string\n): Promise<Record<string, unknown> | null> => {\n try {\n const content = await readFile(packageJsonPath, 'utf-8');\n return JSON.parse(content) as Record<string, unknown>;\n } catch {\n return null;\n }\n};\n\nconst coerceRecord = (value: unknown): Record<string, unknown> | undefined =>\n value && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n\nexport const discoverElementPackages = async (\n options: DiscoverOptions\n): Promise<ElementPackageInfo[]> => {\n const frameworks: PieElementFramework[] =\n options.frameworkFilter === 'all'\n ? (Object.keys(FRAMEWORK_DIRS) as PieElementFramework[])\n : [options.frameworkFilter];\n\n const results: ElementPackageInfo[] = [];\n\n for (const framework of frameworks) {\n const frameworkDir = join(options.rootDir, FRAMEWORK_DIRS[framework]);\n if (!existsSync(frameworkDir)) {\n continue;\n }\n\n const packageDirs = await readdir(frameworkDir);\n for (const dirName of packageDirs) {\n const packageDir = join(frameworkDir, dirName);\n const packageJsonPath = join(packageDir, 'package.json');\n if (!existsSync(packageJsonPath)) {\n continue;\n }\n\n const pkg = await safeReadPackageJson(packageJsonPath);\n if (!pkg) {\n continue;\n }\n\n const packageName = typeof pkg.name === 'string' ? pkg.name : '';\n if (!packageName.startsWith(ELEMENT_PREFIX)) {\n continue;\n }\n\n const elementName = packageName.slice(ELEMENT_PREFIX.length).trim();\n if (!elementName) {\n continue;\n }\n\n if (options.elementFilter && options.elementFilter !== elementName) {\n continue;\n }\n\n results.push({\n elementName,\n packageName,\n framework,\n packageDir,\n packageDescription: typeof pkg.description === 'string' ? pkg.description : undefined,\n exportsMap: coerceRecord(pkg.exports),\n });\n }\n }\n\n return results.sort((a, b) => a.elementName.localeCompare(b.elementName));\n};\n\nexport const inferViewsFromPackageExports = (exportsMap?: Record<string, unknown>): string[] => {\n if (!exportsMap) {\n return ['delivery'];\n }\n\n const views = new Set<string>(['delivery']);\n for (const key of Object.keys(exportsMap)) {\n if (!key.startsWith('./')) {\n continue;\n }\n const view = key.replace('./', '').trim();\n if (\n !view ||\n view === 'delivery' ||\n view === 'configure' ||\n view === 'controller' ||\n view === 'controller.js' ||\n view === 'runtime-support' ||\n view.startsWith('browser/')\n ) {\n continue;\n }\n if (view === 'author' || view === 'print' || view.startsWith('delivery-')) {\n views.add(view);\n }\n }\n\n return Array.from(views).sort();\n};\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { PieDocsContract, PieDocsElementOutput } from './types.js';
|
|
2
|
+
export interface GenerateDocsOptions {
|
|
3
|
+
outputDir: string;
|
|
4
|
+
dryRun: boolean;
|
|
5
|
+
check: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface GenerateDocsResult {
|
|
8
|
+
filesWritten: string[];
|
|
9
|
+
filesChecked: string[];
|
|
10
|
+
driftFiles: string[];
|
|
11
|
+
outputs: PieDocsElementOutput[];
|
|
12
|
+
}
|
|
13
|
+
export declare const generateDocsForContract: (packageDir: string, contract: PieDocsContract, options: GenerateDocsOptions) => Promise<GenerateDocsResult>;
|
|
14
|
+
export declare const toRelativePaths: (rootDir: string, paths: string[]) => string[];
|