@contentstorage/core 0.3.32 → 0.3.33

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/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AppConfig, LanguageCode, ContentStructure } from './types.js';
2
- import { setContentLanguage, getText, getImage, getVariation } from './lib/contentManagement.js';
2
+ import { setContentLanguage, getText, getImage, getVariation, initContentStorage } from './lib/contentManagement.js';
3
+ import { fetchContent } from './lib/functions/fetchContent.js';
3
4
  export { AppConfig, LanguageCode, ContentStructure };
4
- export { setContentLanguage, getText, getImage, getVariation };
5
+ export { initContentStorage, fetchContent, setContentLanguage, getText, getImage, getVariation, };
package/dist/index.js CHANGED
@@ -1,2 +1,50 @@
1
- import { setContentLanguage, getText, getImage, getVariation, } from './lib/contentManagement.js';
2
- export { setContentLanguage, getText, getImage, getVariation };
1
+ import { setContentLanguage, getText, getImage, getVariation, initContentStorage, } from './lib/contentManagement.js';
2
+ import { fetchContent } from './lib/functions/fetchContent.js';
3
+ export { initContentStorage, fetchContent, setContentLanguage, getText, getImage, getVariation, };
4
+ async function isLiveEditorMode() {
5
+ try {
6
+ const inIframe = window.self !== window.top;
7
+ const urlParams = new URLSearchParams(window.location.search);
8
+ const iframeMarkerFromParent = urlParams.get('contentstorage_live_editor');
9
+ return !!(inIframe && iframeMarkerFromParent);
10
+ }
11
+ catch (e) {
12
+ // This catch block is for rare edge cases or highly sandboxed environments
13
+ // where accessing window.top might throw an error.
14
+ // If an error occurs, it's safer to assume it might be in an iframe.
15
+ console.warn('Error accessing window.top, assuming iframe context:', e);
16
+ return false;
17
+ }
18
+ }
19
+ isLiveEditorMode().then(async (isLiveMode) => {
20
+ if (!isLiveMode) {
21
+ return;
22
+ }
23
+ const cdnScriptUrl = `https://your-cdn-domain.com/contentstorage-live-editor.js?contentstorage-live-editor=true`;
24
+ return new Promise((resolve, reject) => {
25
+ console.log(`Attempting to load script from: ${cdnScriptUrl}`);
26
+ // 1. Create a new <script> element
27
+ const scriptElement = document.createElement('script');
28
+ scriptElement.type = 'text/javascript';
29
+ // 2. Set the src attribute to your script's URL
30
+ // The browser will fetch and execute it.
31
+ scriptElement.src = cdnScriptUrl;
32
+ // 3. Handle successful loading
33
+ scriptElement.onload = () => {
34
+ console.log(`Script loaded successfully from: ${cdnScriptUrl}`);
35
+ // The script has been fetched and executed by the browser.
36
+ // If it's an IIFE, it has already run.
37
+ resolve(true); // Resolve the promise indicating success
38
+ };
39
+ // 4. Handle errors during loading (e.g., network error, 404)
40
+ scriptElement.onerror = (error) => {
41
+ console.error(`Failed to load script from: ${cdnScriptUrl}`, error);
42
+ reject(new Error(`Failed to load script: ${cdnScriptUrl}`)); // Reject the promise
43
+ };
44
+ // 5. Append the script element to the document's head (or body)
45
+ // This triggers the browser to start loading the script.
46
+ document.head.appendChild(scriptElement);
47
+ // Or: document.body.appendChild(scriptElement);
48
+ });
49
+ // fetch script to handle iframe communication
50
+ });
@@ -1,25 +1,27 @@
1
- import { ContentStructure, ImageObject } from '../types.js';
1
+ import { AppConfig, ContentStructure, GetImageReturn, GetTextReturn, GetVariationReturn } from '../types.js';
2
+ export declare let activeContent: object | null;
3
+ export declare let appConfig: AppConfig | null;
2
4
  /**
3
5
  * Loads and sets the content for a specific language.
4
6
  * It will internally ensure the application configuration (for contentDir) is loaded.
5
7
  * @param contentJson
6
8
  */
