@builder.io/sdk-svelte 0.7.0 → 0.7.1-0
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/lib/browser/blocks/custom-code/custom-code.svelte +35 -37
- package/lib/browser/components/content/components/enable-editor.svelte +82 -65
- package/lib/browser/components/content/components/enable-editor.svelte.d.ts +3 -3
- package/lib/browser/constants/sdk-version.d.ts +1 -1
- package/lib/browser/constants/sdk-version.js +1 -1
- package/lib/browser/functions/evaluate/choose-eval.d.ts +6 -0
- package/lib/browser/functions/evaluate/choose-eval.js +19 -0
- package/lib/browser/functions/evaluate/evaluate.d.ts +1 -5
- package/lib/browser/functions/evaluate/evaluate.js +7 -30
- package/lib/browser/functions/evaluate/helpers.d.ts +7 -1
- package/lib/browser/functions/evaluate/helpers.js +18 -0
- package/lib/browser/functions/evaluate/node-runtime/index.d.ts +1 -1
- package/lib/browser/functions/evaluate/node-runtime/index.js +1 -1
- package/lib/browser/functions/evaluate/node-runtime/node-runtime.d.ts +2 -0
- package/lib/browser/functions/evaluate/node-runtime/node-runtime.js +120 -0
- package/lib/browser/functions/evaluate/node-runtime/safeDynamicRequire.d.ts +13 -0
- package/lib/browser/functions/evaluate/node-runtime/safeDynamicRequire.js +18 -0
- package/lib/browser/functions/get-content/generate-content-url.js +27 -1
- package/lib/browser/functions/get-content/types.d.ts +94 -3
- package/lib/browser/functions/is-edge-runtime.js +2 -2
- package/lib/browser/functions/is-node-runtime.d.ts +4 -0
- package/lib/browser/functions/is-node-runtime.js +7 -0
- package/lib/edge/blocks/custom-code/custom-code.svelte +35 -37
- package/lib/edge/components/content/components/enable-editor.svelte +82 -65
- package/lib/edge/components/content/components/enable-editor.svelte.d.ts +3 -3
- package/lib/edge/constants/sdk-version.d.ts +1 -1
- package/lib/edge/constants/sdk-version.js +1 -1
- package/lib/edge/functions/evaluate/choose-eval.d.ts +6 -0
- package/lib/edge/functions/evaluate/choose-eval.js +19 -0
- package/lib/edge/functions/evaluate/evaluate.d.ts +1 -5
- package/lib/edge/functions/evaluate/evaluate.js +7 -30
- package/lib/edge/functions/evaluate/helpers.d.ts +7 -1
- package/lib/edge/functions/evaluate/helpers.js +18 -0
- package/lib/edge/functions/evaluate/node-runtime/index.d.ts +1 -1
- package/lib/edge/functions/evaluate/node-runtime/index.js +1 -1
- package/lib/edge/functions/evaluate/node-runtime/node-runtime.d.ts +2 -0
- package/lib/edge/functions/evaluate/node-runtime/node-runtime.js +120 -0
- package/lib/edge/functions/evaluate/node-runtime/safeDynamicRequire.d.ts +13 -0
- package/lib/edge/functions/evaluate/node-runtime/safeDynamicRequire.js +18 -0
- package/lib/edge/functions/get-content/generate-content-url.js +27 -1
- package/lib/edge/functions/get-content/types.d.ts +94 -3
- package/lib/edge/functions/is-edge-runtime.js +2 -2
- package/lib/edge/functions/is-node-runtime.d.ts +4 -0
- package/lib/edge/functions/is-node-runtime.js +7 -0
- package/lib/node/blocks/custom-code/custom-code.svelte +35 -37
- package/lib/node/components/content/components/enable-editor.svelte +82 -65
- package/lib/node/components/content/components/enable-editor.svelte.d.ts +3 -3
- package/lib/node/constants/sdk-version.d.ts +1 -1
- package/lib/node/constants/sdk-version.js +1 -1
- package/lib/node/functions/evaluate/choose-eval.d.ts +6 -0
- package/lib/node/functions/evaluate/choose-eval.js +19 -0
- package/lib/node/functions/evaluate/evaluate.d.ts +1 -5
- package/lib/node/functions/evaluate/evaluate.js +7 -30
- package/lib/node/functions/evaluate/helpers.d.ts +7 -1
- package/lib/node/functions/evaluate/helpers.js +18 -0
- package/lib/node/functions/evaluate/node-runtime/index.d.ts +1 -1
- package/lib/node/functions/evaluate/node-runtime/index.js +1 -1
- package/lib/node/functions/evaluate/node-runtime/node-runtime.d.ts +2 -0
- package/lib/node/functions/evaluate/node-runtime/node-runtime.js +120 -0
- package/lib/node/functions/evaluate/node-runtime/safeDynamicRequire.d.ts +13 -0
- package/lib/node/functions/evaluate/node-runtime/safeDynamicRequire.js +18 -0
- package/lib/node/functions/get-content/generate-content-url.js +27 -1
- package/lib/node/functions/get-content/types.d.ts +94 -3
- package/lib/node/functions/is-edge-runtime.js +2 -2
- package/lib/node/functions/is-node-runtime.d.ts +4 -0
- package/lib/node/functions/is-node-runtime.js +7 -0
- package/package.json +2 -1
- package/src/blocks/custom-code/custom-code.svelte +37 -40
- package/src/blocks/image/image.svelte +1 -1
- package/src/components/content/components/enable-editor.svelte +97 -79
- package/src/constants/sdk-version.ts +1 -1
- package/src/functions/evaluate/choose-eval.ts +22 -0
- package/src/functions/evaluate/evaluate.ts +8 -37
- package/src/functions/evaluate/helpers.ts +24 -1
- package/src/functions/evaluate/node-runtime/index.ts +1 -1
- package/src/functions/evaluate/node-runtime/node-runtime.ts +138 -0
- package/src/functions/evaluate/node-runtime/safeDynamicRequire.ts +18 -0
- package/src/functions/get-content/generate-content-url.ts +36 -1
- package/src/functions/get-content/types.ts +101 -3
- package/src/functions/is-edge-runtime.ts +2 -2
- package/src/functions/is-node-runtime.ts +8 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { runInBrowser } from './browser-runtime/browser.js';
|
|
2
|
+
import { isBrowser } from '../is-browser.js';
|
|
3
|
+
/**
|
|
4
|
+
* THIS IS A MAGICAL IMPORT. It is aliased by the build process of every SDK configuration, so that
|
|
5
|
+
* it points to the correct runtime for that configuration, which are expected to live exactly at:
|
|
6
|
+
* - ./browser-runtime/index.js
|
|
7
|
+
* - ./node-runtime/index.js
|
|
8
|
+
* - ./edge-runtime/index.js
|
|
9
|
+
*
|
|
10
|
+
* We have code in `/output-generation` that does this aliasing, and is re-used by each SDK.
|
|
11
|
+
* Also, each individual `tsconfig.json` aliases this import to the browser runtime so that the
|
|
12
|
+
* types can be resolved correctly.
|
|
13
|
+
*/
|
|
14
|
+
import { evaluator } from '../../../node/functions/evaluate/node-runtime/index.js';
|
|
15
|
+
/**
|
|
16
|
+
* Even though we have separate runtimes for browser/node/edge, sometimes frameworks will
|
|
17
|
+
* end up sending the server runtime code to the browser (most notably in dev mode).
|
|
18
|
+
*/
|
|
19
|
+
export const chooseBrowserOrServerEval = (args) => isBrowser() ? runInBrowser(args) : evaluator(args);
|
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export type EvaluatorArgs = Omit<ExecutorArgs, 'builder' | 'event'> & {
|
|
3
|
-
event?: Event;
|
|
4
|
-
isExpression?: boolean;
|
|
5
|
-
};
|
|
1
|
+
import type { EvaluatorArgs } from './helpers.js';
|
|
6
2
|
export declare function evaluate({ code, context, localState, rootState, rootSetState, event, isExpression }: EvaluatorArgs): any;
|
|
@@ -1,39 +1,16 @@
|
|
|
1
1
|
import { logger } from '../../helpers/logger.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { getUserAttributes } from '../track/helpers.js';
|
|
5
|
-
/**
|
|
6
|
-
* THIS IS A MAGICAL IMPORT. It is aliased by the build process of every SDK configuration, so that
|
|
7
|
-
* it points to the correct runtime for that configuration, which are expected to live exactly at:
|
|
8
|
-
* - ./browser-runtime/index.js
|
|
9
|
-
* - ./node-runtime/index.js
|
|
10
|
-
* - ./edge-runtime/index.js
|
|
11
|
-
*
|
|
12
|
-
* We have code in `/output-generation` that does this aliasing, and is re-used by each SDK.
|
|
13
|
-
* Also, each individual `tsconfig.json` aliases this import to the browser runtime so that the
|
|
14
|
-
* types can be resolved correctly.
|
|
15
|
-
*/
|
|
16
|
-
import { evaluator } from '../../../node/functions/evaluate/node-runtime/index.js';
|
|
2
|
+
import { getBuilderGlobals, parseCode } from './helpers.js';
|
|
3
|
+
import { chooseBrowserOrServerEval } from './choose-eval.js';
|
|
17
4
|
export function evaluate({ code, context, localState, rootState, rootSetState, event, isExpression = true }) {
|
|
18
5
|
if (code === '') {
|
|
19
6
|
logger.warn('Skipping evaluation of empty code block.');
|
|
20
7
|
return;
|
|
21
8
|
}
|
|
22
|
-
const builder = {
|
|
23
|
-
isEditing: isEditing(),
|
|
24
|
-
isBrowser: isBrowser(),
|
|
25
|
-
isServer: !isBrowser(),
|
|
26
|
-
getUserAttributes: () => getUserAttributes()
|
|
27
|
-
};
|
|
28
|
-
// Be able to handle simple expressions like "state.foo" or "1 + 1"
|
|
29
|
-
// as well as full blocks like "var foo = "bar"; return foo"
|
|
30
|
-
const useReturn =
|
|
31
|
-
// we disable this for cases where we definitely don't want a return
|
|
32
|
-
isExpression && !(code.includes(';') || code.includes(' return ') || code.trim().startsWith('return '));
|
|
33
|
-
const useCode = useReturn ? `return (${code});` : code;
|
|
34
9
|
const args = {
|
|
35
|
-
code:
|
|
36
|
-
|
|
10
|
+
code: parseCode(code, {
|
|
11
|
+
isExpression
|
|
12
|
+
}),
|
|
13
|
+
builder: getBuilderGlobals(),
|
|
37
14
|
context,
|
|
38
15
|
event,
|
|
39
16
|
rootSetState,
|
|
@@ -41,7 +18,7 @@ export function evaluate({ code, context, localState, rootState, rootSetState, e
|
|
|
41
18
|
localState
|
|
42
19
|
};
|
|
43
20
|
try {
|
|
44
|
-
return
|
|
21
|
+
return chooseBrowserOrServerEval(args);
|
|
45
22
|
}
|
|
46
23
|
catch (e) {
|
|
47
24
|
logger.error('Failed code evaluation: ' + e.message, {
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { BuilderContextInterface, BuilderRenderState } from '../../context/types.js';
|
|
2
|
-
import
|
|
2
|
+
import { getUserAttributes } from '../track/helpers.js';
|
|
3
|
+
export type EvaluatorArgs = Omit<ExecutorArgs, 'builder' | 'event'> & {
|
|
4
|
+
event?: Event;
|
|
5
|
+
isExpression?: boolean;
|
|
6
|
+
};
|
|
3
7
|
export type BuilderGlobals = {
|
|
4
8
|
isEditing: boolean | undefined;
|
|
5
9
|
isBrowser: boolean | undefined;
|
|
@@ -16,3 +20,5 @@ export type FunctionArguments = ReturnType<typeof getFunctionArguments>;
|
|
|
16
20
|
export declare const getFunctionArguments: ({ builder, context, event, state }: Pick<ExecutorArgs, "context" | "builder" | "event"> & {
|
|
17
21
|
state: BuilderRenderState;
|
|
18
22
|
}) => [string, Event | BuilderRenderState | import("../../context/types.js").BuilderRenderContext | BuilderGlobals | undefined][];
|
|
23
|
+
export declare const getBuilderGlobals: () => BuilderGlobals;
|
|
24
|
+
export declare const parseCode: (code: string, { isExpression }: Pick<EvaluatorArgs, 'isExpression'>) => string;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { isBrowser } from '../is-browser.js';
|
|
2
|
+
import { isEditing } from '../is-editing.js';
|
|
3
|
+
import { getUserAttributes } from '../track/helpers.js';
|
|
1
4
|
export const getFunctionArguments = ({ builder, context, event, state }) => {
|
|
2
5
|
return Object.entries({
|
|
3
6
|
state,
|
|
@@ -8,3 +11,18 @@ export const getFunctionArguments = ({ builder, context, event, state }) => {
|
|
|
8
11
|
event
|
|
9
12
|
});
|
|
10
13
|
};
|
|
14
|
+
export const getBuilderGlobals = () => ({
|
|
15
|
+
isEditing: isEditing(),
|
|
16
|
+
isBrowser: isBrowser(),
|
|
17
|
+
isServer: !isBrowser(),
|
|
18
|
+
getUserAttributes: () => getUserAttributes()
|
|
19
|
+
});
|
|
20
|
+
export const parseCode = (code, { isExpression = true }) => {
|
|
21
|
+
// Be able to handle simple expressions like "state.foo" or "1 + 1"
|
|
22
|
+
// as well as full blocks like "var foo = "bar"; return foo"
|
|
23
|
+
const useReturn =
|
|
24
|
+
// we disable this for cases where we definitely don't want a return
|
|
25
|
+
isExpression && !(code.includes(';') || code.includes(' return ') || code.trim().startsWith('return '));
|
|
26
|
+
const useCode = useReturn ? `return (${code});` : code;
|
|
27
|
+
return useCode;
|
|
28
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { evaluator } from '
|
|
1
|
+
export { runInNode as evaluator } from './node-runtime.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { evaluator } from '
|
|
1
|
+
export { runInNode as evaluator } from './node-runtime.js';
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { getFunctionArguments } from '../helpers.js';
|
|
2
|
+
import { safeDynamicRequire } from './safeDynamicRequire.js';
|
|
3
|
+
import { fastClone } from '../../fast-clone.js';
|
|
4
|
+
import { set } from '../../set.js';
|
|
5
|
+
const ivm = safeDynamicRequire('isolated-vm');
|
|
6
|
+
const getSyncValName = (key) => `bldr_${key}_sync`;
|
|
7
|
+
const BUILDER_SET_STATE_NAME = 'BUILDER_SET_STATE';
|
|
8
|
+
const INJECTED_IVM_GLOBAL = 'BUILDER_IVM';
|
|
9
|
+
// Convert all argument references to proxies, and pass `copySync` method to target object, to return a copy of the original JS object
|
|
10
|
+
// https://github.com/laverdet/isolated-vm#referencecopysync
|
|
11
|
+
const REF_TO_PROXY_FN = `
|
|
12
|
+
var refToProxy = (obj) => {
|
|
13
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
14
|
+
return obj;
|
|
15
|
+
}
|
|
16
|
+
return new Proxy({}, {
|
|
17
|
+
get(target, key) {
|
|
18
|
+
if (key === 'copySync') {
|
|
19
|
+
return () => obj.copySync();
|
|
20
|
+
}
|
|
21
|
+
const val = obj.getSync(key);
|
|
22
|
+
if (typeof val?.getSync === 'function') {
|
|
23
|
+
return refToProxy(val);
|
|
24
|
+
}
|
|
25
|
+
return val;
|
|
26
|
+
},
|
|
27
|
+
set(target, key, value) {
|
|
28
|
+
const v = typeof value === 'object' ? new ${INJECTED_IVM_GLOBAL}.Reference(value) : value;
|
|
29
|
+
obj.setSync(key, v);
|
|
30
|
+
${BUILDER_SET_STATE_NAME}(key, value)
|
|
31
|
+
},
|
|
32
|
+
deleteProperty(target, key) {
|
|
33
|
+
obj.deleteSync(key);
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
`;
|
|
38
|
+
const processCode = ({ code, args }) => {
|
|
39
|
+
const fnArgs = args.map(([name]) => `var ${name} = refToProxy(${getSyncValName(name)}); `).join('');
|
|
40
|
+
// the output is stringified and parsed back to the parent isolate if needed (when it's an `object`)
|
|
41
|
+
return `
|
|
42
|
+
${REF_TO_PROXY_FN}
|
|
43
|
+
${fnArgs}
|
|
44
|
+
function theFunction() {
|
|
45
|
+
${code}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let output = theFunction()
|
|
49
|
+
|
|
50
|
+
if (typeof output === 'object' && output !== null) {
|
|
51
|
+
output = JSON.stringify(output.copySync ? output.copySync() : output);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
output;
|
|
55
|
+
`;
|
|
56
|
+
};
|
|
57
|
+
const getIsolateContext = () => {
|
|
58
|
+
// if (Builder.serverContext) {
|
|
59
|
+
// return Builder.serverContext;
|
|
60
|
+
// }
|
|
61
|
+
// Builder.setServerContext(isolate.createContextSync());
|
|
62
|
+
const isolate = new ivm.Isolate({
|
|
63
|
+
memoryLimit: 128
|
|
64
|
+
});
|
|
65
|
+
return isolate.createContextSync();
|
|
66
|
+
};
|
|
67
|
+
export const runInNode = ({ code, builder, context, event, localState, rootSetState, rootState }) => {
|
|
68
|
+
const state = fastClone({
|
|
69
|
+
...rootState,
|
|
70
|
+
...localState
|
|
71
|
+
});
|
|
72
|
+
const args = getFunctionArguments({
|
|
73
|
+
builder,
|
|
74
|
+
context,
|
|
75
|
+
event,
|
|
76
|
+
state
|
|
77
|
+
});
|
|
78
|
+
const isolateContext = getIsolateContext();
|
|
79
|
+
const jail = isolateContext.global;
|
|
80
|
+
// This makes the global object available in the context as `global`. We use `derefInto()` here
|
|
81
|
+
// because otherwise `global` would actually be a Reference{} object in the new isolate.
|
|
82
|
+
jail.setSync('global', jail.derefInto());
|
|
83
|
+
// We will create a basic `log` function for the new isolate to use.
|
|
84
|
+
jail.setSync('log', function (...logArgs) {
|
|
85
|
+
console.log(...logArgs);
|
|
86
|
+
});
|
|
87
|
+
/**
|
|
88
|
+
* Propagate state changes back to the reactive root state.
|
|
89
|
+
*/
|
|
90
|
+
jail.setSync(BUILDER_SET_STATE_NAME, function (key, value) {
|
|
91
|
+
// mutate the `rootState` object itself. Important for cases where we do not have `rootSetState`
|
|
92
|
+
// like Qwik.
|
|
93
|
+
set(rootState, key, value);
|
|
94
|
+
// call the `rootSetState` function if it exists
|
|
95
|
+
rootSetState?.(rootState);
|
|
96
|
+
});
|
|
97
|
+
args.forEach(([key, arg]) => {
|
|
98
|
+
const val = typeof arg === 'object' ? new ivm.Reference(
|
|
99
|
+
// workaround: methods with default values for arguments is not being cloned over
|
|
100
|
+
key === 'builder' ? {
|
|
101
|
+
...arg,
|
|
102
|
+
getUserAttributes: () => arg.getUserAttributes()
|
|
103
|
+
} : arg) : null;
|
|
104
|
+
jail.setSync(getSyncValName(key), val);
|
|
105
|
+
});
|
|
106
|
+
jail.setSync(INJECTED_IVM_GLOBAL, ivm);
|
|
107
|
+
const evalStr = processCode({
|
|
108
|
+
code,
|
|
109
|
+
args
|
|
110
|
+
});
|
|
111
|
+
const resultStr = isolateContext.evalSync(evalStr);
|
|
112
|
+
try {
|
|
113
|
+
// returning objects throw errors in isolated vm, so we stringify it and parse it back
|
|
114
|
+
const res = JSON.parse(resultStr);
|
|
115
|
+
return res;
|
|
116
|
+
}
|
|
117
|
+
catch (_error) {
|
|
118
|
+
return resultStr;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="react-native" />
|
|
3
|
+
/**
|
|
4
|
+
* Allows us to require node-specific code safely within bundlers.
|
|
5
|
+
*
|
|
6
|
+
* https://github.com/laverdet/isolated-vm/issues/423
|
|
7
|
+
*
|
|
8
|
+
* NOTE: this code should only ever run in `node`, and never in an `edge` runtime.
|
|
9
|
+
* This is guaranteed by the fact that each SDK has separate bundles for each runtime.
|
|
10
|
+
* However, it might still end up running in the `browser` if the `node` bundle is loaded in the
|
|
11
|
+
* browser (which happens in many apps' dev mode, and certain other scenarios like Qwik's prod mode).
|
|
12
|
+
*/
|
|
13
|
+
export declare let safeDynamicRequire: typeof require;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const noop = () => null;
|
|
2
|
+
/**
|
|
3
|
+
* Allows us to require node-specific code safely within bundlers.
|
|
4
|
+
*
|
|
5
|
+
* https://github.com/laverdet/isolated-vm/issues/423
|
|
6
|
+
*
|
|
7
|
+
* NOTE: this code should only ever run in `node`, and never in an `edge` runtime.
|
|
8
|
+
* This is guaranteed by the fact that each SDK has separate bundles for each runtime.
|
|
9
|
+
* However, it might still end up running in the `browser` if the `node` bundle is loaded in the
|
|
10
|
+
* browser (which happens in many apps' dev mode, and certain other scenarios like Qwik's prod mode).
|
|
11
|
+
*/
|
|
12
|
+
export let safeDynamicRequire = noop;
|
|
13
|
+
try {
|
|
14
|
+
safeDynamicRequire = eval('require');
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
/* empty */
|
|
18
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { flatten } from '../../helpers/flatten.js';
|
|
2
2
|
import { getBuilderSearchParamsFromWindow, normalizeSearchParams } from '../get-builder-search-params/index.js';
|
|
3
3
|
import { DEFAULT_API_VERSION } from '../../types/api-version.js';
|
|
4
|
+
const isPositiveNumber = (thing) => typeof thing === 'number' && !isNaN(thing) && thing >= 0;
|
|
4
5
|
export const generateContentUrl = (options) => {
|
|
5
6
|
let { noTraverse = false } = options;
|
|
6
|
-
const { limit = 30, userAttributes, query, model, apiKey, includeRefs = true, enrich, locale, apiVersion = DEFAULT_API_VERSION } = options;
|
|
7
|
+
const { limit = 30, userAttributes, query, model, apiKey, includeRefs = true, enrich, locale, apiVersion = DEFAULT_API_VERSION, fields, omit, offset, cacheSeconds, staleCacheSeconds, sort, includeUnpublished } = options;
|
|
7
8
|
if (!apiKey) {
|
|
8
9
|
throw new Error('Missing API key');
|
|
9
10
|
}
|
|
@@ -15,6 +16,31 @@ export const generateContentUrl = (options) => {
|
|
|
15
16
|
noTraverse = true;
|
|
16
17
|
}
|
|
17
18
|
const url = new URL(`https://cdn.builder.io/api/${apiVersion}/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${locale ? `&locale=${locale}` : ''}${enrich ? `&enrich=${enrich}` : ''}`);
|
|
19
|
+
url.searchParams.set('omit', omit || 'meta.componentsUsed');
|
|
20
|
+
if (fields) {
|
|
21
|
+
url.searchParams.set('fields', fields);
|
|
22
|
+
}
|
|
23
|
+
if (Number.isFinite(offset) && offset > -1) {
|
|
24
|
+
url.searchParams.set('offset', String(Math.floor(offset)));
|
|
25
|
+
}
|
|
26
|
+
if (typeof includeUnpublished === 'boolean') {
|
|
27
|
+
url.searchParams.set('includeUnpublished', String(includeUnpublished));
|
|
28
|
+
}
|
|
29
|
+
if (cacheSeconds && isPositiveNumber(cacheSeconds)) {
|
|
30
|
+
url.searchParams.set('cacheSeconds', String(cacheSeconds));
|
|
31
|
+
}
|
|
32
|
+
if (staleCacheSeconds && isPositiveNumber(staleCacheSeconds)) {
|
|
33
|
+
url.searchParams.set('staleCacheSeconds', String(staleCacheSeconds));
|
|
34
|
+
}
|
|
35
|
+
if (sort) {
|
|
36
|
+
const flattened = flatten({
|
|
37
|
+
sort
|
|
38
|
+
});
|
|
39
|
+
for (const key in flattened) {
|
|
40
|
+
url.searchParams.set(key, JSON.stringify(flattened[key]));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// TODO: how to express 'offset' in the url - as direct queryparam or as flattened in options[key] ?
|
|
18
44
|
const queryOptions = {
|
|
19
45
|
...getBuilderSearchParamsFromWindow(),
|
|
20
46
|
...normalizeSearchParams(options.options || {})
|
|
@@ -5,11 +5,42 @@ export interface GetContentOptions {
|
|
|
5
5
|
apiKey: string;
|
|
6
6
|
/** Number of items to fetch. Default is 1 */
|
|
7
7
|
limit?: number;
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Use to specify an offset for pagination of results. The default is 0.
|
|
10
|
+
*/
|
|
11
|
+
offset?: number;
|
|
12
|
+
/**
|
|
13
|
+
* User attribute key value pairs to be used for targeting
|
|
14
|
+
* https://www.builder.io/c/docs/custom-targeting-attributes
|
|
15
|
+
*
|
|
16
|
+
* e.g.
|
|
17
|
+
* ```js
|
|
18
|
+
* userAttributes: {
|
|
19
|
+
* urlPath: '/',
|
|
20
|
+
* returnVisitor: true,
|
|
21
|
+
* device: 'mobile'
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
9
25
|
userAttributes?: (Record<string, string> & {
|
|
10
26
|
urlPath?: string;
|
|
11
27
|
}) | null;
|
|
12
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Mongodb style query of your data. E.g.:
|
|
30
|
+
*
|
|
31
|
+
* ```js
|
|
32
|
+
* query: {
|
|
33
|
+
* id: 'abc123',
|
|
34
|
+
* data: {
|
|
35
|
+
* myCustomField: { $gt: 20 },
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* See more info on MongoDB's query operators and format.
|
|
41
|
+
*
|
|
42
|
+
* @see {@link https://docs.mongodb.com/manual/reference/operator/query/}
|
|
43
|
+
*/
|
|
13
44
|
query?: Record<string, any>;
|
|
14
45
|
/**
|
|
15
46
|
* Any other API options.
|
|
@@ -30,7 +61,7 @@ export interface GetContentOptions {
|
|
|
30
61
|
*/
|
|
31
62
|
canTrack?: boolean;
|
|
32
63
|
/**
|
|
33
|
-
* Include references in the response. Defaults to `true`.
|
|
64
|
+
* Include content of references in the response. Defaults to `true`.
|
|
34
65
|
* @deprecated use `enrich` instead
|
|
35
66
|
*/
|
|
36
67
|
includeRefs?: boolean;
|
|
@@ -48,4 +79,64 @@ export interface GetContentOptions {
|
|
|
48
79
|
* Defaults to `v3`.
|
|
49
80
|
*/
|
|
50
81
|
apiVersion?: 'v2' | 'v3';
|
|
82
|
+
/**
|
|
83
|
+
* Only include these fields.
|
|
84
|
+
* Note: 'omit' takes precedence over 'fields'
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```
|
|
88
|
+
* fields: 'id, name, data.customField'
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
fields?: string;
|
|
92
|
+
/**
|
|
93
|
+
* Omit only these fields.
|
|
94
|
+
* Note: 'omit' takes precedence over 'fields'
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```
|
|
98
|
+
* omit: 'data.bigField,data.blocks'
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
omit?: string;
|
|
102
|
+
/**
|
|
103
|
+
* Seconds to cache content. Sets the max-age of the cache-control header
|
|
104
|
+
* response header.
|
|
105
|
+
*
|
|
106
|
+
* Use a higher value for better performance, lower for content that will change more frequently
|
|
107
|
+
*
|
|
108
|
+
* @see {@link https://www.builder.io/c/docs/query-api#__next:~:text=%26includeRefs%3Dtrue-,cacheSeconds,-No}
|
|
109
|
+
*/
|
|
110
|
+
cacheSeconds?: number;
|
|
111
|
+
/**
|
|
112
|
+
* Builder.io uses stale-while-revalidate caching at the CDN level. This means we always serve
|
|
113
|
+
* from edge cache and update caches in the background for maximum possible performance. This also
|
|
114
|
+
* means that the more frequently content is requested, the more fresh it will be. The longest we
|
|
115
|
+
* will ever hold something in stale cache is 1 day by default, and you can set this to be shorter
|
|
116
|
+
* yourself as well. We suggest keeping this high unless you have content that must change rapidly
|
|
117
|
+
* and gets very little traffic.
|
|
118
|
+
*
|
|
119
|
+
* @see {@link https://www.fastly.com/blog/prevent-application-network-instability-serve-stale-content}
|
|
120
|
+
*/
|
|
121
|
+
staleCacheSeconds?: number;
|
|
122
|
+
/**
|
|
123
|
+
* Property to order results by.
|
|
124
|
+
* Use 1 for ascending and -1 for descending.
|
|
125
|
+
*
|
|
126
|
+
* The key is what you're sorting on, so the following example sorts by createdDate
|
|
127
|
+
* and because the value is 1, the sort is ascending.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```
|
|
131
|
+
* createdDate: 1
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
sort?: {
|
|
135
|
+
[key: string]: 1 | -1;
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Include content entries in a response that are still in
|
|
139
|
+
* draft mode and un-archived. Default is false.
|
|
140
|
+
*/
|
|
141
|
+
includeUnpublished?: boolean;
|
|
51
142
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isBrowser } from './is-browser.js';
|
|
2
|
+
import { isNodeRuntime } from './is-node-runtime.js';
|
|
2
3
|
/**
|
|
3
4
|
* Identifies edge runtimes (edge, workers, serverless, etc.)
|
|
4
5
|
*/
|
|
5
6
|
export function isEdgeRuntime() {
|
|
6
|
-
|
|
7
|
-
return !isBrowser() && !hasNode();
|
|
7
|
+
return !isBrowser() && !isNodeRuntime();
|
|
8
8
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@builder.io/sdk-svelte",
|
|
3
3
|
"description": "Builder.io SDK for Svelte",
|
|
4
|
-
"version": "0.7.0",
|
|
4
|
+
"version": "0.7.1-0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"lib",
|
|
@@ -83,6 +83,7 @@
|
|
|
83
83
|
}
|
|
84
84
|
},
|
|
85
85
|
"peerDependencies": {
|
|
86
|
+
"isolated-vm": "^4.6.0",
|
|
86
87
|
"svelte": "^4.1.2"
|
|
87
88
|
}
|
|
88
89
|
}
|
|
@@ -11,55 +11,52 @@
|
|
|
11
11
|
export let replaceNodes: CustomCodeProps["replaceNodes"] = undefined;
|
|
12
12
|
export let code: CustomCodeProps["code"];
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
// TODO: Move this function to standalone one in '@builder.io/utils'
|
|
16
|
-
if (elem && elem.getElementsByTagName && typeof window !== "undefined") {
|
|
17
|
-
const scripts = elem.getElementsByTagName("script");
|
|
18
|
-
for (let i = 0; i < scripts.length; i++) {
|
|
19
|
-
const script = scripts[i];
|
|
20
|
-
if (script.src) {
|
|
21
|
-
if (scriptsInserted.includes(script.src)) {
|
|
22
|
-
continue;
|
|
23
|
-
}
|
|
24
|
-
scriptsInserted.push(script.src);
|
|
25
|
-
const newScript = document.createElement("script");
|
|
26
|
-
newScript.async = true;
|
|
27
|
-
newScript.src = script.src;
|
|
28
|
-
document.head.appendChild(newScript);
|
|
29
|
-
} else if (
|
|
30
|
-
!script.type ||
|
|
31
|
-
[
|
|
32
|
-
"text/javascript",
|
|
33
|
-
"application/javascript",
|
|
34
|
-
"application/ecmascript",
|
|
35
|
-
].includes(script.type)
|
|
36
|
-
) {
|
|
37
|
-
if (scriptsRun.includes(script.innerText)) {
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
try {
|
|
41
|
-
scriptsRun.push(script.innerText);
|
|
42
|
-
new Function(script.innerText)();
|
|
43
|
-
} catch (error) {
|
|
44
|
-
console.warn("`CustomCode`: Error running script:", error);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
let elem;
|
|
14
|
+
let elementRef;
|
|
52
15
|
|
|
53
16
|
let scriptsInserted = [];
|
|
54
17
|
let scriptsRun = [];
|
|
55
18
|
|
|
56
19
|
onMount(() => {
|
|
57
|
-
|
|
20
|
+
// TODO: Move this function to standalone one in '@builder.io/utils'
|
|
21
|
+
if (!elementRef?.getElementsByTagName || typeof window === "undefined") {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const scripts = elementRef.getElementsByTagName("script");
|
|
25
|
+
for (let i = 0; i < scripts.length; i++) {
|
|
26
|
+
const script = scripts[i];
|
|
27
|
+
if (script.src) {
|
|
28
|
+
if (scriptsInserted.includes(script.src)) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
scriptsInserted.push(script.src);
|
|
32
|
+
const newScript = document.createElement("script");
|
|
33
|
+
newScript.async = true;
|
|
34
|
+
newScript.src = script.src;
|
|
35
|
+
document.head.appendChild(newScript);
|
|
36
|
+
} else if (
|
|
37
|
+
!script.type ||
|
|
38
|
+
[
|
|
39
|
+
"text/javascript",
|
|
40
|
+
"application/javascript",
|
|
41
|
+
"application/ecmascript",
|
|
42
|
+
].includes(script.type)
|
|
43
|
+
) {
|
|
44
|
+
if (scriptsRun.includes(script.innerText)) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
scriptsRun.push(script.innerText);
|
|
49
|
+
new Function(script.innerText)();
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.warn("`CustomCode`: Error running script:", error);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
58
55
|
});
|
|
59
56
|
</script>
|
|
60
57
|
|
|
61
58
|
<div
|
|
62
|
-
bind:this={
|
|
59
|
+
bind:this={elementRef}
|
|
63
60
|
class={"builder-custom-code" + (replaceNodes ? " replace-nodes" : "")}
|
|
64
61
|
>
|
|
65
62
|
{@html code}
|