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

@blockprotocol/hook

Package Overview
Dependencies
Maintainers
8
Versions
83
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@blockprotocol/hook - npm Package Compare versions

Comparing version 0.0.1-canary.10 to 0.0.1

19

dist/react.d.ts

@@ -15,4 +15,4 @@ import { RefObject } from "react";

/**
* Create a HookBlockHandler instance, using a reference to an element in the
* block.
* Create a HookEmbedderHandler instance, using a reference to an element
* around the block.
*

@@ -26,3 +26,16 @@ * The hookService will only be reconstructed if the element reference changes.

};
/**
* Pass a node by ref to the embedding application's hook service.
*
* @param service The hook service returned by {@link useHookBlockService}
* @param ref A React ref containing the DOM node. This hook will ensure the
* embedding application is notified when the underlying DOM node
* inside the ref changes
* @param type The type of hook – i.e, "text"
* @param path The path to the data associated with the hook
* @param fallback A fallback to be called if the embedding application doesn't
* implement the hook service, or doesn't implement this
* specific type of hook. Return a function to "teardown" your
* fallback (i.e, remove any event listeners).
*/
export declare const useHook: <T extends HTMLElement>(service: HookBlockHandler | null, ref: RefObject<void | T | null>, type: string, path: string, fallback: (node: T) => void | (() => void)) => void;
export declare const useHookRef: <T extends HTMLElement>(service: HookBlockHandler | null, type: string, path: string, fallback: (node: T | null) => void) => (node: T | null) => void;

167

dist/react.js

@@ -10,3 +10,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {

};
import { useCallback, useEffect, useLayoutEffect, useRef, useState, } from "react";
import { useEffect, useLayoutEffect, useRef, useState } from "react";
import { HookBlockHandler, HookEmbedderHandler } from "./index.js";

