@pixelated-tech/components 3.13.15 → 3.14.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/dist/components/admin/site-health/google.api.integration.js +5 -4
- package/dist/components/admin/site-health/site-health-cloudwatch.integration.js +3 -2
- package/dist/components/config/crypto.js +17 -1
- package/dist/components/general/cache-manager.js +19 -2
- package/dist/components/general/carousel.drag.js +21 -24
- package/dist/components/general/intersection-observer.js +4 -0
- package/dist/components/general/metadata.functions.js +1 -1
- package/dist/components/general/sitemap.js +3 -2
- package/dist/components/general/utilities.js +106 -0
- package/dist/components/integrations/contentful.delivery.js +16 -16
- package/dist/components/integrations/contentful.items.components.js +2 -11
- package/dist/components/integrations/flickr.js +7 -4
- package/dist/components/integrations/googleplaces.js +144 -0
- package/dist/components/integrations/socialcard.js +5 -2
- package/dist/components/integrations/wordpress.components.js +2 -1
- package/dist/components/shoppingcart/ebay.components.js +5 -5
- package/dist/components/shoppingcart/ebay.functions.js +5 -3
- package/dist/components/shoppingcart/shipping.to.json +3 -4
- package/dist/components/shoppingcart/shoppingcart.components.js +7 -5
- package/dist/components/shoppingcart/shoppingcart.css +1 -1
- package/dist/components/shoppingcart/shoppingcart.functions.js +5 -14
- package/dist/components/sitebuilder/form/formcomponents.js +151 -0
- package/dist/components/sitebuilder/form/formutils.js +3 -0
- package/dist/components/sitebuilder/page/lib/pageStorageContentful.js +2 -2
- package/dist/config/pixelated.config.json.enc +1 -1
- package/dist/data/form.json +18 -0
- package/dist/index.adminserver.js +1 -3
- package/dist/index.js +1 -1
- package/dist/index.server.js +1 -0
- package/dist/scripts/create-pixelated-app.js +187 -79
- package/dist/scripts/create-pixelated-app.json +51 -1
- package/dist/scripts/pixelated-eslint-plugin.js +142 -0
- package/dist/scripts/release.sh +23 -16
- package/dist/scripts/update.sh +47 -8
- package/dist/types/components/admin/deploy/deployment.integration.d.ts +1 -0
- package/dist/types/components/admin/deploy/deployment.integration.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/google.api.integration.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-cloudwatch.integration.d.ts.map +1 -1
- package/dist/types/components/config/config.types.d.ts +23 -0
- package/dist/types/components/config/config.types.d.ts.map +1 -1
- package/dist/types/components/config/crypto.d.ts +1 -0
- package/dist/types/components/config/crypto.d.ts.map +1 -1
- package/dist/types/components/general/cache-manager.d.ts +16 -2
- package/dist/types/components/general/cache-manager.d.ts.map +1 -1
- package/dist/types/components/general/carousel.drag.d.ts.map +1 -1
- package/dist/types/components/general/intersection-observer.d.ts.map +1 -1
- package/dist/types/components/general/sitemap.d.ts.map +1 -1
- package/dist/types/components/general/utilities.d.ts +39 -0
- package/dist/types/components/general/utilities.d.ts.map +1 -1
- package/dist/types/components/integrations/contentful.delivery.d.ts +16 -16
- package/dist/types/components/integrations/contentful.items.components.d.ts.map +1 -1
- package/dist/types/components/integrations/flickr.d.ts.map +1 -1
- package/dist/types/components/integrations/googleplaces.d.ts +61 -0
- package/dist/types/components/integrations/googleplaces.d.ts.map +1 -0
- package/dist/types/components/integrations/socialcard.d.ts.map +1 -1
- package/dist/types/components/integrations/wordpress.components.d.ts.map +1 -1
- package/dist/types/components/shoppingcart/ebay.functions.d.ts.map +1 -1
- package/dist/types/components/shoppingcart/shoppingcart.components.d.ts.map +1 -1
- package/dist/types/components/shoppingcart/shoppingcart.functions.d.ts +2 -2
- package/dist/types/components/shoppingcart/shoppingcart.functions.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/form/formcomponents.d.ts +22 -0
- package/dist/types/components/sitebuilder/form/formcomponents.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/form/formutils.d.ts.map +1 -1
- package/dist/types/index.adminserver.d.ts +1 -3
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.server.d.ts +1 -0
- package/dist/types/scripts/create-pixelated-app.d.ts +3 -0
- package/dist/types/scripts/create-pixelated-app.d.ts.map +1 -1
- package/dist/types/scripts/pixelated-eslint-plugin.d.ts +20 -0
- package/dist/types/stories/integrations/contentful.items.stories.d.ts.map +1 -0
- package/dist/types/stories/integrations/contentful.stories.d.ts.map +1 -0
- package/dist/types/stories/integrations/google.reviews.stories.d.ts.map +1 -0
- package/dist/types/stories/integrations/googlesearch.stories.d.ts.map +1 -0
- package/dist/types/stories/integrations/gravatar.stories.d.ts.map +1 -0
- package/dist/types/stories/integrations/instagram.stories.d.ts.map +1 -0
- package/dist/types/stories/integrations/wordpress.stories.d.ts.map +1 -0
- package/dist/types/test/test-utils.d.ts +2 -0
- package/dist/types/test/test-utils.d.ts.map +1 -1
- package/dist/types/tests/404.test.d.ts +2 -0
- package/dist/types/tests/404.test.d.ts.map +1 -0
- package/dist/types/tests/carousel.drag.test.d.ts +2 -0
- package/dist/types/tests/carousel.drag.test.d.ts.map +1 -0
- package/dist/types/tests/carouselDrag.test.d.ts +2 -0
- package/dist/types/tests/carouselDrag.test.d.ts.map +1 -0
- package/dist/types/tests/componentAnalysis.test.d.ts +2 -0
- package/dist/types/tests/componentAnalysis.test.d.ts.map +1 -0
- package/dist/types/tests/componentDiscovery.test.d.ts +2 -0
- package/dist/types/tests/componentDiscovery.test.d.ts.map +1 -0
- package/dist/types/tests/componentMap.test.d.ts +2 -0
- package/dist/types/tests/componentMap.test.d.ts.map +1 -0
- package/dist/types/tests/contentful.items.components.test.d.ts +2 -0
- package/dist/types/tests/contentful.items.components.test.d.ts.map +1 -0
- package/dist/types/tests/contentful.management.test.d.ts +2 -0
- package/dist/types/tests/contentful.management.test.d.ts.map +1 -0
- package/dist/types/tests/contentfulManagement.test.d.ts +2 -0
- package/dist/types/tests/contentfulManagement.test.d.ts.map +1 -0
- package/dist/types/tests/countup.test.d.ts +2 -0
- package/dist/types/tests/countup.test.d.ts.map +1 -0
- package/dist/types/tests/crypto.test.d.ts +2 -0
- package/dist/types/tests/crypto.test.d.ts.map +1 -0
- package/dist/types/tests/deployment.integration.test.d.ts +2 -0
- package/dist/types/tests/deployment.integration.test.d.ts.map +1 -0
- package/dist/types/tests/ebay.components.test.d.ts +2 -0
- package/dist/types/tests/ebay.components.test.d.ts.map +1 -0
- package/dist/types/tests/ebayComponents.test.d.ts +2 -0
- package/dist/types/tests/ebayComponents.test.d.ts.map +1 -0
- package/dist/types/tests/flickr.test.d.ts +2 -0
- package/dist/types/tests/flickr.test.d.ts.map +1 -0
- package/dist/types/tests/formgoogleplacesinput.test.d.ts +2 -0
- package/dist/types/tests/formgoogleplacesinput.test.d.ts.map +1 -0
- package/dist/types/tests/formutils.test.d.ts +2 -0
- package/dist/types/tests/formutils.test.d.ts.map +1 -0
- package/dist/types/tests/formvalidator.test.d.ts +2 -0
- package/dist/types/tests/formvalidator.test.d.ts.map +1 -0
- package/dist/types/tests/gemini-api.client.test.d.ts +2 -0
- package/dist/types/tests/gemini-api.client.test.d.ts.map +1 -0
- package/dist/types/tests/gemini-api.server.test.d.ts +2 -0
- package/dist/types/tests/gemini-api.server.test.d.ts.map +1 -0
- package/dist/types/tests/geminiApi.test.d.ts +2 -0
- package/dist/types/tests/geminiApi.test.d.ts.map +1 -0
- package/dist/types/tests/google.reviews.components.test.d.ts +2 -0
- package/dist/types/tests/google.reviews.components.test.d.ts.map +1 -0
- package/dist/types/tests/googleanalytics.test.d.ts +2 -0
- package/dist/types/tests/googleanalytics.test.d.ts.map +1 -0
- package/dist/types/tests/googlemap.test.d.ts +2 -0
- package/dist/types/tests/googlemap.test.d.ts.map +1 -0
- package/dist/types/tests/gravatar.functions.test.d.ts +2 -0
- package/dist/types/tests/gravatar.functions.test.d.ts.map +1 -0
- package/dist/types/tests/hubspot.components.test.d.ts +2 -0
- package/dist/types/tests/hubspot.components.test.d.ts.map +1 -0
- package/dist/types/tests/image-utils.test.d.ts +2 -0
- package/dist/types/tests/image-utils.test.d.ts.map +1 -0
- package/dist/types/tests/instagram.components.test.d.ts +2 -0
- package/dist/types/tests/instagram.components.test.d.ts.map +1 -0
- package/dist/types/tests/instagram.functions.test.d.ts +2 -0
- package/dist/types/tests/instagram.functions.test.d.ts.map +1 -0
- package/dist/types/tests/intersection-observer.test.d.ts +2 -0
- package/dist/types/tests/intersection-observer.test.d.ts.map +1 -0
- package/dist/types/tests/metadata.functions.test.d.ts +2 -0
- package/dist/types/tests/metadata.functions.test.d.ts.map +1 -0
- package/dist/types/tests/metadataComponents.test.d.ts +2 -0
- package/dist/types/tests/metadataComponents.test.d.ts.map +1 -0
- package/dist/types/tests/page-storage.test.d.ts +2 -0
- package/dist/types/tests/page-storage.test.d.ts.map +1 -0
- package/dist/types/tests/pageStorageContentful.test.d.ts +2 -0
- package/dist/types/tests/pageStorageContentful.test.d.ts.map +1 -0
- package/dist/types/tests/pageStorageLocal.test.d.ts +2 -0
- package/dist/types/tests/pageStorageLocal.test.d.ts.map +1 -0
- package/dist/types/tests/pixelated.test.d.ts +2 -0
- package/dist/types/tests/pixelated.test.d.ts.map +1 -0
- package/dist/types/tests/propTypeIntrospection.test.d.ts +2 -0
- package/dist/types/tests/propTypeIntrospection.test.d.ts.map +1 -0
- package/dist/types/tests/save-route-example.test.d.ts +2 -0
- package/dist/types/tests/save-route-example.test.d.ts.map +1 -0
- package/dist/types/tests/saveRouteExample.test.d.ts +2 -0
- package/dist/types/tests/saveRouteExample.test.d.ts.map +1 -0
- package/dist/types/tests/seoConstants.test.d.ts +2 -0
- package/dist/types/tests/seoConstants.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-accessibility.test.d.ts +2 -0
- package/dist/types/tests/site-health-accessibility.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-cloudwatch.integration.test.d.ts +2 -0
- package/dist/types/tests/site-health-cloudwatch.integration.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-dependency-vulnerabilities.test.d.ts +2 -0
- package/dist/types/tests/site-health-dependency-vulnerabilities.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-github.test.d.ts +2 -0
- package/dist/types/tests/site-health-github.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-google-analytics.integration.test.d.ts +2 -0
- package/dist/types/tests/site-health-google-analytics.integration.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-google-analytics.test.d.ts +2 -0
- package/dist/types/tests/site-health-google-analytics.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-google-search-console.integration.test.d.ts +2 -0
- package/dist/types/tests/site-health-google-search-console.integration.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-google-search-console.test.d.ts +2 -0
- package/dist/types/tests/site-health-google-search-console.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-mock-context.test.d.ts +2 -0
- package/dist/types/tests/site-health-mock-context.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-on-site-seo.test.d.ts +2 -0
- package/dist/types/tests/site-health-on-site-seo.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-performance.test.d.ts +2 -0
- package/dist/types/tests/site-health-performance.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-security.integration.test.d.ts +2 -0
- package/dist/types/tests/site-health-security.integration.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-security.test.d.ts +2 -0
- package/dist/types/tests/site-health-security.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-seo.test.d.ts +2 -0
- package/dist/types/tests/site-health-seo.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-uptime.integration.test.d.ts +2 -0
- package/dist/types/tests/site-health-uptime.integration.test.d.ts.map +1 -0
- package/dist/types/tests/site-health-uptime.test.d.ts +2 -0
- package/dist/types/tests/site-health-uptime.test.d.ts.map +1 -0
- package/dist/types/tests/siteHealthGaIntegration.test.d.ts +2 -0
- package/dist/types/tests/siteHealthGaIntegration.test.d.ts.map +1 -0
- package/dist/types/tests/siteHealthGscIntegration.test.d.ts +2 -0
- package/dist/types/tests/siteHealthGscIntegration.test.d.ts.map +1 -0
- package/dist/types/tests/spotify.components.test.d.ts +2 -0
- package/dist/types/tests/spotify.components.test.d.ts.map +1 -0
- package/dist/types/tests/spotify.functions.test.d.ts +2 -0
- package/dist/types/tests/spotify.functions.test.d.ts.map +1 -0
- package/dist/types/tests/test-utils.d.ts +7 -0
- package/dist/types/tests/test-utils.d.ts.map +1 -0
- package/dist/types/tests/usePageBuilder.test.d.ts +2 -0
- package/dist/types/tests/usePageBuilder.test.d.ts.map +1 -0
- package/package.json +48 -41
- package/dist/components/admin/site-health/site-health-google-analytics.integration.js +0 -6
- package/dist/components/admin/site-health/site-health-google-search-console.integration.js +0 -6
- package/dist/components/general/proxy-csp-listener.js +0 -20
- package/dist/scripts/create-pixelated-app-template-mapper.js +0 -80
- package/dist/types/components/admin/site-health/site-health-google-analytics.integration.d.ts +0 -6
- package/dist/types/components/admin/site-health/site-health-google-analytics.integration.d.ts.map +0 -1
- package/dist/types/components/admin/site-health/site-health-google-search-console.integration.d.ts +0 -6
- package/dist/types/components/admin/site-health/site-health-google-search-console.integration.d.ts.map +0 -1
- package/dist/types/components/general/proxy-csp-listener.d.ts +0 -15
- package/dist/types/components/general/proxy-csp-listener.d.ts.map +0 -1
- package/dist/types/scripts/create-pixelated-app-template-mapper.d.ts +0 -5
- package/dist/types/scripts/create-pixelated-app-template-mapper.d.ts.map +0 -1
- package/dist/types/stories/general/callout.many.stories.d.ts +0 -7
- package/dist/types/stories/general/callout.many.stories.d.ts.map +0 -1
- package/dist/types/stories/general/contentful.item.stories.d.ts +0 -12
- package/dist/types/stories/general/contentful.item.stories.d.ts.map +0 -1
- package/dist/types/stories/general/contentful.items.stories.d.ts.map +0 -1
- package/dist/types/stories/general/contentful.stories.d.ts.map +0 -1
- package/dist/types/stories/general/global-error.stories.d.ts +0 -26
- package/dist/types/stories/general/global-error.stories.d.ts.map +0 -1
- package/dist/types/stories/general/google.reviews.stories.d.ts.map +0 -1
- package/dist/types/stories/general/googleanalytics.stories.d.ts +0 -14
- package/dist/types/stories/general/googleanalytics.stories.d.ts.map +0 -1
- package/dist/types/stories/general/googlesearch.stories.d.ts.map +0 -1
- package/dist/types/stories/general/gravatar.stories.d.ts.map +0 -1
- package/dist/types/stories/general/instagram.stories.d.ts.map +0 -1
- package/dist/types/stories/general/loading.stories.d.ts +0 -11
- package/dist/types/stories/general/loading.stories.d.ts.map +0 -1
- package/dist/types/stories/general/metadata.stories.d.ts +0 -25
- package/dist/types/stories/general/metadata.stories.d.ts.map +0 -1
- package/dist/types/stories/general/schema.stories.d.ts +0 -62
- package/dist/types/stories/general/schema.stories.d.ts.map +0 -1
- package/dist/types/stories/general/sitemap.stories.d.ts +0 -8
- package/dist/types/stories/general/sitemap.stories.d.ts.map +0 -1
- package/dist/types/stories/general/wordpress.stories.d.ts.map +0 -1
- package/dist/types/stories/integrations/schema-podcast.stories.d.ts +0 -45
- package/dist/types/stories/integrations/schema-podcast.stories.d.ts.map +0 -1
- /package/dist/types/stories/{general → integrations}/contentful.items.stories.d.ts +0 -0
- /package/dist/types/stories/{general → integrations}/contentful.stories.d.ts +0 -0
- /package/dist/types/stories/{general → integrations}/google.reviews.stories.d.ts +0 -0
- /package/dist/types/stories/{general → integrations}/googlesearch.stories.d.ts +0 -0
- /package/dist/types/stories/{general → integrations}/gravatar.stories.d.ts +0 -0
- /package/dist/types/stories/{general → integrations}/instagram.stories.d.ts +0 -0
- /package/dist/types/stories/{general → integrations}/wordpress.stories.d.ts +0 -0
|
@@ -49,7 +49,6 @@ import { promisify } from 'util';
|
|
|
49
49
|
import readline from 'readline/promises';
|
|
50
50
|
import { stdin as input, stdout as output } from 'process';
|
|
51
51
|
import { fileURLToPath } from 'url';
|
|
52
|
-
import { loadManifest, findTemplateForSlug, pruneTemplateDirs, printAvailableTemplates } from './create-pixelated-app-template-mapper.js';
|
|
53
52
|
import { AmplifyClient, CreateAppCommand, CreateBranchCommand, UpdateAppCommand, UpdateBranchCommand } from '@aws-sdk/client-amplify';
|
|
54
53
|
|
|
55
54
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -70,6 +69,51 @@ async function exists(p) {
|
|
|
70
69
|
}
|
|
71
70
|
}
|
|
72
71
|
|
|
72
|
+
// Template manifest utilities
|
|
73
|
+
export async function loadManifest(baseDir = path.resolve(__dirname)) {
|
|
74
|
+
const manifestPath = path.resolve(baseDir, 'create-pixelated-app.json');
|
|
75
|
+
try {
|
|
76
|
+
if (await exists(manifestPath)) {
|
|
77
|
+
const txt = await fs.readFile(manifestPath, 'utf8');
|
|
78
|
+
return JSON.parse(txt);
|
|
79
|
+
}
|
|
80
|
+
} catch (e) {
|
|
81
|
+
// ignore parse/read errors
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function findTemplateForSlug(manifest, slug) {
|
|
87
|
+
if (!manifest || !Array.isArray(manifest.templates)) return null;
|
|
88
|
+
slug = (slug || '').toLowerCase();
|
|
89
|
+
for (const t of manifest.templates) {
|
|
90
|
+
// Skip templates that have action: "ignore" (metadata routes in Admin section)
|
|
91
|
+
if (t.action === 'ignore') continue;
|
|
92
|
+
if (!t.aliases || !Array.isArray(t.aliases)) continue;
|
|
93
|
+
for (let a of t.aliases) {
|
|
94
|
+
a = a.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
|
|
95
|
+
if (a === slug) return t;
|
|
96
|
+
}
|
|
97
|
+
// also fuzzy match (e.g., 'about-us' -> 'about')
|
|
98
|
+
for (let a of t.aliases) {
|
|
99
|
+
a = a.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
|
|
100
|
+
if (slug === a || slug.startsWith(a + '-') || slug.endsWith('-' + a) || slug.includes('-' + a + '-')) return t;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function printAvailableTemplates(manifest) {
|
|
107
|
+
if (!manifest || !Array.isArray(manifest.templates) || manifest.templates.length === 0) return;
|
|
108
|
+
console.log('\nAvailable templates:');
|
|
109
|
+
for (const t of manifest.templates) {
|
|
110
|
+
// Skip templates in Admin section (marked with action: "ignore")
|
|
111
|
+
if (t.action === 'ignore') continue;
|
|
112
|
+
const aliases = Array.isArray(t.aliases) ? t.aliases.join(', ') : '';
|
|
113
|
+
console.log(` - ${t.name}${aliases ? ': ' + aliases : ''}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
73
117
|
async function countFiles(src) {
|
|
74
118
|
let total = 0;
|
|
75
119
|
async function walk(p) {
|
|
@@ -245,7 +289,8 @@ export async function createAndPushRemote(destPath, siteName, defaultOwner) {
|
|
|
245
289
|
const tmpDir = path.join(destPath, '.px-scripts');
|
|
246
290
|
const tmpFile = path.join(tmpDir, 'get_github_token.ts');
|
|
247
291
|
await fs.mkdir(tmpDir, { recursive: true });
|
|
248
|
-
const
|
|
292
|
+
const configModulePath = path.resolve(destPath, 'src', 'components', 'config', 'config');
|
|
293
|
+
const tmpContent = `import('${configModulePath}').then(m => {
|
|
249
294
|
const cfg = m.getFullPixelatedConfig();
|
|
250
295
|
// Only print the github object (or null) as JSON to stdout
|
|
251
296
|
console.log(JSON.stringify(cfg?.github || null));
|
|
@@ -550,121 +595,184 @@ async function main() {
|
|
|
550
595
|
}
|
|
551
596
|
|
|
552
597
|
|
|
553
|
-
// Pages
|
|
554
|
-
console.log(`\nStep ${stepNumber++}: Page
|
|
598
|
+
// Pages selection: ask which pages user wants (from template or custom new pages)
|
|
599
|
+
console.log(`\nStep ${stepNumber++}: Page Selection`);
|
|
555
600
|
console.log('================================================================================\n');
|
|
556
601
|
if (manifest && Array.isArray(manifest.templates) && manifest.templates.length) {
|
|
557
602
|
printAvailableTemplates(manifest);
|
|
558
603
|
}
|
|
559
|
-
const pagesInput = (await rl.question('Pages
|
|
560
|
-
let
|
|
561
|
-
let existingPages = ['humans.txt', 'styleguide'];
|
|
604
|
+
const pagesInput = (await rl.question('Pages you want (comma-separated, e.g. about,contact,custom-legal) [leave blank to skip]: ')).trim();
|
|
605
|
+
let wantedPages = [];
|
|
562
606
|
if (pagesInput) {
|
|
563
607
|
const raw = pagesInput.split(',').map(s => s.trim()).filter(Boolean);
|
|
564
|
-
// sanitize and normalize
|
|
565
608
|
const seen = new Set();
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
}
|
|
572
|
-
let slug = r.trim().toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
|
|
573
|
-
if (!slug) continue;
|
|
574
|
-
if (seen.has(slug)) continue;
|
|
609
|
+
|
|
610
|
+
// Normalize each input
|
|
611
|
+
for (const userInput of raw) {
|
|
612
|
+
const slug = userInput.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
|
|
613
|
+
if (!slug || seen.has(slug)) continue;
|
|
575
614
|
seen.add(slug);
|
|
615
|
+
|
|
616
|
+
// Check if it's a template page
|
|
576
617
|
const matchedTemplate = findTemplateForSlug(manifest, slug);
|
|
577
|
-
|
|
618
|
+
const isTemplate = !!matchedTemplate;
|
|
619
|
+
|
|
620
|
+
wantedPages.push({
|
|
621
|
+
slug,
|
|
622
|
+
displayName: userInput.trim(),
|
|
623
|
+
isTemplate,
|
|
624
|
+
matchedTemplate
|
|
625
|
+
});
|
|
578
626
|
}
|
|
579
627
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
console.log(` - ${p.slug} (
|
|
628
|
+
if (wantedPages.length) {
|
|
629
|
+
console.log('\nSummary of pages:');
|
|
630
|
+
const templatePages = wantedPages.filter(p => p.isTemplate);
|
|
631
|
+
const customPages = wantedPages.filter(p => !p.isTemplate);
|
|
632
|
+
|
|
633
|
+
if (templatePages.length) {
|
|
634
|
+
console.log(' - Template pages:');
|
|
635
|
+
for (const p of templatePages) {
|
|
636
|
+
console.log(` - ${p.slug} (from template: ${p.matchedTemplate.name})`);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
if (customPages.length) {
|
|
640
|
+
console.log(' - Custom pages (new):');
|
|
641
|
+
for (const p of customPages) {
|
|
642
|
+
console.log(` - ${p.slug}`);
|
|
589
643
|
}
|
|
590
644
|
}
|
|
591
645
|
}
|
|
592
|
-
|
|
646
|
+
|
|
647
|
+
const proceedPages = (await rl.question('Proceed with these pages? (Y/n): ')) || 'y';
|
|
593
648
|
if (proceedPages.toLowerCase() === 'y' || proceedPages.toLowerCase() === 'yes') {
|
|
594
|
-
// perform creation
|
|
595
|
-
const templatePagesHome = path.join(templatePath, 'src', 'app', '(pages)', '(home)');
|
|
596
649
|
const siteRoutesFile = path.join(destPath, 'src', 'app', 'data', 'routes.json');
|
|
597
650
|
let routesJson = null;
|
|
651
|
+
|
|
598
652
|
try {
|
|
599
653
|
routesJson = JSON.parse(await fs.readFile(siteRoutesFile, 'utf8'));
|
|
600
|
-
// Ensure siteInfo exists and set its name to the root display name
|
|
601
654
|
routesJson.siteInfo = routesJson.siteInfo || {};
|
|
602
655
|
routesJson.siteInfo.name = rootDisplayName;
|
|
603
656
|
} catch (e) {
|
|
604
|
-
console.
|
|
657
|
+
console.error('❌ Failed to read routes.json:', e?.message || e);
|
|
658
|
+
process.exit(1);
|
|
605
659
|
}
|
|
606
660
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
661
|
+
const templatePagesHome = path.join(templatePath, 'src', 'app', '(pages)', '(home)');
|
|
662
|
+
const pagesDir = path.join(destPath, 'src', 'app', '(pages)');
|
|
663
|
+
const wantedSlugs = new Set(wantedPages.map(p => p.slug));
|
|
664
|
+
|
|
665
|
+
// Process wanted pages: rename templates or create custom pages
|
|
666
|
+
for (const p of wantedPages) {
|
|
667
|
+
if (p.isTemplate) {
|
|
668
|
+
// Get the actual template folder name (e.g., "about")
|
|
669
|
+
const templateFolderName = path.basename(p.matchedTemplate.src);
|
|
670
|
+
const oldPath = path.join(pagesDir, templateFolderName);
|
|
671
|
+
const newPath = path.join(pagesDir, p.slug);
|
|
672
|
+
|
|
673
|
+
// Rename if user requested a different name
|
|
674
|
+
if (templateFolderName !== p.slug) {
|
|
675
|
+
try {
|
|
676
|
+
await fs.rename(oldPath, newPath);
|
|
677
|
+
console.log(`Renamed ${templateFolderName} → ${p.slug}`);
|
|
678
|
+
|
|
679
|
+
// Update component name in page.tsx
|
|
680
|
+
const pageFile = path.join(newPath, 'page.tsx');
|
|
681
|
+
let content = await fs.readFile(pageFile, 'utf8');
|
|
682
|
+
const compName = p.displayName.replace(/[^a-zA-Z0-9]+/g, ' ').split(/\s+/).map(s => s.charAt(0).toUpperCase() + s.slice(1)).join('') + 'Page';
|
|
683
|
+
content = content.replace(/export default function\s+\w+\s*\(/, `export default function ${compName}(`);
|
|
684
|
+
await fs.writeFile(pageFile, content, 'utf8');
|
|
685
|
+
console.log(` - Updated component name to ${compName}`);
|
|
686
|
+
|
|
687
|
+
// Update route path in routes.json
|
|
688
|
+
const route = routesJson.routes.find(r => r.path === `/${templateFolderName}`);
|
|
689
|
+
if (route) {
|
|
690
|
+
route.path = `/${p.slug}`;
|
|
691
|
+
route.name = p.displayName.split(/\s+/).map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(' ');
|
|
692
|
+
console.log(` - Updated route path to /${p.slug}`);
|
|
693
|
+
}
|
|
694
|
+
} catch (e) {
|
|
695
|
+
console.error(`❌ Failed to rename ${templateFolderName} to ${p.slug}:`, e?.message || e);
|
|
696
|
+
process.exit(1);
|
|
697
|
+
}
|
|
617
698
|
}
|
|
618
699
|
} else {
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
if (!routesJson.routes.some(r => r.path === candidatePath)) {
|
|
638
|
-
routesJson.routes.push({
|
|
639
|
-
"name": p.displayName.split(/\s+/).map(s=>s.charAt(0).toUpperCase()+s.slice(1)).join(' '),
|
|
640
|
-
"path": candidatePath,
|
|
700
|
+
// Create custom page from default template
|
|
701
|
+
try {
|
|
702
|
+
const targetDir = path.join(pagesDir, p.slug);
|
|
703
|
+
await copyRecursive(templatePagesHome, targetDir);
|
|
704
|
+
console.log(`Created custom page ${p.slug}`);
|
|
705
|
+
|
|
706
|
+
// Update component name in page.tsx
|
|
707
|
+
const pageFile = path.join(targetDir, 'page.tsx');
|
|
708
|
+
let content = await fs.readFile(pageFile, 'utf8');
|
|
709
|
+
const compName = p.displayName.replace(/[^a-zA-Z0-9]+/g, ' ').split(/\s+/).map(s => s.charAt(0).toUpperCase() + s.slice(1)).join('') + 'Page';
|
|
710
|
+
content = content.replace(/export default function\s+\w+\s*\(/, `export default function ${compName}(`);
|
|
711
|
+
await fs.writeFile(pageFile, content, 'utf8');
|
|
712
|
+
console.log(` - Updated component name to ${compName}`);
|
|
713
|
+
|
|
714
|
+
// Add route entry
|
|
715
|
+
const newRoute = {
|
|
716
|
+
"name": p.displayName.split(/\s+/).map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(' '),
|
|
717
|
+
"path": `/${p.slug}`,
|
|
641
718
|
"title": `${rootDisplayName} - ${p.displayName}`,
|
|
642
719
|
"description": "",
|
|
643
720
|
"keywords": ""
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
console.log(` -
|
|
721
|
+
};
|
|
722
|
+
routesJson.routes.push(newRoute);
|
|
723
|
+
console.log(` - Added route /${p.slug}`);
|
|
724
|
+
} catch (e) {
|
|
725
|
+
console.error(`❌ Failed to create custom page ${p.slug}:`, e?.message || e);
|
|
726
|
+
process.exit(1);
|
|
647
727
|
}
|
|
648
728
|
}
|
|
649
729
|
}
|
|
650
730
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
731
|
+
// Delete unwanted template pages
|
|
732
|
+
// The Admin section (an object with nested routes for metadata pages) is in routesJson.routes
|
|
733
|
+
// but doesn't have folders in the (pages) directory, so it's never encountered by fs.readdir().
|
|
734
|
+
// We can safely delete page folders without worrying about removing the Admin section.
|
|
735
|
+
try {
|
|
736
|
+
const existingFolders = await fs.readdir(pagesDir);
|
|
737
|
+
const foldersToDelete = [];
|
|
738
|
+
|
|
739
|
+
for (const folderName of existingFolders) {
|
|
740
|
+
if (!wantedSlugs.has(folderName)) {
|
|
741
|
+
const folderTemplate = findTemplateForSlug(manifest, folderName);
|
|
742
|
+
if (folderTemplate) {
|
|
743
|
+
foldersToDelete.push(folderName);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Delete unwanted folders and their routes
|
|
749
|
+
for (const folderName of foldersToDelete) {
|
|
750
|
+
try {
|
|
751
|
+
const folderPath = path.join(pagesDir, folderName);
|
|
752
|
+
await fs.rm(folderPath, { recursive: true });
|
|
753
|
+
console.log(`Deleted template page ${folderName}`);
|
|
754
|
+
|
|
755
|
+
// Remove the corresponding route from routes.json
|
|
756
|
+
routesJson.routes = routesJson.routes.filter(r => r.path !== `/${folderName}`);
|
|
757
|
+
} catch (e) {
|
|
758
|
+
console.warn(`⚠️ Failed to delete ${folderName}:`, e?.message || e);
|
|
759
|
+
}
|
|
655
760
|
}
|
|
761
|
+
} catch (e) {
|
|
762
|
+
// readdir might fail if pages dir doesn't exist, but that's OK
|
|
763
|
+
console.warn(`⚠️ Could not read pages directory for cleanup:`, e?.message || e);
|
|
656
764
|
}
|
|
657
765
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
766
|
+
// Write final routes.json
|
|
767
|
+
try {
|
|
768
|
+
await fs.writeFile(siteRoutesFile, JSON.stringify(routesJson, null, '\t'), 'utf8');
|
|
769
|
+
console.log('✅ routes.json updated.');
|
|
770
|
+
} catch (e) {
|
|
771
|
+
console.error('❌ Failed to write routes.json:', e?.message || e);
|
|
772
|
+
process.exit(1);
|
|
665
773
|
}
|
|
666
774
|
} else {
|
|
667
|
-
console.log('Skipping page
|
|
775
|
+
console.log('Skipping page selection.');
|
|
668
776
|
}
|
|
669
777
|
}
|
|
670
778
|
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
"aliases": ["blog", "blog-posts", "news", "updates", "articles"],
|
|
11
11
|
"src": "../../pixelated-template/src/app/(pages)/blog"
|
|
12
12
|
},
|
|
13
|
+
{
|
|
14
|
+
"name": "Blog Calendar",
|
|
15
|
+
"aliases": ["blogcalendar", "blog-calendar", "calendar", "event-calendar", "events"],
|
|
16
|
+
"src": "../../pixelated-template/src/app/(pages)/blogcalendar"
|
|
17
|
+
},
|
|
13
18
|
{
|
|
14
19
|
"name": "Contact",
|
|
15
20
|
"aliases": ["contact", "contact-us", "contact-us-page", "contactus", "support", "get-in-touch", "reach-out", "get-in-touch"],
|
|
@@ -22,10 +27,40 @@
|
|
|
22
27
|
"src": "../../pixelated-template/src/app/(pages)/faqs",
|
|
23
28
|
"associated_files": ["src/app/data/faqs.json"]
|
|
24
29
|
},
|
|
30
|
+
{
|
|
31
|
+
"name": "Global Error",
|
|
32
|
+
"aliases": ["global-error", "globalerror", "error-boundary"],
|
|
33
|
+
"action": "ignore"
|
|
34
|
+
},
|
|
25
35
|
{
|
|
26
36
|
"name": "Humans.txt",
|
|
27
37
|
"aliases": ["humans", "humans-txt", "humans.txt", "humansfile", "humansfile.txt", "humanstext"],
|
|
28
|
-
"
|
|
38
|
+
"action": "ignore"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "Loading",
|
|
42
|
+
"aliases": ["loading", "skeleton", "loader"],
|
|
43
|
+
"action": "ignore"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"name": "Manifest",
|
|
47
|
+
"aliases": ["manifest", "manifest.json", "manifest-json", "webmanifest"],
|
|
48
|
+
"action": "ignore"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"name": "Not Found",
|
|
52
|
+
"aliases": ["not-found", "notfound", "404", "error-404"],
|
|
53
|
+
"action": "ignore"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "Partners",
|
|
57
|
+
"aliases": ["partners", "partner", "affiliates", "integration-partners", "integrations", "collaborators"],
|
|
58
|
+
"src": "../../pixelated-template/src/app/(pages)/partners"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"name": "Podcast",
|
|
62
|
+
"aliases": ["podcast", "podcasts", "audio", "episodes", "show"],
|
|
63
|
+
"src": "../../pixelated-template/src/app/(pages)/podcast"
|
|
29
64
|
},
|
|
30
65
|
{
|
|
31
66
|
"name": "Projects",
|
|
@@ -33,11 +68,26 @@
|
|
|
33
68
|
"our-projects", "our-project", "case-studies", "examples", "showcase", "samples"],
|
|
34
69
|
"src": "../../pixelated-template/src/app/(pages)/projects"
|
|
35
70
|
},
|
|
71
|
+
{
|
|
72
|
+
"name": "Robots",
|
|
73
|
+
"aliases": ["robots", "robots.txt", "robots-txt"],
|
|
74
|
+
"action": "ignore"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "Security.txt",
|
|
78
|
+
"aliases": ["security", "security.txt", "securitytxt", "security-txt", "well-known", "securityfile", "securityfile.txt", "wellknown"],
|
|
79
|
+
"action": "ignore"
|
|
80
|
+
},
|
|
36
81
|
{
|
|
37
82
|
"name": "Services",
|
|
38
83
|
"aliases": ["services", "service", "our-services", "services-page", "offerings", "solutions", "products"],
|
|
39
84
|
"src": "../../pixelated-template/src/app/(pages)/services"
|
|
40
85
|
},
|
|
86
|
+
{
|
|
87
|
+
"name": "Sitemap",
|
|
88
|
+
"aliases": ["sitemap", "sitemap.xml", "sitemap-xml"],
|
|
89
|
+
"action": "ignore"
|
|
90
|
+
},
|
|
41
91
|
{
|
|
42
92
|
"name": "Style Guide",
|
|
43
93
|
"aliases": ["styleguide", "style-guide", "design-system", "ui-kit", "pattern-library"],
|
|
@@ -1152,6 +1152,146 @@ const noDuplicateExportNamesRule = {
|
|
|
1152
1152
|
}
|
|
1153
1153
|
};
|
|
1154
1154
|
|
|
1155
|
+
/**
|
|
1156
|
+
* no-hardcoded-config-keys Rule
|
|
1157
|
+
*
|
|
1158
|
+
* Prevents hardcoding of Pixelated-specific configuration keys that should come from:
|
|
1159
|
+
* - Config provider (usePixelatedConfig)
|
|
1160
|
+
* - Environment variables
|
|
1161
|
+
* - Function parameters/props
|
|
1162
|
+
*
|
|
1163
|
+
* Only flags keys that are Pixelated-specific to avoid false positives.
|
|
1164
|
+
* Severity: ERROR for secrets, WARNING for other Pixelated config keys.
|
|
1165
|
+
*/
|
|
1166
|
+
const noHardcodedConfigKeysRule = {
|
|
1167
|
+
meta: {
|
|
1168
|
+
type: 'problem',
|
|
1169
|
+
docs: {
|
|
1170
|
+
description: 'Prevent hardcoded Pixelated configuration keys that should come from config provider',
|
|
1171
|
+
category: 'Security',
|
|
1172
|
+
recommended: true,
|
|
1173
|
+
},
|
|
1174
|
+
fixable: false,
|
|
1175
|
+
schema: [],
|
|
1176
|
+
messages: {
|
|
1177
|
+
secretConfigKey: 'Hardcoded SECRET configuration key "{{keyName}}" ({{serviceName}}) detected. Must use config provider (usePixelatedConfig) or environment variables.',
|
|
1178
|
+
publicConfigKey: 'Hardcoded Pixelated config key "{{keyName}}" ({{serviceName}}) detected. Should use config provider (usePixelatedConfig) or pass as parameter instead.',
|
|
1179
|
+
},
|
|
1180
|
+
},
|
|
1181
|
+
create(context) {
|
|
1182
|
+
// Pixelated-SPECIFIC configuration keys (keys that are unlikely to be false positives)
|
|
1183
|
+
// Keys that are unique/distinctive to Pixelated integrations, excluding generic names
|
|
1184
|
+
const pixelatedConfigKeys = {
|
|
1185
|
+
// Contentful (very Pixelated-specific)
|
|
1186
|
+
contentful: ['space_id', 'delivery_access_token', 'management_access_token', 'preview_access_token', 'proxyURL', 'base_url', 'environment'],
|
|
1187
|
+
// eBay (very distinctive)
|
|
1188
|
+
ebay: ['appId', 'appDevId', 'appCertId', 'sbxAppId', 'sbxAppDevId', 'sbxAppCertId', 'globalId', 'baseTokenURL', 'baseSearchURL', 'baseAnalyticsURL', 'qsSearchURL', 'baseItemURL', 'qsItemURL'],
|
|
1189
|
+
// AWS (distinctive with service prefix or secretive names)
|
|
1190
|
+
aws: ['access_key_id', 'secret_access_key', 'session_token'],
|
|
1191
|
+
// Cloudinary
|
|
1192
|
+
cloudinary: ['product_env', 'api_key', 'api_secret'],
|
|
1193
|
+
// Flickr
|
|
1194
|
+
flickr: ['user_id'],
|
|
1195
|
+
// GitHub
|
|
1196
|
+
github: ['token', 'apiBaseUrl', 'defaultOwner'],
|
|
1197
|
+
// Google services
|
|
1198
|
+
google: ['client_id', 'client_secret', 'api_key', 'refresh_token'],
|
|
1199
|
+
// Google Analytics
|
|
1200
|
+
googleAnalytics: [], // Skip 'id' and 'adId' as too generic
|
|
1201
|
+
// Google Maps
|
|
1202
|
+
googleMaps: ['apiKey'],
|
|
1203
|
+
// HubSpot (keep only distinctive ones)
|
|
1204
|
+
hubspot: ['portalId', 'formId', 'trackingCode'],
|
|
1205
|
+
// Instagram
|
|
1206
|
+
instagram: ['accessToken', 'userId'],
|
|
1207
|
+
// NextAuth
|
|
1208
|
+
nextAuth: ['secret'],
|
|
1209
|
+
// PayPal
|
|
1210
|
+
paypal: ['sandboxPayPalApiKey', 'sandboxPayPalSecret', 'payPalApiKey', 'payPalSecret'],
|
|
1211
|
+
// WordPress
|
|
1212
|
+
wordpress: ['baseURL', 'site'],
|
|
1213
|
+
// Puppeteer
|
|
1214
|
+
puppeteer: ['executable_path', 'cache_dir'],
|
|
1215
|
+
// Global
|
|
1216
|
+
global: ['PIXELATED_CONFIG_KEY']
|
|
1217
|
+
};
|
|
1218
|
+
|
|
1219
|
+
// Secret keys that should NEVER be hardcoded (ERROR severity)
|
|
1220
|
+
const secretKeys = new Set([
|
|
1221
|
+
// AWS
|
|
1222
|
+
'access_key_id', 'secret_access_key', 'session_token',
|
|
1223
|
+
// Cloudinary
|
|
1224
|
+
'api_key', 'api_secret',
|
|
1225
|
+
// Contentful
|
|
1226
|
+
'management_access_token', 'preview_access_token',
|
|
1227
|
+
// eBay
|
|
1228
|
+
'sbxAppId',
|
|
1229
|
+
// GitHub
|
|
1230
|
+
'token',
|
|
1231
|
+
// Instagram
|
|
1232
|
+
'accessToken',
|
|
1233
|
+
// PayPal
|
|
1234
|
+
'sandboxPayPalApiKey', 'sandboxPayPalSecret', 'payPalApiKey', 'payPalSecret',
|
|
1235
|
+
// NextAuth
|
|
1236
|
+
'secret',
|
|
1237
|
+
// Global
|
|
1238
|
+
'PIXELATED_CONFIG_KEY'
|
|
1239
|
+
]);
|
|
1240
|
+
|
|
1241
|
+
// Build set of all known Pixelated config keys
|
|
1242
|
+
const allConfigKeys = new Set();
|
|
1243
|
+
Object.values(pixelatedConfigKeys).forEach(keys => {
|
|
1244
|
+
keys.forEach(key => allConfigKeys.add(key));
|
|
1245
|
+
});
|
|
1246
|
+
|
|
1247
|
+
function findServiceForKey(keyName) {
|
|
1248
|
+
for (const [serviceName, keys] of Object.entries(pixelatedConfigKeys)) {
|
|
1249
|
+
if (keys.includes(keyName)) {
|
|
1250
|
+
return serviceName;
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
return 'unknown';
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
function isConfigKey(keyName) {
|
|
1257
|
+
return allConfigKeys.has(keyName);
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
function isSecretKey(keyName) {
|
|
1261
|
+
return secretKeys.has(keyName);
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
return {
|
|
1265
|
+
ObjectExpression(node) {
|
|
1266
|
+
node.properties.forEach(prop => {
|
|
1267
|
+
// Check properties that look like { space_id: "value" } or { api_key: "..." }
|
|
1268
|
+
if (prop.type === 'Property' && prop.key) {
|
|
1269
|
+
const keyName = prop.key.name || prop.key.value;
|
|
1270
|
+
|
|
1271
|
+
// Check if this is a known Pixelated config key
|
|
1272
|
+
if (isConfigKey(keyName)) {
|
|
1273
|
+
// Check if value is a string literal (hardcoded)
|
|
1274
|
+
if (prop.value.type === 'Literal' && typeof prop.value.value === 'string') {
|
|
1275
|
+
const stringValue = prop.value.value;
|
|
1276
|
+
if (stringValue && stringValue.length > 0) {
|
|
1277
|
+
const serviceName = findServiceForKey(keyName);
|
|
1278
|
+
const messageId = isSecretKey(keyName) ? 'secretConfigKey' : 'publicConfigKey';
|
|
1279
|
+
|
|
1280
|
+
context.report({
|
|
1281
|
+
node: prop,
|
|
1282
|
+
messageId,
|
|
1283
|
+
data: { keyName, serviceName },
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
});
|
|
1290
|
+
}
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
};
|
|
1294
|
+
|
|
1155
1295
|
export default {
|
|
1156
1296
|
rules: {
|
|
1157
1297
|
'prop-types-inferprops': propTypesInferPropsRule,
|
|
@@ -1169,6 +1309,7 @@ export default {
|
|
|
1169
1309
|
'file-name-kebab-case': fileNameKebabCaseRule,
|
|
1170
1310
|
'no-duplicate-export-names': noDuplicateExportNamesRule,
|
|
1171
1311
|
'class-name-kebab-case': classNameKebabCaseRule,
|
|
1312
|
+
'no-hardcoded-config-keys': noHardcodedConfigKeysRule,
|
|
1172
1313
|
},
|
|
1173
1314
|
configs: {
|
|
1174
1315
|
recommended: {
|
|
@@ -1188,6 +1329,7 @@ export default {
|
|
|
1188
1329
|
'pixelated/required-proptypes-jsdoc': 'error',
|
|
1189
1330
|
'pixelated/no-duplicate-export-names': 'error',
|
|
1190
1331
|
'pixelated/class-name-kebab-case': 'error',
|
|
1332
|
+
'pixelated/no-hardcoded-config-keys': 'error',
|
|
1191
1333
|
},
|
|
1192
1334
|
},
|
|
1193
1335
|
},
|
package/dist/scripts/release.sh
CHANGED
|
@@ -164,21 +164,15 @@ fi
|
|
|
164
164
|
echo ""
|
|
165
165
|
echo "📦 Step $((STEP_COUNT++)): Updating dependencies (all sections)..."
|
|
166
166
|
echo "================================================="
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
echo "✅ No $scope updates needed"
|
|
177
|
-
fi
|
|
178
|
-
done
|
|
179
|
-
# report peer deps separately
|
|
180
|
-
peers=$(npm outdated --parseable --long --peer | awk -F: '{print $4}')
|
|
181
|
-
printf "peer deps (manual): %s\n" "$peers"
|
|
167
|
+
if [ -f "src/scripts/update.sh" ]; then
|
|
168
|
+
bash src/scripts/update.sh
|
|
169
|
+
elif [ -f "scripts/update.sh" ]; then
|
|
170
|
+
bash scripts/update.sh
|
|
171
|
+
elif command -v npm &> /dev/null; then
|
|
172
|
+
npm run update 2>/dev/null || echo "⚠️ No update script found; skipping dependency update"
|
|
173
|
+
else
|
|
174
|
+
echo "⚠️ Could not find update.sh; skipping dependency update"
|
|
175
|
+
fi
|
|
182
176
|
|
|
183
177
|
|
|
184
178
|
|
|
@@ -198,7 +192,20 @@ npm run lint
|
|
|
198
192
|
|
|
199
193
|
|
|
200
194
|
echo ""
|
|
201
|
-
echo "
|
|
195
|
+
echo "� Step $((STEP_COUNT++)): Running code coverage check..."
|
|
196
|
+
echo "================================================="
|
|
197
|
+
# Check if test directory exists before running coverage
|
|
198
|
+
if [ -d "src/tests" ] || [ -d "src/test" ]; then
|
|
199
|
+
npm run test:coverage || exit 1
|
|
200
|
+
echo "✅ Coverage check passed."
|
|
201
|
+
else
|
|
202
|
+
echo "⚠️ No test directory found; skipping coverage check"
|
|
203
|
+
fi
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
echo ""
|
|
208
|
+
echo "�🔨 Step $((STEP_COUNT++)): Encrypting configuration..."
|
|
202
209
|
echo "================================================="
|
|
203
210
|
if grep -q "\"config:encrypt\":" package.json; then
|
|
204
211
|
echo "🔒 Encrypting configuration..."
|