@notionhq/apps 0.0.47 → 0.0.49
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/dist/notion-as-code/resource.d.ts +2 -2
- package/dist/notion-as-code/resource.d.ts.map +1 -1
- package/dist/notion-as-code/resource.js +3 -1
- package/package.json +1 -1
- package/skills/notion-as-code/SKILL.md +4 -2
- package/skills/workflow/SKILL.md +5 -7
- package/src/notion-as-code/database.test.ts +26 -0
- package/src/notion-as-code/page.test.ts +24 -0
- package/src/notion-as-code/resource.ts +5 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Parent } from "./intents.js";
|
|
2
|
-
/** Validate parent references
|
|
2
|
+
/** Validate parent references. Reserved Apps IDs are allowed as parents. */
|
|
3
3
|
export declare function assertParent(parent: Parent): void;
|
|
4
|
-
/** Reject empty or runtime-reserved
|
|
4
|
+
/** Reject empty or runtime-reserved IDs for created resources. */
|
|
5
5
|
export declare function assertUserResourceId(resourceId: string): void;
|
|
6
6
|
//# sourceMappingURL=resource.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../src/notion-as-code/resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAE7E,
|
|
1
|
+
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../src/notion-as-code/resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAE7E,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAOjD;AAED,kEAAkE;AAClE,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAO7D"}
|
|
@@ -3,7 +3,9 @@ function assertParent(parent) {
|
|
|
3
3
|
if (parent.type !== "resourceId") {
|
|
4
4
|
throw new Error("Notion-as-Code parents must reference a resourceId");
|
|
5
5
|
}
|
|
6
|
-
|
|
6
|
+
if (parent.resourceId.length === 0) {
|
|
7
|
+
throw new Error("Notion-as-Code resourceId must be a non-empty string");
|
|
8
|
+
}
|
|
7
9
|
}
|
|
8
10
|
function assertUserResourceId(resourceId) {
|
|
9
11
|
if (resourceId.length === 0) {
|
package/package.json
CHANGED
|
@@ -155,8 +155,10 @@ Custom views do not accept standard view properties, sorts, or filters. Keep
|
|
|
155
155
|
the view resource ID and the custom-block filename stable across builds.
|
|
156
156
|
|
|
157
157
|
Keep resource IDs stable across builds. They identify declarations, not live
|
|
158
|
-
Notion UUIDs.
|
|
159
|
-
|
|
158
|
+
Notion UUIDs. Do not create resources whose IDs use the reserved
|
|
159
|
+
`__notion_apps_` prefix. Parenting to reserved IDs such as
|
|
160
|
+
`__notion_apps_app_md__` is allowed. Explicit parents use
|
|
161
|
+
`{ type: "resourceId", resourceId: parent.resourceId }`; child helpers set
|
|
160
162
|
this reference for you. Pages and databases without a parent default to private
|
|
161
163
|
top-level resources in the Apps workspace.
|
|
162
164
|
|
package/skills/workflow/SKILL.md
CHANGED
|
@@ -156,7 +156,10 @@ configuration, and do not log secrets or private payloads.
|
|
|
156
156
|
|
|
157
157
|
## Manual workflow inputs
|
|
158
158
|
|
|
159
|
-
Provide up to one `events.manual` to allow triggering the workflow
|
|
159
|
+
Provide up to one `events.manual()` to allow triggering the workflow from the UI
|
|
160
|
+
or CLI on demand. For scheduled workflows, include it alongside
|
|
161
|
+
`events.scheduled()` so users can run the workflow without waiting for the next
|
|
162
|
+
scheduled time.
|
|
160
163
|
|
|
161
164
|
Specify the inputs accepted using `@notionhq/apps/schema-builder`.
|
|
162
165
|
|
|
@@ -247,7 +250,7 @@ import { guide } from "./sayHello/lib/notion.js";
|
|
|
247
250
|
export default workflow({
|
|
248
251
|
name: "Read guide",
|
|
249
252
|
description: "Reads the App's guide on a recurring schedule.",
|
|
250
|
-
triggers: [events.scheduled()],
|
|
253
|
+
triggers: [events.scheduled(), events.manual()],
|
|
251
254
|
access: { guide: access.view(guide) },
|
|
252
255
|
handler: async (_event, context) => {
|
|
253
256
|
await context.step("Read guide", () =>
|
|
@@ -262,11 +265,6 @@ declarations in `access` work too. Importing a declaration alone provisions the
|
|
|
262
265
|
resource but does not create a `context.access` alias. An `access` entry declares
|
|
263
266
|
the needed permission level and a named binding for that NaC resource.
|
|
264
267
|
|
|
265
|
-
For a workflow that uses `events.scheduled()`, also declare a "triggers"
|
|
266
|
-
database with a page-added trigger bound to it. This lets the user manually
|
|
267
|
-
trigger a run at any time by adding a page to that database, without waiting
|
|
268
|
-
for the schedule.
|
|
269
|
-
|
|
270
268
|
`access.view()`, `access.comment()`, `access.edit()`, and `access.fullAccess()`
|
|
271
269
|
accept page, database, and data-source handles. `access.call()` accepts custom-agent
|
|
272
270
|
handles. Keys are workflow-local aliases. The handler's
|
|
@@ -791,6 +791,32 @@ describe("Notion-as-Code database declarations", () => {
|
|
|
791
791
|
expect(serialized.description).toBe("Metadata source");
|
|
792
792
|
});
|
|
793
793
|
|
|
794
|
+
it("allows parenting a database to a reserved Apps resource ID", () => {
|
|
795
|
+
const recorder = startMetadataRecording();
|
|
796
|
+
notion.database("meetings-db", {
|
|
797
|
+
parent: { type: "resourceId", resourceId: "__notion_apps_app_md__" },
|
|
798
|
+
dataSourceResourceId: "meetings-source",
|
|
799
|
+
name: "Meetings",
|
|
800
|
+
schema: { Name: { resourceId: "meeting-name", type: "title" } },
|
|
801
|
+
});
|
|
802
|
+
expect(finishMetadataRecording(recorder).intents[0]).toEqual(
|
|
803
|
+
expect.objectContaining({
|
|
804
|
+
resourceId: "meetings-db",
|
|
805
|
+
parent: { type: "resourceId", resourceId: "__notion_apps_app_md__" },
|
|
806
|
+
}),
|
|
807
|
+
);
|
|
808
|
+
});
|
|
809
|
+
|
|
810
|
+
it("rejects creating a database whose resource ID uses the reserved Apps prefix", () => {
|
|
811
|
+
expect(() =>
|
|
812
|
+
notion.database("__notion_apps_meetings__", {
|
|
813
|
+
dataSourceResourceId: "meetings-source",
|
|
814
|
+
name: "Meetings",
|
|
815
|
+
schema: { Name: { resourceId: "meeting-name", type: "title" } },
|
|
816
|
+
}),
|
|
817
|
+
).toThrow('Resource ID "__notion_apps_meetings__" uses the reserved Apps prefix');
|
|
818
|
+
});
|
|
819
|
+
|
|
794
820
|
it("requires the status property configuration in authoring types", () => {
|
|
795
821
|
const invalidStatusDeclaration = () =>
|
|
796
822
|
notion.database("missing-status-options-database", {
|
|
@@ -28,6 +28,30 @@ describe("Notion-as-Code page declarations", () => {
|
|
|
28
28
|
]);
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
+
it("allows parenting a page to a reserved Apps resource ID", () => {
|
|
32
|
+
const recorder = startMetadataRecording();
|
|
33
|
+
notion.page({
|
|
34
|
+
resourceId: "guide",
|
|
35
|
+
parent: { type: "resourceId", resourceId: "__notion_apps_app_md__" },
|
|
36
|
+
properties: { title: notion.text("Guide") },
|
|
37
|
+
});
|
|
38
|
+
expect(finishMetadataRecording(recorder).intents[0]).toEqual(
|
|
39
|
+
expect.objectContaining({
|
|
40
|
+
resourceId: "guide",
|
|
41
|
+
parent: { type: "resourceId", resourceId: "__notion_apps_app_md__" },
|
|
42
|
+
}),
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("rejects creating a page whose resource ID uses the reserved Apps prefix", () => {
|
|
47
|
+
expect(() =>
|
|
48
|
+
notion.page({
|
|
49
|
+
resourceId: "__notion_apps_guide__",
|
|
50
|
+
properties: { title: notion.text("Guide") },
|
|
51
|
+
}),
|
|
52
|
+
).toThrow('Resource ID "__notion_apps_guide__" uses the reserved Apps prefix');
|
|
53
|
+
});
|
|
54
|
+
|
|
31
55
|
it("records a regular page title separately from Markdown content", () => {
|
|
32
56
|
const properties = {
|
|
33
57
|
title: notion.text("Workflow guide"),
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { APPS_RESERVED_RESOURCE_ID_PREFIX, type Parent } from "./intents.js";
|
|
2
2
|
|
|
3
|
-
/** Validate parent references
|
|
3
|
+
/** Validate parent references. Reserved Apps IDs are allowed as parents. */
|
|
4
4
|
export function assertParent(parent: Parent): void {
|
|
5
5
|
if (parent.type !== "resourceId") {
|
|
6
6
|
throw new Error("Notion-as-Code parents must reference a resourceId");
|
|
7
7
|
}
|
|
8
|
-
|
|
8
|
+
if (parent.resourceId.length === 0) {
|
|
9
|
+
throw new Error("Notion-as-Code resourceId must be a non-empty string");
|
|
10
|
+
}
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
/** Reject empty or runtime-reserved
|
|
13
|
+
/** Reject empty or runtime-reserved IDs for created resources. */
|
|
12
14
|
export function assertUserResourceId(resourceId: string): void {
|
|
13
15
|
if (resourceId.length === 0) {
|
|
14
16
|
throw new Error("Notion-as-Code resourceId must be a non-empty string");
|