@notionhq/custom-blocks-dev-shell 0.1.10 → 0.1.12

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.
@@ -0,0 +1,2 @@
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}}}@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;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--leading-relaxed:1.625;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--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:#32302c;--color-ink-muted:#6b6b68;--color-ink-faint:#9b9a97;--color-ink-fainter:#b3b3b0;--color-nav-ink:#2c2c2b;--color-paper:#fbfbfa;--color-hairline:#e6e5e3;--color-ui-hover:#3b14000d;--color-panel:#42230308;--color-canvas-dark:#191919;--color-pill:#0000000d;--color-pill-dark:#ffffff0e;--color-dark-ink:#ffffffcf;--color-dark-ink-muted:#ffffff75;--color-sidebar:#f7f7f5;--color-sidebar-active:#00000008;--color-sidebar-ink:#5f5e59;--color-sidebar-ink-strong:#1d1b16;--color-sidebar-ink-muted:#7d7a75;--color-hairline-soft:#f0efed;--color-toggle:#e9e9e7;--color-accent:#2383e2;--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}.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)}.end{inset-inline-end:var(--spacing)}.top-0{top:calc(var(--spacing) * 0)}.top-1\/2{top:50%}.top-full{top:100%}.right-0{right:calc(var(--spacing) * 0)}.right-1\.5{right:calc(var(--spacing) * 1.5)}.bottom-full{bottom:100%}.left-0{left:calc(var(--spacing) * 0)}.z-50{z-index:50}.row-1{grid-row:1}.row-2{grid-row:2}.mx-auto{margin-inline:auto}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-9{height:calc(var(--spacing) * 9)}.h-100{height:calc(var(--spacing) * 100)}.h-\[30px\]{height:30px}.h-\[38px\]{height:38px}.h-screen{height:100vh}.max-h-\[85vh\]{max-height:85vh}.min-h-0{min-height:calc(var(--spacing) * 0)}.w-70{width:calc(var(--spacing) * 70)}.w-\[172px\]{width:172px}.w-full{width:100%}.max-w-190{max-width:calc(var(--spacing) * 190)}.max-w-\[560px\]{max-width:560px}.max-w-\[720px\]{max-width:720px}.max-w-\[960px\]{max-width:960px}.max-w-full{max-width:100%}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-40{min-width:calc(var(--spacing) * 40)}.flex-1{flex:1}.flex-none{flex:none}.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-disc{list-style-type:disc}.appearance-none{appearance:none}.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}.justify-end{justify-content:flex-end}.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)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-px{gap:1px}.self-start{align-self:flex-start}.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{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-\[4px\]{border-radius:4px}.rounded-\[6px\]{border-radius:6px}.rounded-\[10px\]{border-radius:10px}.rounded-\[12px\]{border-radius:12px}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-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-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-hairline{border-color:var(--color-hairline)}.border-hairline-soft{border-color:var(--color-hairline-soft)}.bg-accent{background-color:var(--color-accent)}.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-canvas-dark{background-color:var(--color-canvas-dark)}.bg-panel{background-color:var(--color-panel)}.bg-paper{background-color:var(--color-paper)}.bg-pill{background-color:var(--color-pill)}.bg-pill-dark{background-color:var(--color-pill-dark)}.bg-sidebar{background-color:var(--color-sidebar)}.bg-sidebar-active{background-color:var(--color-sidebar-active)}.bg-toggle{background-color:var(--color-toggle)}.bg-ui-hover{background-color:var(--color-ui-hover)}.bg-white{background-color:var(--color-white)}.p-1{padding:calc(var(--spacing) * 1)}.p-2{padding:calc(var(--spacing) * 2)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-10{padding-inline:calc(var(--spacing) * 10)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-10{padding-block:calc(var(--spacing) * 10)}.pt-10{padding-top:calc(var(--spacing) * 10)}.pt-24{padding-top:calc(var(--spacing) * 24)}.pr-1{padding-right:calc(var(--spacing) * 1)}.pr-1\.5{padding-right:calc(var(--spacing) * 1.5)}.pr-6{padding-right:calc(var(--spacing) * 6)}.pb-1{padding-bottom:calc(var(--spacing) * 1)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-6{padding-bottom:calc(var(--spacing) * 6)}.pl-0\.5{padding-left:calc(var(--spacing) * .5)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-3{padding-left: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-body{letter-spacing:-.154px;font-size:14px;line-height:20px}.text-caption{font-size:12px;line-height:16px}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-\[17px\]{font-size:17px}.text-\[32px\]{font-size:32px}.text-\[40px\]{font-size:40px}.leading-4{--tw-leading:calc(var(--spacing) * 4);line-height:calc(var(--spacing) * 4)}.leading-10{--tw-leading:calc(var(--spacing) * 10);line-height:calc(var(--spacing) * 10)}.leading-\[1\.2\]{--tw-leading:1.2;line-height:1.2}.leading-\[22px\]{--tw-leading:22px;line-height:22px}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.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\.442px\]{--tw-tracking:-.442px;letter-spacing:-.442px}.tracking-\[-1\.55px\]{--tw-tracking:-1.55px;letter-spacing:-1.55px}.whitespace-nowrap{white-space:nowrap}.text-dark-ink{color:var(--color-dark-ink)}.text-dark-ink-muted{color:var(--color-dark-ink-muted)}.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-mismatch-ink{color:var(--color-mismatch-ink)}.text-nav-ink{color:var(--color-nav-ink)}.text-sidebar-ink{color:var(--color-sidebar-ink)}.text-sidebar-ink-muted{color:var(--color-sidebar-ink-muted)}.text-sidebar-ink-strong{color:var(--color-sidebar-ink-strong)}.text-white{color:var(--color-white)}.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_4px_12px_rgb\(0_0_0\/10\%\)\]{--tw-shadow:0 4px 12px 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_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{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:bg-sidebar-active:hover{background-color:var(--color-sidebar-active)}.hover\:bg-ui-hover:hover{background-color:var(--color-ui-hover)}.hover\:opacity-90:hover{opacity:.9}}.focus-visible\:opacity-100:focus-visible{opacity:1}.disabled\:cursor-default:disabled{cursor:default}.disabled\:bg-toggle:disabled{background-color:var(--color-toggle)}.disabled\:text-ink-faint:disabled{color:var(--color-ink-faint)}}@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}
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-B9Ip1pFo.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-D7A1CDPg.css">
7
+ <script type="module" crossorigin src="/assets/index-BjlUlu5e.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-D-pOONlZ.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
package/dist-cli/main.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Entry point for the published dev-shell CLI (`npx`-run from a worker
3
- * project). Mirrors the worker mode of the repo's `scripts/dev.ts`: build the
3
+ * project). Mirrors the repo's `scripts/dev.ts`: build the
4
4
  * worker, extract its manifest, serve one Vite dev server per custom block
5
5
  * (using the worker's own Vite install), and serve the prebuilt dev-shell UI
6
6
  * with the block registry injected at runtime.
@@ -14,6 +14,7 @@ import { BLOCK_BASE_PORT, buildBlockRegistry, SHELL_PORT, writeBlockViteConfig,
14
14
  import { runConvert } from "./convert.js";
15
15
  import { readDataSources } from "./data-sources.js";
16
16
  import { materializeWorkerSchemaDataSources } from "./materialize.js";
17
+ import { copyPrebuiltDataSources } from "./prebuilt.js";
17
18
  import { serveUi } from "./serve-ui.js";
18
19
  import { blockCapabilities, findWorkerDir, generateWorkerManifest, } from "./worker-manifest.js";
19
20
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -127,8 +128,9 @@ async function main() {
127
128
  // Materialize schema-only files for the worker's declared sources, then
128
129
  // load the directory. Files are validated before injection; a malformed
129
130
  // file fails spin-up with the problem named.
130
- materializeWorkerSchemaDataSources(manifest, resolve(workerDir, "src/data"));
131
- const dataSources = readDataSources(resolve(workerDir, "src/data"));
131
+ const dataDir = resolve(workerDir, "src/data");
132
+ materializeWorkerSchemaDataSources(manifest, dataDir);
133
+ const dataSources = readDataSources(dataDir);
132
134
  console.log(dataSources.length > 0
133
135
  ? `${label(basename(workerDir))} Data sources from src/data: ${dataSources
134
136
  .map(source => source.name)
@@ -178,11 +180,19 @@ async function main() {
178
180
  throw new Error(`No prebuilt UI found at ${distDir}. This package was not assembled ` +
179
181
  `correctly; reinstall it.`);
180
182
  }
183
+ const prebuiltDir = resolve(__dirname, "..", "data");
181
184
  try {
182
185
  await serveUi(distDir, cliArgs.shellPort, {
183
- mode: "worker",
184
186
  blocks: registry,
185
187
  dataSources,
188
+ prebuiltFilenames: readDataSources(prebuiltDir).map(source => source.filename),
189
+ }, () => {
190
+ const written = copyPrebuiltDataSources(prebuiltDir, dataDir);
191
+ if (written.length > 0) {
192
+ console.log(`${label(basename(workerDir))} Added pre-built data sources: ` +
193
+ written.join(", "));
194
+ }
195
+ return readDataSources(dataDir);
186
196
  });
187
197
  }
188
198
  catch (error) {
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Copy the shell's pre-built sources (`data/*.json`, shipped in the
3
+ * package) into a worker's data directory. Like materialization, existing
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.
8
+ */
9
+ import { copyFileSync, existsSync, mkdirSync } from "node:fs";
10
+ import { resolve } from "node:path";
11
+ import { readDataSources } from "./data-sources.js";
12
+ export function copyPrebuiltDataSources(prebuiltDir, dataDir) {
13
+ mkdirSync(dataDir, { recursive: true });
14
+ const existingKeys = new Set(readDataSources(dataDir).map(source => source.key));
15
+ const written = [];
16
+ for (const source of readDataSources(prebuiltDir)) {
17
+ const filename = `${source.filename}.json`;
18
+ const target = resolve(dataDir, filename);
19
+ if (existsSync(target) || existingKeys.has(source.key)) {
20
+ continue;
21
+ }
22
+ copyFileSync(resolve(prebuiltDir, filename), target);
23
+ written.push(filename);
24
+ }
25
+ return written.sort();
26
+ }
@@ -34,20 +34,53 @@ function injectConfig(html, config) {
34
34
  /**
35
35
  * Serve `distDir` on `port`. Unknown extensionless paths fall back to
36
36
  * `index.html`. Rejects on listen errors (e.g. the port is taken).
37
+ *
38
+ * `addPrebuiltData`, when given, backs `POST /api/prebuilt-data`: it writes
39
+ * the pre-built sources into the worker's data directory and returns
40
+ * the directory's updated contents.
37
41
  */
38
- export function serveUi(distDir, port, config) {
42
+ export function serveUi(distDir, port, config, addPrebuiltData) {
39
43
  const dist = resolve(distDir);
40
- const indexHtml = injectConfig(readFileSync(join(dist, "index.html"), "utf-8"), config);
44
+ const rawIndexHtml = readFileSync(join(dist, "index.html"), "utf-8");
45
+ // Server-owned: updated by the add endpoint, while the caller's `config`
46
+ // stays an untouched input.
47
+ let dataSources = config.dataSources;
41
48
  const server = createServer((req, res) => {
42
- let path;
49
+ let urlPath;
43
50
  try {
44
- path = normalize(decodeURIComponent(req.url?.split("?", 1)[0] ?? "/"));
51
+ urlPath = decodeURIComponent(req.url?.split("?", 1)[0] ?? "/");
45
52
  }
46
53
  catch {
47
54
  res.writeHead(400);
48
55
  res.end();
49
56
  return;
50
57
  }
58
+ // Routed on the raw URL path: normalize() is platform-specific, so it
59
+ // would rewrite "/api/..." to "\api\..." on Windows and never match.
60
+ if (urlPath === "/api/prebuilt-data") {
61
+ if (req.method !== "POST") {
62
+ res.writeHead(405, { Allow: "POST" });
63
+ res.end();
64
+ return;
65
+ }
66
+ if (addPrebuiltData === undefined) {
67
+ res.writeHead(404);
68
+ res.end();
69
+ return;
70
+ }
71
+ try {
72
+ dataSources = addPrebuiltData();
73
+ }
74
+ catch (error) {
75
+ res.writeHead(500, { "Content-Type": CONTENT_TYPES[".json"] });
76
+ res.end(JSON.stringify({ error: error.message }));
77
+ return;
78
+ }
79
+ res.writeHead(200, { "Content-Type": CONTENT_TYPES[".json"] });
80
+ res.end(JSON.stringify({ dataSources }));
81
+ return;
82
+ }
83
+ const path = normalize(urlPath);
51
84
  const filePath = join(dist, path);
52
85
  if (!filePath.startsWith(dist + sep) && filePath !== dist) {
53
86
  res.writeHead(403);
@@ -57,7 +90,9 @@ export function serveUi(distDir, port, config) {
57
90
  const ext = extname(filePath);
58
91
  if (path === "/" || path === `${sep}index.html` || ext === "") {
59
92
  res.writeHead(200, { "Content-Type": CONTENT_TYPES[".html"] });
60
- res.end(indexHtml);
93
+ // Injected per request: `dataSources` changes when pre-built data is
94
+ // added, and a reload must see the updated collection.
95
+ res.end(injectConfig(rawIndexHtml, { ...config, dataSources }));
61
96
  return;
62
97
  }
63
98
  try {
@@ -35,8 +35,8 @@ supports the following types today:
35
35
  }
36
36
  ```
37
37
 
38
- - `type` — the source's kind; `"worker"`, the only kind these files can
39
- declare today, is the default.
38
+ - `type` — the source's kind. Hand-authored files declare `"worker"` (the
39
+ default); the pre-built sources the shell adds carry `"built-in"`.
40
40
  - `key` — what blocks bind against; make it match a `dataSources` key from
41
41
  `worker.customBlock(...)` so properties auto-match. Defaults to the
42
42
  filename.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notionhq/custom-blocks-dev-shell",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "Local preview shell for Notion custom block workers.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -17,6 +17,7 @@
17
17
  },
18
18
  "files": [
19
19
  "bin",
20
+ "data",
20
21
  "dist",
21
22
  "dist-cli",
22
23
  "docs",