@notionhq/custom-blocks-dev-shell 0.1.64 → 0.1.66

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/data/people.json CHANGED
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "type": "built-in",
3
- "key": "people",
4
3
  "name": "People",
5
4
  "icon": "👤",
6
5
  "schema": {
package/data/radar.json CHANGED
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "type": "built-in",
3
- "key": "default",
4
3
  "name": "Radar",
5
4
  "icon": "📡",
6
5
  "schema": {
package/data/tasks.json CHANGED
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "type": "built-in",
3
- "key": "tasks",
4
3
  "name": "Tasks",
5
4
  "icon": "✅",
6
5
  "schema": {
@@ -17,11 +17,10 @@ const UNSUPPORTED_TYPE_FALLBACK = "rich_text";
17
17
  export function parseConvertArgs(argv) {
18
18
  const args = {
19
19
  input: undefined,
20
- key: undefined,
21
20
  name: undefined,
22
21
  };
23
22
  const rejectUnknown = (arg) => {
24
- throw new Error(`Unknown convert option "${arg}". Supported: --in <file>, --key <key>, --name <name>.`);
23
+ throw new Error(`Unknown convert option "${arg}". Supported: --in <file>, --name <name>.`);
25
24
  };
26
25
  parseCliArgs({
27
26
  argv,
@@ -29,9 +28,6 @@ export function parseConvertArgs(argv) {
29
28
  "--in": value => {
30
29
  args.input = value;
31
30
  },
32
- "--key": value => {
33
- args.key = value;
34
- },
35
31
  "--name": value => {
36
32
  args.name = value;
37
33
  },
@@ -68,16 +64,14 @@ export function convertSample(input, overrides = {}) {
68
64
  const sample = parsed.output;
69
65
  const warnings = [];
70
66
  const mappings = buildPropertyMappings(sample.properties, sample.results, warnings);
71
- const key = overrides.key ?? slugify(sample.name ?? "") ?? "data_source";
72
- const name = overrides.name ?? (sample.name || undefined) ?? key;
67
+ const name = overrides.name ?? (sample.name || undefined);
73
68
  const schema = {};
74
69
  for (const mapping of mappings.values()) {
75
70
  schema[mapping.key] = { name: mapping.name, type: mapping.type };
76
71
  }
77
72
  const source = {
78
73
  type: "syncedFromProd",
79
- key,
80
- name,
74
+ ...(name !== undefined ? { name } : {}),
81
75
  schema,
82
76
  rows: (sample.results ?? []).map(row => convertRow(row, mappings)),
83
77
  };
@@ -207,7 +201,6 @@ export async function runConvert(argv) {
207
201
  throw new Error(`Input is not valid JSON — ${formatUnknownError(error)}`);
208
202
  }
209
203
  const { source, warnings } = convertSample(parsed, {
210
- ...(args.key !== undefined ? { key: args.key } : {}),
211
204
  ...(args.name !== undefined ? { name: args.name } : {}),
212
205
  });
213
206
  for (const warning of warnings) {
@@ -60,7 +60,6 @@ export function readDataSources(dataDir) {
60
60
  const nonEmptyString = v.pipe(v.string(), v.nonEmpty());
61
61
  export const sourceFileSchema = v.object({
62
62
  type: v.optional(v.picklist(DEV_SHELL_DATA_SOURCE_TYPES), "worker"),
63
- key: v.optional(nonEmptyString),
64
63
  name: v.optional(nonEmptyString),
65
64
  icon: v.optional(v.string()),
66
65
  schema: v.optional(v.record(v.string(), v.object({
@@ -71,7 +70,7 @@ export const sourceFileSchema = v.object({
71
70
  });
72
71
  /**
73
72
  * Parse and validate one source file. Structural mistakes throw with the file
74
- * and problem named; omitted `key`/`name` fall back to the filename, and
73
+ * and problem named; the filename defines identity and the default `name`, and
75
74
  * omitted `schema`/`rows` to empty — so the minimal valid file is `{}`.
76
75
  */
77
76
  function readSource(file) {
@@ -93,12 +92,11 @@ function readSource(file) {
93
92
  }
94
93
  const { type, icon, schema, rows } = result.output;
95
94
  const filename = basename(file, ".json");
96
- const key = result.output.key ?? filename;
97
95
  return {
98
96
  type,
99
- key,
97
+ key: filename,
100
98
  filename,
101
- name: result.output.name ?? key,
99
+ name: result.output.name ?? filename,
102
100
  ...(icon !== undefined ? { icon } : {}),
103
101
  schema: Object.fromEntries(Object.entries(schema).map(([propertyKey, property]) => [
104
102
  propertyKey,
@@ -23,8 +23,7 @@ const TYPE_ALIASES = {
23
23
  };
24
24
  /**
25
25
  * Generated files are namespaced so they never shadow authored files. The
26
- * filename and `key` carry the prefix keys must stay unique for bindings to
27
- * be unambiguous — while the display name stays as declared, so the sidebar
26
+ * filename carries the prefix, while the display name stays as declared, so the sidebar
28
27
  * shows the clean name.
29
28
  */
30
29
  const WORKER_PREFIX = "worker_";
@@ -69,14 +68,12 @@ export function materializeWorkerSchemaDataSources(manifest, dataDir) {
69
68
  }
70
69
  mkdirSync(dataDir, { recursive: true });
71
70
  for (const [key, descriptor] of descriptors) {
72
- // The key is the worker's contract and lands verbatim in the file's
73
- // `key`; the filename is ours, so path-hostile characters (`/`, `..`)
74
- // are encoded rather than allowed to leave `dataDir` or crash the write.
71
+ // Replace path-hostile characters so the filename stays inside `dataDir`.
75
72
  const file = resolve(dataDir, `${WORKER_PREFIX}${fileSafe(key)}.json`);
76
73
  if (existsSync(file)) {
77
74
  continue;
78
75
  }
79
- writeFileSync(file, `${JSON.stringify(buildSource(key, descriptor), null, 2)}\n`);
76
+ writeFileSync(file, `${JSON.stringify(buildSource(descriptor), null, 2)}\n`);
80
77
  }
81
78
  }
82
79
  function fileSafe(key) {
@@ -90,7 +87,7 @@ function samePropertySchemas(left, right) {
90
87
  left[key].type === right[key].type &&
91
88
  (left[key].name ?? key) === (right[key].name ?? key)));
92
89
  }
93
- function buildSource(key, descriptor) {
90
+ function buildSource(descriptor) {
94
91
  const { name, properties } = descriptor;
95
92
  const schema = {};
96
93
  for (const [propertyKey, property] of Object.entries(properties)) {
@@ -101,7 +98,6 @@ function buildSource(key, descriptor) {
101
98
  }
102
99
  return {
103
100
  type: "worker",
104
- key: `${WORKER_PREFIX}${key}`,
105
101
  name,
106
102
  schema,
107
103
  rows: [],
@@ -2,21 +2,18 @@
2
2
  * Copy the shell's pre-built sources (`data/*.json`, shipped in the
3
3
  * package) into a worker's data directory. Like materialization, existing
4
4
  * worker data always wins: a bundled source is skipped when its filename is
5
- * already taken, and also when its `key` is already claimed by any existing
6
- * source — `key` is a source's binding/lookup identity, so a duplicate would
7
- * make one of the two ambiguous.
5
+ * already taken. The filename defines the source identity.
8
6
  */
9
7
  import { copyFileSync, existsSync, mkdirSync } from "node:fs";
10
8
  import { resolve } from "node:path";
11
9
  import { readDataSources } from "./data-sources.js";
12
10
  export function copyPrebuiltDataSources(prebuiltDir, dataDir) {
13
11
  mkdirSync(dataDir, { recursive: true });
14
- const existingKeys = new Set(readDataSources(dataDir).map(source => source.key));
15
12
  const written = [];
16
13
  for (const source of readDataSources(prebuiltDir)) {
17
14
  const filename = `${source.filename}.json`;
18
15
  const target = resolve(dataDir, filename);
19
- if (existsSync(target) || existingKeys.has(source.key)) {
16
+ if (existsSync(target)) {
20
17
  continue;
21
18
  }
22
19
  copyFileSync(resolve(prebuiltDir, filename), target);
@@ -14,7 +14,6 @@ supports the following types today:
14
14
  ```json
15
15
  {
16
16
  "type": "worker",
17
- "key": "tasks",
18
17
  "name": "Tasks",
19
18
  "icon": "✅",
20
19
  "schema": {
@@ -37,17 +36,16 @@ supports the following types today:
37
36
 
38
37
  - `type` — the source's kind. Hand-authored files declare `"worker"` (the
39
38
  default); the pre-built sources the shell adds carry `"built-in"`.
40
- - `key` — what blocks bind against; make it match a `dataSources` key from
41
- `worker.customBlock(...)` so properties auto-match. Defaults to the
42
- filename.
43
- - `name` — the label shown in the shell sidebar. Defaults to `key`.
39
+ - `name` — the label shown in the shell sidebar. If omitted, it defaults to
40
+ the filename without `.json`.
44
41
  - `icon` — optional emoji shown alongside the name.
45
- - `schema` — property key `{ name, type }`. Use the same property keys and
42
+ - `schema` — maps each property key to `{ name, type }`. If omitted, it defaults
43
+ to `{}`. Use the same property keys and
46
44
  types the block declares. Types: `title`, `rich_text`, `number`, `select`,
47
45
  `multi_select`, `status`, `date`, `checkbox`, `url`, `email`,
48
46
  `phone_number`, `people`, `files`, `relation`.
49
- - `rows` — each row needs a unique string `id`; property values live under
50
- their schema keys.
47
+ - `rows` — the source records. If omitted, it defaults to `[]`. Each row needs
48
+ a unique string `id`. Store property values under their schema keys.
51
49
 
52
50
  Value shapes by property type:
53
51
 
@@ -67,8 +65,8 @@ Value shapes by property type:
67
65
  Files are validated at spin-up, before they reach the shell UI. A malformed
68
66
  file fails the run with the file and problem named, e.g.
69
67
  `data/tasks.json: rows.0.id: Invalid key: Expected "id" but received undefined`.
70
- Omitted `key`/`name` fall back to the filename; omitted `schema`/`rows` to
71
- empty.
68
+ The filename without `.json` is the source identity used by bindings and
69
+ source pickers. Renaming a file changes its identity.
72
70
 
73
71
  ## Querying
74
72
 
@@ -86,7 +84,7 @@ materializes a file for every data source the worker declares — both
86
84
  schemas — that doesn't already have one: `data/worker_<key>.json`, the declared
87
85
  schema with empty `rows`, mirroring a managed database before any sync.
88
86
 
89
- - The `worker_` prefix on the filename and `key` namespaces generated files
87
+ - The `worker_` prefix on the filename namespaces generated files
90
88
  away from ones you author yourself, so both coexist; the display `name`
91
89
  stays as declared, so the sidebar shows the clean name.
92
90
  - Files are only ever written when absent: fill in `rows` freely and your
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notionhq/custom-blocks-dev-shell",
3
- "version": "0.1.64",
3
+ "version": "0.1.66",
4
4
  "description": "Local preview shell for Notion custom block workers.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -34,7 +34,7 @@
34
34
  "typescript": "^7.0.2",
35
35
  "vite": "^8.2.2",
36
36
  "vitest": "^5.0.0",
37
- "@notionhq/custom-blocks-host": "0.1.14",
37
+ "@notionhq/custom-blocks-host": "0.1.16",
38
38
  "@notionhq/custom-blocks-protocol": "0.1.0"
39
39
  },
40
40
  "scripts": {