Socket
Socket
Sign inDemoInstall

@stackblitz/sdk

Package Overview
Dependencies
Maintainers
4
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@stackblitz/sdk - npm Package Compare versions

Comparing version 1.9.0-alpha.1 to 1.9.0-alpha.2

77

bundles/sdk.js

@@ -16,2 +16,5 @@ "use strict";

];
const UI_SIDEBAR_VIEWS = ["project", "search", "ports", "settings"];
const UI_THEMES = ["light", "dark"];
const UI_VIEWS = ["editor", "preview"];
const generators = {

@@ -24,7 +27,10 @@ clickToLoad: (value) => trueParam("ctl", value),

hideNavigation: (value) => trueParam("hideNavigation", value),
openFile: (value) => stringParams("file", value),
showSidebar: (value) => booleanParam("showSidebar", value),
openFile: (value) => stringParams("file", value).join("&"),
sidebarView: (value) => enumParam("sidebarView", value, UI_SIDEBAR_VIEWS),
startScript: (value) => stringParams("startScript", value),
terminalHeight: (value) => percentParam("terminalHeight", value),
theme: (value) => enumParam("theme", ["light", "dark"], value),
view: (value) => enumParam("view", ["preview", "editor"], value)
theme: (value) => enumParam("theme", value, UI_THEMES),
view: (value) => enumParam("view", value, UI_VIEWS),
zenMode: (value) => trueParam("zenMode", value)
};