7
9
  export declare function setContentLanguage(contentJson: object): void;
10
+ export declare function initContentStorage(config: AppConfig): void;
8
11
  /**
9
12
  * Retrieves the text string from the loaded JSON content for the given path.
10
13
  * Autocompletion for pathString is enabled via module augmentation of CustomContentStructure.
11
14
  * `setContentLanguage()` must be called successfully before using this.
12
15
  *
13
- * @param pathString A dot-notation path string (e.g., 'HomePage.Login'). Autocompletion is provided.
16
+ * @param contentKey A dot-notation path string (e.g., 'HomePage.Login'). Autocompletion is provided.
14
17
  * @param variables Variables help to render dynamic content inside text strings
15
- * @param fallbackValue Optional string to return if the path is not found or the value is not a string.
16
18
  * If not provided, and path is not found/value not string, undefined is returned.
17
19
  * @returns The text string from the JSON, or the fallbackValue, or undefined.
18
20
  */
19
- export declare function getText<Path extends keyof ContentStructure>(pathString: Path, variables?: ContentStructure[Path] extends {
21
+ export declare function getText<Path extends keyof ContentStructure>(contentKey: Path, variables?: ContentStructure[Path] extends {
20
22
  variables: infer Vars;
21
- } ? keyof Vars : Record<string, any>): string | undefined;
22
- export declare function getImage(pathString: keyof ContentStructure, fallbackValue?: ImageObject): ImageObject | undefined;
23
- export declare function getVariation<Path extends keyof ContentStructure>(pathString: Path, variationKey?: ContentStructure[Path] extends {
23
+ } ? keyof Vars : Record<string, any>): GetTextReturn | '';
24
+ export declare function getImage(contentKey: keyof ContentStructure): GetImageReturn | undefined;
25
+ export declare function getVariation<Path extends keyof ContentStructure>(contentKey: Path, variationKey?: ContentStructure[Path] extends {
24
26
  data: infer D;
25
- } ? keyof D : string, variables?: Record<string, any>): string | undefined;
27
+ } ? keyof D : string, variables?: Record<string, any>): GetVariationReturn;
@@ -1,5 +1,6 @@
1
1
  import { populateTextWithVariables } from '../helpers/populateTextWithVariables.js';
2
- let activeContent = null;
2
+ export let activeContent = null;
3
+ export let appConfig = null;
3
4
  /**
4
5
  * Loads and sets the content for a specific language.
5
6
  * It will internally ensure the application configuration (for contentDir) is loaded.
@@ -18,94 +19,127 @@ export function setContentLanguage(contentJson) {
18
19
  console.error(`[Contentstorage] Failed to load content. Error: ${error.message}`);
19
20
  }
20
21
  }
22
+ export function initContentStorage(config) {
23
+ if (!config ||
24
+ typeof config !== 'object' ||
25
+ !config.contentKey ||
26
+ !Array.isArray(config.languageCodes)) {
27
+ if (!config.contentKey) {
28
+ throw new Error('[Contentstorage] No contentKey provided in initContentStorage function.');
29
+ }
30
+ if (!Array.isArray(config.languageCodes)) {
31
+ throw new Error('[Contentstorage] No languageCodes provided in initContentStorage function.');
32
+ }
33
+ throw new Error('[Contentstorage] Invalid config.');
34
+ }
35
+ appConfig = config;
36
+ }
21
37
  /**
22
38
  * Retrieves the text string from the loaded JSON content for the given path.
23
39
  * Autocompletion for pathString is enabled via module augmentation of CustomContentStructure.
24
40
  * `setContentLanguage()` must be called successfully before using this.
25
41
  *
26
- * @param pathString A dot-notation path string (e.g., 'HomePage.Login'). Autocompletion is provided.
42
+ * @param contentKey A dot-notation path string (e.g., 'HomePage.Login'). Autocompletion is provided.
27
43
  * @param variables Variables help to render dynamic content inside text strings
28
- * @param fallbackValue Optional string to return if the path is not found or the value is not a string.
29
44
  * If not provided, and path is not found/value not string, undefined is returned.
30
45
  * @returns The text string from the JSON, or the fallbackValue, or undefined.
31
46
  */