@@ -47,4 +47,4 @@ const useHookServiceConstructor = ({ Handler, constructorArgs, ref, }) => {

/**
* Create a HookBlockHandler instance, using a reference to an element in the
* block.
* Create a HookEmbedderHandler instance, using a reference to an element
* around the block.
*

@@ -62,5 +62,29 @@ * The hookService will only be reconstructed if the element reference changes.

};
/**
* Pass a node by ref to the embedding application's hook service.
*
* @param service The hook service returned by {@link useHookBlockService}
* @param ref A React ref containing the DOM node. This hook will ensure the
* embedding application is notified when the underlying DOM node
* inside the ref changes
* @param type The type of hook – i.e, "text"
* @param path The path to the data associated with the hook
* @param fallback A fallback to be called if the embedding application doesn't
* implement the hook service, or doesn't implement this
* specific type of hook. Return a function to "teardown" your
* fallback (i.e, remove any event listeners).
*/
export const useHook = (service, ref, type, path, fallback) => {
const hookRef = useRef(null);
const [, setError] = useState();
/**
* React can't catch async errors to handle them within ErrorBoundary's, etc,
* but if you throw it inside the callback for a setState function, it can.
*
* @see https://github.com/facebook/react/issues/14981#issuecomment-468460187
*/
const [, catchError] = useState();
/**
* The fallback may change in between the hook message being sent, and the
* not implemented error being received. This allows to ensure we call the
* latest fallback, with no chance of calling a stale closure
*/
const fallbackRef = useRef(fallback);

@@ -70,7 +94,14 @@ useLayoutEffect(() => {

});
const existingHookRef = useRef(null);
/**
* We can't use the normal effect teardown to trigger the hook teardown, as
* in order to detect changes to the node underlying the ref, we run our main
* effect on every render. Therefore, we create a "mount" effect and trigger
* the teardown in the mount effect teardown.
*/
useLayoutEffect(() => {
return () => {
var _a, _b;
(_b = (_a = hookRef.current) === null || _a === void 0 ? void 0 : _a.teardown) === null || _b === void 0 ? void 0 : _b.call(_a).catch((err) => {
setError(() => {
(_b = (_a = existingHookRef.current) === null || _a === void 0 ? void 0 : _a.teardown) === null || _b === void 0 ? void 0 : _b.call(_a).catch((err) => {
catchError(() => {
throw err;

@@ -83,4 +114,13 @@ });

var _a, _b, _c, _d, _e, _f;
const existingHook = (_a = hookRef.current) === null || _a === void 0 ? void 0 : _a.params;
const existingHook = (_a = existingHookRef.current) === null || _a === void 0 ? void 0 : _a.params;
const node = ref.current;
/**
* We cannot use the dependency array for the effect, as refs aren't updated
* during render, so the value passed into the dependency array for the ref
* won't have updated and therefore updates to the underlying node wouldn't
* trigger this effect, and embedding applications wouldn't be notified.
*
* Instead, we run the effect on every render and do our own change
* detection.
*/
if (existingHook &&

@@ -93,5 +133,10 @@ existingHook.service === service &&

}
const teardownPromise = (_d = (_c = (_b = hookRef.current) === null || _b === void 0 ? void 0 : _b.teardown) === null || _c === void 0 ? void 0 : _c.call(_b).catch()) !== null && _d !== void 0 ? _d : Promise.resolve();
const teardownPromise = (_d = (_c = (_b = existingHookRef.current) === null || _b === void 0 ? void 0 : _b.teardown) === null || _c === void 0 ? void 0 : _c.call(_b).catch()) !== null && _d !== void 0 ? _d : Promise.resolve();
if (node && service) {
const controller = new AbortController();
/**
* Is this an update to the existing hook, or is it a whole new hook? The
* only param to the hook which can change without creating a new hook is
* the node. Any other change will result in a new hook being created
*/
const reuseId = existingHook &&

@@ -102,3 +147,3 @@ existingHook.service === service &&

const hook = {
id: reuseId ? (_f = (_e = hookRef.current) === null || _e === void 0 ? void 0 : _e.id) !== null && _f !== void 0 ? _f : null : null,
id: reuseId ? (_f = (_e = existingHookRef.current) === null || _e === void 0 ? void 0 : _e.id) !== null && _f !== void 0 ? _f : null : null,
params: {

@@ -110,33 +155,39 @@ service,

},
teardown: () => __awaiter(void 0, void 0, void 0, function* () {
controller.abort();
if (hook.id) {
try {
hook.id = null;
if (hookRef.current === hook) {
hookRef.current = null;
teardown() {
return __awaiter(this, void 0, void 0, function* () {
if (controller.signal.aborted) {
return;
}
controller.abort();
const hookId = hook.id;
if (hookId) {
try {
hook.id = null;
if (existingHookRef.current === hook) {
existingHookRef.current = null;
}
if (!service.destroyed) {
yield service.hook({
data: {
hookId,
path,
type,
node: null,
},
});
}
}
if (!service.destroyed) {
yield service.hook({
data: {
hookId: hook.id,
path,
type,
node: null,
},
catch (err) {
catchError(() => {
throw err;
});
}
}
catch (err) {
setError(() => {
throw err;
});
}
}
}),
});
},
};
hookRef.current = hook;
existingHookRef.current = hook;
teardownPromise
.then(() => {
if (service.destroyed) {
if (service.destroyed || controller.signal.aborted) {
return;

@@ -178,3 +229,3 @@ }

.catch((err) => {
setError(() => {
catchError(() => {
throw err;

@@ -185,50 +236,6 @@ });

else {
hookRef.current = null;
existingHookRef.current = null;
}
});
};
export const useHookRef = (service, type, path, fallback) => {
const hookId = useRef(null);
const controllerRef = useRef(null);
const fallbackRef = useRef(fallback);
const [, setError] = useState();
useLayoutEffect(() => {
fallbackRef.current = fallback;
});
return useCallback((node) => {
var _a;
(_a = controllerRef.current) === null || _a === void 0 ? void 0 : _a.abort();
const controller = new AbortController();
controllerRef.current = controller;
service === null || service === void 0 ? void 0 : service.hook({
data: {
hookId: hookId.current,
node,
type,
path,
},
}).then((response) => {
if (!controller.signal.aborted) {
if (response.errors) {
if (response.errors.length === 1 &&
response.errors[0].code === "NOT_IMPLEMENTED") {
fallbackRef.current(node);
}
else {
// eslint-disable-next-line no-console
console.error(response.errors);
throw new Error("Unknown error in hook");
}
}
else if (response.data) {
hookId.current = response.data.hookId;
}
}
}).catch((err) => {
setError(() => {
throw err;
});
});
}, [path, service, type]);
};
//# sourceMappingURL=react.js.map

@@ -9,3 +9,3 @@ import { MessageCallback } from "@blockprotocol/core";

path: string;
hookId?: string | null;
hookId: string | null;
};

@@ -12,0 +12,0 @@ export declare type BlockHookMessageCallbacks = {};

{
"name": "@blockprotocol/hook",
"version": "0.0.1-canary.10",
"version": "0.0.1",
"description": "Implementation of the Block Protocol Hook service specification for blocks and embedding applications",

@@ -5,0 +5,0 @@ "keywords": [

## Block Protocol – Hook Service
This package implements the Block Protocol Hook service for blocks and embedding applications.
This package implements the Block Protocol Hraph service for blocks and embedding applications.
### Todo
To get started:
- [ ] Write docs
1. `yarn add @blockprotocol/hook` or `npm install @blockprotocol/hook`
1. Follow the instructions to use the hook service as a [block](#blocks) or an [embedding application](#embedding-applications)
## Blocks
To create a `HookBlockHandler`, pass the constructor an element in your block, along with any callbacks you wish to register to handle incoming messages.
To send a hook message, you call the `hook` function.
```typescript
import { HookBlockHandler } from "@blockprotocol/hook";
const handler = new HookBlockHandler({ element });
handler.hook({
data: {
blockId: "hookId",
node,
type: "text",
path: "$.text",
},
});
```
### React example
For React, we provide a `useHookBlockService` hook, which accepts a `ref` to an element. This will return an object with the shape of `{ hookService: HookBlockHandler | null }` which you can use to send hook messages.
We also provide a `useHook` hook to make sending hook messages easier.
```typescript
import { useHook } from "@blockprotocol/hook/react";
useHook(hookService, nodeRef, "text", "$.text", (node) => {
node.innerText = "hook fallback";
return () => {
node.innerText = "";
};
});
```
Where `nodeRef` is a `RefObject` containing the DOM node you'd like to pass to the embedding application.
### Custom elements
There are no helpers for custom elements yet.
## Embedding applications
To create a `HookEmbedderHandler`, pass the constructor:
1. An `element` wrapping your block
1. `callbacks` to respond to messages from the block
1. The starting values for any of the following messages you implement:
- `hook`
```typescript
import { HookEmbedderHandler } from "@blockprotocol/hook";
const hookIds = new WeakMap<HTMLElement, string>();
const nodes = new Map<string, HTMLElement>();
const generateId = () => (Math.random() + 1).toString(36).substring(7);
const hookService = new HookEmbedderHandler({
callbacks: {
hook({ data }) {
if (data.hookId) {
const node = nodes.get(data.hookId);
if (node) node.innerText = "";
nodes.delete(data.hookId);
}
const hookId = data.hookId ?? generateId();
if (data.node) {
nodes.set(hookId, data.node);
data.node.innerText = `Hook of type ${data.type} for path ${data.path}`;
}
return { hookId };
},
},
element: elementWrappingTheBlock,
});
```
### React
For React embedding applications, we provide a `useHookEmbedderService` hook, which accepts a `ref` to an element, and optionally any additional constructor arguments you wish to pass.
```tsx
import { useHookEmbedderService } from "@blockprotocol/hook/react";
import { useRef } from "react";
export const App = () => {
const wrappingRef = useRef<HTMLDivElement>(null);
useHookEmbedderService(blockRef, {
hook({ data }) {
// As above
},
});
return (
<div ref={wrappingRef}>
<Block />
</div>
);
};
```

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