@notionhq/custom-blocks-dev-shell 0.1.65 → 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 +0 -1
- package/data/radar.json +0 -1
- package/data/tasks.json +0 -1
- package/dist-cli/convert.js +3 -10
- package/dist-cli/data-sources.js +3 -5
- package/dist-cli/materialize.js +4 -8
- package/dist-cli/prebuilt.js +2 -5
- package/docs/data-sources.md +9 -11
- package/package.json +1 -1
package/data/people.json
CHANGED
package/data/radar.json
CHANGED
package/data/tasks.json
CHANGED
package/dist-cli/convert.js
CHANGED
|
@@ -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>, --
|
|
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
|
|
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
|
-
|
|
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) {
|
package/dist-cli/data-sources.js
CHANGED
|
@@ -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;
|
|
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 ??
|
|
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,
|
package/dist-cli/materialize.js
CHANGED
|
@@ -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
|
|
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
|
-
//
|
|
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(
|
|
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(
|
|
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: [],
|
package/dist-cli/prebuilt.js
CHANGED
|
@@ -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
|
|
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)
|
|
16
|
+
if (existsSync(target)) {
|
|
20
17
|
continue;
|
|
21
18
|
}
|
|
22
19
|
copyFileSync(resolve(prebuiltDir, filename), target);
|
package/docs/data-sources.md
CHANGED
|
@@ -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
|
-
- `
|
|
41
|
-
|
|
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
|
|
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` —
|
|
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
|
-
|
|
71
|
-
|
|
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
|
|
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
|