@contentstorage/core 0.3.8 → 0.3.10

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.
@@ -0,0 +1,6 @@
1
+ import { AppConfig } from '../types.js';
2
+ /**
3
+ * Helper function to define your application configuration.
4
+ * Provides autocompletion and type-checking for contentstorage.config.js files.
5
+ */
6
+ export declare function defineConfig(config: AppConfig): AppConfig;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Helper function to define your application configuration.
3
+ * Provides autocompletion and type-checking for contentstorage.config.js files.
4
+ */
5
+ export function defineConfig(config) {
6
+ // You can add basic runtime validation here if desired,
7
+ // e.g., check if contentUrl is a valid URL format,
8
+ // or if languageCodes is not empty.
9
+ if (!config.languageCodes || config.languageCodes.length === 0) {
10
+ console.warn('Warning: languageCodes array is empty or missing in the configuration.');
11
+ }
12
+ if (!config.contentDir) {
13
+ // This would typically be a hard error, but defineConfig is more for type safety at edit time.
14
+ // Runtime validation (see point 3) is better for hard errors.
15
+ console.warn('Warning: contentDir is missing in the configuration.');
16
+ }
17
+ // ... other checks
18
+ return config;
19
+ }
package/dist/index.d.ts CHANGED
@@ -1,2 +1,4 @@
1
- import { AppConfig } from './lib/configLoader.js';
2
- export { AppConfig };
1
+ import { AppConfig, LanguageCode } from './types.js';
2
+ import { defineConfig } from './helpers/defineConfig.js';
3
+ export type { AppConfig, LanguageCode };
4
+ export { defineConfig };
package/dist/index.js CHANGED
@@ -1 +1,2 @@
1
- export {};
1
+ import { defineConfig } from './helpers/defineConfig.js';
2
+ export { defineConfig };
@@ -1,6 +1,2 @@
1
- export interface AppConfig {
2
- contentUrl: string;
3
- contentDir: string;
4
- typesOutputFile: string;
5
- }
1
+ import { AppConfig } from '../types.js';
6
2
  export declare function loadConfig(): Promise<AppConfig>;
@@ -1,8 +1,9 @@
1
1
  import path from 'path';
2
2
  import fs from 'fs';
3
3
  const DEFAULT_CONFIG = {
4
- contentDir: path.join('src', 'assets', 'content'),
5
- typesOutputFile: path.join('src', 'generated', 'content-types.ts'),
4
+ languageCodes: [],
5
+ contentDir: path.join('src', 'content', 'json'),
6
+ typesOutputFile: path.join('src', 'content', 'content-types.ts'),
6
7
  };
