create-ncblock 0.0.16 → 0.0.17

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ncblock",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "description": "Create a Notion custom view block project.",
5
5
  "type": "module",
6
6
  "bin": {
package/scripts/init.ts CHANGED
@@ -9,6 +9,7 @@ import {
9
9
  moveCursor,
10
10
  } from "readline"
11
11
  import { fileURLToPath } from "url"
12
+ import { resolveInitArgs } from "./utils/resolveInitArgs"
12
13
  import {
13
14
  getTemplateByName,
14
15
  getTemplates,
@@ -563,18 +564,30 @@ async function main() {
563
564
  args.install as boolean | undefined,
564
565
  )
565
566
 
566
- // Ask for the database URL/ID upfront — alongside the other prompts. The
567
- // prompt itself only fires when we'll actually install (no manifest pull
568
- // otherwise), but --collection is always honored.
569
- const collectionAnswer =
570
- (args.collection as string | undefined) ??
571
- (installDeps
567
+ // Ask for the database URL/ID upfront — alongside the other prompts.
568
+ // Precedence: --collection > --block/positional > prompt. A positional
569
+ // Notion ID is almost always a block inside a collection_view (or the
570
+ // view block itself); `manifest pull`'s resolveId() handles both cases,
571
+ // so we can feed the block ID straight through without re-prompting.
572
+ const blockIdArg = args.block as string | undefined
573
+ const promptedCollection =
574
+ args.collection === undefined && blockIdArg === undefined && installDeps
572
575
  ? (await ask("Database URL/ID (enter to skip):", "skip")).trim()
573
- : "skip")
574
- const collectionId =
575
- collectionAnswer && collectionAnswer !== "skip"
576
- ? collectionAnswer
577
576
  : undefined
577
+ const collectionOverride =
578
+ (args.collection as string | undefined) ??
579
+ (promptedCollection && promptedCollection !== "skip"
580
+ ? promptedCollection
581
+ : undefined)
582
+
583
+ const resolved = resolveInitArgs({
584
+ collection: collectionOverride,
585
+ block: blockIdArg,
586
+ envBlockId: process.env.BLOCK_ID,
587
+ envName: process.env.ENV,
588
+ installDeps,
589
+ })
590
+ const { blockId, collectionId } = resolved
578
591
 
579
592
  printSummary({
580
593
  dest,
@@ -615,16 +628,13 @@ async function main() {
615
628
  step("Initialized git repo")
616
629
  }
617
630
 
618
- const blockId =
619
- (args.block as string | undefined) || process.env.BLOCK_ID || undefined
620
- const envName = process.env.ENV
621
-
622
631
  // Always seed .notion/target.json so every project starts in a known
623
632
  // state. env / block_id are populated from what we have; data_sources
624
633
  // gets filled in by `manifest pull` if it runs.
625
- writeInitialTarget(dest, { env: envName, blockId })
634
+ writeInitialTarget(dest, { env: resolved.env, blockId })
626
635
  step(`Seeded .notion/target.json`)
627
636
 
637
+ let pulled = false
628
638
  if (installDeps) {
629
639
  // Close the readline interface before shelling out — otherwise it
630
640
  // holds onto stdin/stdout and the inherited stdio in child processes
@@ -640,7 +650,6 @@ async function main() {
640
650
  // block URL to a manifest entry AND merges the resolved data_source_id
641
651
  // into target.json's data_sources. Then `connect` (no flags needed —
642
652
  // reads everything from target.json) PATCHes the block if one's set.
643
- let pulled = false
644
653
  if (collectionId) {
645
654
  console.log("")
646
655
  try {
@@ -674,13 +683,30 @@ async function main() {
674
683
  }
675
684
  console.log(` ${pm} run build`)
676
685
  if (deployCommand) {
677
- console.log(` ${deployCommand}\n`)
686
+ console.log(` ${deployCommand}`)
678
687
  } else {
679
688
  console.log(
680
- `\n Then, go back to the instructions in Notion and paste the ${c.bold}ntn deploy${c.reset} command.\n`,
689
+ `\n Then, go back to the instructions in Notion and paste the ${c.bold}ntn deploy${c.reset} command.`,
681
690
  )
682
691
  }
683
692
 
693
+ // If install ran but no data source was wired (no collectionId, or a
694
+ // pull/connect failure), surface the manual CLI commands explicitly.
695
+ // Agents read this scrollback — being concrete here keeps them from
696
+ // reinventing the bridge or hardcoding IDs.
697
+ if (installDeps && !pulled) {
698
+ console.log(
699
+ `\n ${c.yellow}No data source connected yet.${c.reset} To wire one up:`,
700
+ )
701
+ console.log(` npx ncblock manifest pull <database-url-or-id>`)
702
+ if (!blockId) {
703
+ console.log(` npx ncblock connect --block <block-id-or-url>`)
704
+ } else {
705
+ console.log(` npx ncblock connect`)
706
+ }
707
+ }
708
+ console.log("")
709
+
684
710
  closePromptInterface()
685
711
  }
686
712
 
@@ -2,6 +2,14 @@
2
2
 
3
3
  A **Notion custom view** — a sandboxed `<iframe>` rendered inside a Notion block. The iframe is the entire viewport; the only channel to the host is a `postMessage` bridge wrapped by `ncblock`.
4
4
 
5
+ ## Connecting to a Notion database
6
+
7
+ If `custom_blocks.json` or `.notion/target.json` doesn't yet reference a datasource, ask the user if they want to connect a database by url or id. Use the `npx ncblock` cli to connect the database and the project. Discover available commands with:
8
+
9
+ ```bash
10
+ npx ncblock --help
11
+ ```
12
+
5
13
  ## Talking to the host
6
14
 
7
15
  - Always use the React hooks from `ncblock`. Never call `window.parent.postMessage` directly — the SDK owns the protocol.
@@ -32,7 +40,6 @@ Hooks at a glance:
32
40
 
33
41
  - Mount into `<div id="root">` — `useCustomBlockAutoResize` looks for that exact id.
34
42
  - `custom_blocks.json` at the project root defines the data contract. The SDK's Vite plugin serves it in dev; `ntn` bundles it into the deploy.
35
- - `custom_blocks.json` is the **portable contract** — no IDs. `.notion/target.json` holds the per-deploy IDs (block IDs, data-source IDs, resolved property IDs) and is committed alongside it.
36
43
 
37
44
  ## Previewing during development
38
45
 
@@ -45,23 +52,6 @@ Two options:
45
52
  cd custom && pnpm install && pnpm run dev:shell # http://localhost:9875
46
53
  ```
47
54
 
48
- ## Connecting to Notion
49
-
50
- `ncblock` cli provides helpers to wire a scaffolded project to a Notion block and data source. Wirings are saved to `.notion/target.json`. Check the output of the cli for latest syntax instead of copying these commands verbatim.
51
-
52
- ```bash
53
- # Pull a schema manifest from a Notion database into custom_blocks.json
54
- npx ncblock manifest pull <db-id-or-url>
55
-
56
- # Connect a local project to a Notion block and/or data source.
57
- npx ncblock connect
58
-
59
- # Deploy a dist/ directory to a block.
60
- npx ncblock deploy
61
- ```
62
-
63
- Templates will often already have some of these set in `.notion/target.json`.
64
-
65
55
  ## Where to look next
66
56
 
67
57
  - `node_modules/ncblock/README.md` — landing page with a TOC into the per-category docs below.
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Pure resolution of init.ts's data-source / block / env wiring decisions.
3
+ *
4
+ * Pulled out of init.ts so the precedence rules — especially "positional/--block
5
+ * Notion ID should also drive `manifest pull` when no --collection is given" —
6
+ * are unit-testable without spawning a tsx subprocess.
7
+ */
8
+
9
+ export type InitArgsInput = {
10
+ /** Value of --collection, if explicitly passed. */
11
+ collection?: string
12
+ /** Value of --block or a positional Notion ID, if passed. */
13
+ block?: string
14
+ /** `process.env.BLOCK_ID` — used as a last resort for block resolution. */
15
+ envBlockId?: string
16
+ /** `process.env.ENV` — populates `.notion/target.json#env`. */
17
+ envName?: string
18
+ /** Whether `init` will run install + ncblock pull/connect (--install / --no-install). */
19
+ installDeps: boolean
20
+ }
21
+
22
+ export type InitArgsResolution = {
23
+ blockId: string | undefined
24
+ collectionId: string | undefined
25
+ env: string
26
+ /** Will init invoke `ncblock manifest pull`? */
27
+ willPullManifest: boolean
28
+ /** Will init invoke `ncblock connect`? (only when pull will also run) */
29
+ willConnect: boolean
30
+ }
31
+
32
+ /**
33
+ * Decide what init will actually do, given the args. Precedence:
34
+ *
35
+ * 1. `--collection` is the explicit manifest-pull target (highest priority).
36
+ * 2. Otherwise, a positional/`--block` Notion ID doubles as the pull target —
37
+ * `manifest pull`'s resolveId() handles "block inside collection_view" and
38
+ * walks to the parent data source. This is the path users hit with
39
+ * `bun create ncblock <block-id>`.
40
+ * 3. When neither is set, no pull happens.
41
+ *
42
+ * `manifest pull` and `connect` only run when install ran (otherwise the
43
+ * ncblock CLI isn't on disk to call).
44
+ */
45
+ export function resolveInitArgs(input: InitArgsInput): InitArgsResolution {
46
+ const blockId = input.block || input.envBlockId || undefined
47
+ // A block ID doubles as the pull target: `manifest pull` accepts a block
48
+ // (resolveId walks block → parent → data source), and that's the path
49
+ // users hit with `bun create ncblock <block-id>`. Derived from `blockId`
50
+ // rather than `input.block` directly so envBlockId flows through too —
51
+ // no point treating `--block` and `BLOCK_ID=` differently.
52
+ const collectionId = input.collection ?? blockId
53
+ const env = input.envName ?? "production"
54
+
55
+ const willPullManifest = input.installDeps && collectionId !== undefined
56
+ const willConnect = willPullManifest && blockId !== undefined
57
+
58
+ return { blockId, collectionId, env, willPullManifest, willConnect }
59
+ }
package/sdk-version.json CHANGED
@@ -1 +1 @@
1
- {"version":"0.0.14"}
1
+ {"version":"0.0.15"}