This commit is contained in:
babayaga 2025-12-27 18:44:50 +01:00
parent 94eddc3cf9
commit 5c81694024
3 changed files with 121 additions and 169 deletions

View File

@ -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

View File

@ -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<string, string>) =>
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<ICADNodeSch
file,
name: path.basename(file)
}
CAD_EXTENSIONS.forEach(ext => result[ext] = decodeURIComponent(forward_slash(CAD_URL(file.replace('.SLDASM', ext), data as Record<string, string>))))
CAD_EXTENSIONS().forEach(ext => result[ext] = decodeURIComponent(forward_slash(CAD_URL(file.replace('.SLDASM', ext), data as Record<string, string>))))
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<ICADNodeSch
item.data.cad = cadMeta
item.data.preview3d = cadMeta[0].html
if (CAD_EXPORT_CONFIGURATIONS) {
if (CAD_EXPORT_CONFIGURATIONS()) {
const assemblies = cadMeta.filter((assembly) => 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<ICADNodeSch
return
}
const configurations = Object.keys(model.Configurations).filter((c) => {
return c !== CAD_DEFAULT_CONFIGURATION &&
return c !== CAD_DEFAULT_CONFIGURATION() &&
parseBoolean(model.Configurations[c].Hide || '')
})
if (!configurations.length ||

View File

@ -1,150 +1,74 @@
interface PolymechConfig {
productCategory?: string;
languages?: string[];
LANGUAGES_PROD?: string[];
products?: string[];
features?: string[];
apiEndpoints?: Record<string, string>;
// 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, string>) => string;
ASSET_URL?: (file: string, variables: Record<string, string>) => string;
ITEM_ASSET_URL?: (variables: Record<string, string>) => 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;
};
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;
};
assets?: {
cad_url?: string;
url?: string;
item_url_r?: string;
item_url?: string;
};
features?: Record<string, boolean>;
defaults?: {
image_url?: string;
license?: string;
contact?: string;
};
optimization?: {
image_settings?: any;
presets?: any;
};
i18n?: {
store?: string;
cache?: boolean;
asset_path?: string;
};
// Optimization - Images
O_IMAGE?: {
sizes_thumbs: unknown;
sizes_large: unknown;
sizes: unknown;
};
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;
};
};
// 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;
};
// Legacy/Flat fields (kept for compatibility or non-config settings)
productCategory?: string;
apiEndpoints?: Record<string, string>;
COLLECTION_FILTERS?: any;
callbacks?: {
onConfigUpdate?: (config: PolymechConfig) => void;
@ -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 || {}; }
}