7
8
  export async function loadConfig() {
8
9
  const configPath = path.resolve(process.cwd(), 'contentstorage.config.js'); // Look in user's current working dir
@@ -37,6 +38,7 @@ export async function loadConfig() {
37
38
  }
38
39
  // Resolve paths relative to the user's project root (process.cwd())
39
40
  const finalConfig = {
41
+ languageCodes: mergedConfig.languageCodes || [],
40
42
  contentUrl: mergedConfig.contentUrl,
41
43
  contentDir: path.resolve(process.cwd(), mergedConfig.contentDir),
42
44
  typesOutputFile: path.resolve(process.cwd(), mergedConfig.typesOutputFile),
@@ -6,57 +6,78 @@ import chalk from 'chalk';
6
6
  import { loadConfig } from '../lib/configLoader.js';
7
7
  export async function pullContent() {
8
8
  console.log(chalk.blue('Starting content pull...'));
9
+ // Load configuration (assuming this function is defined elsewhere and works)
9
10
  const config = await loadConfig();
10
- console.log(chalk.gray(`Getting content from: ${config.contentUrl}`));
11
+ console.log(chalk.gray(`Content base URL: ${config.contentUrl}`));
11
12
  console.log(chalk.gray(`Saving content to: ${config.contentDir}`));
12
13
  try {
13
- // Fetch data
14
- const response = await axios.get(config.contentUrl);
15
- const jsonData = response.data; // Assume axios parses JSON automatically
16
- if (!jsonData) {
17
- throw new Error('No data received from the URL.');
14
+ // Validate languageCodes array
15
+ if (!Array.isArray(config.languageCodes)) {
16
+ console.log(chalk.red(`Expected array from config.languageCodes, but received type ${typeof config.languageCodes}. Cannot pull files.`));
17
+ return; // Exit if languageCodes is not an array
18
18
  }
19
- // Ensure the output directory exists
20
- await fs.mkdir(config.contentDir, { recursive: true });
21
- // --- How to save the data? ---
22
- // Option 1: Save the entire response as one file (e.g., content.json)
23
- // const outputPath = path.join(config.contentDir, 'content.json');
24
- // await fs.writeFile(outputPath, JSON.stringify(jsonData, null, 2));
25
- // console.log(chalk.green(`Content saved successfully to ${outputPath}`));
26
- // Check if jsonData is a single, non-null object (and not an array)
27
- if (typeof jsonData !== 'object' || Array.isArray(jsonData)) {
28
- console.log(chalk.red(`Expected a single JSON object from ${config.contentUrl}, but received type ${Array.isArray(jsonData) ? 'array' : typeof jsonData}. Cannot save the file.`));
29
- return;
30
- }
31
- console.log(chalk.green(`Received JSON. Saving it to ${config.contentDir}`));
32
- // Determine filename for the single object.
33
- // Use 'id' or 'slug' from the object if available, otherwise use 'data' as a fallback base name.
34
- const objectData = jsonData; // Use type assertion to access potential properties
35
- const baseFilename = objectData.id || objectData.slug || 'data';
36
- const filename = `${baseFilename}.json`;
37
- const outputPath = path.join(config.contentDir, filename);
38
- console.log(chalk.gray(`Received a single JSON object. Attempting to save as ${filename}...`));
39
- try {
40
- // Ensure the output directory exists
41
- await fs.mkdir(config.contentDir, { recursive: true });
42
- // Write the single JSON object to the file
43
- await fs.writeFile(outputPath, JSON.stringify(jsonData, null, 2));
44
- console.log(chalk.green(`Successfully saved the object to ${outputPath}`));
19
+ if (config.languageCodes.length === 0) {
20
+ console.log(chalk.yellow('config.languageCodes array is empty. No files to pull.'));
21
+ return; // Exit if languageCodes array is empty
45
22
  }
46
- catch (error) {
47
- console.error(chalk.red('Error fetching or saving content:'));
48
- if (axios.isAxiosError(error)) {
49
- console.error(chalk.red(`Status: ${error.response?.status}`));
50
- console.error(chalk.red(`Data: ${JSON.stringify(error.response?.data)}`));
23
+ // Ensure the output directory exists (create it once before the loop)
24
+ await fs.mkdir(config.contentDir, { recursive: true });
25
+ // Process each language code
26
+ for (const languageCode of config.languageCodes) {
27
+ const fileUrl = `${config.contentUrl}/${languageCode}.json`;
28
+ const filename = `${languageCode}.json`;
29
+ const outputPath = path.join(config.contentDir, filename);
30
+ console.log(chalk.blue(`\nProcessing language: ${languageCode}`));
31
+ console.log(chalk.gray(`Workspaceing from: ${fileUrl}`));
32
+ try {
33
+ // Fetch data for the current language
34
+ const response = await axios.get(fileUrl);
35
+ const jsonData = response.data;
36
+ // Basic check for data existence, although axios usually throws for non-2xx responses
37
+ if (jsonData === undefined || jsonData === null) {
38
+ throw new Error(`No data received from ${fileUrl} for language ${languageCode}.`);
39
+ }
40
+ // Validate that jsonData is a single, non-null JSON object (not an array)
41
+ // This check mirrors the original code's expectation for the content of a JSON file.
42
+ if (typeof jsonData !== 'object' ||
43
+ Array.isArray(jsonData) /* jsonData === null is already covered */) {
44
+ throw new Error(`Expected a single JSON object from ${fileUrl} for language ${languageCode}, but received type ${Array.isArray(jsonData) ? 'array' : typeof jsonData}. Cannot save the file.`);
45
+ }
46
+ console.log(chalk.green(`Received JSON for ${languageCode}. Saving to ${outputPath}`));
47
+ // Write the JSON data to the file
48
+ await fs.writeFile(outputPath, JSON.stringify(jsonData, null, 2));
49
+ console.log(chalk.green(`Successfully saved ${outputPath}`));
51
50
  }
52
- else {
53
- console.error(chalk.red(error.message));
51
+ catch (error) {
52
+ // Catch errors related to fetching or saving a single language file
53
+ console.error(chalk.red(`\nError processing language ${languageCode} from ${fileUrl}:`));
54
+ if (axios.isAxiosError(error)) {
55
+ console.error(chalk.red(` Status: ${error.response?.status}`));
56
+ console.error(chalk.red(`Response Data: ${error.response?.data ? JSON.stringify(error.response.data) : 'N/A'}`));
57
+ console.error(chalk.red(` Message: ${error.message}`)); // Axios error message
58
+ }
59
+ else {
60
+ // For non-Axios errors (e.g., manually thrown errors, fs errors)
61
+ console.error(chalk.red(` Error: ${error.message}`));
62
+ }
63
+ // Re-throw the error to be caught by the outer try-catch block,
64
+ // which will then call process.exit(1), maintaining original exit behavior on error.
65
+ throw error;
54
66
  }
55
- process.exit(1); // Exit with error code
56
67
  }
68
+ console.log(chalk.green('\nAll content successfully pulled and saved.'));
57
69
  }
58
- catch (error) {
59
- console.error(chalk.red(error.message));
70
+ catch {
71
+ // Outer catch for setup errors (like loadConfig) or re-thrown errors from the loop
72
+ // The specific error details for a file operation would have been logged by the inner catch.
73
+ // This block provides a general failure message and ensures the process exits with an error code.
74
+ console.error(chalk.red('\n-----------------------------------------------------'));
75
+ console.error(chalk.red('Content pull failed due to an error. See details above.'));
76
+ // error.message from the re-thrown error will be implicitly part of the error object logged by some environments,
77
+ // or if you add console.error(error) here.
78
+ // The original code logged error.message at this level:
79
+ // if (error.message) console.error(chalk.red(`Underlying error: ${error.message}`));
80
+ console.error(chalk.red('-----------------------------------------------------'));
60
81
  process.exit(1); // Exit with error code
61
82
  }
62
83
  }
@@ -0,0 +1,7 @@
1
+ export type AppConfig = {
2
+ languageCodes: LanguageCode[];
3
+ contentUrl: string;
4
+ contentDir: string;
5
+ typesOutputFile: string;
6
+ };
7
+ export type LanguageCode = 'SQ' | 'BE' | 'BS' | 'BG' | 'HR' | 'CS' | 'DA' | 'NL' | 'EN' | 'ET' | 'FI' | 'FR' | 'DE' | 'EL' | 'HU' | 'GA' | 'IT' | 'LV' | 'LT' | 'MK' | 'NO' | 'PL' | 'PT' | 'RO' | 'RU' | 'SR' | 'SK' | 'SL' | 'ES' | 'SV' | 'TR' | 'UK';
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@contentstorage/core",
3
3
  "author": "Kaido Hussar <kaidohus@gmail.com>",
4
4
  "homepage": "https://contentstorage.app",
5
- "version": "0.3.8",
5
+ "version": "0.3.10",
6
6
  "type": "module",
7
7
  "description": "Fetch content from contentstorage and generate TypeScript types",
8
8
  "module": "dist/index.js",