diff --git a/packages/polymech/src/app/config.ts b/packages/polymech/src/app/config.ts index 91a1545..a8ba02f 100644 --- a/packages/polymech/src/app/config.ts +++ b/packages/polymech/src/app/config.ts @@ -28,7 +28,7 @@ export const HOWTO_MIGRATION = () => path.resolve(resolve(config.products.howto_ // Products export const PRODUCT_ROOT = () => path.resolve(resolve(config.products.root)) -export const PRODUCT_BRANCHES = read(path.join(PRODUCT_ROOT(), 'config/machines.json'), 'json') +export const PRODUCT_BRANCHES = read('library.json', 'json') export const PRODUCT_GLOB = config.products.glob // Product compiler diff --git a/packages/polymech/src/model/component.ts b/packages/polymech/src/model/component.ts index a9d13b0..d156efc 100644 --- a/packages/polymech/src/model/component.ts +++ b/packages/polymech/src/model/component.ts @@ -3,21 +3,6 @@ import { findUp } from 'find-up' import { sync as read } from '@polymech/fs/read' import { sync as exists } from '@polymech/fs/exists' -import { filesEx, forward_slash, resolveConfig } from '@polymech/commons' -import { ICADNodeSchema, IComponentConfig } from '@polymech/commons/component' - -import { DataEntry } from "astro:content" -import type { Loader, LoaderContext } from 'astro/loaders' - -import { - CAD_MAIN_MATCH, PRODUCT_BRANCHES, - CAD_EXTENSIONS, CAD_MODEL_EXT, PRODUCT_DIR, PRODUCT_GLOB, - PRODUCT_ROOT, CAD_EXPORT_CONFIGURATIONS, - CAD_DEFAULT_CONFIGURATION, - CAD_URL, - parseBoolean -} from 'config/config.js' - import { env } from '@/base/index.js' import { gallery } from '@polymech/astro-base/base/media.js'; @@ -27,6 +12,44 @@ import { PFilterValid } from '@polymech/commons/filter' import { IAssemblyData } from '@polymech/cad' import { logger as log } from '@/base/index.js' +import { filesEx, forward_slash, resolveConfig, template } from '@polymech/commons' +import { ICADNodeSchema, IComponentConfig } from '@polymech/commons/component' + +import { DataEntry } from "astro:content" +import type { Loader, LoaderContext } from 'astro/loaders' + +import { PolymechInstance } from '../registry.js'; + +// Access config safely +const c = () => { + const cfg = PolymechInstance.getConfig(); + if (!cfg) throw new Error("Polymech configuration missing. Ensure setConfig is called."); + return cfg; +} + +// Config Accessors +const PRODUCT_ROOT = () => c().products?.root || ''; +const PRODUCT_GLOB = () => c().products?.glob || ''; +const PRODUCT_DIR = (rel: string) => path.join(PRODUCT_ROOT(), rel); + +const CAD_MAIN_MATCH = (product: string) => template(c().cad?.main_match || '', { product }); +const CAD_URL = (file: string, variables: Record) => + template(c().assets?.cad_url || '', { file, ...variables }); + +const CAD_EXTENSIONS = () => c().cad?.extensions || []; +const CAD_MODEL_EXT = ".tree.json"; +const CAD_EXPORT_CONFIGURATIONS = () => c().cad?.export_configurations; +const CAD_DEFAULT_CONFIGURATION = () => c().cad?.default_configuration || ''; + +// Product Branches +const PRODUCT_BRANCHES = () => { + const enabled = c().products?.enabled; + const resolvedPath = enabled ? path.resolve(enabled) : null; + return (resolvedPath && exists(resolvedPath)) ? read(resolvedPath, 'json') : null; +} + +const parseBoolean = (value: any) => value === '1' || value === true || String(value).toLowerCase() === 'true'; + interface ILoaderContextEx extends LoaderContext { } interface IComponentConfigEx extends IComponentConfig { @@ -39,21 +62,20 @@ interface IComponentConfigEx extends IComponentConfig { export interface IStoreItem extends DataEntry { data: IComponentConfigEx } - const filterBranch = (items: { rel: string, config, path }[], branch: string = 'site-prod') => { - if (!PRODUCT_BRANCHES) { + const branches = PRODUCT_BRANCHES(); + if (!branches) { return items } - const branchItems = PRODUCT_BRANCHES[branch] + const branchItems = branches[branch] if (!branchItems) { return [] } return items.filter((item) => branchItems.includes(item.rel)) } -export const items = (branch: string) => filterBranch(get(`${PRODUCT_ROOT()}/${PRODUCT_GLOB}`, PRODUCT_ROOT(), PFilterValid.library_component), branch) - +export const items = (branch: string) => filterBranch(get(`${PRODUCT_ROOT()}/${PRODUCT_GLOB()}`, PRODUCT_ROOT(), PFilterValid.library_component), branch) const onComponent = async (item: IStoreItem, ctx: ILoaderContextEx) => { /* @@ -89,7 +111,7 @@ const cad = async (item: IStoreItem, ctx: ILoaderContextEx): Promise result[ext] = decodeURIComponent(forward_slash(CAD_URL(file.replace('.SLDASM', ext), data as Record)))) + CAD_EXTENSIONS().forEach(ext => result[ext] = decodeURIComponent(forward_slash(CAD_URL(file.replace('.SLDASM', ext), data as Record)))) result.model = path.join(root, file.replace('.SLDASM', CAD_MODEL_EXT)) return result }) @@ -99,7 +121,7 @@ const cad = async (item: IStoreItem, ctx: ILoaderContextEx): Promise assembly.model && exists(assembly.model)) const components = cadMeta.map((assembly) => { const modelPath = assembly.model as string @@ -108,7 +130,7 @@ const cad = async (item: IStoreItem, ctx: ILoaderContextEx): Promise { - return c !== CAD_DEFAULT_CONFIGURATION && + return c !== CAD_DEFAULT_CONFIGURATION() && parseBoolean(model.Configurations[c].Hide || '') }) if (!configurations.length || diff --git a/packages/polymech/src/registry.ts b/packages/polymech/src/registry.ts index 747b4b6..3e4fc64 100644 --- a/packages/polymech/src/registry.ts +++ b/packages/polymech/src/registry.ts @@ -1,151 +1,75 @@ interface PolymechConfig { - productCategory?: string; - languages?: string[]; - LANGUAGES_PROD?: string[]; - products?: string[]; - features?: string[]; - apiEndpoints?: Record; - - // i18n constants - I18N_CACHE?: boolean; - I18N_SOURCE_LANGUAGE?: string; - I18N_STORE?: (root: string, lang: string) => string; - I18N_ASSET_PATH?: string; - - // Products - PRODUCT_ROOT?: () => string; - PRODUCT_BRANCHES?: unknown; - PRODUCT_GLOB?: string; - PRODUCT_CONFIG?: (product: string) => string; - PRODUCT_DIR?: (product: string) => string; - PRODUCT_HUGO_TEMPLATE?: string; - PRODUCTS_TARGET_SRC?: string; - PRODUCTS_TARGET?: (lang: string) => string; - ENABLED_PRODUCTS?: string; - PRODUCT_SPECS?: (rel: string) => string; - - // OSRL - Language - IS_DEV?: boolean; - OSRL_ENV?: string; - OSRL_ENV_DEV?: string; - OSRL_ENVIRONMENT?: string; - OSRL_MODULE_NAME?: string; - OSRL_PRODUCT_PROFILE?: string; - OSRL_LANG_FLAVOR?: string; - - // Tasks - TASK_CONFIG_LOG_DIRECTORY?: string; - TASK_COMPILE_CONTENT?: boolean; - TASK_COMPILE_CONTENT_CACHE?: boolean; - TASK_LOG_DIRECTORY?: string; - - // Task - Retail Config - REGISTER_PRODUCT_TASKS?: boolean; - RETAIL_PRODUCT_BRANCH?: string; - RETAIL_COMPILE_CACHE?: boolean; - RETAIL_MEDIA_CACHE?: boolean; - RETAIL_LOG_LEVEL_I18N_PRODUCT_ASSETS?: string; - - // Product media - ConvertProductMedia?: boolean; - TranslateProductAssets?: boolean; - PopulateProductDefaults?: boolean; - - // CAD - CAD_MAIN_MATCH?: (product: string) => string; - CAD_CAM_MAIN_MATCH?: (product: string) => string; - CAD_CACHE?: boolean; - CAD_EXPORT_CONFIGURATIONS?: boolean; - CAD_EXPORT_SUB_COMPONENTS?: boolean; - CAD_MODEL_FILE_PATH?: (source: string, configuration?: string) => string; - CAD_DEFAULT_CONFIGURATION?: string; - CAD_RENDERER?: string; - CAD_RENDERER_VIEW?: string; - CAD_RENDERER_QUALITY?: number; - CAD_EXTENSIONS?: string[]; - CAD_MODEL_EXT?: string; - CAD_URL?: (file: string, variables: Record) => string; - ASSET_URL?: (file: string, variables: Record) => string; - ITEM_ASSET_URL?: (variables: Record) => string; - - // Rendering - SHOW_DESCRIPTION?: boolean; - SHOW_LICENSE?: boolean; - SHOW_RENDERINGS?: boolean; - SHOW_TABS?: boolean; - SHOW_GALLERY?: boolean; - SHOW_FILES?: boolean; - SHOW_SPECS?: boolean; - SHOW_CHECKOUT?: boolean; - SHOW_3D_PREVIEW?: boolean; - SHOW_RESOURCES?: boolean; - SHOW_DEBUG?: boolean; - SHOW_SAMPLES?: boolean; - SHOW_README?: boolean; - - // RSS - RSS_CONFIG?: { + // Config groups matching app-config.json + site?: any; + core?: { + logging_namespace?: string; + translate_content?: boolean; + languages?: string[]; + languages_prod?: string[]; + rtl_languages?: string[]; + osr_root?: string; + }; + products?: { + root?: string; + howto_migration?: string; + glob?: string; + enabled?: string; + }; + retail?: { + library_branch?: string; + projects_branch?: string; + }; + rss?: { title: string; description: string; }; - - // Defaults - DEFAULT_IMAGE_URL?: string; - default_image?: () => { - alt: string; - src: string; - thumb: string; + osrl?: { + env?: string; + env_dev?: string; + module_name?: string; + lang_flavor?: string; + product_profile?: string; }; - - // Optimization - Images - O_IMAGE?: { - sizes_thumbs: unknown; - sizes_large: unknown; - sizes: unknown; + cad?: { + cache?: boolean; + export_configurations?: boolean; + export_sub_components?: boolean; + renderer?: string; + renderer_view?: string; + renderer_quality?: number; + extensions?: string[]; + model_ext?: string; + default_configuration?: string; + main_match?: string; + cam_main_match?: string; }; - IMAGE_SETTINGS?: { - GALLERY: { - SHOW_TITLE: boolean; - SHOW_DESCRIPTION: boolean; - SIZES_THUMB: unknown; - SIZES_LARGE: unknown; - SIZES_REGULAR: unknown; - }; - LIGHTBOX: { - SHOW_TITLE: boolean; - SHOW_DESCRIPTION: boolean; - SIZES_THUMB: unknown; - SIZES_LARGE: unknown; - SIZES_REGULAR: unknown; - }; + assets?: { + cad_url?: string; + url?: string; + item_url_r?: string; + item_url?: string; }; - - // Collection filters - COLLECTION_FILTERS?: { - // Enable/disable specific default filters - ENABLE_VALID_FRONTMATTER_CHECK?: boolean; - ENABLE_FOLDER_FILTER?: boolean; - ENABLE_DRAFT_FILTER?: boolean; - ENABLE_TITLE_FILTER?: boolean; - ENABLE_BODY_FILTER?: boolean; - ENABLE_DESCRIPTION_FILTER?: boolean; - ENABLE_IMAGE_FILTER?: boolean; - ENABLE_AUTHOR_FILTER?: boolean; - ENABLE_PUBDATE_FILTER?: boolean; - ENABLE_TAGS_FILTER?: boolean; - ENABLE_FILE_EXTENSION_FILTER?: boolean; - - // Additional filter settings - REQUIRED_FIELDS?: string[]; - REQUIRED_TAGS?: string[]; - EXCLUDE_TAGS?: string[]; - - // Date filtering - FILTER_FUTURE_POSTS?: boolean; - FILTER_OLD_POSTS?: boolean; - OLD_POST_CUTOFF_DAYS?: number; + features?: Record; + defaults?: { + image_url?: string; + license?: string; + contact?: string; }; - + optimization?: { + image_settings?: any; + presets?: any; + }; + i18n?: { + store?: string; + cache?: boolean; + asset_path?: string; + }; + + // Legacy/Flat fields (kept for compatibility or non-config settings) + productCategory?: string; + apiEndpoints?: Record; + COLLECTION_FILTERS?: any; + callbacks?: { onConfigUpdate?: (config: PolymechConfig) => void; onRouteRender?: (route: string, params: any) => void; @@ -184,7 +108,7 @@ class PolymechRegistry { const newConfig = { ...this.config, ...config }; this.config = newConfig; G.__MYPAGES_CONFIG__ = newConfig; - + // Trigger callbacks this.config.callbacks?.onConfigUpdate?.(this.config); this.emit('configUpdate', { newConfig: this.config }); @@ -211,11 +135,17 @@ class PolymechRegistry { } // Convenience getters + // Convenience getters (Mapping new config structure to old accessors if needed, or just helpers) get productCategory() { return this.config.productCategory || 'Unknown'; } - get languages() { return this.config.languages || ['en']; } - get LANGUAGES_PROD() { return this.config.LANGUAGES_PROD || ['en']; } - get products() { return this.config.products || []; } - get features() { return this.config.features || []; } + get languages() { return this.config.core?.languages || ['en']; } + get LANGUAGES_PROD() { return this.config.core?.languages_prod || ['en']; } + // products was string[]? in old config it was string[], now it's an object config.products + // Old: get products() { return this.config.products || []; } + // We can leave 'products' as the category list if it exists in 'site' or somewhere? + // Actually config.products is now { root, glob... }. + // If the old getter meant 'list of product categories', that's not in the new config yet? + // Let's assume accessing raw config is preferred now. + get apiEndpoints() { return this.config.apiEndpoints || {}; } get COLLECTION_FILTERS() { return this.config.COLLECTION_FILTERS || {}; } }