32
- export function getText(pathString, variables) {
47
+ export function getText(contentKey, variables) {
33
48
  if (!activeContent) {
34
- const msg = `[Contentstorage] getText: Content not loaded (Key: "${String(pathString)}"). Ensure setContentLanguage() was called and completed successfully.`;
49
+ const msg = `[Contentstorage] getText: Content not loaded (Key: "${String(contentKey)}"). Ensure setContentLanguage() was called and completed successfully.`;
35
50
  console.warn(msg);
36
51
  return '';
37
52
  }
38
- const keys = pathString.split('.');
53
+ const keys = contentKey.split('.');
39
54
  let current = activeContent;
40
55
  for (const key of keys) {
41
56
  if (current && typeof current === 'object' && key in current) {
42
57
  current = current[key];
43
58
  }
44
59
  else {
45
- const msg = `[Contentstorage] getText: Path "${String(pathString)}" not found in loaded content.`;
60
+ const msg = `[Contentstorage] getText: Path "${String(contentKey)}" not found in loaded content.`;
46
61
  console.warn(msg);
47
62
  return '';
48
63
  }
49
64
  }
50
65
  if (typeof current === 'string') {
51
66
  if (!variables || Object.keys(variables).length === 0) {
52
- return current;
67
+ return {
68
+ contentKey,
69
+ text: current,
70
+ };
53
71
  }
54
- return populateTextWithVariables(current, variables, pathString);
72
+ return {
73
+ contentKey,
74
+ text: populateTextWithVariables(current, variables, contentKey),
75
+ };
55
76
  }
56
77
  else {
57
- const msg = `[Contentstorage] getText: Value at path "${String(pathString)}" is not a string (actual type: ${typeof current}).`;
78
+ const msg = `[Contentstorage] getText: Value at path "${String(contentKey)}" is not a string (actual type: ${typeof current}).`;
58
79
  console.warn(msg);
59
80
  return '';
60
81
  }
61
82
  }
62
- export function getImage(pathString, fallbackValue) {
83
+ export function getImage(contentKey) {
84
+ const defaultVal = {
85
+ contentKey,
86
+ data: { url: '', altText: '', contentstorage_type: 'image' },
87
+ };
63
88
  if (!activeContent) {
64
- const msg = `[Contentstorage] getImage: Content not loaded (Key: "${pathString}"). Ensure setContentLanguage() was called and completed successfully.`;
89
+ const msg = `[Contentstorage] getImage: Content not loaded (Key: "${contentKey}"). Ensure setContentLanguage() was called and completed successfully.`;
65
90
  console.warn(msg);
66
- return fallbackValue;
91
+ return {
92
+ contentKey,
93
+ data: { url: '', altText: '', contentstorage_type: 'image' },
94
+ };
67
95
  }
68
- const keys = pathString.split('.');
96
+ const keys = contentKey.split('.');
69
97
  let current = activeContent;
70
98
  for (const key of keys) {
71
99
  if (current && typeof current === 'object' && key in current) {
72
100
  current = current[key];
73
101
  }
74
102
  else {
75
- const msg = `[Contentstorage] getImage: Path "${pathString}" not found in loaded content.`;
103
+ const msg = `[Contentstorage] getImage: Path "${contentKey}" not found in loaded content.`;
76
104
  console.warn(msg);
77
- return fallbackValue;
105
+ return defaultVal;
78
106
  }
79
107
  }
80
108
  if (current &&
81
109
  typeof current === 'object' &&
82
110
  current.contentstorage_type === 'image' &&
83
- typeof current.url === 'string' &&
84
- typeof current.altText === 'string') {
85
- return current;
111
+ typeof current.url === 'string') {
112
+ return {
113
+ contentKey,
114
+ data: current,
115
+ };
86
116
  }
87
117
  else {
88
- const msg = `[Contentstorage] getImage: Value at path "${pathString}" is not a valid image object (actual value: ${JSON.stringify(current)}).`;
118
+ const msg = `[Contentstorage] getImage: Value at path "${contentKey}" is not a valid image object (actual value: ${JSON.stringify(current)}).`;
89
119
  console.warn(msg);
90
- return fallbackValue;
120
+ return defaultVal;
91
121
  }
92
122
  }
93
- export function getVariation(pathString, variationKey, variables) {
123
+ export function getVariation(contentKey, variationKey, variables) {
124
+ const defaultVal = {
125
+ contentKey,
126
+ text: '',
127
+ };
94
128
  if (!activeContent) {
95
- const msg = `[Contentstorage] getVariation: Content not loaded (Key: "${pathString}", Variation: "${variationKey?.toString()}"). Ensure setContentLanguage() was called and completed successfully.`;
129
+ const msg = `[Contentstorage] getVariation: Content not loaded (Key: "${contentKey}", Variation: "${variationKey?.toString()}"). Ensure setContentLanguage() was called and completed successfully.`;
96
130
  console.warn(msg);
97
- return '';
131
+ return defaultVal;
98
132
  }
99
- const keys = pathString.split('.');
133
+ const keys = contentKey.split('.');
100
134
  let current = activeContent;
101
135
  for (const key of keys) {
102
136
  if (current && typeof current === 'object' && key in current) {
103
137
  current = current[key];
104
138
  }
105
139
  else {
106
- const msg = `[Contentstorage] getVariation: Path "${pathString}" for variation object not found in loaded content.`;
140
+ const msg = `[Contentstorage] getVariation: Path "${contentKey}" for variation object not found in loaded content.`;
107
141
  console.warn(msg);
108
- return '';
142
+ return defaultVal;
109
143
  }
110
144
  }
111
145
  if (current &&
@@ -120,12 +154,18 @@ export function getVariation(pathString, variationKey, variables) {
120
154
  if (typeof variationObject.data[variationKey] === 'string') {
121
155
  const current = variationObject.data[variationKey];
122
156
  if (!variables || Object.keys(variables).length === 0) {
123
- return current;
157
+ return {
158
+ contentKey,
159
+ text: current,
160
+ };
124
161
  }
125
- return populateTextWithVariables(current, variables, pathString);
162
+ return {
163
+ contentKey,
164
+ text: populateTextWithVariables(current, variables, contentKey),
165
+ };
126
166
  }
127
167
  else {
128
- const msg = `[Contentstorage] getVariation: Variation value for key "${variationKey}" at path "${pathString}" is not a string (actual type: ${typeof variationObject.data[variationKey]}).`;
168
+ const msg = `[Contentstorage] getVariation: Variation value for key "${variationKey}" at path "${contentKey}" is not a string (actual type: ${typeof variationObject.data[variationKey]}).`;
129
169
  console.warn(msg);
130
170
  }
131
171
  }
@@ -133,20 +173,23 @@ export function getVariation(pathString, variationKey, variables) {
133
173
  if ('default' in variationObject.data && typeof variationKey === 'string') {
134
174
  if (typeof variationObject.data.default === 'string') {
135
175
  if (variationKey && variationKey !== 'default') {
136
- console.warn(`[Contentstorage] getVariation: Variation key "${variationKey}" not found at path "${pathString}". Returning 'default' variation.`);
176
+ console.warn(`[Contentstorage] getVariation: Variation key "${variationKey}" not found at path "${contentKey}". Returning 'default' variation.`);
137
177
  }
138
- return variationObject.data.default;
178
+ return {
179
+ contentKey,
180
+ text: variationObject.data.default,
181
+ };
139
182
  }
140
183
  else {
141
- console.warn(`[Contentstorage] getVariation: 'default' variation value at path "${pathString}" is not a string (actual type: ${typeof variationObject.data.default}).`);
184
+ console.warn(`[Contentstorage] getVariation: 'default' variation value at path "${contentKey}" is not a string (actual type: ${typeof variationObject.data.default}).`);
142
185
  }
143
186
  }
144
187
  // If neither specific key nor 'default' is found or valid
145
- console.warn(`[Contentstorage] getVariation: Neither variation key "${variationKey?.toString()}" nor 'default' variation found or valid at path "${pathString}".`);
146
- return '';
188
+ console.warn(`[Contentstorage] getVariation: Neither variation key "${variationKey?.toString()}" nor 'default' variation found or valid at path "${contentKey}".`);
189
+ return defaultVal;
147
190
  }
148
191
  else {
149
- console.warn(`[Contentstorage] getVariation: Value at path "${pathString}" is not a valid variation object (actual value: ${JSON.stringify(current)}).`);
150
- return '';
192
+ console.warn(`[Contentstorage] getVariation: Value at path "${contentKey}" is not a valid variation object (actual value: ${JSON.stringify(current)}).`);
193
+ return defaultVal;
151
194
  }
152
195
  }
@@ -0,0 +1,2 @@
1
+ import { LanguageCode } from '../../types.js';
2
+ export declare function fetchContent(language?: LanguageCode): Promise<void>;
@@ -0,0 +1,43 @@
1
+ import axios from 'axios';
2
+ import { CONTENTSTORAGE_CONFIG } from '../../contentstorage-config.js';
3
+ import { appConfig, setContentLanguage } from '../contentManagement.js';
4
+ export async function fetchContent(language) {
5
+ const languageToFetch = language || appConfig?.languageCodes?.[0];
6
+ console.log(`Starting content fetch for language ${language}...`);
7
+ if (!languageToFetch) {
8
+ throw Error(`No language found`);
9
+ }
10
+ if (!appConfig) {
11
+ throw Error(`No app config found`);
12
+ }
13
+ const fileUrl = `${CONTENTSTORAGE_CONFIG.BASE_URL}/${appConfig.contentKey}/content/${languageToFetch}.json`;
14
+ try {
15
+ // Fetch data for the current language
16
+ const response = await axios.get(fileUrl);
17
+ const jsonData = response.data;
18
+ // Basic check for data existence, although axios usually throws for non-2xx responses
19
+ if (jsonData === undefined || jsonData === null) {
20
+ throw new Error(`No data received from ${fileUrl} for language ${languageToFetch}.`);
21
+ }
22
+ // Validate that jsonData is a single, non-null JSON object (not an array)
23
+ // This check mirrors the original code's expectation for the content of a JSON file.
24
+ if (typeof jsonData !== 'object') {
25
+ throw new Error(`Expected a single JSON object from ${fileUrl} for language ${languageToFetch}, but received type ${typeof jsonData}. Cannot proceed.`);
26
+ }
27
+ console.log(`Received JSON for ${languageToFetch}`);
28
+ setContentLanguage(jsonData);
29
+ }
30
+ catch (error) {
31
+ // Catch errors related to fetching or saving a single language file
32
+ console.error(`\nError processing language ${languageToFetch} from ${fileUrl}:`);
33
+ if (axios.isAxiosError(error)) {
34
+ console.error(` Status: ${error.response?.status}`);
35
+ console.error(`Response Data: ${error.response?.data ? JSON.stringify(error.response.data) : 'N/A'}`);
36
+ console.error(` Message: ${error.message}`); // Axios error message
37
+ }
38
+ else {
39
+ // For non-Axios errors (e.g., manually thrown errors, fs errors)
40
+ console.error(` Error: ${error.message}`);
41
+ }
42
+ }
43
+ }
package/dist/types.d.ts CHANGED
@@ -22,6 +22,18 @@ export type LanguageCode = 'SQ' | 'BE' | 'BS' | 'BG' | 'HR' | 'CS' | 'DA' | 'NL'
22
22
  */
23
23
  export interface ContentStructure {
24
24
  }
25
+ export type GetTextReturn = {
26
+ contentKey: string;
27
+ text: string;
28
+ };
29
+ export type GetImageReturn = {
30
+ contentKey: string;
31
+ data: ImageObject;
32
+ };
33
+ export type GetVariationReturn = {
34
+ contentKey: string;
35
+ text: string;
36
+ };
25
37
  export interface ImageObject {
26
38
  contentstorage_type: 'image';
27
39
  url: string;
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.32",
5
+ "version": "0.3.33",
6
6
  "type": "module",
7
7
  "description": "Fetch content from contentstorage and generate TypeScript types",
8
8
  "module": "dist/index.js",