@@ -55,9 +61,9 @@ function buildParams(options = {}) {

const clamped = Math.min(100, Math.max(0, value));
return `${name}=${Math.round(clamped)}`;
return `${name}=${encodeURIComponent(Math.round(clamped))}`;
}
return "";
}
function enumParam(name, oneOf, value) {
if (typeof value === "string" && oneOf.includes(value)) {
return `${name}=${value}`;
function enumParam(name, value = "", allowList = []) {
if (allowList.includes(value)) {
return `${name}=${encodeURIComponent(value)}`;
}

@@ -68,3 +74,3 @@ return "";

const values = Array.isArray(value) ? value : [value];
return values.filter((val) => typeof val === "string" && val.trim() !== "").map((val) => `${name}=${encodeURIComponent(val.trim())}`);
return values.filter((val) => typeof val === "string" && val.trim() !== "").map((val) => `${name}=${encodeURIComponent(val)}`).join("&");
}

@@ -395,19 +401,28 @@ function genID() {

}
function bracketedFilePath(path) {
return `[${path.replace(/\[/g, "%5B").replace(/\]/g, "%5D")}]`;
function encodeFilePath(path) {
return path.replace(/\[/g, "%5B").replace(/\]/g, "%5D");
}
function createProjectForm(project) {
if (!PROJECT_TEMPLATES.includes(project.template)) {
function createProjectForm({
template,
title,
description,
dependencies,
files,
settings
}) {
if (!PROJECT_TEMPLATES.includes(template)) {
const names = PROJECT_TEMPLATES.map((t) => `'${t}'`).join(", ");
console.warn(`Unsupported project.template: must be one of ${names}`);
}
const isWebContainers = project.template === "node";
const form = document.createElement("form");
form.method = "POST";
form.setAttribute("style", "display:none!important;");
form.appendChild(createHiddenInput("project[title]", project.title));
form.appendChild(createHiddenInput("project[description]", project.description));
form.appendChild(createHiddenInput("project[template]", project.template));
if (project.dependencies) {
if (isWebContainers) {
const inputs = [];
const addInput = (name, value, defaultValue = "") => {
inputs.push(createHiddenInput(name, typeof value === "string" ? value : defaultValue));
};
addInput("project[title]", title);
if (typeof description === "string" && description.length > 0) {
addInput("project[description]", description);
}
addInput("project[template]", template, "javascript");
if (dependencies) {
if (template === "node") {
console.warn(

@@ -417,17 +432,15 @@ `Invalid project.dependencies: dependencies must be provided as a 'package.json' file when using the 'node' template.`

} else {
form.appendChild(
createHiddenInput("project[dependencies]", JSON.stringify(project.dependencies))
);
addInput("project[dependencies]", JSON.stringify(dependencies));
}
}
if (project.settings) {
form.appendChild(createHiddenInput("project[settings]", JSON.stringify(project.settings)));
if (settings) {
addInput("project[settings]", JSON.stringify(settings));
}
Object.keys(project.files).forEach((path) => {
const name = "project[files]" + bracketedFilePath(path);
const value = project.files[path];
if (typeof value === "string") {
form.appendChild(createHiddenInput(name, value));
}
Object.entries(files).forEach(([path, contents]) => {
addInput(`project[files][${encodeFilePath(path)}]`, contents);
});
const form = document.createElement("form");
form.method = "POST";
form.setAttribute("style", "display:none!important;");
form.append(...inputs);
return form;

@@ -434,0 +447,0 @@ }

@@ -15,2 +15,5 @@ const CONNECT_INTERVAL = 500;

];
const UI_SIDEBAR_VIEWS = ["project", "search", "ports", "settings"];
const UI_THEMES = ["light", "dark"];
const UI_VIEWS = ["editor", "preview"];
const generators = {

@@ -23,7 +26,10 @@ clickToLoad: (value) => trueParam("ctl", value),

hideNavigation: (value) => trueParam("hideNavigation", value),
openFile: (value) => stringParams("file", value),
showSidebar: (value) => booleanParam("showSidebar", value),
openFile: (value) => stringParams("file", value).join("&"),
sidebarView: (value) => enumParam("sidebarView", value, UI_SIDEBAR_VIEWS),
startScript: (value) => stringParams("startScript", value),
terminalHeight: (value) => percentParam("terminalHeight", value),
theme: (value) => enumParam("theme", ["light", "dark"], value),
view: (value) => enumParam("view", ["preview", "editor"], value)
theme: (value) => enumParam("theme", value, UI_THEMES),
view: (value) => enumParam("view", value, UI_VIEWS),
zenMode: (value) => trueParam("zenMode", value)
};

@@ -54,9 +60,9 @@ function buildParams(options = {}) {

const clamped = Math.min(100, Math.max(0, value));
return `${name}=${Math.round(clamped)}`;
return `${name}=${encodeURIComponent(Math.round(clamped))}`;
}
return "";
}
function enumParam(name, oneOf, value) {
if (typeof value === "string" && oneOf.includes(value)) {
return `${name}=${value}`;
function enumParam(name, value = "", allowList = []) {
if (allowList.includes(value)) {
return `${name}=${encodeURIComponent(value)}`;
}

@@ -67,3 +73,3 @@ return "";

const values = Array.isArray(value) ? value : [value];
return values.filter((val) => typeof val === "string" && val.trim() !== "").map((val) => `${name}=${encodeURIComponent(val.trim())}`);
return values.filter((val) => typeof val === "string" && val.trim() !== "").map((val) => `${name}=${encodeURIComponent(val)}`).join("&");
}

@@ -394,19 +400,28 @@ function genID() {

}
function bracketedFilePath(path) {
return `[${path.replace(/\[/g, "%5B").replace(/\]/g, "%5D")}]`;
function encodeFilePath(path) {
return path.replace(/\[/g, "%5B").replace(/\]/g, "%5D");
}
function createProjectForm(project) {
if (!PROJECT_TEMPLATES.includes(project.template)) {
function createProjectForm({
template,
title,
description,
dependencies,
files,
settings
}) {
if (!PROJECT_TEMPLATES.includes(template)) {
const names = PROJECT_TEMPLATES.map((t) => `'${t}'`).join(", ");
console.warn(`Unsupported project.template: must be one of ${names}`);
}
const isWebContainers = project.template === "node";
const form = document.createElement("form");
form.method = "POST";
form.setAttribute("style", "display:none!important;");
form.appendChild(createHiddenInput("project[title]", project.title));
form.appendChild(createHiddenInput("project[description]", project.description));
form.appendChild(createHiddenInput("project[template]", project.template));
if (project.dependencies) {
if (isWebContainers) {
const inputs = [];
const addInput = (name, value, defaultValue = "") => {
inputs.push(createHiddenInput(name, typeof value === "string" ? value : defaultValue));
};
addInput("project[title]", title);
if (typeof description === "string" && description.length > 0) {
addInput("project[description]", description);
}
addInput("project[template]", template, "javascript");
if (dependencies) {
if (template === "node") {
console.warn(

@@ -416,17 +431,15 @@ `Invalid project.dependencies: dependencies must be provided as a 'package.json' file when using the 'node' template.`

} else {
form.appendChild(
createHiddenInput("project[dependencies]", JSON.stringify(project.dependencies))
);
addInput("project[dependencies]", JSON.stringify(dependencies));
}
}
if (project.settings) {
form.appendChild(createHiddenInput("project[settings]", JSON.stringify(project.settings)));
if (settings) {
addInput("project[settings]", JSON.stringify(settings));
}
Object.keys(project.files).forEach((path) => {
const name = "project[files]" + bracketedFilePath(path);
const value = project.files[path];
if (typeof value === "string") {
form.appendChild(createHiddenInput(name, value));
}
Object.entries(files).forEach(([path, contents]) => {
addInput(`project[files][${encodeFilePath(path)}]`, contents);
});
const form = document.createElement("form");
form.method = "POST";
form.setAttribute("style", "display:none!important;");
form.append(...inputs);
return form;

@@ -433,0 +446,0 @@ }

@@ -19,2 +19,5 @@ (function(global, factory) {

];
const UI_SIDEBAR_VIEWS = ["project", "search", "ports", "settings"];
const UI_THEMES = ["light", "dark"];
const UI_VIEWS = ["editor", "preview"];
const generators = {

@@ -27,7 +30,10 @@ clickToLoad: (value) => trueParam("ctl", value),

hideNavigation: (value) => trueParam("hideNavigation", value),
openFile: (value) => stringParams("file", value),
showSidebar: (value) => booleanParam("showSidebar", value),
openFile: (value) => stringParams("file", value).join("&"),
sidebarView: (value) => enumParam("sidebarView", value, UI_SIDEBAR_VIEWS),
startScript: (value) => stringParams("startScript", value),
terminalHeight: (value) => percentParam("terminalHeight", value),
theme: (value) => enumParam("theme", ["light", "dark"], value),
view: (value) => enumParam("view", ["preview", "editor"], value)
theme: (value) => enumParam("theme", value, UI_THEMES),
view: (value) => enumParam("view", value, UI_VIEWS),
zenMode: (value) => trueParam("zenMode", value)
};

@@ -58,9 +64,9 @@ function buildParams(options = {}) {

const clamped = Math.min(100, Math.max(0, value));
return `${name}=${Math.round(clamped)}`;
return `${name}=${encodeURIComponent(Math.round(clamped))}`;
}
return "";
}
function enumParam(name, oneOf, value) {
if (typeof value === "string" && oneOf.includes(value)) {
return `${name}=${value}`;
function enumParam(name, value = "", allowList = []) {
if (allowList.includes(value)) {
return `${name}=${encodeURIComponent(value)}`;
}

@@ -71,3 +77,3 @@ return "";

const values = Array.isArray(value) ? value : [value];
return values.filter((val) => typeof val === "string" && val.trim() !== "").map((val) => `${name}=${encodeURIComponent(val.trim())}`);
return values.filter((val) => typeof val === "string" && val.trim() !== "").map((val) => `${name}=${encodeURIComponent(val)}`).join("&");
}

@@ -398,19 +404,28 @@ function genID() {

}
function bracketedFilePath(path) {
return `[${path.replace(/\[/g, "%5B").replace(/\]/g, "%5D")}]`;
function encodeFilePath(path) {
return path.replace(/\[/g, "%5B").replace(/\]/g, "%5D");
}
function createProjectForm(project) {
if (!PROJECT_TEMPLATES.includes(project.template)) {
function createProjectForm({
template,
title,
description,
dependencies,
files,
settings
}) {
if (!PROJECT_TEMPLATES.includes(template)) {
const names = PROJECT_TEMPLATES.map((t) => `'${t}'`).join(", ");
console.warn(`Unsupported project.template: must be one of ${names}`);
}
const isWebContainers = project.template === "node";
const form = document.createElement("form");
form.method = "POST";
form.setAttribute("style", "display:none!important;");
form.appendChild(createHiddenInput("project[title]", project.title));
form.appendChild(createHiddenInput("project[description]", project.description));
form.appendChild(createHiddenInput("project[template]", project.template));
if (project.dependencies) {
if (isWebContainers) {
const inputs = [];
const addInput = (name, value, defaultValue = "") => {
inputs.push(createHiddenInput(name, typeof value === "string" ? value : defaultValue));
};
addInput("project[title]", title);
if (typeof description === "string" && description.length > 0) {
addInput("project[description]", description);
}
addInput("project[template]", template, "javascript");
if (dependencies) {
if (template === "node") {
console.warn(

@@ -420,17 +435,15 @@ `Invalid project.dependencies: dependencies must be provided as a 'package.json' file when using the 'node' template.`

} else {
form.appendChild(
createHiddenInput("project[dependencies]", JSON.stringify(project.dependencies))
);
addInput("project[dependencies]", JSON.stringify(dependencies));
}
}
if (project.settings) {
form.appendChild(createHiddenInput("project[settings]", JSON.stringify(project.settings)));
if (settings) {
addInput("project[settings]", JSON.stringify(settings));
}
Object.keys(project.files).forEach((path) => {
const name = "project[files]" + bracketedFilePath(path);
const value = project.files[path];
if (typeof value === "string") {
form.appendChild(createHiddenInput(name, value));
}
Object.entries(files).forEach(([path, contents]) => {
addInput(`project[files][${encodeFilePath(path)}]`, contents);
});
const form = document.createElement("form");
form.method = "POST";
form.setAttribute("style", "display:none!important;");
form.append(...inputs);
return form;

@@ -437,0 +450,0 @@ }

# @stackblitz/sdk changelog
## v1.9.0 (unreleased)
- Moved the StackBlitz SDK to a dedicated repository: https://github.com/stackblitz/sdk.
- Added support for new options: `startScript`, `sidebarView` and `zenMode`. (https://github.com/stackblitz/sdk/pull/4)
- Changed `project.description` to be optional. (https://github.com/stackblitz/sdk/pull/5)
## v1.8.2 (2023-01-26)

@@ -4,0 +10,0 @@

{
"name": "@stackblitz/sdk",
"version": "1.9.0-alpha.1",
"version": "1.9.0-alpha.2",
"description": "SDK for generating and embedding StackBlitz projects.",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -21,1 +21,13 @@ /**

export declare const PROJECT_TEMPLATES: readonly ["angular-cli", "create-react-app", "html", "javascript", "node", "polymer", "typescript", "vue"];
/**
* Supported sidebar views
*/
export declare const UI_SIDEBAR_VIEWS: readonly ["project", "search", "ports", "settings"];
/**
* Supported editor themes
*/
export declare const UI_THEMES: readonly ["light", "dark"];
/**
* Supported editor view modes
*/
export declare const UI_VIEWS: readonly ["editor", "preview"];
import type { Project, EmbedOptions, OpenOptions } from './interfaces';
export declare function createProjectForm(project: Project): HTMLFormElement;
export declare function createProjectForm({ template, title, description, dependencies, files, settings, }: Project): HTMLFormElement;
export declare function createProjectFrameHTML(project: Project, options?: EmbedOptions): string;
export declare function openNewProject(project: Project, options?: OpenOptions): void;
import { connect, embedGithubProject, embedProject, embedProjectId, openGithubProject, openProject, openProjectId } from './lib';
export type { Project, ProjectOptions, ProjectDependencies, ProjectFiles, ProjectSettings, ProjectTemplate, EmbedOptions, OpenOptions, OpenFileOption, UiThemeOption, UiViewOption, } from './interfaces';
export type { Project, ProjectDependencies, ProjectFiles, ProjectSettings, ProjectTemplate, ProjectOptions, EmbedOptions, OpenOptions, OpenFileOption, UiThemeOption, UiViewOption, } from './interfaces';
export type { FsDiff, VM } from './vm';

@@ -4,0 +4,0 @@ declare const StackBlitzSDK: {

@@ -1,5 +0,5 @@

import type { PROJECT_TEMPLATES } from './constants';
import type { PROJECT_TEMPLATES, UI_SIDEBAR_VIEWS, UI_THEMES, UI_VIEWS } from './constants';
export interface Project {
title: string;
description: string;
description?: string;
/**

@@ -50,2 +50,38 @@ * The project’s template name tells StackBlitz how to compile and run project files.

/**
* Show a UI dialog asking users to click a button to run the project.
*
* Defaults to `false`.
*/
clickToLoad?: boolean;
/**
* Height of the Console panel below the preview page (as a percentage number, between `0` and `100`).
*
* By default, the Console will appear collapsed, and can be opened by users.
*
* This option is ignored in WebContainers-based projects.
*/
devToolsHeight?: number;
/**
* Use the “embed” layout of the editor.
*
* Defaults to `true` for `embedProject*` methods, and `false` for `openProject*` methods.
*
* @deprecated May be removed in a future release.
*/
forceEmbedLayout?: boolean;
/**
* Completely hide the Console panel below the preview page.
*
* This option is ignored in WebContainers-based projects.
*
* Defaults to `false`.
*/
hideDevTools?: boolean;
/**
* Hide the ActivityBar (sidebar icons).
*
* Defaults to `false`.
*/
hideExplorer?: boolean;
/**
* Select one or several project files to open initially.

@@ -66,64 +102,58 @@ *

/**
* Show only the code editor or only the preview page.
* Set the origin URL of your StackBlitz EE server.
*
* Defaults to showing both the editor and the preview.
* Defaults to `https://stackblitz.com`.
*/
view?: UiViewOption;
origin?: string;
/**
* Select the color theme for the editor UI.
* Show the sidebar as open or closed on page load.
*
* Available themes: `light` and `dark`.
*/
theme?: UiThemeOption;
/**
* Height of the Terminal panel below the editor (as a percentage number).
* This might be ignored on narrow viewport widths (mobile and/or tablets).
*
* Values such as `0` and `100` may not be applied as-is, but result instead in the minimum or maximum height allowed for the Terminal.
*
* The Terminal only appears in WebContainers-based projects.
* On larger viewports, defaults to `false` for `embedProject*` methods, and `true` for `openProject*` methods.
*/
terminalHeight?: number;
showSidebar?: boolean;
/**
* Height of the Console panel below the preview page (as a percentage number, between `0` and `100`).
* Choose the sidebar view to open on project load.
*
* By default, the Console will appear collapsed, and can be opened by users.
* This option is ignored in WebContainers-based projects.
* Available views: `project` (default), `search`, `ports` (WebContainers only) and `settings`.
*/
devToolsHeight?: number;
sidebarView?: UiSidebarView;
/**
* Completely hide the Console panel below the preview page.
* Name(s) of the npm script(s) to run on project load.
*
* This option is ignored in WebContainers-based projects.
*/
hideDevTools?: boolean;
/**
* Hide the ActivityBar (sidebar icons).
*/
hideExplorer?: boolean;
/**
* Show the sidebar as open or closed on page load.
* Must be a single script name, or a comma-separated list of script names, matching the keys of the `scripts` object in the `package.json` file at the root of the project. Arbitrary shell commands are not supported.
*
* This might be ignored on narrow viewport widths (mobile and/or tablets).
* Example usage:
*
* On larger viewports, defaults to `false` for `embedProject*` methods, and `true` for `openProject*` methods.
* // Run the 'build' script after dependencies are installed
* startScript: 'build'
*
* // Run the 'build' script then the 'serve' script, which may look like:
* // `npm install && npm run build && npm run serve`
* startScript: 'build,serve'
*
* Defaults to looking for a `dev` script or a `start` script. Ignored in EngineBlock projects.
*/
showSidebar?: boolean;
startScript?: string;
/**
* Use the “embed” layout of the editor.
* Height of the Terminal panel below the editor (as a percentage number).
*
* Defaults to `true` for `embedProject*` methods, and `false` for `openProject*` methods.
* Values such as `0` and `100` may not be applied as-is, but result instead in the minimum or maximum height allowed for the Terminal.
*
* @deprecated May be removed in a future release.
* The Terminal only appears in WebContainers-based projects.
*/
forceEmbedLayout?: boolean;
terminalHeight?: number;
/**
* Show a UI dialog asking users to click a button to run the project.
* Select the color theme for the editor UI.
*
* Available themes: `dark` (default) and `light`.
*/
clickToLoad?: boolean;
theme?: UiThemeOption;
/**
* Set the origin URL of your StackBlitz EE server.
* Show only the code editor or only the preview page.
*
* Defaults to `https://stackblitz.com`.
* Defaults to showing both the editor and the preview.
*/
origin?: string;
view?: UiViewOption;
}

@@ -133,5 +163,12 @@ export interface OpenOptions extends ProjectOptions {

* Opens the project in a new browser tab.
*
* Defaults to `true`; use `false` to open in the current tab.
*/
newWindow?: boolean;
/**
* Opens the project with the editor UI partially hidden (known as “zen mode”).
*
* Defaults to `false`.
*/
zenMode?: boolean;
}

@@ -153,3 +190,4 @@ export interface EmbedOptions extends ProjectOptions {

export declare type OpenFileOption = string | string[];
export declare type UiViewOption = 'default' | 'preview' | 'editor';
export declare type UiThemeOption = 'default' | 'light' | 'dark';
export declare type UiSidebarView = 'default' | (typeof UI_SIDEBAR_VIEWS)[number];
export declare type UiThemeOption = 'default' | (typeof UI_THEMES)[number];
export declare type UiViewOption = 'default' | (typeof UI_VIEWS)[number];
import type { EmbedOptions, OpenOptions } from './interfaces';
declare type Options = Omit<OpenOptions & EmbedOptions, 'origin' | 'newWindow' | 'height' | 'width'>;
export declare type ParamOptions = Omit<OpenOptions & EmbedOptions, 'origin' | 'newWindow' | 'height' | 'width'>;
/**
* URL parameter names supported by the StackBlitz instance.
* Note that while updated instances perform a case-insensitive lookup
* for query parameters, some Enterprise Edition deployments may not,
* and we need to use specific (and sometimes inconsistent) casing;
* see for example 'hidedevtools' vs 'hideNavigation'.
*
* A couple notes:
*
* - Names don't always match the keys in EmbedOptions / OpenOptions.
* For example, options use `openFile` but the expected param is `file`.
* - While updated instances perform a case-insensitive lookup for query
* parameters, some Enterprise Edition deployments may not, and we need to
* use specific (and sometimes inconsistent) casing; see for example
* 'hidedevtools' vs 'hideNavigation'.
*/
declare type ParamName = '_test' | 'clicktoload' | 'ctl' | 'devtoolsheight' | 'embed' | 'file' | 'hidedevtools' | 'hideExplorer' | 'hideNavigation' | 'initialpath' | 'showSidebar' | 'terminalHeight' | 'theme' | 'view';
export declare function buildParams(options?: Options): string;
declare type ParamName = '_test' | 'clicktoload' | 'ctl' | 'devtoolsheight' | 'embed' | 'file' | 'hidedevtools' | 'hideExplorer' | 'hideNavigation' | 'initialpath' | 'showSidebar' | 'sidebarView' | 'startScript' | 'terminalHeight' | 'theme' | 'view' | 'zenMode';
export declare const generators: Record<keyof ParamOptions, (value: any) => string>;
export declare function buildParams(options?: ParamOptions): string;
export declare function trueParam(name: ParamName, value?: boolean): string;
export declare function booleanParam(name: ParamName, value?: boolean): string;
export declare function percentParam(name: ParamName, value?: number): string;
export declare function enumParam(name: ParamName, oneOf: string[], value?: string): string;
export declare function stringParams(name: ParamName, value?: string | string[]): string[];
export declare function enumParam(name: ParamName, value?: string, allowList?: readonly string[]): string;
export declare function stringParams(name: ParamName, value?: string | string[]): string;
export {};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc