@notionhq/custom-blocks-dev-shell 0.1.2 → 0.1.3

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/README.md CHANGED
@@ -23,16 +23,15 @@ Options:
23
23
  - `--block-base-port <port>` — first port handed to the per-block dev servers
24
24
  (default 9876; blocks count up from there).
25
25
 
26
- ## Data sources
27
-
28
- The shell reads local data sources from the worker's `src/data/*.json` one
29
- source per file: `{ type: "worker", key, name, icon?, schema, rows }`, where
30
- `schema` maps property keys to `{ name, type }` and each row carries a unique
31
- string `id` plus values under the schema's keys. The format is documented in
32
- full in [`docs/data-sources.md`](docs/data-sources.md), which ships with this
33
- package. Files are validated at spin-up, and
34
- a malformed file fails with the file and problem named. The shell shows
35
- exactly the sources in `src/data/` — none yet means an empty DATA sidebar.
26
+ ## Reference
27
+
28
+ One page per topic, shipped in this package's `docs/` so they're readable
29
+ from `node_modules`:
30
+
31
+ - [`docs/data-sources.md`](./docs/data-sources.md) local data sources: the
32
+ `src/data/*.json` file format, value shapes per property type, validation,
33
+ and how missing sources are materialized from the worker's declared
34
+ schemas.
36
35
 
37
36
  ## Requirements
38
37
 
@@ -1,2 +1,2 @@
1
1
  /*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
2
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-duration:initial;--tw-outline-style:solid}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xl:36rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-ink:#37352f;--color-ink-muted:#6b6b68;--color-ink-faint:#9b9a97;--color-ink-fainter:#b3b3b0;--color-paper:#fbfbfa;--color-hairline:#e5e5e3;--color-hairline-soft:#efefee;--color-hover:#efefee;--color-pressed:#e6e6e4;--color-toggle:#e9e9e7;--color-accent:#2383e2;--color-tooltip:#2f2f2d;--color-match:#dcf3e3;--color-match-ink:#1f6d3d;--color-mismatch:#fbe4e4;--color-mismatch-ink:#a33}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.top-0{top:calc(var(--spacing) * 0)}.top-\[calc\(100\%\+7px\)\]{top:calc(100% + 7px)}.left-0{left:calc(var(--spacing) * 0)}.z-10{z-index:10}.z-50{z-index:50}.row-1{grid-row:1}.row-2{grid-row:2}.mx-1{margin-inline:calc(var(--spacing) * 1)}.mx-1\.5{margin-inline:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.block{display:block}.flex{display:flex}.grid{display:grid}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.h-screen{height:100vh}.max-h-\[80vh\]{max-height:80vh}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-60{min-height:calc(var(--spacing) * 60)}.w-60{width:calc(var(--spacing) * 60)}.w-full{width:100%}.w-max{width:max-content}.max-w-52{max-width:calc(var(--spacing) * 52)}.max-w-60{max-width:calc(var(--spacing) * 60)}.max-w-\[50\%\]{max-width:50%}.max-w-\[960px\]{max-width:960px}.max-w-\[min\(420px\,calc\(100vw-32px\)\)\]{max-width:min(420px,100vw - 32px)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.flex-1{flex:1}.flex-none{flex:none}.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.-translate-y-0\.5{--tw-translate-y:calc(var(--spacing) * -.5);translate:var(--tw-translate-x) var(--tw-translate-y)}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-disc{list-style-type:disc}.grid-cols-\[minmax\(0\,1fr\)_auto_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1fr) auto minmax(0,1fr)}.flex-col{flex-direction:column}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-hairline{border-color:var(--color-hairline)}.border-hairline-soft{border-color:var(--color-hairline-soft)}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab, red, red)){.bg-black\/40{background-color:color-mix(in oklab, var(--color-black) 40%, transparent)}}.bg-match{background-color:var(--color-match)}.bg-mismatch{background-color:var(--color-mismatch)}.bg-paper{background-color:var(--color-paper)}.bg-pressed{background-color:var(--color-pressed)}.bg-toggle{background-color:var(--color-toggle)}.bg-tooltip{background-color:var(--color-tooltip)}.bg-white{background-color:var(--color-white)}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-\[9px\]{padding-inline:9px}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-\[5px\]{padding-block:5px}.py-\[7px\]{padding-block:7px}.pt-1\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-5{padding-left:calc(var(--spacing) * 5)}.text-center{text-align:center}.text-left{text-align:left}.align-top{vertical-align:top}.font-mono{font-family:var(--font-mono)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.leading-\[1\.4\]{--tw-leading:1.4;line-height:1.4}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[0\.04em\]{--tw-tracking:.04em;letter-spacing:.04em}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.text-ink{color:var(--color-ink)}.text-ink-faint{color:var(--color-ink-faint)}.text-ink-fainter{color:var(--color-ink-fainter)}.text-ink-muted{color:var(--color-ink-muted)}.text-match-ink{color:var(--color-match-ink)}.text-mismatch-ink{color:var(--color-mismatch-ink)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.opacity-0{opacity:0}.shadow-\[0_1px_2px_rgb\(0_0_0\/12\%\)\]{--tw-shadow:0 1px 2px var(--tw-shadow-color,#0000001f);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_4px_12px_rgb\(0_0_0\/18\%\)\]{--tw-shadow:0 4px 12px var(--tw-shadow-color,#0000002e);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_12px_40px_rgb\(0_0_0\/25\%\)\]{--tw-shadow:0 12px 40px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.transition-\[opacity\,transform\,visibility\]{transition-property:opacity,transform,visibility;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}@media (hover:hover){.group-hover\:visible:is(:where(.group):hover *){visibility:visible}.group-hover\:translate-y-0:is(:where(.group):hover *){--tw-translate-y:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.group-focus-visible\:visible:is(:where(.group):focus-visible *){visibility:visible}.group-focus-visible\:translate-y-0:is(:where(.group):focus-visible *){--tw-translate-y:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.group-focus-visible\:opacity-100:is(:where(.group):focus-visible *){opacity:1}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:bg-hover:hover{background-color:var(--color-hover)}.hover\:text-ink:hover{color:var(--color-ink)}}.focus-visible\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\:outline-offset-1:focus-visible{outline-offset:1px}.focus-visible\:outline-offset-2:focus-visible{outline-offset:2px}.focus-visible\:outline-accent:focus-visible{outline-color:var(--color-accent)}.disabled\:cursor-default:disabled{cursor:default}.disabled\:opacity-50:disabled{opacity:.5}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-duration{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-duration:initial;--tw-outline-style:solid}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xl:36rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-ink:#37352f;--color-ink-muted:#6b6b68;--color-ink-faint:#9b9a97;--color-ink-fainter:#b3b3b0;--color-paper:#fbfbfa;--color-hairline:#e5e5e3;--color-hairline-soft:#efefee;--color-hover:#efefee;--color-pressed:#e6e6e4;--color-toggle:#e9e9e7;--color-accent:#2383e2;--color-tooltip:#2f2f2d;--color-match:#dcf3e3;--color-match-ink:#1f6d3d;--color-mismatch:#fbe4e4;--color-mismatch-ink:#a33}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.top-0{top:calc(var(--spacing) * 0)}.top-\[calc\(100\%\+7px\)\]{top:calc(100% + 7px)}.left-0{left:calc(var(--spacing) * 0)}.z-10{z-index:10}.z-50{z-index:50}.row-1{grid-row:1}.row-2{grid-row:2}.mx-1{margin-inline:calc(var(--spacing) * 1)}.mx-1\.5{margin-inline:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.block{display:block}.flex{display:flex}.grid{display:grid}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.h-screen{height:100vh}.max-h-\[80vh\]{max-height:80vh}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-60{min-height:calc(var(--spacing) * 60)}.w-60{width:calc(var(--spacing) * 60)}.w-full{width:100%}.w-max{width:max-content}.max-w-52{max-width:calc(var(--spacing) * 52)}.max-w-60{max-width:calc(var(--spacing) * 60)}.max-w-\[50\%\]{max-width:50%}.max-w-\[960px\]{max-width:960px}.max-w-\[min\(420px\,calc\(100vw-32px\)\)\]{max-width:min(420px,100vw - 32px)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.flex-1{flex:1}.flex-none{flex:none}.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.-translate-y-0\.5{--tw-translate-y:calc(var(--spacing) * -.5);translate:var(--tw-translate-x) var(--tw-translate-y)}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-disc{list-style-type:disc}.grid-cols-\[minmax\(0\,1fr\)_auto_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1fr) auto minmax(0,1fr)}.flex-col{flex-direction:column}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-hairline{border-color:var(--color-hairline)}.border-hairline-soft{border-color:var(--color-hairline-soft)}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab, red, red)){.bg-black\/40{background-color:color-mix(in oklab, var(--color-black) 40%, transparent)}}.bg-match{background-color:var(--color-match)}.bg-mismatch{background-color:var(--color-mismatch)}.bg-paper{background-color:var(--color-paper)}.bg-pressed{background-color:var(--color-pressed)}.bg-toggle{background-color:var(--color-toggle)}.bg-tooltip{background-color:var(--color-tooltip)}.bg-white{background-color:var(--color-white)}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-\[9px\]{padding-inline:9px}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-\[5px\]{padding-block:5px}.py-\[7px\]{padding-block:7px}.pt-1\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-5{padding-left:calc(var(--spacing) * 5)}.text-center{text-align:center}.text-left{text-align:left}.align-top{vertical-align:top}.font-mono{font-family:var(--font-mono)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.leading-\[1\.4\]{--tw-leading:1.4;line-height:1.4}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[0\.04em\]{--tw-tracking:.04em;letter-spacing:.04em}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.text-ink{color:var(--color-ink)}.text-ink-faint{color:var(--color-ink-faint)}.text-ink-fainter{color:var(--color-ink-fainter)}.text-ink-muted{color:var(--color-ink-muted)}.text-match-ink{color:var(--color-match-ink)}.text-mismatch-ink{color:var(--color-mismatch-ink)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.opacity-0{opacity:0}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_1px_2px_rgb\(0_0_0\/12\%\)\]{--tw-shadow:0 1px 2px var(--tw-shadow-color,#0000001f);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_4px_12px_rgb\(0_0_0\/18\%\)\]{--tw-shadow:0 4px 12px var(--tw-shadow-color,#0000002e);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_12px_40px_rgb\(0_0_0\/25\%\)\]{--tw-shadow:0 12px 40px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.transition-\[opacity\,transform\,visibility\]{transition-property:opacity,transform,visibility;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}@media (hover:hover){.group-hover\:visible:is(:where(.group):hover *){visibility:visible}.group-hover\:translate-y-0:is(:where(.group):hover *){--tw-translate-y:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.group-focus-visible\:visible:is(:where(.group):focus-visible *){visibility:visible}.group-focus-visible\:translate-y-0:is(:where(.group):focus-visible *){--tw-translate-y:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.group-focus-visible\:opacity-100:is(:where(.group):focus-visible *){opacity:1}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:bg-hover:hover{background-color:var(--color-hover)}.hover\:text-ink:hover{color:var(--color-ink)}}.focus-visible\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\:outline-offset-1:focus-visible{outline-offset:1px}.focus-visible\:outline-offset-2:focus-visible{outline-offset:2px}.focus-visible\:outline-accent:focus-visible{outline-color:var(--color-accent)}.disabled\:cursor-default:disabled{cursor:default}.disabled\:opacity-50:disabled{opacity:.5}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-duration{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}
package/dist/index.html CHANGED
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Workers local shell</title>
7
- <script type="module" crossorigin src="/assets/index-B1zP6MFl.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-DvRqSoqY.css">
7
+ <script type="module" crossorigin src="/assets/index-a8PSkfam.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-CzXh8_H1.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
@@ -1,9 +1,8 @@
1
1
  /**
2
2
  * Load a worker's dev-shell data sources from `<dataDir>/*.json` — one source
3
- * per file, hand-authored (the scaffolded worker AGENTS.md documents the
4
- * format). Every file is validated here, before it reaches the shell, so a
5
- * malformed source fails spin-up naming the file and the problem instead of
6
- * breaking the UI.
3
+ * per file, hand-authored. Every file is validated here, before it reaches
4
+ * the shell, so a malformed source fails spin-up naming the file and the
5
+ * problem instead of breaking the UI.
7
6
  */
8
7
  import { existsSync, readdirSync, readFileSync } from "node:fs";
9
8
  import { basename, resolve } from "node:path";
package/dist-cli/main.js CHANGED
@@ -12,6 +12,7 @@ import { basename, dirname, join, resolve } from "node:path";
12
12
  import { fileURLToPath } from "node:url";
13
13
  import { BLOCK_BASE_PORT, buildBlockRegistry, SHELL_2_PORT, writeBlockViteConfig, } from "./block-server.js";
14
14
  import { readDataSources } from "./data-sources.js";
15
+ import { materializeWorkerSchemaDataSources } from "./materialize.js";
15
16
  import { serveUi } from "./serve-ui.js";
16
17
  import { blockCapabilities, findWorkerDir, generateWorkerManifest, } from "./worker-manifest.js";
17
18
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -115,9 +116,10 @@ async function main() {
115
116
  // Not an error — start the shell anyway; it shows "None" under Blocks.
116
117
  console.log(`${label(basename(workerDir))} Worker declares no custom blocks.`);
117
118
  }
118
- // Hand-authored data sources under the worker's src/data see the
119
- // scaffolded AGENTS.md for the file format. Validated before injection; a
120
- // malformed file fails spin-up with the problem named.
119
+ // Materialize schema-only files for the worker's declared sources, then
120
+ // load the directory. Files are validated before injection; a malformed
121
+ // file fails spin-up with the problem named.
122
+ materializeWorkerSchemaDataSources(manifest, resolve(workerDir, "src/data"));
121
123
  const dataSources = readDataSources(resolve(workerDir, "src/data"));
122
124
  console.log(dataSources.length > 0
123
125
  ? `${label(basename(workerDir))} Data sources from src/data: ${dataSources
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Materialize a worker's declared data sources as `<dataDir>/worker_<key>.json`
3
+ * files: the schema with no rows, mirroring a managed database before any
4
+ * sync. Rows are added by editing the file; `data-sources.ts` reads and
5
+ * validates whatever ends up in the directory.
6
+ *
7
+ * A block's data source can come from a `worker.database` or from an inline
8
+ * schema declared on the block (`worker.customBlock({ dataSources })`); both
9
+ * are materialized so all sources are treated equivalently — just files in
10
+ * `src/data/`. The `worker_` prefix keeps generated sources from ever colliding
11
+ * with hand-authored files, so both can coexist.
12
+ *
13
+ * Files are written only when absent, so hand-edited or hand-authored sources
14
+ * survive across restarts; delete a file to regenerate it from the schema.
15
+ */
16
+ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
17
+ import { resolve } from "node:path";
18
+ import { blockCapabilities } from "./worker-manifest.js";
19
+ // Worker authoring type names → public data-source (NotionPropertyType) names.
20
+ const TYPE_ALIASES = {
21
+ text: "rich_text",
22
+ file: "files",
23
+ };
24
+ /**
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
28
+ * shows the clean name.
29
+ */
30
+ const GENERATED_PREFIX = "worker_";
31
+ export function materializeWorkerSchemaDataSources(manifest, dataDir) {
32
+ mkdirSync(dataDir, { recursive: true });
33
+ // One descriptor per data source key: databases first (source of truth for
34
+ // anything they back), then inline block schemas for keys no database
35
+ // provides.
36
+ const descriptors = new Map();
37
+ for (const database of manifest.databases) {
38
+ descriptors.set(database.key, {
39
+ name: database.config.initialTitle ?? database.key,
40
+ properties: (database.config.schema?.properties ?? {}),
41
+ });
42
+ }
43
+ for (const block of blockCapabilities(manifest)) {
44
+ for (const [key, slot] of Object.entries(block.config.manifest.dataSources)) {
45
+ const properties = (slot.properties ?? {});
46
+ const existing = descriptors.get(key);
47
+ if (existing !== undefined) {
48
+ // Same key from two blocks with different shapes: slot keys are only
49
+ // unique per block, so one file can't serve both. First block wins;
50
+ // say so instead of leaving the loser silently unbindable.
51
+ if (existing.blockKey !== undefined &&
52
+ !samePropertySchemas(existing.properties, properties)) {
53
+ console.warn(`Blocks "${existing.blockKey}" and "${block.key}" both declare data source ` +
54
+ `"${key}" with different schemas; ${GENERATED_PREFIX}${key}.json uses the ` +
55
+ `schema from "${existing.blockKey}". Author a src/data file for "${block.key}" by hand.`);
56
+ }
57
+ continue;
58
+ }
59
+ descriptors.set(key, {
60
+ name: slot.name ?? key,
61
+ properties,
62
+ blockKey: block.key,
63
+ });
64
+ }
65
+ }
66
+ for (const [key, descriptor] of descriptors) {
67
+ // The key is the worker's contract and lands verbatim in the file's
68
+ // `key`; the filename is ours, so path-hostile characters (`/`, `..`)
69
+ // are encoded rather than allowed to leave `dataDir` or crash the write.
70
+ const file = resolve(dataDir, `${GENERATED_PREFIX}${fileSafe(key)}.json`);
71
+ if (existsSync(file)) {
72
+ continue;
73
+ }
74
+ writeFileSync(file, `${JSON.stringify(buildSource(key, descriptor), null, 2)}\n`);
75
+ }
76
+ }
77
+ function fileSafe(key) {
78
+ return key.replace(/[^a-zA-Z0-9_-]/g, "-");
79
+ }
80
+ function samePropertySchemas(left, right) {
81
+ const leftKeys = Object.keys(left).sort();
82
+ const rightKeys = Object.keys(right).sort();
83
+ return (leftKeys.length === rightKeys.length &&
84
+ leftKeys.every((key, index) => key === rightKeys[index] &&
85
+ left[key].type === right[key].type &&
86
+ (left[key].name ?? key) === (right[key].name ?? key)));
87
+ }
88
+ function buildSource(key, descriptor) {
89
+ const { name, properties } = descriptor;
90
+ const schema = {};
91
+ for (const [propertyKey, property] of Object.entries(properties)) {
92
+ schema[propertyKey] = {
93
+ name: property.name ?? propertyKey,
94
+ type: TYPE_ALIASES[property.type] ?? property.type,
95
+ };
96
+ }
97
+ return {
98
+ type: "worker",
99
+ key: `${GENERATED_PREFIX}${key}`,
100
+ name,
101
+ schema,
102
+ rows: [],
103
+ };
104
+ }
@@ -96,7 +96,9 @@ export async function extractWorkerManifest(workerDir, options = {}) {
96
96
  // (per the localhost verification doc's `w.manifest || w.capabilities`).
97
97
  const raw = worker.manifest ?? worker.capabilities;
98
98
  if (isManifestShape(raw)) {
99
- return raw;
99
+ // The shape check only guarantees `capabilities`; older manifests omit
100
+ // the other arrays.
101
+ return { ...raw, databases: raw.databases ?? [], pacers: raw.pacers ?? [] };
100
102
  }
101
103
  if (Array.isArray(raw)) {
102
104
  return { databases: [], pacers: [], capabilities: raw };
@@ -9,7 +9,6 @@ supports the following types today:
9
9
  - `manual` — sources a user creates themselves in the shell.
10
10
  - `built-in` — sources we provide.
11
11
 
12
-
13
12
  ## File format
14
13
 
15
14
  ```json
@@ -70,3 +69,20 @@ file fails the run with the file and problem named, e.g.
70
69
  `src/data/tasks.json: rows.0.id: Invalid key: Expected "id" but received undefined`.
71
70
  Omitted `key`/`name` fall back to the filename; omitted `schema`/`rows` to
72
71
  empty.
72
+
73
+ ## Materialization
74
+
75
+ You don't have to write these files from scratch. At spin-up the shell
76
+ materializes a file for every data source the worker declares — both
77
+ `worker.database(...)` entries and inline `worker.customBlock({ dataSources })`
78
+ schemas — that doesn't already have one: `worker_<key>.json`, the declared
79
+ schema with empty `rows`, mirroring a managed database before any sync.
80
+
81
+ - The `worker_` prefix on the filename and `key` namespaces generated files
82
+ away from ones you author yourself, so both coexist; the display `name`
83
+ stays as declared, so the sidebar shows the clean name.
84
+ - Files are only ever written when absent: fill in `rows` freely and your
85
+ edits survive restarts. Delete a generated file to regenerate it from the
86
+ schema.
87
+
88
+ The shell shows exactly the sources in `src/data/`, nothing else.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notionhq/custom-blocks-dev-shell",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Local preview shell for Notion custom block workers.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -26,7 +26,7 @@
26
26
  "react": "^19.2.5",
27
27
  "react-dom": "^19.2.5",
28
28
  "valibot": "^1.3.1",
29
- "@notionhq/custom-blocks": "0.1.0"
29
+ "@notionhq/custom-blocks": "0.1.1"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@tailwindcss/vite": "^4.2.4",