@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 +3 -2
- package/dist/index.js +50 -2
- package/dist/lib/contentManagement.d.ts +10 -8
- package/dist/lib/contentManagement.js +80 -37
- package/dist/lib/functions/fetchContent.d.ts +2 -0
- package/dist/lib/functions/fetchContent.js +43 -0
- package/dist/types.d.ts +12 -0
- package/package.json +1 -1
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
|
-
|
|
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,
|
|
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
|
|
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>(
|
|
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>):
|
|
22
|
-
export declare function getImage(
|
|
23
|
-
export declare function getVariation<Path extends keyof ContentStructure>(
|
|
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>):
|
|
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
|
|
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(
|
|
47
|
+
export function getText(contentKey, variables) {
|
|
33
48
|
if (!activeContent) {
|
|
34
|
-
const msg = `[Contentstorage] getText: Content not loaded (Key: "${String(
|
|
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 =
|
|
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(
|
|
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
|
|
67
|
+
return {
|
|
68
|
+
contentKey,
|
|
69
|
+
text: current,
|
|
70
|
+
};
|
|
53
71
|
}
|
|
54
|
-
return
|
|
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(
|
|
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(
|
|
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: "${
|
|
89
|
+
const msg = `[Contentstorage] getImage: Content not loaded (Key: "${contentKey}"). Ensure setContentLanguage() was called and completed successfully.`;
|
|
65
90
|
console.warn(msg);
|
|
66
|
-
return
|
|
91
|
+
return {
|
|
92
|
+
contentKey,
|
|
93
|
+
data: { url: '', altText: '', contentstorage_type: 'image' },
|
|
94
|
+
};
|
|
67
95
|
}
|
|
68
|
-
const keys =
|
|
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 "${
|
|
103
|
+
const msg = `[Contentstorage] getImage: Path "${contentKey}" not found in loaded content.`;
|
|
76
104
|
console.warn(msg);
|
|
77
|
-
return
|
|
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
|
-
|
|
85
|
-
|
|
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 "${
|
|
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
|
|
120
|
+
return defaultVal;
|
|
91
121
|
}
|
|
92
122
|
}
|
|
93
|
-
export function getVariation(
|
|
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: "${
|
|
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 =
|
|
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 "${
|
|
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
|
|
157
|
+
return {
|
|
158
|
+
contentKey,
|
|
159
|
+
text: current,
|
|
160
|
+
};
|
|
124
161
|
}
|
|
125
|
-
return
|
|
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 "${
|
|
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 "${
|
|
176
|
+
console.warn(`[Contentstorage] getVariation: Variation key "${variationKey}" not found at path "${contentKey}". Returning 'default' variation.`);
|
|
137
177
|
}
|
|
138
|
-
return
|
|
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 "${
|
|
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 "${
|
|
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 "${
|
|
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,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.
|
|
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",
|