@adobe-commerce/elsie 2.0.0 → 2.0.1-alpha-20260728135101
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/.elsie.js +3 -3
- package/CHANGELOG.md +385 -112
- package/LICENSE.md +257 -157
- package/README.md +4 -2
- package/__mocks__/svg.js +3 -3
- package/bin/builders/build/index.js +2 -1
- package/bin/builders/changeset/index.js +1 -1
- package/bin/builders/concurrently/index.js +1 -1
- package/bin/builders/generate/api/index.js +7 -7
- package/bin/builders/generate/component/index.js +8 -8
- package/bin/builders/generate/config/index.js +5 -5
- package/bin/builders/generate/config/templates/elsie.js +1 -1
- package/bin/builders/generate/container/index.js +7 -7
- package/bin/builders/generate/index.js +36 -36
- package/bin/builders/gql/index.js +28 -28
- package/bin/builders/gql/validate.js +116 -105
- package/bin/builders/lint/index.js +1 -1
- package/bin/builders/serve/index.js +1 -1
- package/bin/builders/storybook/index.js +9 -1
- package/bin/builders/types/index.js +1 -2
- package/bin/builders/types/validate-tsconfig.js +5 -5
- package/bin/index.js +12 -6
- package/bin/lib/cli.js +9 -8
- package/bin/lib/resolve-bin.js +9 -0
- package/bin/lib/validate-typeof.js +3 -3
- package/bin/lib/write-file.js +3 -3
- package/bin/lib/write-parent-index.js +4 -4
- package/config/eslint.mjs +2 -1
- package/config/jest.mjs +7 -2
- package/config/plugins/dts-normalize-relative-replacer.cjs +1 -1
- package/config/plugins/dts.mjs +4 -3
- package/config/prettier.json +25 -3
- package/config/setEnvVars.mjs +2 -2
- package/config/storybook/addon.js +5 -5
- package/config/storybook/components/FileTree/FileTree.jsx +4 -4
- package/config/storybook/components/FileTree/index.js +4 -4
- package/config/storybook/components/Flex/Flex.jsx +3 -3
- package/config/storybook/components/Flex/index.js +3 -3
- package/config/storybook/components/OptionsTable/OptionsTable.jsx +3 -3
- package/config/storybook/components/OptionsTable/index.js +4 -4
- package/config/storybook/components/Panel/Panel.tsx +7 -7
- package/config/storybook/components/Panel/index.ts +3 -3
- package/config/storybook/components/Screenshot/Screenshot.jsx +3 -3
- package/config/storybook/components/Screenshot/index.js +4 -4
- package/config/storybook/components/Steps/Steps.jsx +3 -3
- package/config/storybook/components/Steps/index.js +4 -4
- package/config/storybook/components/StoryWrapper/StoryWrapper.jsx +3 -3
- package/config/storybook/components/StoryWrapper/index.js +3 -3
- package/config/storybook/components/Summary/Summary.jsx +3 -3
- package/config/storybook/components/Summary/index.js +3 -3
- package/config/storybook/components/Variants/Variants.jsx +11 -7
- package/config/storybook/components/Variants/index.js +3 -3
- package/config/storybook/manager.js +3 -3
- package/config/storybook/preview.jsx +3 -3
- package/config/storybook/theming/fonts.css +12 -4
- package/config/storybook/theming/preview.css +3 -1
- package/config/storybook/theming/theme.js +3 -3
- package/config/vite.mjs +53 -26
- package/package.json +36 -34
- package/src/components/Accordion/Accordion.css +1 -1
- package/src/components/Accordion/Accordion.stories.tsx +18 -18
- package/src/components/Accordion/Accordion.tsx +12 -8
- package/src/components/Accordion/index.ts +3 -3
- package/src/components/ActionButton/ActionButton.stories.tsx +8 -8
- package/src/components/ActionButton/ActionButton.tsx +7 -5
- package/src/components/ActionButton/index.ts +3 -3
- package/src/components/ActionButtonGroup/ActionButtonGroup.stories.tsx +3 -3
- package/src/components/ActionButtonGroup/ActionButtonGroup.tsx +2 -2
- package/src/components/ActionButtonGroup/index.ts +3 -3
- package/src/components/AlertBanner/AlertBanner.stories.tsx +6 -6
- package/src/components/AlertBanner/AlertBanner.tsx +12 -10
- package/src/components/AlertBanner/index.ts +3 -3
- package/src/components/Breadcrumbs/Breadcrumbs.stories.tsx +14 -14
- package/src/components/Breadcrumbs/Breadcrumbs.tsx +3 -3
- package/src/components/Breadcrumbs/index.ts +3 -3
- package/src/components/Button/Button.mdx +24 -11
- package/src/components/Button/Button.stories.tsx +6 -6
- package/src/components/Button/Button.tsx +7 -8
- package/src/components/Button/index.ts +3 -3
- package/src/components/Card/Card.stories.tsx +6 -6
- package/src/components/Card/Card.tsx +3 -3
- package/src/components/Card/index.ts +3 -3
- package/src/components/CartItem/CartItem.stories.tsx +12 -12
- package/src/components/CartItem/CartItem.tsx +4 -2
- package/src/components/CartItem/CartItemSkeleton.tsx +3 -3
- package/src/components/CartItem/index.ts +3 -3
- package/src/components/CartList/CartList.tsx +3 -3
- package/src/components/CartList/index.ts +3 -3
- package/src/components/Checkbox/Checkbox.stories.tsx +17 -14
- package/src/components/Checkbox/Checkbox.tsx +8 -6
- package/src/components/Checkbox/index.ts +3 -3
- package/src/components/ColorSwatch/ColorSwatch.css +8 -4
- package/src/components/ColorSwatch/ColorSwatch.stories.tsx +6 -6
- package/src/components/ColorSwatch/ColorSwatch.tsx +8 -6
- package/src/components/ColorSwatch/index.ts +3 -3
- package/src/components/ContentGrid/ContentGrid.css +15 -15
- package/src/components/ContentGrid/ContentGrid.stories.tsx +4 -4
- package/src/components/ContentGrid/ContentGrid.tsx +3 -3
- package/src/components/ContentGrid/index.ts +3 -3
- package/src/components/Divider/Divider.stories.tsx +7 -4
- package/src/components/Divider/Divider.tsx +3 -3
- package/src/components/Divider/index.ts +4 -4
- package/src/components/Field/Field.stories.tsx +7 -7
- package/src/components/Field/Field.tsx +4 -2
- package/src/components/Field/index.ts +3 -3
- package/src/components/Header/Header.stories.tsx +9 -10
- package/src/components/Header/Header.tsx +11 -7
- package/src/components/Header/index.ts +3 -3
- package/src/components/Icon/Icon.stories.helpers.jsx +4 -4
- package/src/components/Icon/Icon.stories.tsx +74 -60
- package/src/components/Icon/Icon.tsx +77 -44
- package/src/components/Icon/index.ts +3 -3
- package/src/components/IllustratedMessage/IllustratedMessage.stories.tsx +8 -8
- package/src/components/IllustratedMessage/IllustratedMessage.tsx +7 -5
- package/src/components/IllustratedMessage/index.ts +3 -3
- package/src/components/Image/Image.stories.tsx +3 -3
- package/src/components/Image/Image.tsx +4 -4
- package/src/components/Image/index.ts +3 -3
- package/src/components/ImageSwatch/ImageSwatch.css +8 -4
- package/src/components/ImageSwatch/ImageSwatch.stories.tsx +10 -10
- package/src/components/ImageSwatch/ImageSwatch.tsx +25 -23
- package/src/components/ImageSwatch/index.ts +3 -3
- package/src/components/InLineAlert/InLineAlert.stories.tsx +12 -7
- package/src/components/InLineAlert/InLineAlert.tsx +4 -2
- package/src/components/InLineAlert/index.ts +3 -3
- package/src/components/Incrementer/Incrementer.stories.tsx +9 -9
- package/src/components/Incrementer/Incrementer.tsx +75 -37
- package/src/components/Incrementer/index.ts +3 -3
- package/src/components/Input/Input.css +4 -1
- package/src/components/Input/Input.stories.tsx +5 -5
- package/src/components/Input/Input.tsx +5 -3
- package/src/components/Input/index.ts +3 -3
- package/src/components/InputDate/InputDate.tsx +3 -3
- package/src/components/InputDate/index.ts +3 -3
- package/src/components/InputFile/InputFile.css +16 -16
- package/src/components/InputFile/InputFile.stories.tsx +21 -16
- package/src/components/InputFile/InputFile.tsx +8 -6
- package/src/components/InputFile/index.ts +5 -5
- package/src/components/InputPassword/InputPassword.stories.tsx +4 -4
- package/src/components/InputPassword/InputPassword.tsx +5 -4
- package/src/components/InputPassword/PasswordStatusIndicator/PasswordStatusIndicator.tsx +1 -1
- package/src/components/InputPassword/PasswordStatusIndicator/index.ts +3 -3
- package/src/components/InputPassword/index.ts +3 -3
- package/src/components/Modal/Modal.stories.tsx +27 -16
- package/src/components/Modal/Modal.tsx +10 -11
- package/src/components/Modal/index.ts +3 -3
- package/src/components/MultiSelect/MultiSelect.stories.tsx +15 -15
- package/src/components/MultiSelect/MultiSelect.tsx +15 -15
- package/src/components/Pagination/Pagination.css +1 -1
- package/src/components/Pagination/Pagination.stories.tsx +0 -1
- package/src/components/Pagination/Pagination.tsx +17 -12
- package/src/components/Pagination/PaginationButton.tsx +2 -3
- package/src/components/Pagination/index.ts +3 -3
- package/src/components/Picker/Picker.css +3 -1
- package/src/components/Picker/Picker.stories.tsx +1 -1
- package/src/components/Picker/Picker.tsx +8 -6
- package/src/components/Picker/index.ts +3 -3
- package/src/components/Portal/Portal.stories.tsx +50 -44
- package/src/components/Portal/Portal.tsx +4 -4
- package/src/components/Price/Price.stories.tsx +3 -3
- package/src/components/Price/Price.tsx +4 -2
- package/src/components/Price/index.ts +3 -3
- package/src/components/PriceRange/PriceRange.stories.tsx +3 -3
- package/src/components/PriceRange/PriceRange.tsx +8 -6
- package/src/components/PriceRange/index.ts +3 -3
- package/src/components/ProductItemCard/ProductItemCard.tsx +4 -2
- package/src/components/ProductItemCard/ProductItemCardSkeleton.tsx +16 -16
- package/src/components/ProductItemCard/index.ts +4 -4
- package/src/components/ProgressSpinner/ProgressSpinner.stories.tsx +8 -8
- package/src/components/ProgressSpinner/ProgressSpinner.tsx +7 -5
- package/src/components/ProgressSpinner/index.ts +3 -3
- package/src/components/RadioButton/RadioButton.stories.tsx +1 -1
- package/src/components/RadioButton/RadioButton.tsx +4 -2
- package/src/components/Skeleton/Skeleton.stories.tsx +4 -4
- package/src/components/Skeleton/Skeleton.tsx +11 -7
- package/src/components/Skeleton/index.ts +3 -3
- package/src/components/Table/Table.css +106 -99
- package/src/components/Table/Table.stories.tsx +404 -227
- package/src/components/Table/Table.tsx +11 -7
- package/src/components/Table/index.ts +4 -4
- package/src/components/Tag/Tag.stories.tsx +6 -6
- package/src/components/Tag/Tag.tsx +7 -5
- package/src/components/Tag/index.ts +3 -3
- package/src/components/TextArea/TextArea.css +3 -1
- package/src/components/TextArea/TextArea.stories.tsx +9 -6
- package/src/components/TextArea/TextArea.tsx +3 -3
- package/src/components/TextArea/index.ts +3 -3
- package/src/components/TextSwatch/TextSwatch.css +4 -2
- package/src/components/TextSwatch/TextSwatch.stories.tsx +8 -8
- package/src/components/TextSwatch/TextSwatch.tsx +12 -7
- package/src/components/TextSwatch/index.ts +3 -3
- package/src/components/ToggleButton/ToggleButton.css +6 -2
- package/src/components/ToggleButton/ToggleButton.stories.tsx +10 -6
- package/src/components/ToggleButton/ToggleButton.tsx +8 -3
- package/src/components/ToggleButton/index.ts +3 -3
- package/src/components/UIProvider/UIProvider.css +3 -2
- package/src/components/UIProvider/UIProvider.tsx +11 -7
- package/src/components/UIProvider/debugger.css +5 -6
- package/src/components/UIProvider/index.ts +3 -3
- package/src/docs/API/event-bus.mdx +64 -37
- package/src/docs/API/graphql.mdx +69 -36
- package/src/docs/API/initializer.mdx +58 -35
- package/src/docs/API/render.mdx +45 -32
- package/src/docs/Design/colors.mdx +10 -12
- package/src/docs/Design/grid.mdx +41 -14
- package/src/docs/Design/overview.mdx +20 -4
- package/src/docs/Design/shapes.mdx +8 -7
- package/src/docs/Design/spacing.mdx +3 -1
- package/src/docs/Design/typography.mdx +3 -2
- package/src/docs/Utilities/VComponent.mdx +27 -10
- package/src/docs/Utilities/classList.mdx +7 -5
- package/src/docs/Utilities/debounce.mdx +6 -7
- package/src/docs/Utilities/getCookie.mdx +1 -2
- package/src/docs/Utilities/getFormErrors.mdx +1 -2
- package/src/docs/Utilities/getFormValues.mdx +1 -2
- package/src/docs/Utilities/getPathValue.mdx +2 -4
- package/src/docs/Utilities/links.mdx +16 -7
- package/src/docs/cli-usage.mdx +8 -3
- package/src/docs/components/overview.mdx +14 -4
- package/src/docs/quick-start.mdx +69 -22
- package/src/docs/slots.mdx +74 -37
- package/src/docs/welcome.mdx +13 -4
- package/src/i18n/index.ts +3 -3
- package/src/lib/aem/assets.ts +9 -9
- package/src/lib/aem/configs.ts +16 -8
- package/src/lib/classes.ts +4 -4
- package/src/lib/config.ts +3 -3
- package/src/lib/debounce.ts +3 -3
- package/src/lib/deepmerge.ts +6 -13
- package/src/lib/deviceUtils.ts +3 -3
- package/src/lib/form-values.ts +3 -3
- package/src/lib/get-price-formatter.ts +8 -3
- package/src/lib/i18n.ts +3 -3
- package/src/lib/image-params-keymap.ts +4 -5
- package/src/lib/initializer.ts +11 -12
- package/src/lib/is-number.ts +3 -3
- package/src/lib/locale-config.ts +4 -4
- package/src/lib/render.tsx +14 -8
- package/src/lib/resolve-image.ts +19 -16
- package/src/lib/signals.ts +4 -4
- package/src/lib/slot.tsx +34 -27
- package/src/lib/tests.tsx +6 -8
- package/src/lib/types.ts +3 -3
- package/src/lib/vcomponent.tsx +3 -3
- package/src/shims/importmap.js +3107 -20
- package/static/assets/images/index.ts +3 -3
- package/storybook-stories.js +3 -3
- package/tests/__mocks__/browserMocks.ts +3 -3
- package/tests/__mocks__/fileMocks.ts +3 -3
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Copyright 2025 Adobe
|
|
3
3
|
* All Rights Reserved.
|
|
4
4
|
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this
|
|
6
|
-
* file in accordance with the terms of the Adobe license agreement
|
|
7
|
-
* accompanying it.
|
|
5
|
+
* NOTICE: Adobe permits you to use, modify, and distribute this
|
|
6
|
+
* file in accordance with the terms of the Adobe license agreement
|
|
7
|
+
* accompanying it.
|
|
8
8
|
*******************************************************************/
|
|
9
9
|
|
|
10
10
|
const path = require('path');
|
|
@@ -53,7 +53,7 @@ module.exports = async function newComponentBuilder({
|
|
|
53
53
|
await writeFile(
|
|
54
54
|
path.resolve(dir, `${basename}.css`),
|
|
55
55
|
templateStyles({ basename, cssPrefix }),
|
|
56
|
-
force
|
|
56
|
+
force,
|
|
57
57
|
);
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -61,28 +61,28 @@ module.exports = async function newComponentBuilder({
|
|
|
61
61
|
await writeFile(
|
|
62
62
|
path.resolve(dir, `${basename}.stories.tsx`),
|
|
63
63
|
templateStory({ name, basename, pathname, group, importPath }),
|
|
64
|
-
force
|
|
64
|
+
force,
|
|
65
65
|
);
|
|
66
66
|
|
|
67
67
|
// Write Jest Test file
|
|
68
68
|
await writeFile(
|
|
69
69
|
path.resolve(dir, `${basename}.test.tsx`),
|
|
70
70
|
templateTest({ name, basename, pathname, group, importPath, cssPrefix }),
|
|
71
|
-
force
|
|
71
|
+
force,
|
|
72
72
|
);
|
|
73
73
|
|
|
74
74
|
// Write Component file
|
|
75
75
|
await writeFile(
|
|
76
76
|
path.resolve(dir, `${basename}.tsx`),
|
|
77
77
|
templateComponent({ basename, importPath, skipCSS, cssPrefix }),
|
|
78
|
-
force
|
|
78
|
+
force,
|
|
79
79
|
);
|
|
80
80
|
|
|
81
81
|
// Write Index file
|
|
82
82
|
await writeFile(
|
|
83
83
|
path.resolve(dir, 'index.ts'),
|
|
84
84
|
templateIndex({ basename, importPath }),
|
|
85
|
-
force
|
|
85
|
+
force,
|
|
86
86
|
);
|
|
87
87
|
|
|
88
88
|
// Update parent index.ts
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Copyright 2025 Adobe
|
|
3
3
|
* All Rights Reserved.
|
|
4
4
|
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this
|
|
6
|
-
* file in accordance with the terms of the Adobe license agreement
|
|
7
|
-
* accompanying it.
|
|
5
|
+
* NOTICE: Adobe permits you to use, modify, and distribute this
|
|
6
|
+
* file in accordance with the terms of the Adobe license agreement
|
|
7
|
+
* accompanying it.
|
|
8
8
|
*******************************************************************/
|
|
9
9
|
|
|
10
10
|
const path = require('path');
|
|
@@ -56,8 +56,8 @@ module.exports = async function newConfigBuilder({ name, force }) {
|
|
|
56
56
|
console.log(
|
|
57
57
|
m(
|
|
58
58
|
`Update your \x1b[33mtsconfig.json\x1b[0m to include path \x1b[33m"paths": { "${value}": ["./src/*'] }\x1b[0m`,
|
|
59
|
-
'warning'
|
|
60
|
-
)
|
|
59
|
+
'warning',
|
|
60
|
+
),
|
|
61
61
|
);
|
|
62
62
|
}
|
|
63
63
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { source } = require('common-tags');
|
|
2
2
|
|
|
3
3
|
module.exports = ({ name, importPath }) =>
|
|
4
|
-
`/********************************************************************
|
|
4
|
+
`/********************************************************************
|
|
5
5
|
* Copyright 2025 Adobe
|
|
6
6
|
* All Rights Reserved.
|
|
7
7
|
*
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Copyright 2025 Adobe
|
|
3
3
|
* All Rights Reserved.
|
|
4
4
|
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this
|
|
6
|
-
* file in accordance with the terms of the Adobe license agreement
|
|
7
|
-
* accompanying it.
|
|
5
|
+
* NOTICE: Adobe permits you to use, modify, and distribute this
|
|
6
|
+
* file in accordance with the terms of the Adobe license agreement
|
|
7
|
+
* accompanying it.
|
|
8
8
|
*******************************************************************/
|
|
9
9
|
|
|
10
10
|
const path = require('path');
|
|
@@ -39,28 +39,28 @@ module.exports = async function newContainerBuilder({ pathname, force }) {
|
|
|
39
39
|
await writeFile(
|
|
40
40
|
path.resolve(dir, `${basename}.stories.tsx`),
|
|
41
41
|
templateStory({ basename, pathname, importPath }),
|
|
42
|
-
force
|
|
42
|
+
force,
|
|
43
43
|
);
|
|
44
44
|
|
|
45
45
|
// Write Jest Test file
|
|
46
46
|
await writeFile(
|
|
47
47
|
path.resolve(dir, `${basename}.test.tsx`),
|
|
48
48
|
templateTest({ name, basename, pathname, importPath }),
|
|
49
|
-
force
|
|
49
|
+
force,
|
|
50
50
|
);
|
|
51
51
|
|
|
52
52
|
// Write Container file
|
|
53
53
|
await writeFile(
|
|
54
54
|
path.resolve(dir, `${basename}.tsx`),
|
|
55
55
|
templateComponent({ basename, importPath }),
|
|
56
|
-
force
|
|
56
|
+
force,
|
|
57
57
|
);
|
|
58
58
|
|
|
59
59
|
// Write Index file
|
|
60
60
|
await writeFile(
|
|
61
61
|
path.resolve(dir, 'index.ts'),
|
|
62
62
|
templateIndex({ basename, importPath }),
|
|
63
|
-
force
|
|
63
|
+
force,
|
|
64
64
|
);
|
|
65
65
|
|
|
66
66
|
// Update parent index.ts
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Copyright 2025 Adobe
|
|
3
3
|
* All Rights Reserved.
|
|
4
4
|
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this
|
|
6
|
-
* file in accordance with the terms of the Adobe license agreement
|
|
7
|
-
* accompanying it.
|
|
5
|
+
* NOTICE: Adobe permits you to use, modify, and distribute this
|
|
6
|
+
* file in accordance with the terms of the Adobe license agreement
|
|
7
|
+
* accompanying it.
|
|
8
8
|
*******************************************************************/
|
|
9
9
|
|
|
10
10
|
const path = require('path');
|
|
@@ -35,7 +35,7 @@ module.exports = function generateResourceBuilder(yargs) {
|
|
|
35
35
|
},
|
|
36
36
|
});
|
|
37
37
|
},
|
|
38
|
-
require('./config')
|
|
38
|
+
require('./config'),
|
|
39
39
|
)
|
|
40
40
|
|
|
41
41
|
// New Api Function
|
|
@@ -61,14 +61,14 @@ module.exports = function generateResourceBuilder(yargs) {
|
|
|
61
61
|
throw new Error(
|
|
62
62
|
m(
|
|
63
63
|
'Configuration file ".elsie.cjs" not found. Make sure you are in the root directory of your project or generate a new one.',
|
|
64
|
-
'error'
|
|
65
|
-
)
|
|
64
|
+
'error',
|
|
65
|
+
),
|
|
66
66
|
);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
if (!config.name) {
|
|
70
70
|
throw new Error(
|
|
71
|
-
m(`Missing \x1b[31mname\x1b[0m in "./.elsie.cjs".`, 'error')
|
|
71
|
+
m(`Missing \x1b[31mname\x1b[0m in "./.elsie.cjs".`, 'error'),
|
|
72
72
|
);
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -86,10 +86,10 @@ module.exports = function generateResourceBuilder(yargs) {
|
|
|
86
86
|
.map((e) =>
|
|
87
87
|
m(
|
|
88
88
|
`Invalid \x1b[31mapi.${e}\x1b[0m value "${config.api[e]}" in "./.elsie.cjs".`,
|
|
89
|
-
'error'
|
|
90
|
-
)
|
|
89
|
+
'error',
|
|
90
|
+
),
|
|
91
91
|
)
|
|
92
|
-
.join('\n')
|
|
92
|
+
.join('\n'),
|
|
93
93
|
);
|
|
94
94
|
}
|
|
95
95
|
|
|
@@ -98,17 +98,17 @@ module.exports = function generateResourceBuilder(yargs) {
|
|
|
98
98
|
throw new Error(
|
|
99
99
|
m(
|
|
100
100
|
`\x1b[4m${basename}\x1b[0m is not a valid API function name. Try naming your API function with camel case. i.e. \x1b[4m${toCamelCase(
|
|
101
|
-
basename
|
|
101
|
+
basename,
|
|
102
102
|
)}\x1b[0m`,
|
|
103
|
-
'error'
|
|
104
|
-
)
|
|
103
|
+
'error',
|
|
104
|
+
),
|
|
105
105
|
);
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
return true;
|
|
109
109
|
}, false);
|
|
110
110
|
},
|
|
111
|
-
require('./api')
|
|
111
|
+
require('./api'),
|
|
112
112
|
)
|
|
113
113
|
|
|
114
114
|
// New Component
|
|
@@ -140,8 +140,8 @@ module.exports = function generateResourceBuilder(yargs) {
|
|
|
140
140
|
throw new Error(
|
|
141
141
|
m(
|
|
142
142
|
'Configuration file ".elsie.cjs" not found. Make sure you are in the root directory of your project or generate a new one.',
|
|
143
|
-
'error'
|
|
144
|
-
)
|
|
143
|
+
'error',
|
|
144
|
+
),
|
|
145
145
|
);
|
|
146
146
|
}
|
|
147
147
|
|
|
@@ -151,7 +151,7 @@ module.exports = function generateResourceBuilder(yargs) {
|
|
|
151
151
|
|
|
152
152
|
if (!config.name) {
|
|
153
153
|
throw new Error(
|
|
154
|
-
m(`Missing \x1b[31mname\x1b[0m in "./.elsie.cjs".`, 'error')
|
|
154
|
+
m(`Missing \x1b[31mname\x1b[0m in "./.elsie.cjs".`, 'error'),
|
|
155
155
|
);
|
|
156
156
|
}
|
|
157
157
|
|
|
@@ -176,10 +176,10 @@ module.exports = function generateResourceBuilder(yargs) {
|
|
|
176
176
|
.map((e) =>
|
|
177
177
|
m(
|
|
178
178
|
`Invalid \x1b[31mcomponents[${group.id}].${e}\x1b[0m value "${group[e]}" in "./.elsie.cjs".`,
|
|
179
|
-
'error'
|
|
180
|
-
)
|
|
179
|
+
'error',
|
|
180
|
+
),
|
|
181
181
|
)
|
|
182
|
-
.join('\n')
|
|
182
|
+
.join('\n'),
|
|
183
183
|
);
|
|
184
184
|
}
|
|
185
185
|
|
|
@@ -188,17 +188,17 @@ module.exports = function generateResourceBuilder(yargs) {
|
|
|
188
188
|
throw new Error(
|
|
189
189
|
m(
|
|
190
190
|
`\x1b[4m${basename}\x1b[0m is not a valid component name. Try naming your component with pascal case. i.e. \x1b[4m${toPascalCase(
|
|
191
|
-
basename
|
|
191
|
+
basename,
|
|
192
192
|
)}\x1b[0m`,
|
|
193
|
-
'error'
|
|
194
|
-
)
|
|
193
|
+
'error',
|
|
194
|
+
),
|
|
195
195
|
);
|
|
196
196
|
}
|
|
197
197
|
|
|
198
198
|
return true;
|
|
199
199
|
}, false);
|
|
200
200
|
},
|
|
201
|
-
require('./component')
|
|
201
|
+
require('./component'),
|
|
202
202
|
)
|
|
203
203
|
|
|
204
204
|
// New Container
|
|
@@ -224,8 +224,8 @@ module.exports = function generateResourceBuilder(yargs) {
|
|
|
224
224
|
throw new Error(
|
|
225
225
|
m(
|
|
226
226
|
'Configuration file ".elsie.cjs" not found. Make sure you are in the root directory of your project or generate a new one.',
|
|
227
|
-
'error'
|
|
228
|
-
)
|
|
227
|
+
'error',
|
|
228
|
+
),
|
|
229
229
|
);
|
|
230
230
|
}
|
|
231
231
|
|
|
@@ -233,14 +233,14 @@ module.exports = function generateResourceBuilder(yargs) {
|
|
|
233
233
|
throw new Error(
|
|
234
234
|
m(
|
|
235
235
|
`Missing \x1b[31mcontainers\x1b[0m in "./.elsie.cjs".`,
|
|
236
|
-
'error'
|
|
237
|
-
)
|
|
236
|
+
'error',
|
|
237
|
+
),
|
|
238
238
|
);
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
if (!config.name) {
|
|
242
242
|
throw new Error(
|
|
243
|
-
m(`Missing \x1b[31mname\x1b[0m in "./.elsie.cjs".`, 'error')
|
|
243
|
+
m(`Missing \x1b[31mname\x1b[0m in "./.elsie.cjs".`, 'error'),
|
|
244
244
|
);
|
|
245
245
|
}
|
|
246
246
|
|
|
@@ -259,10 +259,10 @@ module.exports = function generateResourceBuilder(yargs) {
|
|
|
259
259
|
.map((e) =>
|
|
260
260
|
m(
|
|
261
261
|
`Invalid \x1b[31mcontainers.${e}\x1b[0m value "${config.containers[e]}" in "./.elsie.cjs".`,
|
|
262
|
-
'error'
|
|
263
|
-
)
|
|
262
|
+
'error',
|
|
263
|
+
),
|
|
264
264
|
)
|
|
265
|
-
.join('\n')
|
|
265
|
+
.join('\n'),
|
|
266
266
|
);
|
|
267
267
|
}
|
|
268
268
|
|
|
@@ -271,17 +271,17 @@ module.exports = function generateResourceBuilder(yargs) {
|
|
|
271
271
|
throw new Error(
|
|
272
272
|
m(
|
|
273
273
|
`\x1b[4m${basename}\x1b[0m is not a valid container name. Try naming your container with pascal case. i.e. \x1b[4m${toPascalCase(
|
|
274
|
-
basename
|
|
274
|
+
basename,
|
|
275
275
|
)}\x1b[0m`,
|
|
276
|
-
'error'
|
|
277
|
-
)
|
|
276
|
+
'error',
|
|
277
|
+
),
|
|
278
278
|
);
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
return true;
|
|
282
282
|
}, false);
|
|
283
283
|
},
|
|
284
|
-
require('./container')
|
|
284
|
+
require('./container'),
|
|
285
285
|
)
|
|
286
286
|
|
|
287
287
|
//
|
|
@@ -29,7 +29,7 @@ module.exports = async function generateResourceBuilder(yargs) {
|
|
|
29
29
|
},
|
|
30
30
|
},
|
|
31
31
|
},
|
|
32
|
-
true
|
|
32
|
+
true,
|
|
33
33
|
);
|
|
34
34
|
})
|
|
35
35
|
.command('mocks', 'Generate mocks and types', async () => {
|
|
@@ -69,33 +69,33 @@ module.exports = async function generateResourceBuilder(yargs) {
|
|
|
69
69
|
});
|
|
70
70
|
})
|
|
71
71
|
.command(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
72
|
+
'validate',
|
|
73
|
+
'Validate GraphQL operations',
|
|
74
|
+
async (yargs) => {
|
|
75
|
+
return yargs
|
|
76
|
+
.option('source', {
|
|
77
|
+
alias: 's',
|
|
78
|
+
describe: 'Path to the source code containing GraphQL operations',
|
|
79
|
+
type: 'array',
|
|
80
|
+
demandOption: true,
|
|
81
|
+
})
|
|
82
|
+
.option('excluded', {
|
|
83
|
+
alias: 'x',
|
|
84
|
+
describe: 'Paths to exclude from validation',
|
|
85
|
+
type: 'array',
|
|
86
|
+
demandOption: false,
|
|
87
|
+
})
|
|
88
|
+
.option('endpoints', {
|
|
89
|
+
alias: 'e',
|
|
90
|
+
describe: 'Path to GraphQL endpoints',
|
|
91
|
+
type: 'array',
|
|
92
|
+
demandOption: true,
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
async (argv) => {
|
|
96
|
+
const { source, excluded, endpoints } = argv;
|
|
97
|
+
await validate(source, endpoints, excluded);
|
|
98
|
+
},
|
|
99
99
|
)
|
|
100
100
|
.demandCommand(1, 1, 'choose a command: types, mocks or validate');
|
|
101
101
|
};
|
|
@@ -3,134 +3,145 @@ const fsPromises = require('node:fs/promises');
|
|
|
3
3
|
const path = require('node:path');
|
|
4
4
|
const parser = require('@babel/parser');
|
|
5
5
|
const traverse = require('@babel/traverse');
|
|
6
|
-
const {
|
|
6
|
+
const {
|
|
7
|
+
getIntrospectionQuery,
|
|
8
|
+
buildClientSchema,
|
|
9
|
+
parse,
|
|
10
|
+
validate,
|
|
11
|
+
} = require('graphql');
|
|
7
12
|
|
|
8
13
|
async function walk(dir, excludedPaths = [], collected = []) {
|
|
9
|
-
|
|
14
|
+
if (excludedPaths.includes(dir)) return collected;
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
const dirents = await fsPromises.readdir(dir, { withFileTypes: true });
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
|
|
18
|
+
for (const d of dirents) {
|
|
19
|
+
const full = path.resolve(dir, d.name);
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
21
|
+
if (d.isDirectory()) {
|
|
22
|
+
if (excludedPaths.includes(full)) continue;
|
|
23
|
+
if (d.name === 'node_modules' || d.name.startsWith('.')) continue;
|
|
24
|
+
await walk(full, excludedPaths, collected);
|
|
25
|
+
} else if (/\.(c?m?js|ts|tsx)$/.test(d.name)) {
|
|
26
|
+
if (excludedPaths.includes(full)) continue;
|
|
27
|
+
collected.push(full);
|
|
24
28
|
}
|
|
25
|
-
|
|
29
|
+
}
|
|
30
|
+
return collected;
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
function extractConstants(code) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
34
|
+
const ast = parser.parse(code, {
|
|
35
|
+
sourceType: 'unambiguous',
|
|
36
|
+
plugins: [
|
|
37
|
+
'typescript',
|
|
38
|
+
'jsx',
|
|
39
|
+
'classProperties',
|
|
40
|
+
'objectRestSpread',
|
|
41
|
+
'dynamicImport',
|
|
42
|
+
'optionalChaining',
|
|
43
|
+
'nullishCoalescingOperator',
|
|
44
|
+
],
|
|
45
|
+
});
|
|
46
|
+
const found = [];
|
|
47
|
+
traverse.default(ast, {
|
|
48
|
+
VariableDeclaration(path) {
|
|
49
|
+
if (path.node.kind !== 'const') return;
|
|
50
|
+
for (const decl of path.node.declarations) {
|
|
51
|
+
const { id, init } = decl;
|
|
52
|
+
if (!init || id.type !== 'Identifier') continue;
|
|
53
|
+
let text = null;
|
|
54
|
+
switch (init.type) {
|
|
55
|
+
case 'TemplateLiteral': {
|
|
56
|
+
// join all raw chunks; ignores embedded ${expr} for simplicity
|
|
57
|
+
text = init.quasis.map((q) => q.value.cooked).join('');
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
case 'StringLiteral':
|
|
61
|
+
text = init.value;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
if (text) {
|
|
65
|
+
const match = text.match(/\b(query|mutation|fragment)\b/i);
|
|
66
|
+
if (match) {
|
|
67
|
+
found.push(text.trim());
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
});
|
|
68
73
|
|
|
69
|
-
|
|
74
|
+
return found;
|
|
70
75
|
}
|
|
71
76
|
|
|
72
77
|
async function fetchSchema(endpoint) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
const body = JSON.stringify({ query: getIntrospectionQuery() });
|
|
79
|
+
const res = await fetch(endpoint, {
|
|
80
|
+
method: 'POST',
|
|
81
|
+
headers: { 'Content-Type': 'application/json' },
|
|
82
|
+
body,
|
|
83
|
+
});
|
|
84
|
+
if (!res.ok) throw new Error(`Introspection query failed: ${res.statusText}`);
|
|
85
|
+
const { data, errors } = await res.json();
|
|
86
|
+
if (errors?.length)
|
|
87
|
+
throw new Error(`Server returned errors: ${JSON.stringify(errors)}`);
|
|
88
|
+
return buildClientSchema(data);
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
async function validateGqlOperations(endpoint, operation) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
} catch (e) {
|
|
98
|
-
console.error(e);
|
|
99
|
-
process.exitCode = 1;
|
|
92
|
+
console.log(`\nValidating against endpoint: ${endpoint}`);
|
|
93
|
+
try {
|
|
94
|
+
const document = parse(operation);
|
|
95
|
+
const errors = validate(await fetchSchema(endpoint), document);
|
|
96
|
+
if (errors.length) {
|
|
97
|
+
console.error('❌ Operation is NOT valid for this schema:');
|
|
98
|
+
errors.forEach((e) => console.error('-', e.message));
|
|
99
|
+
process.exitCode = 1;
|
|
100
|
+
} else {
|
|
101
|
+
console.log('✅ Operation is valid!');
|
|
100
102
|
}
|
|
103
|
+
} catch (e) {
|
|
104
|
+
console.error(e);
|
|
105
|
+
process.exitCode = 1;
|
|
106
|
+
}
|
|
101
107
|
}
|
|
102
108
|
|
|
103
109
|
async function getAllOperations(directories, excludedPaths = []) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
110
|
+
let fullContent = '';
|
|
111
|
+
for (const directory of directories) {
|
|
112
|
+
const files = await walk(
|
|
113
|
+
path.resolve(directory),
|
|
114
|
+
excludedPaths.map((p) => path.resolve(p)),
|
|
115
|
+
);
|
|
116
|
+
for (const f of files) {
|
|
117
|
+
const code = await fsPromises.readFile(f, 'utf8');
|
|
109
118
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
119
|
+
let extracted;
|
|
120
|
+
try {
|
|
121
|
+
extracted = extractConstants(code); // may throw on bad syntax
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.error(
|
|
124
|
+
`⚠️ Skipping ${path.relative(process.cwd(), f)}\n` +
|
|
125
|
+
` ${err.message}`,
|
|
126
|
+
);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
fullContent += extracted;
|
|
122
130
|
}
|
|
123
|
-
|
|
131
|
+
}
|
|
132
|
+
return fullContent;
|
|
124
133
|
}
|
|
125
134
|
|
|
126
135
|
module.exports = async function main(sources, endpoints, excluded) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
136
|
+
for (const endpoint of endpoints) {
|
|
137
|
+
const operations = await getAllOperations(sources, excluded);
|
|
138
|
+
if (!operations) {
|
|
139
|
+
console.error(
|
|
140
|
+
'No GraphQL operations found in the specified directories.',
|
|
141
|
+
);
|
|
142
|
+
process.exitCode = 0;
|
|
143
|
+
return;
|
|
135
144
|
}
|
|
136
|
-
|
|
145
|
+
await validateGqlOperations(endpoint, operations);
|
|
146
|
+
}
|
|
147
|
+
};
|