cloudcommerce 0.40.5 → 0.41.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/CHANGELOG.md +20 -0
- package/package.json +2 -2
- package/packages/api/package.json +1 -1
- package/packages/apps/affilate-program/package.json +1 -1
- package/packages/apps/correios/package.json +1 -1
- package/packages/apps/custom-payment/package.json +1 -1
- package/packages/apps/custom-shipping/package.json +1 -1
- package/packages/apps/datafrete/package.json +1 -1
- package/packages/apps/discounts/package.json +1 -1
- package/packages/apps/emails/package.json +1 -1
- package/packages/apps/fb-conversions/package.json +1 -1
- package/packages/apps/flash-courier/package.json +1 -1
- package/packages/apps/frenet/package.json +1 -1
- package/packages/apps/galaxpay/package.json +1 -1
- package/packages/apps/google-analytics/package.json +1 -1
- package/packages/apps/jadlog/package.json +1 -1
- package/packages/apps/loyalty-points/package.json +1 -1
- package/packages/apps/mandae/package.json +1 -1
- package/packages/apps/melhor-envio/package.json +1 -1
- package/packages/apps/mercadopago/package.json +1 -1
- package/packages/apps/pagarme/package.json +1 -1
- package/packages/apps/pagarme-v5/package.json +1 -1
- package/packages/apps/paghiper/package.json +1 -1
- package/packages/apps/pix/package.json +1 -1
- package/packages/apps/tiny-erp/package.json +1 -1
- package/packages/apps/webhooks/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/config/package.json +1 -1
- package/packages/emails/package.json +1 -1
- package/packages/eslint/package.json +1 -1
- package/packages/eslint/storefront.eslintrc.cjs +2 -0
- package/packages/events/package.json +1 -1
- package/packages/feeds/package.json +1 -1
- package/packages/firebase/package.json +1 -1
- package/packages/i18n/package.json +1 -1
- package/packages/modules/package.json +1 -1
- package/packages/passport/package.json +1 -1
- package/packages/ssr/package.json +2 -2
- package/packages/storefront/astro.config.mjs +3 -0
- package/packages/storefront/config/storefront.cms.js +14 -7
- package/packages/storefront/config/storefront.config.mjs +14 -1
- package/packages/storefront/package.json +4 -3
- package/packages/storefront/scripts/build-prod.sh +1 -0
- package/packages/storefront/src/lib/components/AccountLink.vue +9 -3
- package/packages/storefront/src/lib/content.d.ts +2 -2
- package/packages/storefront/src/lib/layouts/BaseHead.astro +1 -0
- package/packages/storefront/src/lib/layouts/use-page-main.ts +34 -16
- package/packages/storefront/src/lib/ssr-context.ts +1 -3
- package/packages/test-base/package.json +1 -1
- package/packages/types/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [0.41.0](https://github.com/ecomplus/cloud-commerce/compare/v0.40.5...v0.41.0) (2024-01-04)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### ⚠ BREAKING CHANGES
|
|
9
|
+
|
|
10
|
+
* **storefront:** Changed expected page content schema for content entry (with markdown)
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
* **storefront:** Adding support to .md files with frontmatter on (CMS) content ([1681506](https://github.com/ecomplus/cloud-commerce/commit/1681506c695c011956d209a11d982551ae42a7e1))
|
|
15
|
+
* **storefront:** New section `content-entry` on page main composable ([5469278](https://github.com/ecomplus/cloud-commerce/commit/54692789aaa1f5c84a6648ee98585d6dd5911360))
|
|
16
|
+
* **storefront:** Set `BUILD_MINIMAL` env on first build sted ([f5c464f](https://github.com/ecomplus/cloud-commerce/commit/f5c464f9bddb66dbd464be5c810bf17ba86d62ee))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
* **deps:** Revert Vue semver to ^3.4.0 ([4b06a30](https://github.com/ecomplus/cloud-commerce/commit/4b06a30de5891b6124ea6d1f3a75989be811da45))
|
|
22
|
+
* **storefront:** Fixiing `ContentData` (may be null) and `PageContent` typedefs ([44ab06c](https://github.com/ecomplus/cloud-commerce/commit/44ab06c92e016f9c477f2dda83b7faf158aec1d2))
|
|
23
|
+
* **storefront:** Prevent hydration mismatch with `<AccountLink>` and (client-only) location ([eb57285](https://github.com/ecomplus/cloud-commerce/commit/eb57285f84f84cac59bb9417a8db1c7be6ca503d))
|
|
24
|
+
|
|
5
25
|
### [0.40.5](https://github.com/ecomplus/cloud-commerce/compare/v0.40.4...v0.40.5) (2024-01-01)
|
|
6
26
|
|
|
7
27
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cloudcommerce",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.41.0",
|
|
5
5
|
"description": "Open fair-code headless commerce platform: API-first, microservices based, event driven and cloud native",
|
|
6
6
|
"main": "packages/api/lib/index.js",
|
|
7
7
|
"author": "E-Com Club Softwares para E-commerce <ti@e-com.club>",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"vite": "^5.0.10",
|
|
31
31
|
"vitest": "^1.1.1",
|
|
32
32
|
"zx": "^7.2.3",
|
|
33
|
-
"@cloudcommerce/eslint": "0.
|
|
33
|
+
"@cloudcommerce/eslint": "0.41.0"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"fix-install": "bash scripts/pre-install.sh && pnpm i",
|
|
@@ -12,6 +12,7 @@ module.exports = {
|
|
|
12
12
|
'comma-dangle': 'warn',
|
|
13
13
|
'consistent-return': 'warn',
|
|
14
14
|
'array-bracket-spacing': 'warn',
|
|
15
|
+
'no-restricted-syntax': 'warn',
|
|
15
16
|
'quote-props': 'off',
|
|
16
17
|
'quotes': 'off',
|
|
17
18
|
'global-require': 'off',
|
|
@@ -26,6 +27,7 @@ module.exports = {
|
|
|
26
27
|
'Skeleton',
|
|
27
28
|
'Prices',
|
|
28
29
|
'Banner',
|
|
30
|
+
'Breadcrumbs',
|
|
29
31
|
'Countdown',
|
|
30
32
|
'Collapse',
|
|
31
33
|
'Accordion',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudcommerce/ssr",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.41.0",
|
|
5
5
|
"description": "E-Com Plus Cloud Commerce storefront SSR",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"firebase-admin": "^11.11.1",
|
|
39
39
|
"firebase-functions": "^4.5.0",
|
|
40
40
|
"mitt": "^3.0.1",
|
|
41
|
-
"vue": "^3.4.
|
|
41
|
+
"vue": "^3.4.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@cloudcommerce/types": "workspace:*",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
global.__storefrontCMS = (fs, resolvePath) => {
|
|
1
|
+
global.__storefrontCMS = (fs, resolvePath, _parseMatter) => {
|
|
2
2
|
const { STOREFRONT_BASE_DIR } = process.env;
|
|
3
3
|
let baseDir;
|
|
4
4
|
if (STOREFRONT_BASE_DIR) {
|
|
@@ -8,6 +8,7 @@ global.__storefrontCMS = (fs, resolvePath) => {
|
|
|
8
8
|
}
|
|
9
9
|
process.env.STOREFRONT_BASE_DIR = baseDir;
|
|
10
10
|
const dirContent = resolvePath(baseDir, 'content');
|
|
11
|
+
const resolveContent = (filename) => resolvePath(dirContent, filename);
|
|
11
12
|
|
|
12
13
|
const contentCache = {};
|
|
13
14
|
const getContent = (filename) => {
|
|
@@ -17,7 +18,7 @@ global.__storefrontCMS = (fs, resolvePath) => {
|
|
|
17
18
|
let content = contentCache[filename];
|
|
18
19
|
if (!content) {
|
|
19
20
|
if (filename.endsWith('/')) {
|
|
20
|
-
const dirColl =
|
|
21
|
+
const dirColl = resolveContent(filename);
|
|
21
22
|
return new Promise((resolve) => {
|
|
22
23
|
const slugs = fs.existsSync(dirColl)
|
|
23
24
|
? fs.readdirSync(dirColl)
|
|
@@ -27,16 +28,22 @@ global.__storefrontCMS = (fs, resolvePath) => {
|
|
|
27
28
|
resolve(slugs);
|
|
28
29
|
});
|
|
29
30
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
const jsonFilepath = resolveContent(`${filename}.json`);
|
|
32
|
+
if (fs.existsSync(jsonFilepath)) {
|
|
33
|
+
content = JSON.parse(fs.readFileSync(jsonFilepath, 'utf8'));
|
|
34
|
+
} else if (_parseMatter && fs.existsSync(resolveContent(`${filename}.md`))) {
|
|
35
|
+
const rawMd = fs.readFileSync(resolveContent(`${filename}.md`), 'utf8');
|
|
36
|
+
const { markdown, matter } = _parseMatter(rawMd);
|
|
37
|
+
content = { ...matter, markdown };
|
|
38
|
+
} else {
|
|
39
|
+
content = null;
|
|
40
|
+
}
|
|
35
41
|
if (!filename.includes('/')) {
|
|
36
42
|
// Caching root content only (not collections)
|
|
37
43
|
contentCache[filename] = content;
|
|
38
44
|
}
|
|
39
45
|
}
|
|
46
|
+
if (typeof content.then === 'function') return content;
|
|
40
47
|
return filename === 'settings'
|
|
41
48
|
? content
|
|
42
49
|
: new Promise((resolve) => { resolve(content); });
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import { join as joinPath, resolve as resolvePath } from 'node:path';
|
|
3
|
+
import { parse as parseYaml } from 'yaml';
|
|
3
4
|
import config from '@cloudcommerce/config';
|
|
4
5
|
import './storefront.cms.js';
|
|
5
6
|
|
|
@@ -15,13 +16,25 @@ export default () => {
|
|
|
15
16
|
config.set({ storeId: Number(ECOM_STORE_ID) });
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
const parseFrontmatter = (markdown) => {
|
|
20
|
+
let matter = {};
|
|
21
|
+
if (markdown.substring(0, 4) === '---\n') {
|
|
22
|
+
const [frontmatter, _md] = markdown.substring(4).split('\n---\n');
|
|
23
|
+
markdown = _md;
|
|
24
|
+
const _matter = parseYaml(frontmatter);
|
|
25
|
+
if (typeof _matter === 'object' && _matter && !Array.isArray(_matter)) {
|
|
26
|
+
matter = _matter;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return { markdown, matter };
|
|
30
|
+
};
|
|
18
31
|
const {
|
|
19
32
|
domain,
|
|
20
33
|
primaryColor,
|
|
21
34
|
secondaryColor,
|
|
22
35
|
settings,
|
|
23
36
|
getContent,
|
|
24
|
-
} = global.__storefrontCMS(fs, resolvePath);
|
|
37
|
+
} = global.__storefrontCMS(fs, resolvePath, parseFrontmatter);
|
|
25
38
|
config.set({ settingsContent: settings });
|
|
26
39
|
|
|
27
40
|
let { storeId } = config.get();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudcommerce/storefront",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.41.0",
|
|
5
5
|
"description": "E-Com Plus Cloud Commerce storefront with Astro",
|
|
6
6
|
"bin": {
|
|
7
7
|
"storefront": "./scripts/build-prod.sh"
|
|
@@ -57,8 +57,9 @@
|
|
|
57
57
|
"unplugin-auto-import": "^0.17.3",
|
|
58
58
|
"vite": "^5.0.10",
|
|
59
59
|
"vite-plugin-pwa": "^0.17.4",
|
|
60
|
-
"vue": "^3.4.
|
|
61
|
-
"wade": "0.3.3"
|
|
60
|
+
"vue": "^3.4.0",
|
|
61
|
+
"wade": "0.3.3",
|
|
62
|
+
"yaml": "^2.3.4"
|
|
62
63
|
},
|
|
63
64
|
"devDependencies": {
|
|
64
65
|
"@cloudcommerce/eslint": "workspace:*",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed } from 'vue';
|
|
2
|
+
import { ref, computed, nextTick } from 'vue';
|
|
3
3
|
|
|
4
4
|
export interface Props {
|
|
5
5
|
to?: 'orders' | 'favorites';
|
|
@@ -10,17 +10,23 @@ export interface Props {
|
|
|
10
10
|
|
|
11
11
|
const props = withDefaults(defineProps<Props>(), {
|
|
12
12
|
accountUrl: globalThis.$storefront?.settings.accountUrl || '/app/account',
|
|
13
|
-
returnUrl: globalThis.location?.href,
|
|
14
13
|
});
|
|
14
|
+
const locationUrl = ref('');
|
|
15
|
+
if (globalThis.location?.href) {
|
|
16
|
+
nextTick(() => {
|
|
17
|
+
locationUrl.value = globalThis.location.href;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
15
20
|
const href = computed(() => {
|
|
16
21
|
let url = props.accountUrl;
|
|
22
|
+
const returnUrl = props.returnUrl || locationUrl.value;
|
|
17
23
|
if (!props.to) {
|
|
18
24
|
if (props.isSignUp) {
|
|
19
25
|
url += '?sign_up&';
|
|
20
26
|
} else {
|
|
21
27
|
url += '?';
|
|
22
28
|
}
|
|
23
|
-
return
|
|
29
|
+
return returnUrl ? `${url}return_url=${returnUrl}` : url;
|
|
24
30
|
}
|
|
25
31
|
const { settings } = globalThis.$storefront;
|
|
26
32
|
if (props.to === 'orders' && settings.ordersUrl) {
|
|
@@ -38,7 +38,7 @@ export interface PageContent {
|
|
|
38
38
|
thumbnail?: string;
|
|
39
39
|
author?: string;
|
|
40
40
|
description?: string;
|
|
41
|
-
|
|
41
|
+
markdown?: string;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
export type ContentFilename = 'settings'
|
|
@@ -50,7 +50,7 @@ export type ContentData<T extends ContentFilename> =
|
|
|
50
50
|
T extends `${string}/` ? Array<string> :
|
|
51
51
|
T extends 'settings' ? SettingsContent :
|
|
52
52
|
T extends 'layout' ? LayoutContent :
|
|
53
|
-
T extends `${string}/${string}` ? PageContent :
|
|
53
|
+
T extends `${string}/${string}` ? PageContent | null :
|
|
54
54
|
null;
|
|
55
55
|
|
|
56
56
|
export type ContentGetter = <T extends ContentFilename>(filename: T) =>
|
|
@@ -53,6 +53,7 @@ if (searchPageTerm) {
|
|
|
53
53
|
const description = state.meta_description ||
|
|
54
54
|
state.metaDescription ||
|
|
55
55
|
state.short_description ||
|
|
56
|
+
state.description ||
|
|
56
57
|
settings.description;
|
|
57
58
|
const favicon = settings.icon ? getIconUrl(32) : '/favicon.ico';
|
|
58
59
|
const shortcutIcon = settings.icon ? getIconUrl(192) : null;
|
|
@@ -49,7 +49,15 @@ type ProductDetailsProps = { hasDescription?: boolean, hasSpecifications?: boole
|
|
|
49
49
|
|
|
50
50
|
export const usePageSections = async <T extends CustomSection = CustomSection>
|
|
51
51
|
({ routeContext, handleCustomSection }: Props) => {
|
|
52
|
-
const
|
|
52
|
+
const { cmsContent } = routeContext;
|
|
53
|
+
let sectionsContent = cmsContent?.sections;
|
|
54
|
+
if (
|
|
55
|
+
cmsContent?.markdown
|
|
56
|
+
&& !sectionsContent?.find(({ type }) => type === 'content-entry')
|
|
57
|
+
) {
|
|
58
|
+
if (!sectionsContent) sectionsContent = [];
|
|
59
|
+
sectionsContent.push({ type: 'content-entry' });
|
|
60
|
+
}
|
|
53
61
|
const sections: Array<
|
|
54
62
|
T
|
|
55
63
|
| { type: 'product-shelf', props: UseProductShelfProps }
|
|
@@ -62,8 +70,10 @@ export const usePageSections = async <T extends CustomSection = CustomSection>
|
|
|
62
70
|
| { type: 'product-specifications', props: {} }
|
|
63
71
|
| { type: 'search-showcase' | 'context-showcase', props: UseSearchShowcaseProps }
|
|
64
72
|
| { type: 'page-title', props: {} }
|
|
73
|
+
| { type: 'content-entry', props: { title: string, markdown: string } }
|
|
65
74
|
| { type: 'custom-html', props: { html: string } }
|
|
66
75
|
> = [];
|
|
76
|
+
|
|
67
77
|
if (sectionsContent) {
|
|
68
78
|
await Promise.all(sectionsContent.map(async ({ type, ...sectionContent }, index) => {
|
|
69
79
|
if (type === 'product-shelf' || type === 'related-products') {
|
|
@@ -181,16 +191,30 @@ export const usePageSections = async <T extends CustomSection = CustomSection>
|
|
|
181
191
|
return;
|
|
182
192
|
}
|
|
183
193
|
|
|
184
|
-
if (type === 'banners-grid') {
|
|
185
|
-
sections[index] = {
|
|
186
|
-
type,
|
|
187
|
-
props: {
|
|
188
|
-
banners: parseBanners(sectionContent.banners || []),
|
|
189
|
-
},
|
|
190
|
-
};
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
194
|
switch (type) {
|
|
195
|
+
case 'banners-grid':
|
|
196
|
+
sections[index] = {
|
|
197
|
+
type,
|
|
198
|
+
props: {
|
|
199
|
+
banners: parseBanners(sectionContent.banners || []),
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
return;
|
|
203
|
+
case 'custom-html':
|
|
204
|
+
sections[index] = {
|
|
205
|
+
type,
|
|
206
|
+
props: { html: sectionContent.html || '' },
|
|
207
|
+
};
|
|
208
|
+
return;
|
|
209
|
+
case 'content-entry':
|
|
210
|
+
sections[index] = {
|
|
211
|
+
type,
|
|
212
|
+
props: {
|
|
213
|
+
title: sectionContent.title || cmsContent?.title || '',
|
|
214
|
+
markdown: sectionContent.markdown || cmsContent?.markdown || '',
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
return;
|
|
194
218
|
case 'breadcrumbs':
|
|
195
219
|
case 'product-details':
|
|
196
220
|
case 'doc-description':
|
|
@@ -203,12 +227,6 @@ export const usePageSections = async <T extends CustomSection = CustomSection>
|
|
|
203
227
|
props: sectionContent,
|
|
204
228
|
};
|
|
205
229
|
return;
|
|
206
|
-
case 'custom-html':
|
|
207
|
-
sections[index] = {
|
|
208
|
-
type,
|
|
209
|
-
props: { html: sectionContent.html || '' },
|
|
210
|
-
};
|
|
211
|
-
return;
|
|
212
230
|
default:
|
|
213
231
|
}
|
|
214
232
|
if (typeof handleCustomSection === 'function') {
|
|
@@ -5,8 +5,8 @@ import type { ResourceId, CategoriesList, BrandsList } from '@cloudcommerce/api/
|
|
|
5
5
|
import type { ContentGetter, SettingsContent, PageContent } from '@@sf/content';
|
|
6
6
|
import { EventEmitter } from 'node:events';
|
|
7
7
|
import api from '@cloudcommerce/api';
|
|
8
|
-
import { termify } from '../helpers/sf-utils';
|
|
9
8
|
import _getConfig from '../../config/storefront.config.mjs';
|
|
9
|
+
import { termify } from '../helpers/sf-utils';
|
|
10
10
|
|
|
11
11
|
export type StorefrontConfig = {
|
|
12
12
|
storeId: BaseConfig['storeId'],
|
|
@@ -244,8 +244,6 @@ const loadRouteContext = async (
|
|
|
244
244
|
return routeContext;
|
|
245
245
|
};
|
|
246
246
|
|
|
247
|
-
export default loadRouteContext;
|
|
248
|
-
|
|
249
247
|
export {
|
|
250
248
|
getConfig,
|
|
251
249
|
loadRouteContext,
|