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 +1 -1
- package/scripts/init.ts +44 -18
- package/scripts/scaffold-assets/AGENTS.md +8 -18
- package/scripts/utils/resolveInitArgs.ts +59 -0
- package/sdk-version.json +1 -1
package/package.json
CHANGED
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.
|
|
567
|
-
//
|
|
568
|
-
//
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
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:
|
|
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}
|
|
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
|
|
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.
|
|
1
|
+
{"version":"0.0.15"}
|