New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

seqflow-js

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

seqflow-js - npm Package Compare versions

Comparing version 0.0.1-beta.12 to 0.0.1-beta.13

tests/replaceChild.test.tsx

32

dist/index.d.ts

@@ -10,7 +10,10 @@ import { BrowserRouter, InMemoryRouter, NavigationEvent, Router } from './router';

export interface Log {
type: "info" | "debug" | "error";
message: string;
data?: unknown;
}
export type LogFunction = (log: Log) => void;
export interface LogFunction {
info: (l: Log) => void;
error: (l: Log) => void;
debug: (l: Log) => void;
}
export interface SeqflowAppContext {

@@ -61,3 +64,3 @@ log: LogFunction;

preventDefault?: boolean;
}) => EventAsyncGenerator<HTMLElementEventMap[K]>;
} | string) => EventAsyncGenerator<HTMLElementEventMap[K]>;
/**

@@ -74,2 +77,16 @@ * Wait for a domain event to happen

/**
* Get a child component by its key
*
* @param key the key of the child to get
* @returns the child component
*/
getChild(key: string): HTMLElement;
/**
* Get a child component by its key
*
* @param key the key of the child to get
* @returns the child component or null if not found
*/
findChild(key: string): HTMLElement | null;
/**
* Replace a child component with a new one

@@ -81,3 +98,3 @@ *

*/
replaceChild: (key: string, newChild: () => JSX.Element | Promise<JSX.Element>) => void;
replaceChild: (key: string, newChild: () => JSX.Element | Promise<JSX.Element>) => void | Promise<void>;
/**

@@ -115,3 +132,5 @@ * The DOM element where this component is mounted

children?: ChildenType[];
}>(root: HTMLElement, firstComponent: Component, componentOption: FirstComponentData | undefined, seqflowConfiguration: Partial<SeqflowConfiguration>): AbortController;
}>(root: HTMLElement, firstComponent: Component, componentOption: FirstComponentData | undefined, seqflowConfiguration: Partial<Omit<SeqflowConfiguration, "log"> & {
log?: Partial<LogFunction>;
}>): AbortController;
type ChildenType = Element | Element[];

@@ -130,2 +149,4 @@ declare global {

style?: Partial<CSSStyleDeclaration> | string;
onClick?: (ev: MouseEvent) => void;
key?: string;
}>;

@@ -137,2 +158,3 @@ };

key?: string;
onClick?: (ev: MouseEvent) => void;
wrapperClass?: string;

@@ -139,0 +161,0 @@ }

2

package.json
{
"name": "seqflow-js",
"version": "0.0.1-beta.12",
"version": "0.0.1-beta.13",
"description": "SeqFlow is a modern web framework that is designed to be simple and easy to use. It optimizes the development process by providing a simple and easy-to-understand API. It is a good choice for those who want to create web applications without the complexity of other frameworks.",

@@ -5,0 +5,0 @@ "main": "./dist/index.mjs",

@@ -39,3 +39,3 @@ # SeqFlow JS

// Perform an async operation
const quote = quote = await getRandomQuote();
const quote = await getRandomQuote();

@@ -42,0 +42,0 @@ // Replace loading message with quote

@@ -20,7 +20,10 @@ import * as DomainsPackage from "./domains";

export interface Log {
type: "info" | "debug" | "error";
message: string;
data?: unknown;
}
export type LogFunction = (log: Log) => void;
export interface LogFunction {
info: (l: Log) => void;
error: (l: Log) => void;
debug: (l: Log) => void;
}

@@ -76,6 +79,8 @@ export interface SeqflowAppContext {

eventType: K,
options: {
el: HTMLElement;
preventDefault?: boolean;
},
options:
| {
el: HTMLElement;
preventDefault?: boolean;
}
| string,
) => EventAsyncGenerator<HTMLElementEventMap[K]>;

@@ -95,2 +100,16 @@ /**

/**
* Get a child component by its key
*
* @param key the key of the child to get
* @returns the child component
*/
getChild(key: string): HTMLElement;
/**
* Get a child component by its key
*
* @param key the key of the child to get
* @returns the child component or null if not found
*/
findChild(key: string): HTMLElement | null;
/**
* Replace a child component with a new one

@@ -105,3 +124,3 @@ *

newChild: () => JSX.Element | Promise<JSX.Element>,
) => void;
) => void | Promise<void>;
/**

@@ -124,3 +143,5 @@ * The DOM element where this component is mounted

children,
}: { children?: ChildenType[] }): DocumentFragment;
}: {
children?: ChildenType[];
}): DocumentFragment;
}

@@ -157,4 +178,3 @@ export type SeqflowFunction<T> = (

const componentName = component.name;
parentContext.app.log({
type: "debug",
parentContext.app.log.debug({
message: "startComponent",

@@ -215,2 +235,20 @@ data: { componentOption, componentName },

},
getChild(this: SeqflowFunctionContext, key: string): HTMLElement {
const child = this.findChild(key);
if (!child) {
this.app.log.error({
message: "getChild: wrapper not found",
data: { key },
});
throw new Error("getChild: wrapper not found");
}
return child;
},
findChild(this: SeqflowFunctionContext, key: string): HTMLElement | null {
const child = componentChildren.find((c) => c.key === key);
if (child) {
return child.el;
}
return null;
},
replaceChild(

@@ -220,7 +258,6 @@ this: SeqflowFunctionContext,

newChild: () => JSX.Element | Promise<JSX.Element>,
) {
): void | Promise<void> {
const oldChildIndex = componentChildren.findIndex((c) => c.key === key);
if (oldChildIndex < 0) {
this.app.log({
type: "error",
this.app.log.error({
message: "replaceChild: wrapper not found",

@@ -243,8 +280,21 @@ data: { key, newChild },

for (const otherChild of componentChildren) {
// If we replace a child which contains another child,
// we have to abort the other child also
if (oldChild.el.contains(otherChild.el)) {
this.app.log.debug({
message: "replaceChild: wrapper contains other child",
data: { parent: key, child: otherChild.key },
});
this.abortController.signal.dispatchEvent(
new Event(`abort-component-${otherChild.key}`),
);
}
}
const a = newChild();
if (a instanceof Promise) {
a.then((child) => {
return a.then((child) => {
wrapper.replaceWith(child as Node);
});
return;
}

@@ -257,10 +307,20 @@

eventType: K,
options: {
el: HTMLElement;
preventDefault?: boolean;
},
options:
| {
el: HTMLElement;
preventDefault?: boolean;
}
| string,
): EventAsyncGenerator<HTMLElementEventMap[K]> {
let el: HTMLElement;
let preventDefault = false;
if (typeof options === "string") {
el = this.getChild(options);
} else {
el = options.el;
preventDefault = options.preventDefault ?? false;
}
return domEvent(eventType, {
el: options.el,
preventDefault: options.preventDefault ?? false,
el,
preventDefault,
});

@@ -277,4 +337,3 @@ },

navigationEvent(): EventAsyncGenerator<NavigationEvent> {
this.app.log({
type: "debug",
this.app.log.debug({
message: "navigationEvent",

@@ -297,4 +356,3 @@ data: {

): DocumentFragment {
this.app.log({
type: "debug",
this.app.log.debug({
message: "createDOMFragment",

@@ -328,4 +386,3 @@ data: { children },

this.app.log({
type: "error",
this.app.log.error({
message: "Unsupported child type. Implement me",

@@ -342,7 +399,6 @@ data: { child, children },

tagName: string,
options?: { [key: string]: string },
options?: { [key: string]: unknown },
...children: ChildenType[]
): Node {
this.app.log({
type: "debug",
this.app.log.debug({
message: "createDOMElement",

@@ -356,9 +412,28 @@ data: { tagName, options, children },

if (key === "className") {
el.setAttribute("class", options[key]);
el.setAttribute("class", options[key] as string);
continue;
}
if (key === "htmlFor") {
el.setAttribute("for", options[key]);
el.setAttribute("for", options[key] as string);
continue;
}
if (key === "onClick") {
const k = (options.key as string) ?? Math.random().toString();
const elAbortController = new AbortController();
this.abortController.signal.addEventListener(
`abort-component-${k}`,
() => {
elAbortController.abort();
},
{ once: true },
);
componentChildren.push({
key: k,
el,
});
el.addEventListener("click", options[key] as EventListener, {
signal: elAbortController.signal,
});
continue;
}
if (key === "style") {

@@ -378,3 +453,12 @@ const style = options[key] as string | Partial<CSSStyleDeclaration>;

}
el.setAttribute(key, options[key]);
// keep the key for the componentChildren array
if (key === "key") {
componentChildren.push({
key: options[key] as string,
el,
});
}
el.setAttribute(key, options[key] as string);
}

@@ -400,6 +484,11 @@

this.app.log({
type: "error",
this.app.log.error({
message: "Unsupported child type. Implement me",
data: { child, children, tagName, options, el },
data: {
child,
children,
tagName,
options,
el,
},
});

@@ -415,14 +504,26 @@ throw new Error("Unsupported child type");

const opt = options || {};
if (!opt?.key) {
opt.key = Math.random().toString();
}
const wrapper = document.createElement("div");
if (options?.key) {
componentChildren.push({
key: options.key,
el: wrapper,
componentChildren.push({
key: opt.key as string,
el: wrapper,
});
if (opt.wrapperClass) {
wrapper.classList.add(opt.wrapperClass as string);
}
if (typeof opt.onClick === "function") {
wrapper.addEventListener("click", opt.onClick as EventListener, {
signal: childContext.abortController.signal,
});
}
if (options?.wrapperClass) {
wrapper.classList.add(options.wrapperClass);
}
startComponent(childContext, wrapper, tagName, { ...options, children });
startComponent(childContext, wrapper, tagName, {
...opt,
children,
});
return wrapper;

@@ -444,11 +545,12 @@ },

() => {
parentContext.app.log({
type: "debug",
parentContext.app.log.debug({
message: "Component rendering ended",
data: { componentOption, componentName },
data: {
componentOption,
componentName,
},
});
},
(e) => {
parentContext.app.log({
type: "error",
parentContext.app.log.error({
message: "Component throws an error",

@@ -471,3 +573,5 @@ data: {

// biome-ignore lint/suspicious/noExplicitAny: We don't care about the component properties
FirstComponentData extends Record<string, any> & { children?: ChildenType[] },
FirstComponentData extends Record<string, any> & {
children?: ChildenType[];
},
>(

@@ -477,3 +581,5 @@ root: HTMLElement,

componentOption: FirstComponentData | undefined,
seqflowConfiguration: Partial<SeqflowConfiguration>,
seqflowConfiguration: Partial<
Omit<SeqflowConfiguration, "log"> & { log?: Partial<LogFunction> }
>,
): AbortController {

@@ -496,6 +602,8 @@ const seqflowConfig = applyDefaults(seqflowConfiguration);

seqflowConfig.router.getEventTarget().addEventListener("navigation", (ev) => {
appContext.log({
type: "info",
appContext.log.info({
message: "navigate",
data: { path: (ev as NavigationEvent).path, event: ev },
data: {
path: (ev as NavigationEvent).path,
event: ev,
},
});

@@ -513,2 +621,8 @@ });

},
getChild: () => {
throw new Error("getChild is not supported in the main context");
},
findChild: () => {
throw new Error("findChild is not supported in the main context");
},
replaceChild: () => {

@@ -567,3 +681,5 @@ throw new Error("replaceChild is not supported in the main context");

function applyDefaults(
seqflowConfiguration: Partial<SeqflowConfiguration>,
seqflowConfiguration: Partial<
Omit<SeqflowConfiguration, "log"> & { log?: Partial<LogFunction> }
>,
): SeqflowConfiguration {

@@ -576,6 +692,18 @@ function noop() {}

if (seqflowConfiguration.log === undefined) {
seqflowConfiguration.log = {};
}
if (seqflowConfiguration.log.info === undefined) {
seqflowConfiguration.log.info = noop;
}
if (seqflowConfiguration.log.error === undefined) {
seqflowConfiguration.log.error = noop;
}
if (seqflowConfiguration.log.debug === undefined) {
seqflowConfiguration.log.debug = noop;
}
return Object.assign(
{},
{
log: noop,
config: {},

@@ -653,2 +781,4 @@ domains: {},

style?: Partial<CSSStyleDeclaration> | string;
onClick?: (ev: MouseEvent) => void;
key?: string;
}>;

@@ -660,2 +790,3 @@ };

key?: string;
onClick?: (ev: MouseEvent) => void;
wrapperClass?: string;

@@ -662,0 +793,0 @@ }

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

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

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

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