refactor models

This commit is contained in:
lovebird 2025-03-31 20:47:25 +02:00
parent 8d4e880a3a
commit b8d44fd215
19 changed files with 367 additions and 210 deletions

View File

@ -23,7 +23,7 @@
"format": "unix-time"
}
],
"default": "2025-03-31T18:28:08.800Z"
"default": "2025-03-31T18:45:06.624Z"
},
"description": {
"type": "string",

View File

@ -1,5 +1,5 @@
export default new Map([
["src/content/infopages/contact.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Finfopages%2Fcontact.mdx&astroContentModuleFlag=true")],
["src/content/resources/workflow.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fresources%2Fworkflow.mdx&astroContentModuleFlag=true")]]);
["src/content/resources/workflow.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fresources%2Fworkflow.mdx&astroContentModuleFlag=true")],
["src/content/infopages/contact.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Finfopages%2Fcontact.mdx&astroContentModuleFlag=true")]]);

File diff suppressed because one or more lines are too long

View File

@ -552,7 +552,7 @@
},
"https://github.com/%5Bfiltered%5D": {
"isValid": false,
"timestamp": 1743445732144
"timestamp": 1743446744432
},
"https://github.com/darigovresearch": {
"isValid": true,
@ -670,7 +670,7 @@
},
"https://scholarworks.uni.edu/cgi/viewcontent.cgi?article=3680%5C&context=grp": {
"isValid": false,
"timestamp": 1743445690980
"timestamp": 1743446708264
},
"https://pmc.ncbi.nlm.nih.gov/articles/PMC10489002/": {
"isValid": true,
@ -754,7 +754,7 @@
},
"https://journals.plos.org/plosone/article?id=10.1371%252Fjournal.pone.0288696": {
"isValid": false,
"timestamp": 1743445696843
"timestamp": 1743446719043
},
"https://www.youtube.com/watch?v=_a7usMe_K38": {
"isValid": true,
@ -841,7 +841,7 @@
},
"https://www.toraytac.com/media/c3feb206-1398-4e0e-bca6-df7780f11745/tcCurg/TenCate%2520Advanced%2520Composites/Documents/Technical%2520papers/TenCate_chopped_fiber_thermoplastics_compression_molding_technical_paper.pdf": {
"isValid": false,
"timestamp": 1743445691831
"timestamp": 1743446708939
},
"https://youtu.be/qtZv96cifIU": {
"isValid": true,
@ -1397,7 +1397,7 @@
},
"https://www.amazon.it/s?k=cnc+CNC%20Router": {
"isValid": true,
"timestamp": 1743445692320,
"timestamp": 1743446709933,
"meta": {
"title": "Ci dispiace",
"image": "https://images-eu.ssl-images-amazon.com/images/G/29/x-locale/communities/people/logo.gif",
@ -1897,7 +1897,7 @@
},
"https://digitalcommons.calpoly.edu/cgi/viewcontent.cgi?article=1288%5C&context=eesp": {
"isValid": false,
"timestamp": 1743445693492
"timestamp": 1743446711171
},
"*": {
"isValid": false,
@ -1905,7 +1905,7 @@
},
"https://partners.noplasticsunday.com/NPSblog/?bmode=view%5C&idx=11164797": {
"isValid": true,
"timestamp": 1743445694627,
"timestamp": 1743446715113,
"meta": {
"title": "노플라스틱선데이",
"description": "지속가능한 제조 서비스 NPS Partners",
@ -2062,7 +2062,7 @@
},
"https://www.youtube.com/watch?v=Eq9IbetsLB4%5C&t=2s": {
"isValid": true,
"timestamp": 1743445695078,
"timestamp": 1743446716528,
"meta": {
"title": "Injection molding machine for recycling plastic",
"description": "Injection molding machine for recycling plastic (called \"Smart Injector\"). The design is low-cost and uses easy componentsIMPORTANT! The machine is still wor...",
@ -2647,7 +2647,7 @@
},
"https://www.youtube.com/watch?time_continue=163%5C&v=95aPYlXShTY%5C&feature=emb_logo": {
"isValid": true,
"timestamp": 1743445695576,
"timestamp": 1743446717894,
"meta": {
"title": "Hands-Free Door Opener: Technical Information",
"description": "Discover our available models, printing and mounting instructions, and informational sticker for our 3D-printed hands-free door opener to avoid passing on CO...",
@ -2895,7 +2895,7 @@
},
"https://crescent.education/wp-content/uploads/2019/02/MODULE-II-%25E2%2580%2593-FUNDAMENTALS-OF-EXTRUSION-MOULDING.pdf": {
"isValid": false,
"timestamp": 1743445696698
"timestamp": 1743446718866
},
"https://rjginc.com/essential-injection-molding-safety-standards-and-practices/": {
"isValid": true,
@ -2920,7 +2920,7 @@
},
"https://www.oldergeeks.com/downloads/search.php?limit=100%5C&string=Power+Software+Ltd.%5C&sort=file_name%5C&order=asc%5C&id=0%5C&page=9": {
"isValid": true,
"timestamp": 1743445697371,
"timestamp": 1743446720119,
"meta": {
"favicon": "https://www.oldergeeks.com/favicon.ico"
}
@ -3131,7 +3131,7 @@
},
"https://papers.ssrn.com/sol3/Delivery.cfm/733008ad-9620-43bf-896c-aa4a2e9931e5-MECA.pdf?abstractid=4611811%5C&mirid=1": {
"isValid": true,
"timestamp": 1743445698706,
"timestamp": 1743446723798,
"meta": {
"title": "Page Cannot be Found",
"favicon": "https://papers.ssrn.com/favicon.ico"
@ -3231,7 +3231,7 @@
},
"https://en.wikipedia.org/wiki/Jigsaw_%5C(power_tool%5C": {
"isValid": false,
"timestamp": 1743445699826
"timestamp": 1743446723984
},
"https://www.amazon.de/-/en/Stanley-10-099-Classic/dp/B001FWP58U": {
"isValid": false,
@ -3819,7 +3819,7 @@
},
"https://scibizsw.com/20_THE%2520OFFICIAL%2520RASPBERRY%2520PI%2520PROJECTS%2520BOOK%2520v3.pdf": {
"isValid": false,
"timestamp": 1743445730383
"timestamp": 1743446742609
},
"https://archive.org/stream/MagPi/Projects_Book_v3_djvu.txt": {
"isValid": true,
@ -5834,7 +5834,7 @@
},
"https://www.rainbow-pkg.com/news/youpinzhiku%25E4%25B8%25A8hot-stamping-and-cold-stamping-technology-which-one-is-more-suitable-for-your-packaging-products/": {
"isValid": false,
"timestamp": 1743445703799
"timestamp": 1743446726706
},
"https://ch-wauters.com/en/cold-foil-stamping-by-wauters/": {
"isValid": true,
@ -6091,7 +6091,7 @@
},
"https://%5Bfiltered%5D.github.io/academy/build/compression": {
"isValid": false,
"timestamp": 1743445704158
"timestamp": 1743446727151
},
"https://davehakkens.nl/community/forums/topic/v4-sheet-press-mould-development/index.html": {
"isValid": true,
@ -7218,7 +7218,7 @@
},
"https://guides.lib.virginia.edu/c.php?g=1164312%5C&p=8718414": {
"isValid": true,
"timestamp": 1743445705612,
"timestamp": 1743446729252,
"meta": {
"title": "LibGuides: COVID-19 Pandemic Children's Book Collection: Normalizing Face Masks",
"description": "LibGuides: COVID-19 Pandemic Children's Book Collection: Normalizing Face Masks",
@ -7462,7 +7462,7 @@
},
"https://forum.freecad.org/viewtopic.php?style=1%5C&t=62057": {
"isValid": true,
"timestamp": 1743445706338,
"timestamp": 1743446729884,
"meta": {
"title": "Step by step tutorial on injection mold design - FreeCAD Forum",
"image": "https://forum.freecad.org/styles/elegance/theme/images/logo.png",
@ -7664,7 +7664,7 @@
},
"https://www.youtube.com/watch?v=YzjTm3FRLVY%5C&t=5s": {
"isValid": true,
"timestamp": 1743445706630,
"timestamp": 1743446731175,
"meta": {
"title": "Recycling plastic waste on the beaches of Panama",
"description": "Precious Plastic community submission! Thanks Thomas, check him out in our forums:https://davehakkens.nl/community/members/thomasthefirst/More information: h...",
@ -7880,8 +7880,13 @@
}
},
"https://seafood.media/fis/worldnEws/worldnews.asp?monthyear=9-2024%5C&day=18%5C&id=131886%5C&l=e%5C&country=%5C&special=%5C&ndb=1%5C&df=1": {
"isValid": false,
"timestamp": 1743445729274
"isValid": true,
"timestamp": 1743446741406,
"meta": {
"title": "Seafood Media Group - Worldnews",
"image": "https://seafood.media/fis/gif/free/flags/ES.gif",
"favicon": "https://seafood.media/favicon.ico"
}
},
"https://theoceancleanup.com/oceans/": {
"isValid": true,
@ -8028,7 +8033,7 @@
},
"https://%5Bfiltered%5D.github.io/academy/build/sheetpressbuild": {
"isValid": false,
"timestamp": 1743445729461
"timestamp": 1743446741634
},
"https://www.singhalglobal.com/blog/sheets-of-hdpe-manufacturing-processes-and-various-use": {
"isValid": true,
@ -8499,7 +8504,7 @@
},
"https://www.youtube.com/watch?v=gxkcffQD3eQ%5C&t=131s": {
"isValid": true,
"timestamp": 1743445730780,
"timestamp": 1743446743571,
"meta": {
"title": "🎄⭐🎅Como hacer figuras de plástico- Figuras Navideñas de Plástico Reciclado🎄⭐🎅",
"description": "En este tutorial reciclamos tapas de botellas y las convertimos en figuras navideñas usando la dremel motosaw y un horno de pizza",
@ -9404,7 +9409,7 @@
},
"https://scholarworks.uark.edu/cgi/viewcontent.cgi?article=1066%5C&context=inquiry": {
"isValid": false,
"timestamp": 1743445733821
"timestamp": 1743446745917
},
"https://www.youtube.com/watch?v=1OZVCOYlYy8": {
"isValid": true,
@ -9430,7 +9435,7 @@
},
"https://www.forum.linuxcnc.org/30-cnc-machines/53486-the-linuxcnc-rigid-CNC%20Router-an-open-source-dual-z-axis-gantry-machine": {
"isValid": true,
"timestamp": 1743445734477,
"timestamp": 1743446747446,
"meta": {
"title": "The LinuxCNC "Rigid Router" an open-source dual z-axis gantry machine",
"description": "Hi all, I recently designed an open-source CNC router. My goal was to make a rigid, medium-format CNC router that can self-manufacture new machines and not...",
@ -9517,7 +9522,7 @@
},
"https://www.bunnings.com.au/search/products?q=fiber%2520cement": {
"isValid": false,
"timestamp": 1743445734754
"timestamp": 1743446747639
},
"https://safeworkwear.com.au/electrical-gloves": {
"isValid": false,
@ -10094,7 +10099,7 @@
},
"https://citeseerx.ist.psu.edu/document?repid=rep1%5C&type=pdf%5C&doi=2d21d208bf921ec8278814cfbee00e60e54acfb4": {
"isValid": false,
"timestamp": 1743445735783
"timestamp": 1743446748314
},
"https://www.youtube.com/watch?v=viwbxM6F7zc": {
"isValid": true,
@ -10299,7 +10304,7 @@
},
"https://dspace.mit.edu/bitstream/handle/1721.1/127868/1196826370-MIT.pdf?sequence=1%5C&isAllowed=y": {
"isValid": true,
"timestamp": 1743445737987,
"timestamp": 1743446752351,
"meta": {
"favicon": "https://dspace.mit.edu/favicon.ico"
}
@ -10395,7 +10400,7 @@
},
"*No%20link%20provided%20in%20source%20text*": {
"isValid": false,
"timestamp": 1743445738440
"timestamp": 1743446752449
},
"https://www.instructables.com/Bottle-Cap-Table-with-Poured-Resin-Surface/": {
"isValid": true,

View File

@ -1 +1,49 @@
export const HOWTO_ROOT = () => '/howto';
export const HOWTO_ROOT = () => '/howto';
export const DIRECTORY_ROOT = () => '/directory';
export const HOWTO_FILES_WEB = () => '/howto';
export const DIRECTORY_FILES_WEB = () => '/directory';
export const HOWTO_FILES_ABS = () => '/howto';
export const DIRECTORY_FILES_ABS = () => '/directory';
export const HOWTO_FILTER_LLM = () => true;
export const DIRECTORY_FILTER_LLM = () => true;
export const HOWTO_GLOB = () => '**/*.md';
export const DIRECTORY_GLOB = () => '**/*.md';
export const HOWTO_MIGRATION = () => 'data/migration.json';
export const DIRECTORY_MIGRATION = () => 'data/migration.json';
export const HOWTO_ANNOTATIONS = () => true;
export const DIRECTORY_ANNOTATIONS = () => true;
export const HOWTO_COMPLETE_RESOURCES = () => true;
export const DIRECTORY_COMPLETE_RESOURCES = () => true;
export const HOWTO_ADD_HARDWARE = () => true;
export const DIRECTORY_ADD_HARDWARE = () => true;
export const HOWTO_COMPLETE_SKILLS = () => true;
export const DIRECTORY_COMPLETE_SKILLS = () => true;
export const HOWTO_LOCAL_RESOURCES = () => true;
export const DIRECTORY_LOCAL_RESOURCES = () => true;
export const HOWTO_ADD_RESOURCES = () => true;
export const DIRECTORY_ADD_RESOURCES = () => true;
export const HOWTO_ADD_REFERENCES = () => true;
export const DIRECTORY_ADD_REFERENCES = () => true;
export const HOWTO_SEO_LLM = () => true;
export const DIRECTORY_SEO_LLM = () => true;
export const HOWTO_MAX_ITEMS = () => 1000;
export const DIRECTORY_MAX_ITEMS = () => 1000;
export const default_image = () => ({
src: '/images/default.png',
alt: 'Default image'
});

View File

@ -45,7 +45,8 @@ type LLMConfig = z.infer<typeof LLMConfigSchema>;
export const enum TemplateContext {
COMMONS = 'commons',
HOWTO = 'howto',
MARKETPLACE = 'marketplace'
MARKETPLACE = 'marketplace',
DIRECTORY = 'directory'
}
// Default configuration
export const DEFAULT_CONFIG: LLMConfig = {

View File

@ -2,7 +2,7 @@
import fs from "fs";
import path from "path";
import { decode } from "html-entities";
import { IHowto, asset_local_rel } from "@/model/howto/howto.jswto.js";
import { IHowto, asset_local_rel } from "@/model/howto/howto.js";
import { Img } from "imagetools/components";
import { i18n as Translate } from "@polymech/astro-base";
import BaseLayout from "@/layouts/BaseLayout.astro";

View File

@ -3,7 +3,7 @@ import { default_image, IMAGE_SETTINGS } from "config/config.js";
import Translate from "@/components/polymech/i18n.astro";
import { Img } from "imagetools/components";
import Sidebar from "@/components/howtos/sidebar2.astro";
import { asset_local_abs,asset_local_rel, IHowto } from "@/model/howto/howto.jswto.js";
import { asset_local_abs,asset_local_rel, IHowto } from "@/model/howto/howto.js";
const { title, url, model, selected = false } = Astro.props;
const item: IHowto = model.item;
const classes = `group relative bg-white overflow-hidden group rounded-xl ${selected ? "ring-2 ring-orange-500" : ""}`;

View File

@ -1,6 +1,6 @@
---
// Import the required interfaces and utilities
import { IHowto } from "@/model/howto/howto.jswto.js";
import { IHowto } from "@/model/howto/howto.js";
import { i18n as Translate } from "@polymech/astro-base";
import { getCollection } from 'astro:content';
const items = await getCollection('howtos');

View File

@ -1,6 +1,6 @@
---
import { getCollection } from 'astro:content';
import { IHowto } from "@/model/howto/howto.jswto.js";
import { IHowto } from "@/model/howto/howto.js";
import { i18n as Translate } from "@polymech/astro-base";
const locale = Astro.currentLocale;
const items = await getCollection('howtos')

View File

@ -20,7 +20,6 @@ export const I18N_CACHE = true
export const I18N_ASSET_PATH = "${SRC_DIR}/${SRC_NAME}-${DST_LANG}${SRC_EXT}"
// Library - Howtos
export const HOWTO_GLOB = '**/config.json'
export const FILES_WEB = 'https://files.polymech.io/files/machines/howtos/'
export const HOWTO_EDIT_ROOT = 'https://git.polymech.io/osr-plastic/osr-machines/src/branch/master/howtos'
@ -43,6 +42,29 @@ export const HOWTO_FILES_ABS = (id) => `${HOWTO_ROOT()}/${id}`
export const HOWTO_FILES_WEB = (id: string) => `${FILES_WEB}/${id}`
export const HOWTO_EDIT_URL = (id: string, lang: string) => `${HOWTO_EDIT_ROOT}/${id}`
// Library - Directory
export const DIRECTORY_GLOB = '**/config.json'
export const DIRECTORY_FILES_BASE = 'https://files.polymech.io/files/directory/'
export const DIRECTORY_EDIT_ROOT = 'https://git.polymech.io/osr-plastic/osr-machines/src/branch/master/directory'
export const DIRECTORY_FILTER_LLM = true
export const DIRECTORY_ANNOTATIONS = false
export const DIRECTORY_ANNOTATIONS_CACHE = false
export const DIRECTORY_COMPLETE_RESOURCES = true
export const DIRECTORY_ADD_HARDWARE = false
export const DIRECTORY_ADD_RESOURCES = true
export const DIRECTORY_ADD_REFERENCES = true
export const DIRECTORY_COMPLETE_SKILLS = false
export const DIRECTORY_LOCAL_RESOURCES = false
export const DIRECTORY_SEO_LLM = true
export const DIRECTORY_MAX_ITEMS = 200
export const DIRECTORY_MIGRATION = () => path.resolve(resolve("./data/last.json"))
export const DIRECTORY_ROOT_INTERN = () => path.resolve(resolve("./public/resources/directory"))
export const DIRECTORY_ROOT = () => path.resolve(resolve("${OSR_ROOT}/osr-machines/directory"))
export const DIRECTORY_FILES_ABS = (id) => `${DIRECTORY_ROOT()}/${id}`
export const DIRECTORY_FILES_WEB = (id: string) => `${DIRECTORY_FILES_BASE}/${id}`
export const DIRECTORY_EDIT_URL = (id: string, lang: string) => `${DIRECTORY_EDIT_ROOT}/${id}`
// Products
export const PRODUCT_ROOT = () => path.resolve(resolve("${OSR_ROOT}/products"))
export const PRODUCT_BRANCHES = read(path.join(PRODUCT_ROOT(), 'config/machines.json'), 'json')

View File

@ -18,7 +18,7 @@ import {
IComponentConfigEx,
group_by_path,
group_path,
} from "@/model/component/component.jsmponent.js";
} from "@/model/component/component.js";
import "flowbite";

View File

@ -1,129 +0,0 @@
import * as path from 'path'
import { findUp } from 'find-up'
import { sync as read } from '@polymech/fs/read'
import { resolveConfig } from '@polymech/commons'
import { DataEntry } from "astro:content"
import type { Loader, LoaderContext } from 'astro/loaders'
import { logger } from '@/base/index.js'
import {
PRODUCT_BRANCHES,
PRODUCT_DIR, PRODUCT_GLOB,
PRODUCT_ROOT
} from 'config/config.js'
import { env } from '../../base/index.js'
import { gallery } from '../../base/media.js';
import { get } from '@polymech/commons/component'
import { PFilterValid } from '@polymech/commons/filter'
import { translate } from "@/base/i18n.js"
import { I18N_SOURCE_LANGUAGE } from "config/config.js"
import { slugify } from "@/base/strings.js"
import { I_PC_USER } from 'site/types/types.js'
export interface I_User extends I_PC_USER {
content: string
[key: string]: unknown
}
export interface IStoreItem extends DataEntry {
data: I_User,
}
const filterBranch = (items: { rel: string, config, path }[], branch: string) => {
if (!PRODUCT_BRANCHES) {
return items
}
const branchItems = PRODUCT_BRANCHES[branch]
if (!branchItems) {
return items
}
return items.filter((item) => branchItems.includes(item.rel))
}
export const items = (branch: string) =>
filterBranch(get(`${PRODUCT_ROOT()}/${PRODUCT_GLOB}`,
PRODUCT_ROOT(), PFilterValid.marketplace_component), branch)
const onItem = async (item: IStoreItem, ctx: LoaderContext) => {
if (!item || !item.data) {
ctx.logger.error(`Error completing ${''}: no data`);
return
}
let data: I_User = item.data
data = resolveConfig(data as Record<string, string>) as I_User
}
export function loader(branch: string): Loader {
const load = async ({
config,
logger,
watcher,
parseData,
store,
generateDigest }: LoaderContext) => {
store.clear();
let products = items(branch)
for (const item of products) {
const product: any = item.config
const id = product.slug;
const data = {
rel: item.rel,
slug: id,
id,
title: product.name,
type: 'directory',
...product,
}
//const parsedData = await parseData({ id, data: data });
const storeItem = {
digest: await generateDigest(data),
filePath: id,
assetImports: [],
id: `${item.rel}`,
data: data
}
await onItem(storeItem, {
logger,
watcher,
parseData,
store,
generateDigest
} as any)
storeItem.data['config'] = JSON.stringify({
...storeItem.data
}, null, 2)
store.set(storeItem)
}
}
return {
name: "directory-loader",
load
};
}
export const group_path = (item) => item.id.split("/")[1]
const group_label = async (text: string, locale) => await translate(slugify(text), I18N_SOURCE_LANGUAGE, locale)
const group = async (items, locale) => {
return items.reduce(async (accPromise, item) => {
const acc = await accPromise
const id = group_path(item)
let key: string = await group_label(id, locale)
key = key.charAt(0).toUpperCase() + key.slice(1)
if (!acc[key]) {
acc[key] = []
}
acc[key].push(item)
return acc
}, {})
}
export const group_by_path = async (items, locale): Promise<I_User[]> => await group(items, locale)

207
src/model/directory/item.ts Normal file
View File

@ -0,0 +1,207 @@
import * as path from 'path'
import { findUp } from 'find-up'
import pMap from 'p-map'
import { sanitizeFilename } from "@polymech/fs/utils"
import { execFileSync, execFile } from "child_process";
import { sync as read } from '@polymech/fs/read'
import { sync as exists } from '@polymech/fs/exists'
import { sync as mkdir } from '@polymech/fs/dir'
import { sync as rm } from '@polymech/fs/remove'
import { sync as write } from '@polymech/fs/write'
import type { Loader, LoaderContext } from 'astro/loaders'
import { resolveVariables } from "@polymech/commons/variables"
import { IUser } from './types.js'
import { blacklist, default_filters_markdown, validateLinks } from '../../base/filters.js'
import { download } from '../download.js'
import { filter } from "@/base/kbot.js"
import { slugify } from "@/base/strings.js"
import { urlCache } from '../../base/url-cache.js';
const expandUrls = true
import {
DIRECTORY_FILES_WEB,
DIRECTORY_FILES_ABS,
DIRECTORY_FILTER_LLM,
default_image,
DIRECTORY_ROOT,
DIRECTORY_GLOB,
DIRECTORY_MIGRATION,
DIRECTORY_ANNOTATIONS,
DIRECTORY_COMPLETE_RESOURCES,
DIRECTORY_ADD_HARDWARE,
DIRECTORY_COMPLETE_SKILLS,
DIRECTORY_LOCAL_RESOURCES,
DIRECTORY_ADD_RESOURCES,
DIRECTORY_ADD_REFERENCES,
DIRECTORY_SEO_LLM,
DIRECTORY_MAX_ITEMS
} from "config/config.js"
import { env, logger } from '@/base/index.js'
import { applyFilters, default_filters_plain, FilterFunction } from '../../base/filters.js'
import { TemplateContext, buildPrompt, LLMConfig, createTemplates } from '@/base/kbot-templates.js'
import { template_filter } from '@/base/kbot.js'
/////////////////////////////////////////////////////////////////////////
//
// Assets
//
/////////////////////////////////////////////////////////////////////////
export const item_path = (item: IUser) => `${DIRECTORY_ROOT()}/${item._id}`
/////////////////////////////////////////////////////////////////////////
//
// Data
//
/////////////////////////////////////////////////////////////////////////
export const raw = async () => {
const src = DIRECTORY_MIGRATION()
const data = read(src, 'json') as any;
let users = data.v3_mappins as any[]
users = users.filter((u) => u.moderation == 'accepted' && !u._deleted);
users = users.filter((u: IUser) => !blacklist.includes(u._id))
users = users.slice(0, DIRECTORY_MAX_ITEMS)
return users
}
export const defaults = async (data: any, cwd: string, root: string) => {
let defaultsJSON = await findUp('defaults.json', {
stopAt: root,
cwd: cwd
});
try {
if (defaultsJSON) {
data = {
...read(defaultsJSON, 'json') as any,
...data,
};
}
} catch (error) {
}
return data;
}
/////////////////////////////////////////////////////////////////////////
//
// Content filters & conversions
//
/////////////////////////////////////////////////////////////////////////
const commons = async (text: string): Promise<string> => {
return await template_filter(text, 'simple', TemplateContext.COMMONS);
}
const content = async (str: string, filters: FilterFunction[] = default_filters_plain) => await applyFilters(str, filters)
/////////////////////////////////////////////////////////////////////////
//
// Store
//
/////////////////////////////////////////////////////////////////////////
const complete = async (item: IUser) => {
const configPath = path.join(item_path(item), 'config.json')
const config = read(configPath, 'json') as IUser || {}
// item = { ...item, ...config }
if (!DIRECTORY_ANNOTATIONS) {
// return item
}
// commons: language, tone, bullshit filter, and a piece of love, just a bit, at least :)
if (DIRECTORY_FILTER_LLM) {
item.detail = await commons(item.detail || '')
}
item.detail = await applyFilters(item.detail || '', [validateLinks])
// Generate keywords using the keywords template
if (DIRECTORY_ADD_RESOURCES) {
item.data = await applyFilters(item.data, default_filters_markdown);
write(path.join(item_path(item), 'resources.md'), item.data as string)
}
if (DIRECTORY_SEO_LLM) {
item.brief = await template_filter(item.detail, 'brief', TemplateContext.DIRECTORY);
}
item.detail = await applyFilters(item.detail || '', [validateLinks])
return item
}
const onStoreItem = async (store: any) => {
let item = store.data.item as IUser
item = await complete(item)
const configPath = path.join(item_path(item), 'config.json')
write(configPath, JSON.stringify(item, null, 2))
logger.info(`Stored item ${item._id} at ${configPath}`)
store.data.item = item
return store
}
export function loader(): Loader {
const load = async ({
config,
logger,
watcher,
parseData,
store,
generateDigest }: LoaderContext) => {
store.clear()
if (expandUrls) {
//await urlCache.expandUrls()
}
let items = await raw()
for (const item of items) {
const id = item._id
const data = {
slug: item._id,
id,
title: item.type,
type: 'directory',
components: [],
item
}
let storeItem = {
digest: await generateDigest(data),
filePath: id,
id: `${item._id}`,
data: data
}
storeItem = await onStoreItem(storeItem)
storeItem.data['config'] = JSON.stringify(storeItem.data, null, 2)
store.set(storeItem)
}
}
return {
name: `astro:store:directory`,
load
};
}
/////////////////////////////////////////////////////////////////////////
//
// Taxonomy
//
/////////////////////////////////////////////////////////////////////////
export const group_by_type = (items: IUser[]) => {
return items.reduce((acc: Record<string, IUser[]>, item: IUser) => {
const type = item?.type || 'untyped'
if (type === 'untyped') {
return acc
}
if (!acc[type]) {
acc[type] = []
}
acc[type].push(item)
return acc
}, {})
}

View File

@ -0,0 +1,38 @@
export interface IUser {
_modified: string
_id: string
subType: string
moderation: string
_deleted: boolean
verified: boolean
type: string
location: ILocation
_created: string
geo: IGeo
data: any
detail: any
brief?: string
}
export interface ILocation {
lat: number
lng: number
}
export interface IGeo {
latitude: number
lookupSource: string
longitude: number
localityLanguageRequested: string
continent: string
continentCode: string
countryName: string
countryCode: string
principalSubdivision: string
principalSubdivisionCode: string
city: string
locality: string
postcode: string
plusCode: string
localityInfo: any
}

View File

@ -1,4 +1,6 @@
import { IUser } from '../directory/types.js'
export const ITEM_TYPE = 'howto'
export interface ICoverImage {
name: string
downloadUrl: string
@ -52,43 +54,6 @@ export interface ITag {
_id: string
}
export interface IUser {
_modified: string
_id: string
subType: string
moderation: string
_deleted: boolean
verified: boolean
type: string
location: ILocation
_created: string
geo: IGeo
data: any
detail: any
}
export interface ILocation {
lat: number
lng: number
}
export interface IGeo {
latitude: number
lookupSource: string
longitude: number
localityLanguageRequested: string
continent: string
continentCode: string
countryName: string
countryCode: string
principalSubdivision: string
principalSubdivisionCode: string
city: string
locality: string
postcode: string
plusCode: string
localityInfo: any
}
// Extended IHowto interface with version field
export interface IHowto {

View File

@ -7,7 +7,7 @@ import config from "config/config.json";
import { getCollection } from "astro:content";
import StoreEntries from "@/components/store/StoreEntries.astro";
import CtaOne from "@/components/cta/CtaOne.astro";
import { group_by_path } from "@/model/component/component.jsmponent.js";
import { group_by_path } from "@/model/component/component.js";
const view = "store"
const items = await getCollection(view)

View File

@ -1,5 +1,5 @@
---
import { IHowto } from "@/model/howto/howto.jswto.js";
import { IHowto } from "@/model/howto/howto.js";
import { getCollection } from "astro:content";
import List from "@/components/howtos/List.astro";
import { LANGUAGES_PROD as LANGUAGES } from "config/config.js";

View File

@ -1,5 +1,5 @@
---
import { group_by_cat } from "@/model/howto/howto.jswto.js";
import { group_by_cat } from "@/model/howto/howto.js";
import { getCollection } from "astro:content";
import BaseLayout from "@/layouts/BaseLayout.astro";
import Wrapper from "@/components/containers/Wrapper.astro";