@notionhq/apps 0.0.19 → 0.0.20
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 +5 -1
- package/dist/notion-as-code/date.d.ts +3 -2
- package/dist/notion-as-code/date.d.ts.map +1 -1
- package/dist/notion-as-code/handles.d.ts +8 -11
- package/dist/notion-as-code/handles.d.ts.map +1 -1
- package/dist/notion-as-code/handles.js +8 -7
- package/dist/notion-as-code/index.d.ts +8 -11
- package/dist/notion-as-code/index.d.ts.map +1 -1
- package/dist/notion-as-code/page.d.ts +49 -1
- package/dist/notion-as-code/page.d.ts.map +1 -1
- package/dist/notion-as-code/page.test.d.ts +2 -0
- package/dist/notion-as-code/page.test.d.ts.map +1 -0
- package/package.json +1 -1
- package/skills/notion-as-code/SKILL.md +8 -3
- package/skills/workflow/SKILL.md +3 -1
- package/src/notion-as-code/date.ts +4 -2
- package/src/notion-as-code/handles.ts +16 -12
- package/src/notion-as-code/index.ts +10 -1
- package/src/notion-as-code/page.test.ts +35 -0
- package/src/notion-as-code/page.ts +60 -2
package/README.md
CHANGED
|
@@ -23,8 +23,12 @@ Import the helpers your app uses:
|
|
|
23
23
|
|
|
24
24
|
```ts
|
|
25
25
|
import { page, workflow } from "@notionhq/apps";
|
|
26
|
+
import { notion } from "@notionhq/apps/notion-as-code";
|
|
26
27
|
|
|
27
|
-
const home = page({
|
|
28
|
+
const home = page({
|
|
29
|
+
resourceId: "home",
|
|
30
|
+
properties: { title: notion.text("App home") },
|
|
31
|
+
});
|
|
28
32
|
|
|
29
33
|
export default workflow({
|
|
30
34
|
name: "Follow up",
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import type { TextValue } from "./page.js";
|
|
1
2
|
/** Serialize Notion-as-Code date values for Apps property payloads. */
|
|
2
|
-
export declare function date(startDate: string, endDate?: string):
|
|
3
|
+
export declare function date(startDate: string, endDate?: string): TextValue;
|
|
3
4
|
/** Serialize Notion-as-Code datetime values for Apps property payloads. */
|
|
4
5
|
export declare function datetime(value: {
|
|
5
6
|
start: string;
|
|
6
7
|
end?: string;
|
|
7
8
|
timeZone?: string;
|
|
8
|
-
}):
|
|
9
|
+
}): TextValue;
|
|
9
10
|
//# sourceMappingURL=date.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/notion-as-code/date.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,wBAAgB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/notion-as-code/date.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,uEAAuE;AACvE,wBAAgB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAWnE;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CA6B7F"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { customAgent } from "./custom-agent.js";
|
|
2
2
|
import { database } from "./database.js";
|
|
3
3
|
import { date, datetime } from "./date.js";
|
|
4
|
-
import { page } from "./page.js";
|
|
4
|
+
import { page, type TextValue, type VerificationInput, type VerificationPropertyValue } from "./page.js";
|
|
5
5
|
import { teamspace } from "./teamspace.js";
|
|
6
6
|
import { view } from "./view.js";
|
|
7
7
|
declare const notionAsCodeFacade: {
|
|
@@ -10,22 +10,19 @@ declare const notionAsCodeFacade: {
|
|
|
10
10
|
page: typeof page;
|
|
11
11
|
customAgent: typeof customAgent;
|
|
12
12
|
view: typeof view;
|
|
13
|
-
text: (value: string) =>
|
|
14
|
-
number: (value: number) =>
|
|
13
|
+
text: (value: string) => TextValue;
|
|
14
|
+
number: (value: number) => TextValue;
|
|
15
15
|
date: typeof date;
|
|
16
16
|
datetime: typeof datetime;
|
|
17
|
+
verification: (value: VerificationInput) => VerificationPropertyValue;
|
|
17
18
|
select: (value: string) => string;
|
|
18
19
|
status: (value: string) => string;
|
|
19
20
|
multiSelect: (values: readonly string[]) => string;
|
|
20
|
-
checkbox: (value: boolean) =>
|
|
21
|
-
url: (value: string) =>
|
|
22
|
-
email: (value: string) =>
|
|
23
|
-
phone: (value: string) =>
|
|
21
|
+
checkbox: (value: boolean) => TextValue;
|
|
22
|
+
url: (value: string) => TextValue;
|
|
23
|
+
email: (value: string) => TextValue;
|
|
24
|
+
phone: (value: string) => TextValue;
|
|
24
25
|
relation: (value: string | readonly string[]) => string | any[] | readonly string[];
|
|
25
|
-
file: (resourceId: string) => {
|
|
26
|
-
type: "file";
|
|
27
|
-
resourceId: string;
|
|
28
|
-
};
|
|
29
26
|
};
|
|
30
27
|
export type NotionAsCodeFacade = typeof notionAsCodeFacade;
|
|
31
28
|
/** Create the runtime facade used to declare Notion-as-Code project metadata. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handles.d.ts","sourceRoot":"","sources":["../../src/notion-as-code/handles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,
|
|
1
|
+
{"version":3,"file":"handles.d.ts","sourceRoot":"","sources":["../../src/notion-as-code/handles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EACN,IAAI,EACJ,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,QAAA,MAAM,kBAAkB;;;;;;kBAMT,MAAM,KAAG,SAAS;oBAChB,MAAM,KAAG,SAAS;;;0BAGZ,iBAAiB,KAAG,yBAAyB;oBAInD,MAAM;oBACN,MAAM;0BACA,SAAS,MAAM,EAAE;sBACrB,OAAO,KAAG,SAAS;iBACxB,MAAM,KAAG,SAAS;mBAChB,MAAM,KAAG,SAAS;mBAClB,MAAM,KAAG,SAAS;sBACf,MAAM,GAAG,SAAS,MAAM,EAAE;CAC5C,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,OAAO,kBAAkB,CAAC;AAE3D,iFAAiF;AACjF,wBAAgB,YAAY,IAAI,kBAAkB,CAEjD"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { customAgent } from "./custom-agent.js";
|
|
2
2
|
import { database } from "./database.js";
|
|
3
3
|
import { date, datetime } from "./date.js";
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
page
|
|
6
|
+
} from "./page.js";
|
|
6
7
|
import { teamspace } from "./teamspace.js";
|
|
7
8
|
import { view } from "./view.js";
|
|
8
9
|
const notionAsCodeFacade = {
|
|
@@ -15,6 +16,10 @@ const notionAsCodeFacade = {
|
|
|
15
16
|
number: (value) => [[String(value)]],
|
|
16
17
|
date,
|
|
17
18
|
datetime,
|
|
19
|
+
verification: (value) => ({
|
|
20
|
+
...value,
|
|
21
|
+
type: "verification"
|
|
22
|
+
}),
|
|
18
23
|
select: (value) => value,
|
|
19
24
|
status: (value) => value,
|
|
20
25
|
multiSelect: (values) => values.join(","),
|
|
@@ -22,11 +27,7 @@ const notionAsCodeFacade = {
|
|
|
22
27
|
url: (value) => [[value, [["a", value]]]],
|
|
23
28
|
email: (value) => [[value, [["a", `mailto:${value}`]]]],
|
|
24
29
|
phone: (value) => [[value]],
|
|
25
|
-
relation: (value) => Array.isArray(value) ? [...value] : value
|
|
26
|
-
file: (resourceId) => {
|
|
27
|
-
assertUserResourceId(resourceId);
|
|
28
|
-
return { type: "file", resourceId };
|
|
29
|
-
}
|
|
30
|
+
relation: (value) => Array.isArray(value) ? [...value] : value
|
|
30
31
|
};
|
|
31
32
|
function createNotion() {
|
|
32
33
|
return notionAsCodeFacade;
|
|
@@ -2,7 +2,7 @@ export { APPS_RESERVED_RESOURCE_ID_PREFIX, APPS_WORKSPACE_RESOURCE_ID } from "./
|
|
|
2
2
|
export type { DatabaseIntent, DataSourceDefinition, NotionAsCodeIcon, NotionAsCodeProperty, NotionAsCodePropertyConfig, NotionAsCodeSchema, NotionAsCodeSelectOption, NotionAsCodeStatusOption, Parent, ResourceId, } from "./intents.js";
|
|
3
3
|
export type { CustomAgentArgs, CustomAgentHandle } from "./custom-agent.js";
|
|
4
4
|
export type { ChildDatabaseArgs, ChildDatabaseFactory, ChildMultiSourceDatabaseArgs, ChildSingleSourceDatabaseArgs, DataSourceArgs, DataSourceHandle, DataSourceMap, DatabaseArgs, DatabaseHandle, MultiSourceDatabaseArgs, SingleSourceDatabaseArgs, SingleSourceDatabaseHandle, } from "./database.js";
|
|
5
|
-
export type { ChildPageArgs, PageArgs, PageHandle } from "./page.js";
|
|
5
|
+
export type { ChildPageArgs, PageArgs, PageHandle, PropertyValue, SimpleTextToken, TextValue, VerificationInput, VerificationPropertyValue, } from "./page.js";
|
|
6
6
|
export type { TeamspaceArgs, TeamspaceHandle } from "./teamspace.js";
|
|
7
7
|
export type { ViewArgs, ViewHandle } from "./view.js";
|
|
8
8
|
export type { AdvancedFilterSchema, BasePropertyFilter, BaseViewSchema, BoardViewSchema, CalendarViewSchema, CheckboxGroupByFormat, CheckboxPropertyFilter, CoverAspectFormat, CoverFormat, CoverSizeFormat, DatabaseViewSortDirection, DateFilterMode, DateGroupByFormat, DatePropertyFilter, DatePropertyFilterValue, DatePropertyTypes, ExactDatePropertyFilterValue, ExactRangeDatePropertyFilterValue, FeedViewSchema, FilterSchema, FormulaGroupByFormat, GalleryViewSchema, GroupByFormat, GroupByFormatBase, GroupFormat, ListViewSchema, LocationGroupByFormat, MultiSelectPropertyFilter, NumberGroupByFormat, NumberPropertyFilter, PersonGroupByFormat, PersonPropertyFilter, PropertyFilterSchema, PropertyFormat, PropertyViewSortSchema, PropertyVisibility, RelationGroupByFormat, RelationPropertyFilter, RelativeDatePreset, RelativeDatePropertyFilterValue, RelativeDateRangeUnit, RelativeToTodayDatePropertyFilterValue, SelectGroupByFormat, SelectPropertyFilter, StatusGroupByFormat, StatusPropertyFilter, TableViewSchema, TextGroupByFormat, TextPropertyFilter, TimelineViewSchema, ViewSchema, ViewType, } from "./views.js";
|
|
@@ -13,21 +13,18 @@ export declare const notion: {
|
|
|
13
13
|
page: typeof import("./page.js").page;
|
|
14
14
|
customAgent: typeof import("./custom-agent.js").customAgent;
|
|
15
15
|
view: typeof import("./view.js").view;
|
|
16
|
-
text: (value: string) =>
|
|
17
|
-
number: (value: number) =>
|
|
16
|
+
text: (value: string) => import("./page.js").TextValue;
|
|
17
|
+
number: (value: number) => import("./page.js").TextValue;
|
|
18
18
|
date: typeof import("./date.js").date;
|
|
19
19
|
datetime: typeof import("./date.js").datetime;
|
|
20
|
+
verification: (value: import("./page.js").VerificationInput) => import("./page.js").VerificationPropertyValue;
|
|
20
21
|
select: (value: string) => string;
|
|
21
22
|
status: (value: string) => string;
|
|
22
23
|
multiSelect: (values: readonly string[]) => string;
|
|
23
|
-
checkbox: (value: boolean) =>
|
|
24
|
-
url: (value: string) => (
|
|
25
|
-
email: (value: string) => (
|
|
26
|
-
phone: (value: string) =>
|
|
24
|
+
checkbox: (value: boolean) => import("./page.js").TextValue;
|
|
25
|
+
url: (value: string) => import("./page.js").TextValue;
|
|
26
|
+
email: (value: string) => import("./page.js").TextValue;
|
|
27
|
+
phone: (value: string) => import("./page.js").TextValue;
|
|
27
28
|
relation: (value: string | readonly string[]) => string | any[] | readonly string[];
|
|
28
|
-
file: (resourceId: string) => {
|
|
29
|
-
type: "file";
|
|
30
|
-
resourceId: string;
|
|
31
|
-
};
|
|
32
29
|
};
|
|
33
30
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/notion-as-code/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gCAAgC,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC5F,YAAY,EACX,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,0BAA0B,EAC1B,kBAAkB,EAClB,wBAAwB,EACxB,wBAAwB,EACxB,MAAM,EACN,UAAU,GACV,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,YAAY,EACX,iBAAiB,EACjB,oBAAoB,EACpB,4BAA4B,EAC5B,6BAA6B,EAC7B,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,cAAc,EACd,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,GAC1B,MAAM,eAAe,CAAC;AACvB,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/notion-as-code/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gCAAgC,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC5F,YAAY,EACX,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,0BAA0B,EAC1B,kBAAkB,EAClB,wBAAwB,EACxB,wBAAwB,EACxB,MAAM,EACN,UAAU,GACV,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,YAAY,EACX,iBAAiB,EACjB,oBAAoB,EACpB,4BAA4B,EAC5B,6BAA6B,EAC7B,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,cAAc,EACd,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,GAC1B,MAAM,eAAe,CAAC;AACvB,YAAY,EACX,aAAa,EACb,QAAQ,EACR,UAAU,EACV,aAAa,EACb,eAAe,EACf,SAAS,EACT,iBAAiB,EACjB,yBAAyB,GACzB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACrE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACtD,YAAY,EACX,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,yBAAyB,EACzB,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EACjB,4BAA4B,EAC5B,iCAAiC,EACjC,cAAc,EACd,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,qBAAqB,EACrB,yBAAyB,EACzB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,sBAAsB,EACtB,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,EAClB,+BAA+B,EAC/B,qBAAqB,EACrB,sCAAsC,EACtC,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,UAAU,EACV,QAAQ,GACR,MAAM,YAAY,CAAC;AAEpB,wEAAwE;AACxE,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;CAAiB,CAAC"}
|
|
@@ -1,11 +1,59 @@
|
|
|
1
1
|
import { type Parent, type ResourceId } from "./intents.js";
|
|
2
2
|
import { type ChildDatabaseFactory } from "./database.js";
|
|
3
|
+
/**
|
|
4
|
+
* A single text token: plain text as `[string]`, or text with annotations as
|
|
5
|
+
* `[string, ...annotations]`.
|
|
6
|
+
*/
|
|
7
|
+
export type SimpleTextToken = [string] | [string, ...unknown[]];
|
|
8
|
+
/**
|
|
9
|
+
* The JSON-serializable text format returned by Notion-as-Code text helpers.
|
|
10
|
+
*/
|
|
11
|
+
export type TextValue = SimpleTextToken[];
|
|
12
|
+
export type VerificationInput = {
|
|
13
|
+
state: "verified";
|
|
14
|
+
/** Set an expiration with `notion.datetime(...)`; omit it for indefinite verification. */
|
|
15
|
+
datetime?: TextValue;
|
|
16
|
+
} | {
|
|
17
|
+
state: "unverified";
|
|
18
|
+
};
|
|
19
|
+
export type VerificationPropertyValue = VerificationInput & {
|
|
20
|
+
type: "verification";
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* A page property value accepted by Notion as Code.
|
|
24
|
+
*
|
|
25
|
+
* Use helpers from `@notionhq/apps/notion-as-code` to construct rich values
|
|
26
|
+
* such as text, dates, checkboxes, and URLs.
|
|
27
|
+
*/
|
|
28
|
+
export type PropertyValue = string | number | TextValue | string[] | VerificationPropertyValue | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Arguments for declaring a page.
|
|
31
|
+
*
|
|
32
|
+
* For a regular page, set its title through
|
|
33
|
+
* `properties.title: notion.text("My Page Title")`. For a database page, use
|
|
34
|
+
* the title property's schema name instead of `title`.
|
|
35
|
+
*/
|
|
3
36
|
export type PageArgs = {
|
|
4
37
|
resourceId: ResourceId;
|
|
5
38
|
/** Omit to create a private top-level page in the Apps workspace. */
|
|
6
39
|
parent?: Parent;
|
|
7
40
|
cover?: unknown;
|
|
8
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Page properties, including the page title.
|
|
43
|
+
*
|
|
44
|
+
* @example Regular page
|
|
45
|
+
* properties: { title: notion.text("My Page Title") }
|
|
46
|
+
*
|
|
47
|
+
* @example Database page
|
|
48
|
+
* properties: { Name: notion.text("Task Name"), Status: "In Progress" }
|
|
49
|
+
*/
|
|
50
|
+
properties?: Record<string, PropertyValue | undefined>;
|
|
51
|
+
/**
|
|
52
|
+
* Page body in Notion-flavored Markdown.
|
|
53
|
+
*
|
|
54
|
+
* Markdown headings create child blocks. They do not set the page title;
|
|
55
|
+
* set a regular page's title with `properties.title`.
|
|
56
|
+
*/
|
|
9
57
|
content?: string;
|
|
10
58
|
fullWidth?: boolean;
|
|
11
59
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../src/notion-as-code/page.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,MAAM,EACX,KAAK,UAAU,EACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAI/E,MAAM,MAAM,QAAQ,GAAG;IACtB,UAAU,EAAE,UAAU,CAAC;IACvB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,KAAK,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../src/notion-as-code/page.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,MAAM,EACX,KAAK,UAAU,EACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAI/E;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AAEhE;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC;AAE1C,MAAM,MAAM,iBAAiB,GAC1B;IACA,KAAK,EAAE,UAAU,CAAC;IAClB,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,SAAS,CAAC;CACpB,GACD;IAAE,KAAK,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3B,MAAM,MAAM,yBAAyB,GAAG,iBAAiB,GAAG;IAC3D,IAAI,EAAE,cAAc,CAAC;CACrB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GACtB,MAAM,GACN,MAAM,GACN,SAAS,GACT,MAAM,EAAE,GACR,yBAAyB,GACzB,SAAS,CAAC;AAEb;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG;IACtB,UAAU,EAAE,UAAU,CAAC;IACvB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC,CAAC;IACvD;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAErD,MAAM,MAAM,UAAU,GAAG;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE,oBAAoB,CAAC;IAClC,OAAO,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,UAAU,CAAC;CAC7C,CAAC;AAEF,oFAAoF;AACpF,wBAAgB,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAS/C;AAED,6DAA6D;AAC7D,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CAgBrF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.test.d.ts","sourceRoot":"","sources":["../../src/notion-as-code/page.test.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -75,7 +75,8 @@ root exports support:
|
|
|
75
75
|
|
|
76
76
|
- `teamspace({ resourceId, name, accessLevel })`, with `addPage` and
|
|
77
77
|
`teamspace.addDatabase(id, args)` on the returned handle.
|
|
78
|
-
- `page({ resourceId, parent?, properties?, content? })
|
|
78
|
+
- `page({ resourceId, parent?, properties?, content? })`; regular page titles use
|
|
79
|
+
`properties: { title: notion.text("My Page Title") }`. It also has
|
|
79
80
|
`addPage` and `page.addDatabase(id, args)` for children.
|
|
80
81
|
- `database(resourceId, { dataSourceResourceId, name, schema, parent?, views? })`,
|
|
81
82
|
returning a single source as `handle.dataSource`, or
|
|
@@ -90,6 +91,11 @@ root exports support:
|
|
|
90
91
|
Use property resource IDs in view filters, sorts, and layout options; calendar
|
|
91
92
|
views require `calendarBy`, and timeline views require `timelineBy`.
|
|
92
93
|
|
|
94
|
+
For a regular page, set the title with
|
|
95
|
+
`properties: { title: notion.text("My Page Title") }`. A Markdown heading in
|
|
96
|
+
`content` creates a child heading block; it does not set the page title. For a
|
|
97
|
+
database page, use the title property's schema name instead of `title`.
|
|
98
|
+
|
|
93
99
|
A database declaration must include at least one data source or at least one
|
|
94
100
|
view. A linked-only database may omit `datasources`, or use `datasources: {}`,
|
|
95
101
|
only when `views` is nonempty. `{}`, `{ datasources: {} }`, and
|
|
@@ -131,8 +137,7 @@ The Apps SDK exposes a subset of Notion as Code. Data sources are nested inside
|
|
|
131
137
|
Apps deployment rejects workspace creation or changes and supplies the App's
|
|
132
138
|
workspace binding itself. Value helpers and types stay on their existing
|
|
133
139
|
subpaths. For example, import `{ notion }` from `@notionhq/apps/notion-as-code`
|
|
134
|
-
for `notion.text(...)
|
|
135
|
-
reference, not an upload or file declaration. These helpers are not root exports.
|
|
140
|
+
for `notion.text(...)`. These helpers are not root exports.
|
|
136
141
|
CLI acceptance of a serialized intent envelope alone does not establish server
|
|
137
142
|
support for its contents.
|
|
138
143
|
|
package/skills/workflow/SKILL.md
CHANGED
|
@@ -120,10 +120,12 @@ guide page in `src/workflows/sayHello/lib/notion.ts`:
|
|
|
120
120
|
|
|
121
121
|
```ts
|
|
122
122
|
import { page } from "@notionhq/apps";
|
|
123
|
+
import { notion } from "@notionhq/apps/notion-as-code";
|
|
123
124
|
|
|
124
125
|
export const guide = page({
|
|
125
126
|
resourceId: "workflow-guide",
|
|
126
|
-
|
|
127
|
+
properties: { title: notion.text("Workflow guide") },
|
|
128
|
+
content: "This App runs a scheduled workflow.",
|
|
127
129
|
});
|
|
128
130
|
```
|
|
129
131
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { TextValue } from "./page.js";
|
|
2
|
+
|
|
1
3
|
/** Serialize Notion-as-Code date values for Apps property payloads. */
|
|
2
|
-
export function date(startDate: string, endDate?: string):
|
|
4
|
+
export function date(startDate: string, endDate?: string): TextValue {
|
|
3
5
|
const start_date = parseIsoDate(startDate);
|
|
4
6
|
const end_date = endDate === undefined ? undefined : parseIsoDate(endDate);
|
|
5
7
|
if (end_date !== undefined && end_date < start_date) {
|
|
@@ -13,7 +15,7 @@ export function date(startDate: string, endDate?: string): unknown[][] {
|
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
/** Serialize Notion-as-Code datetime values for Apps property payloads. */
|
|
16
|
-
export function datetime(value: { start: string; end?: string; timeZone?: string }):
|
|
18
|
+
export function datetime(value: { start: string; end?: string; timeZone?: string }): TextValue {
|
|
17
19
|
const timeZone = value.timeZone ?? "UTC";
|
|
18
20
|
try {
|
|
19
21
|
new Intl.DateTimeFormat("en-US", { timeZone }).format();
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { customAgent } from "./custom-agent.js";
|
|
2
2
|
import { database } from "./database.js";
|
|
3
3
|
import { date, datetime } from "./date.js";
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
page,
|
|
6
|
+
type TextValue,
|
|
7
|
+
type VerificationInput,
|
|
8
|
+
type VerificationPropertyValue,
|
|
9
|
+
} from "./page.js";
|
|
6
10
|
import { teamspace } from "./teamspace.js";
|
|
7
11
|
import { view } from "./view.js";
|
|
8
12
|
|
|
@@ -12,22 +16,22 @@ const notionAsCodeFacade = {
|
|
|
12
16
|
page,
|
|
13
17
|
customAgent,
|
|
14
18
|
view,
|
|
15
|
-
text: (value: string) => [[value]],
|
|
16
|
-
number: (value: number) => [[String(value)]],
|
|
19
|
+
text: (value: string): TextValue => [[value]],
|
|
20
|
+
number: (value: number): TextValue => [[String(value)]],
|
|
17
21
|
date,
|
|
18
22
|
datetime,
|
|
23
|
+
verification: (value: VerificationInput): VerificationPropertyValue => ({
|
|
24
|
+
...value,
|
|
25
|
+
type: "verification",
|
|
26
|
+
}),
|
|
19
27
|
select: (value: string) => value,
|
|
20
28
|
status: (value: string) => value,
|
|
21
29
|
multiSelect: (values: readonly string[]) => values.join(","),
|
|
22
|
-
checkbox: (value: boolean) => [[value ? "Yes" : "No"]],
|
|
23
|
-
url: (value: string) => [[value, [["a", value]]]],
|
|
24
|
-
email: (value: string) => [[value, [["a", `mailto:${value}`]]]],
|
|
25
|
-
phone: (value: string) => [[value]],
|
|
30
|
+
checkbox: (value: boolean): TextValue => [[value ? "Yes" : "No"]],
|
|
31
|
+
url: (value: string): TextValue => [[value, [["a", value]]]],
|
|
32
|
+
email: (value: string): TextValue => [[value, [["a", `mailto:${value}`]]]],
|
|
33
|
+
phone: (value: string): TextValue => [[value]],
|
|
26
34
|
relation: (value: string | readonly string[]) => (Array.isArray(value) ? [...value] : value),
|
|
27
|
-
file: (resourceId: string) => {
|
|
28
|
-
assertUserResourceId(resourceId);
|
|
29
|
-
return { type: "file" as const, resourceId };
|
|
30
|
-
},
|
|
31
35
|
};
|
|
32
36
|
|
|
33
37
|
export type NotionAsCodeFacade = typeof notionAsCodeFacade;
|
|
@@ -28,7 +28,16 @@ export type {
|
|
|
28
28
|
SingleSourceDatabaseArgs,
|
|
29
29
|
SingleSourceDatabaseHandle,
|
|
30
30
|
} from "./database.js";
|
|
31
|
-
export type {
|
|
31
|
+
export type {
|
|
32
|
+
ChildPageArgs,
|
|
33
|
+
PageArgs,
|
|
34
|
+
PageHandle,
|
|
35
|
+
PropertyValue,
|
|
36
|
+
SimpleTextToken,
|
|
37
|
+
TextValue,
|
|
38
|
+
VerificationInput,
|
|
39
|
+
VerificationPropertyValue,
|
|
40
|
+
} from "./page.js";
|
|
32
41
|
export type { TeamspaceArgs, TeamspaceHandle } from "./teamspace.js";
|
|
33
42
|
export type { ViewArgs, ViewHandle } from "./view.js";
|
|
34
43
|
export type {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, expect, expectTypeOf, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { notion, type PageArgs, type PropertyValue } from "./index.js";
|
|
4
|
+
import { finishMetadataRecording, startMetadataRecording } from "./recorder.js";
|
|
5
|
+
|
|
6
|
+
describe("Notion-as-Code page declarations", () => {
|
|
7
|
+
it("records a regular page title separately from Markdown content", () => {
|
|
8
|
+
const properties = {
|
|
9
|
+
title: notion.text("Workflow guide"),
|
|
10
|
+
} satisfies Record<string, PropertyValue | undefined>;
|
|
11
|
+
const recorder = startMetadataRecording();
|
|
12
|
+
|
|
13
|
+
notion.page({
|
|
14
|
+
resourceId: "workflow-guide",
|
|
15
|
+
properties,
|
|
16
|
+
content: "# Body heading",
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
expectTypeOf<PageArgs["properties"]>().toEqualTypeOf<
|
|
20
|
+
Record<string, PropertyValue | undefined> | undefined
|
|
21
|
+
>();
|
|
22
|
+
expect(finishMetadataRecording(recorder).intents).toEqual([
|
|
23
|
+
{
|
|
24
|
+
type: "page",
|
|
25
|
+
resourceId: "workflow-guide",
|
|
26
|
+
parent: {
|
|
27
|
+
type: "resourceId",
|
|
28
|
+
resourceId: "__notion_apps_workspace__",
|
|
29
|
+
},
|
|
30
|
+
properties: { title: [["Workflow guide"]] },
|
|
31
|
+
content: "# Body heading",
|
|
32
|
+
},
|
|
33
|
+
]);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -8,14 +8,72 @@ import { createChildDatabase, type ChildDatabaseFactory } from "./database.js";
|
|
|
8
8
|
import { recordIntent } from "./recorder.js";
|
|
9
9
|
import { assertParent, assertUserResourceId } from "./resource.js";
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* A single text token: plain text as `[string]`, or text with annotations as
|
|
13
|
+
* `[string, ...annotations]`.
|
|
14
|
+
*/
|
|
15
|
+
export type SimpleTextToken = [string] | [string, ...unknown[]];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The JSON-serializable text format returned by Notion-as-Code text helpers.
|
|
19
|
+
*/
|
|
20
|
+
export type TextValue = SimpleTextToken[];
|
|
21
|
+
|
|
22
|
+
export type VerificationInput =
|
|
23
|
+
| {
|
|
24
|
+
state: "verified";
|
|
25
|
+
/** Set an expiration with `notion.datetime(...)`; omit it for indefinite verification. */
|
|
26
|
+
datetime?: TextValue;
|
|
27
|
+
}
|
|
28
|
+
| { state: "unverified" };
|
|
29
|
+
|
|
30
|
+
export type VerificationPropertyValue = VerificationInput & {
|
|
31
|
+
type: "verification";
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A page property value accepted by Notion as Code.
|
|
36
|
+
*
|
|
37
|
+
* Use helpers from `@notionhq/apps/notion-as-code` to construct rich values
|
|
38
|
+
* such as text, dates, checkboxes, and URLs.
|
|
39
|
+
*/
|
|
40
|
+
export type PropertyValue =
|
|
41
|
+
| string
|
|
42
|
+
| number
|
|
43
|
+
| TextValue
|
|
44
|
+
| string[]
|
|
45
|
+
| VerificationPropertyValue
|
|
46
|
+
| undefined;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Arguments for declaring a page.
|
|
50
|
+
*
|
|
51
|
+
* For a regular page, set its title through
|
|
52
|
+
* `properties.title: notion.text("My Page Title")`. For a database page, use
|
|
53
|
+
* the title property's schema name instead of `title`.
|
|
54
|
+
*/
|
|
11
55
|
export type PageArgs = {
|
|
12
56
|
resourceId: ResourceId;
|
|
13
57
|
/** Omit to create a private top-level page in the Apps workspace. */
|
|
14
58
|
parent?: Parent;
|
|
15
59
|
// TODO: Port cover types.
|
|
16
60
|
cover?: unknown;
|
|
17
|
-
|
|
18
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Page properties, including the page title.
|
|
63
|
+
*
|
|
64
|
+
* @example Regular page
|
|
65
|
+
* properties: { title: notion.text("My Page Title") }
|
|
66
|
+
*
|
|
67
|
+
* @example Database page
|
|
68
|
+
* properties: { Name: notion.text("Task Name"), Status: "In Progress" }
|
|
69
|
+
*/
|
|
70
|
+
properties?: Record<string, PropertyValue | undefined>;
|
|
71
|
+
/**
|
|
72
|
+
* Page body in Notion-flavored Markdown.
|
|
73
|
+
*
|
|
74
|
+
* Markdown headings create child blocks. They do not set the page title;
|
|
75
|
+
* set a regular page's title with `properties.title`.
|
|
76
|
+
*/
|
|
19
77
|
content?: string;
|
|
20
78
|
fullWidth?: boolean;
|
|
21
79
|
};
|