@notionhq/apps 0.0.10 → 0.0.11

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.
Files changed (67) hide show
  1. package/dist/cli/build.d.ts +2 -2
  2. package/dist/cli/build.d.ts.map +1 -1
  3. package/dist/cli/build.js +44 -2
  4. package/dist/cli/codegen.d.ts +5 -0
  5. package/dist/cli/codegen.d.ts.map +1 -1
  6. package/dist/cli/codegen.js +15 -1
  7. package/dist/cli/emit-manifest.d.ts +3 -0
  8. package/dist/cli/emit-manifest.d.ts.map +1 -1
  9. package/dist/cli/emit-manifest.js +12 -1
  10. package/dist/notion-as-code/custom-agent.d.ts +18 -0
  11. package/dist/notion-as-code/custom-agent.d.ts.map +1 -0
  12. package/dist/notion-as-code/custom-agent.js +13 -0
  13. package/dist/notion-as-code/database.d.ts +44 -0
  14. package/dist/notion-as-code/database.d.ts.map +1 -0
  15. package/dist/notion-as-code/database.js +68 -0
  16. package/dist/notion-as-code/date.d.ts +9 -0
  17. package/dist/notion-as-code/date.d.ts.map +1 -0
  18. package/dist/notion-as-code/date.js +69 -0
  19. package/dist/notion-as-code/handles.d.ts +32 -0
  20. package/dist/notion-as-code/handles.d.ts.map +1 -0
  21. package/dist/notion-as-code/handles.js +34 -0
  22. package/dist/notion-as-code/index.d.ts +30 -0
  23. package/dist/notion-as-code/index.d.ts.map +1 -0
  24. package/dist/notion-as-code/index.js +8 -0
  25. package/dist/notion-as-code/intents.d.ts +115 -0
  26. package/dist/notion-as-code/intents.d.ts.map +1 -0
  27. package/dist/notion-as-code/intents.js +6 -0
  28. package/dist/notion-as-code/page.d.ts +22 -0
  29. package/dist/notion-as-code/page.d.ts.map +1 -0
  30. package/dist/notion-as-code/page.js +31 -0
  31. package/dist/notion-as-code/provisioning.d.ts +22 -0
  32. package/dist/notion-as-code/provisioning.d.ts.map +1 -0
  33. package/dist/notion-as-code/provisioning.js +25 -0
  34. package/dist/notion-as-code/recorder.d.ts +10 -0
  35. package/dist/notion-as-code/recorder.d.ts.map +1 -0
  36. package/dist/notion-as-code/recorder.js +21 -0
  37. package/dist/notion-as-code/resource.d.ts +6 -0
  38. package/dist/notion-as-code/resource.d.ts.map +1 -0
  39. package/dist/notion-as-code/resource.js +19 -0
  40. package/dist/notion-as-code/schema.d.ts +63 -0
  41. package/dist/notion-as-code/schema.d.ts.map +1 -0
  42. package/dist/notion-as-code/schema.js +94 -0
  43. package/dist/notion-as-code/teamspace.d.ts +18 -0
  44. package/dist/notion-as-code/teamspace.d.ts.map +1 -0
  45. package/dist/notion-as-code/teamspace.js +30 -0
  46. package/dist/sync.d.ts +15 -2
  47. package/dist/sync.d.ts.map +1 -1
  48. package/dist/sync.js +14 -3
  49. package/package.json +9 -1
  50. package/src/cli/build.test.ts +91 -1
  51. package/src/cli/build.ts +61 -6
  52. package/src/cli/codegen.ts +21 -0
  53. package/src/cli/discover.test.ts +6 -0
  54. package/src/cli/emit-manifest.ts +18 -0
  55. package/src/notion-as-code/custom-agent.ts +30 -0
  56. package/src/notion-as-code/database.ts +143 -0
  57. package/src/notion-as-code/date.ts +91 -0
  58. package/src/notion-as-code/handles.ts +36 -0
  59. package/src/notion-as-code/index.ts +16 -0
  60. package/src/notion-as-code/intents.ts +127 -0
  61. package/src/notion-as-code/page.ts +61 -0
  62. package/src/notion-as-code/provisioning.ts +50 -0
  63. package/src/notion-as-code/recorder.ts +26 -0
  64. package/src/notion-as-code/resource.ts +19 -0
  65. package/src/notion-as-code/schema.ts +149 -0
  66. package/src/notion-as-code/teamspace.ts +50 -0
  67. package/src/sync.ts +63 -5
@@ -6,8 +6,8 @@ export type BuildResult = {
6
6
  };
7
7
  /**
8
8
  * Build an app project: discover capability files by convention, generate
9
- * the entry module, bundle it into a single `dist/worker.js`, and emit
10
- * `dist/manifest.json` describing every capability.
9
+ * the Worker and build-only metadata entries, bundle the Worker, and emit
10
+ * the Worker manifest plus any recorded Notion-as-Code provisioning artifact.
11
11
  */
12
12
  export declare function buildApp(projectRoot: string): Promise<BuildResult>;
13
13
  //# sourceMappingURL=build.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAKlD,MAAM,MAAM,WAAW,GAAG;IACzB,QAAQ,EAAE,WAAW,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAmCxE"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAUlD,MAAM,MAAM,WAAW,GAAG;IACzB,QAAQ,EAAE,WAAW,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAoCxE"}
package/dist/cli/build.js CHANGED
@@ -1,9 +1,13 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import { rolldown } from "rolldown";
4
- import { generateEntry } from "./codegen.js";
4
+ import {
5
+ createProvisioningArtifact
6
+ } from "../notion-as-code/provisioning.js";
7
+ import { clearRegisteredPacers } from "../pacer.js";
8
+ import { generateEntry, generateMetadataEntry } from "./codegen.js";
5
9
  import { discoverCapabilities } from "./discover.js";
6
- import { extractManifest } from "./emit-manifest.js";
10
+ import { extractManifest, extractProvisioning } from "./emit-manifest.js";
7
11
  async function buildApp(projectRoot) {
8
12
  const capabilities = await discoverCapabilities(projectRoot);
9
13
  if (capabilities.length === 0) {
@@ -29,8 +33,46 @@ async function buildApp(projectRoot) {
29
33
  const manifestPath = path.join(projectRoot, "dist", "manifest.json");
30
34
  await fs.promises.writeFile(manifestPath, `${JSON.stringify(manifest, null, " ")}
31
35
  `);
36
+ await emitProvisioningArtifact(projectRoot, capabilities);
32
37
  return { manifest, bundlePath, manifestPath };
33
38
  }
39
+ async function emitProvisioningArtifact(projectRoot, capabilities) {
40
+ const entityProvisioning = await buildMetadata(projectRoot, capabilities);
41
+ if (entityProvisioning.intents.length === 0) return;
42
+ const artifact = createProvisioningArtifact(entityProvisioning.intents);
43
+ await fs.promises.writeFile(
44
+ path.join(projectRoot, "dist", "provisioning.json"),
45
+ `${JSON.stringify(artifact, null, " ")}
46
+ `
47
+ );
48
+ }
49
+ async function buildMetadata(projectRoot, capabilities) {
50
+ const metadataEntryPath = path.join(projectRoot, ".notion", "metadata-entry.ts");
51
+ const metadataBundlePath = path.join(projectRoot, ".notion", "metadata.js");
52
+ await fs.promises.writeFile(metadataEntryPath, generateMetadataEntry(capabilities));
53
+ clearRegisteredPacers();
54
+ try {
55
+ const metadataBundle = await rolldown({
56
+ input: metadataEntryPath,
57
+ platform: "node",
58
+ // Keep SDK packages external so the metadata bundle resolves the app's installed SDK.
59
+ external: (id) => !id.startsWith(".") && !path.isAbsolute(id)
60
+ });
61
+ try {
62
+ await metadataBundle.write({
63
+ format: "esm",
64
+ file: metadataBundlePath,
65
+ codeSplitting: false
66
+ });
67
+ } finally {
68
+ await metadataBundle.close();
69
+ }
70
+ return await extractProvisioning(metadataBundlePath);
71
+ } finally {
72
+ clearRegisteredPacers();
73
+ await fs.promises.rm(metadataBundlePath, { force: true });
74
+ }
75
+ }
34
76
  export {
35
77
  buildApp
36
78
  };
@@ -7,4 +7,9 @@ import type { DiscoveredCapability } from "./discover.js";
7
7
  * the app project, so imports are relative to that location.
8
8
  */
9
9
  export declare function generateEntry(capabilities: readonly DiscoveredCapability[]): string;
10
+ /**
11
+ * Generate the build-only metadata entry. Dynamic imports run after the
12
+ * recorder starts and remain isolated from the deployed Worker entry.
13
+ */
14
+ export declare function generateMetadataEntry(capabilities: readonly DiscoveredCapability[]): string;
10
15
  //# sourceMappingURL=codegen.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/cli/codegen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE1D;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,SAAS,oBAAoB,EAAE,GAAG,MAAM,CAyCnF"}
1
+ {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/cli/codegen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE1D;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,SAAS,oBAAoB,EAAE,GAAG,MAAM,CAyCnF;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,SAAS,oBAAoB,EAAE,GAAG,MAAM,CAe3F"}
@@ -36,6 +36,20 @@ export async function run(
36
36
  }
37
37
  `;
38
38
  }
39
+ function generateMetadataEntry(capabilities) {
40
+ const imports = capabilities.map((capability) => `await import(${JSON.stringify(`../${capability.sourcePath}`)});`).join("\n");
41
+ return `// Generated by \`notion-apps build\`. Do not edit.
42
+ import {
43
+ finishMetadataRecording,
44
+ startMetadataRecording,
45
+ } from "@notionhq/apps/notion-as-code/recorder";
46
+
47
+ const recorder = startMetadataRecording();
48
+ ${imports}
49
+ export default finishMetadataRecording(recorder);
50
+ `;
51
+ }
39
52
  export {
40
- generateEntry
53
+ generateEntry,
54
+ generateMetadataEntry
41
55
  };
@@ -1,7 +1,10 @@
1
+ import { type RecordedProvisioning } from "../notion-as-code/provisioning.js";
1
2
  import type { AppManifest } from "../manifest.js";
2
3
  import type { DiscoveredCapability } from "./discover.js";
3
4
  /** Extract the app manifest from a built bundle. */
4
5
  export declare function extractManifest(bundlePath: string, capabilities: readonly DiscoveredCapability[]): Promise<AppManifest>;
6
+ /** Import the metadata bundle and return the provisioning declarations it recorded. */
7
+ export declare function extractProvisioning(bundlePath: string): Promise<RecordedProvisioning>;
5
8
  /**
6
9
  * Throw if `value` contains anything `JSON.stringify` would silently drop or
7
10
  * rewrite, so invalid manifest configuration fails during the build.
@@ -1 +1 @@
1
- {"version":3,"file":"emit-manifest.d.ts","sourceRoot":"","sources":["../../src/cli/emit-manifest.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAA6C,MAAM,gBAAgB,CAAC;AAE7F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AA0M1D,oDAAoD;AACpD,wBAAsB,eAAe,CACpC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,SAAS,oBAAoB,EAAE,GAC3C,OAAO,CAAC,WAAW,CAAC,CA6EtB;AAkCD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAoCjE"}
1
+ {"version":3,"file":"emit-manifest.d.ts","sourceRoot":"","sources":["../../src/cli/emit-manifest.ts"],"names":[],"mappings":"AAMA,OAAO,EAEN,KAAK,oBAAoB,EACzB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAA6C,MAAM,gBAAgB,CAAC;AAE7F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AA0M1D,oDAAoD;AACpD,wBAAsB,eAAe,CACpC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,SAAS,oBAAoB,EAAE,GAC3C,OAAO,CAAC,WAAW,CAAC,CA6EtB;AAED,uFAAuF;AACvF,wBAAsB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAW3F;AAkCD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAoCjE"}
@@ -2,6 +2,9 @@ import { createRequire } from "node:module";
2
2
  import { pathToFileURL } from "node:url";
3
3
  import { Ajv } from "ajv";
4
4
  import { APPS_MANIFEST_SCHEMA } from "../manifest.js";
5
+ import {
6
+ isRecordedProvisioning
7
+ } from "../notion-as-code/provisioning.js";
5
8
  import { clearRegisteredPacers, registeredPacers } from "../pacer.js";
6
9
  const SDK_VERSION = (() => {
7
10
  const require2 = createRequire(import.meta.url);
@@ -221,6 +224,13 @@ async function extractManifest(bundlePath, capabilities) {
221
224
  }
222
225
  return manifest;
223
226
  }
227
+ async function extractProvisioning(bundlePath) {
228
+ const bundle = await importBundle(bundlePath);
229
+ if (typeof bundle !== "object" || bundle === null || !("default" in bundle) || !isRecordedProvisioning(bundle.default)) {
230
+ throw new Error("Metadata bundle did not export a Notion-as-Code provisioning record");
231
+ }
232
+ return bundle.default;
233
+ }
224
234
  let importNonce = 0;
225
235
  async function importBundle(bundlePath) {
226
236
  try {
@@ -277,5 +287,6 @@ function assertJsonSafe(value, path) {
277
287
  }
278
288
  export {
279
289
  assertJsonSafe,
280
- extractManifest
290
+ extractManifest,
291
+ extractProvisioning
281
292
  };
@@ -0,0 +1,18 @@
1
+ import type { NotionAsCodeIcon, ResourceId } from "./intents.js";
2
+ export type CustomAgentArgs = {
3
+ resourceId: ResourceId;
4
+ name: string;
5
+ icon?: Exclude<NotionAsCodeIcon, {
6
+ type: "file";
7
+ }>;
8
+ instructions?: string;
9
+ model?: "ambrosia-tart-high" | "opal-quince-medium" | "almond-croissant-low";
10
+ sharedResources?: readonly ResourceId[];
11
+ triggers?: readonly unknown[];
12
+ };
13
+ export type CustomAgentHandle = {
14
+ readonly resourceId: string;
15
+ };
16
+ /** Declare a custom agent and validate every shared resource reference. */
17
+ export declare function customAgent(args: CustomAgentArgs): CustomAgentHandle;
18
+ //# sourceMappingURL=custom-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-agent.d.ts","sourceRoot":"","sources":["../../src/notion-as-code/custom-agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqB,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAIpF,MAAM,MAAM,eAAe,GAAG;IAC7B,UAAU,EAAE,UAAU,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC,gBAAgB,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,oBAAoB,GAAG,oBAAoB,GAAG,sBAAsB,CAAC;IAC7E,eAAe,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAExC,QAAQ,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,2EAA2E;AAC3E,wBAAgB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,iBAAiB,CASpE"}
@@ -0,0 +1,13 @@
1
+ import { recordIntent } from "./recorder.js";
2
+ import { assertUserResourceId } from "./resource.js";
3
+ function customAgent(args) {
4
+ assertUserResourceId(args.resourceId);
5
+ for (const resourceId of args.sharedResources ?? []) {
6
+ assertUserResourceId(resourceId);
7
+ }
8
+ recordIntent({ type: "custom_agent", ...args });
9
+ return { resourceId: args.resourceId };
10
+ }
11
+ export {
12
+ customAgent
13
+ };
@@ -0,0 +1,44 @@
1
+ import type { Database } from "../database.js";
2
+ import type { DataSourceDefinition, NotionAsCodeIcon, NotionAsCodeProperty, Parent, ResourceId } from "./intents.js";
3
+ import { type ChildPageArgs, type PageHandle } from "./page.js";
4
+ import { type AppsSchemaForProperties } from "./schema.js";
5
+ /** Input for declaring a database and its optional data sources. */
6
+ export type DatabaseArgs<DataSources extends readonly DataSourceDefinition[] = readonly DataSourceDefinition[]> = {
7
+ resourceId: ResourceId;
8
+ parent: Parent;
9
+ dataSources?: DataSources;
10
+ views?: readonly unknown[];
11
+ icon?: NotionAsCodeIcon;
12
+ cover?: unknown;
13
+ hideDataSourceTitle?: boolean;
14
+ hideDatabaseTitleIfEmpty?: boolean;
15
+ name?: string;
16
+ description?: string;
17
+ };
18
+ /** Input for adding a database beneath an existing resource. */
19
+ export type ChildDatabaseArgs<DataSources extends readonly DataSourceDefinition[] = readonly DataSourceDefinition[]> = Omit<DatabaseArgs<DataSources>, "parent">;
20
+ /** Resolves one data source ID to the properties declared for it. */
21
+ type DataSourcePropertiesForResourceId<DataSources extends readonly DataSourceDefinition[], ResourceId extends DataSources[number]["resourceId"]> = Extract<DataSources[number], {
22
+ resourceId: ResourceId;
23
+ }> extends DataSourceDefinition<infer Properties> ? Properties : never;
24
+ /** Handle for a data source and the Apps database it backs. */
25
+ export type DataSourceHandle<Properties extends readonly NotionAsCodeProperty[] = readonly NotionAsCodeProperty[]> = {
26
+ readonly resourceId: string;
27
+ readonly schema: Properties;
28
+ readonly database: Database<AppsSchemaForProperties<Properties>>;
29
+ addPage: (args: ChildPageArgs) => PageHandle;
30
+ };
31
+ /** Handle for a database with data sources indexed by resource ID. */
32
+ export type DatabaseHandle<DataSources extends readonly DataSourceDefinition[] = readonly DataSourceDefinition[]> = {
33
+ readonly resourceId: string;
34
+ readonly dataSources: {
35
+ readonly [ResourceId in DataSources[number]["resourceId"]]: DataSourceHandle<DataSourcePropertiesForResourceId<DataSources, ResourceId>>;
36
+ };
37
+ addView: (view: unknown) => void;
38
+ };
39
+ /** Declare a top-level database and its data sources. */
40
+ export declare function database<const DataSources extends readonly DataSourceDefinition[]>(args: DatabaseArgs<DataSources>): DatabaseHandle<DataSources>;
41
+ /** Record a database declaration and create handles for each of its data sources. */
42
+ export declare function createDatabase(args: DatabaseArgs, parent: Parent): DatabaseHandle;
43
+ export {};
44
+ //# sourceMappingURL=database.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/notion-as-code/database.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EACX,oBAAoB,EAEpB,gBAAgB,EAChB,oBAAoB,EACpB,MAAM,EACN,UAAU,EACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAc,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAG5E,OAAO,EAAsB,KAAK,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE/E,oEAAoE;AACpE,MAAM,MAAM,YAAY,CACvB,WAAW,SAAS,SAAS,oBAAoB,EAAE,GAAG,SAAS,oBAAoB,EAAE,IAClF;IACH,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B,KAAK,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,gBAAgB,CAAC;IAExB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,gEAAgE;AAChE,MAAM,MAAM,iBAAiB,CAC5B,WAAW,SAAS,SAAS,oBAAoB,EAAE,GAAG,SAAS,oBAAoB,EAAE,IAClF,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,CAAC;AAE9C,qEAAqE;AACrE,KAAK,iCAAiC,CACrC,WAAW,SAAS,SAAS,oBAAoB,EAAE,EACnD,UAAU,SAAS,WAAW,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,IAEpD,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE;IAAE,UAAU,EAAE,UAAU,CAAA;CAAE,CAAC,SAAS,oBAAoB,CACpF,MAAM,UAAU,CAChB,GACE,UAAU,GACV,KAAK,CAAC;AAEV,+DAA+D;AAC/D,MAAM,MAAM,gBAAgB,CAC3B,UAAU,SAAS,SAAS,oBAAoB,EAAE,GAAG,SAAS,oBAAoB,EAAE,IACjF;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC,CAAC;IACjE,OAAO,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,UAAU,CAAC;CAC7C,CAAC;AAEF,sEAAsE;AACtE,MAAM,MAAM,cAAc,CACzB,WAAW,SAAS,SAAS,oBAAoB,EAAE,GAAG,SAAS,oBAAoB,EAAE,IAClF;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE;QACrB,QAAQ,EAAE,UAAU,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,GAAG,gBAAgB,CAC3E,iCAAiC,CAAC,WAAW,EAAE,UAAU,CAAC,CAC1D;KACD,CAAC;IACF,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACjC,CAAC;AAEF,yDAAyD;AACzD,wBAAgB,QAAQ,CAAC,KAAK,CAAC,WAAW,SAAS,SAAS,oBAAoB,EAAE,EACjF,IAAI,EAAE,YAAY,CAAC,WAAW,CAAC,GAC7B,cAAc,CAAC,WAAW,CAAC,CAAC;AAM/B,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,CA+BjF"}
@@ -0,0 +1,68 @@
1
+ import { createPage } from "./page.js";
2
+ import { recordIntent } from "./recorder.js";
3
+ import { assertParent, assertUserResourceId } from "./resource.js";
4
+ import { createAppsDatabase } from "./schema.js";
5
+ function database(args) {
6
+ assertParent(args.parent);
7
+ return createDatabase(args, args.parent);
8
+ }
9
+ function createDatabase(args, parent) {
10
+ assertUserResourceId(args.resourceId);
11
+ const dataSources = args.dataSources ?? [];
12
+ const dataSourceIds = /* @__PURE__ */ new Set();
13
+ const handles = {};
14
+ for (const dataSource of dataSources) {
15
+ assertUserResourceId(dataSource.resourceId);
16
+ if (dataSourceIds.has(dataSource.resourceId)) {
17
+ throw new Error(
18
+ `Database "${args.resourceId}" has duplicate data source "${dataSource.resourceId}"`
19
+ );
20
+ }
21
+ dataSourceIds.add(dataSource.resourceId);
22
+ handles[dataSource.resourceId] = createDataSourceHandle(dataSource);
23
+ }
24
+ recordIntent({
25
+ type: "database",
26
+ ...args,
27
+ parent,
28
+ dataSources: [...dataSources]
29
+ });
30
+ return {
31
+ resourceId: args.resourceId,
32
+ dataSources: handles,
33
+ addView(view) {
34
+ recordIntent({ type: "view", databaseResourceId: args.resourceId, view });
35
+ }
36
+ };
37
+ }
38
+ function createDataSourceHandle(dataSource) {
39
+ const propertyResourceIds = /* @__PURE__ */ new Set();
40
+ const propertyNames = /* @__PURE__ */ new Set();
41
+ for (const property of dataSource.properties) {
42
+ assertUserResourceId(property.resourceId);
43
+ if (propertyResourceIds.has(property.resourceId)) {
44
+ throw new Error(
45
+ `Data source "${dataSource.resourceId}" has duplicate property resourceId "${property.resourceId}"`
46
+ );
47
+ }
48
+ if (propertyNames.has(property.name)) {
49
+ throw new Error(
50
+ `Data source "${dataSource.resourceId}" has duplicate property name "${property.name}"`
51
+ );
52
+ }
53
+ propertyResourceIds.add(property.resourceId);
54
+ propertyNames.add(property.name);
55
+ }
56
+ return {
57
+ resourceId: dataSource.resourceId,
58
+ schema: dataSource.properties,
59
+ database: createAppsDatabase(dataSource.resourceId, dataSource),
60
+ addPage(pageArgs) {
61
+ return createPage(pageArgs, { type: "resourceId", resourceId: dataSource.resourceId });
62
+ }
63
+ };
64
+ }
65
+ export {
66
+ createDatabase,
67
+ database
68
+ };
@@ -0,0 +1,9 @@
1
+ /** Serialize Notion-as-Code date values for Apps property payloads. */
2
+ export declare function date(startDate: string, endDate?: string): unknown[][];
3
+ /** Serialize Notion-as-Code datetime values for Apps property payloads. */
4
+ export declare function datetime(value: {
5
+ start: string;
6
+ end?: string;
7
+ timeZone?: string;
8
+ }): unknown[][];
9
+ //# sourceMappingURL=date.d.ts.map
@@ -0,0 +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,OAAO,EAAE,EAAE,CAWrE;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,OAAO,EAAE,EAAE,CA6B/F"}
@@ -0,0 +1,69 @@
1
+ function date(startDate, endDate) {
2
+ const start_date = parseIsoDate(startDate);
3
+ const end_date = endDate === void 0 ? void 0 : parseIsoDate(endDate);
4
+ if (end_date !== void 0 && end_date < start_date) {
5
+ throw new Error("Date range end must be on or after start.");
6
+ }
7
+ const value = end_date === void 0 ? { type: "date", start_date } : { type: "daterange", start_date, end_date };
8
+ return [["\u2023", [["d", value]]]];
9
+ }
10
+ function datetime(value) {
11
+ const timeZone = value.timeZone ?? "UTC";
12
+ try {
13
+ new Intl.DateTimeFormat("en-US", { timeZone }).format();
14
+ } catch {
15
+ throw new Error("Invalid time zone: " + timeZone);
16
+ }
17
+ const start = parseIsoDatetime(value.start);
18
+ const end = value.end === void 0 ? void 0 : parseIsoDatetime(value.end);
19
+ if (end !== void 0 && end.date + "T" + end.time < start.date + "T" + start.time) {
20
+ throw new Error("Datetime range end must be on or after start.");
21
+ }
22
+ const dateValue = end === void 0 ? {
23
+ type: "datetime",
24
+ start_date: start.date,
25
+ start_time: start.time,
26
+ time_zone: timeZone
27
+ } : {
28
+ type: "datetimerange",
29
+ start_date: start.date,
30
+ start_time: start.time,
31
+ end_date: end.date,
32
+ end_time: end.time,
33
+ time_zone: timeZone
34
+ };
35
+ return [["\u2023", [["d", dateValue]]]];
36
+ }
37
+ function parseIsoDate(value) {
38
+ const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
39
+ if (match === null) {
40
+ throw new Error("Invalid ISO 8601 date: " + value + ". Expected format like 2024-01-15");
41
+ }
42
+ if (!isValidCalendarDate(match) || Number.isNaN(new Date(value).getTime())) {
43
+ throw new Error("Invalid date: " + value);
44
+ }
45
+ return value;
46
+ }
47
+ function parseIsoDatetime(value) {
48
+ const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/.exec(value);
49
+ if (match === null) {
50
+ throw new Error(
51
+ "Invalid ISO 8601 datetime: " + value + ". Expected format like 2024-01-15T10:30 or 2024-01-15T10:30:00Z"
52
+ );
53
+ }
54
+ if (!isValidCalendarDate(match) || Number(match[4]) > 23 || Number(match[5]) > 59 || Number.isNaN(new Date(value).getTime())) {
55
+ throw new Error("Invalid datetime: " + value);
56
+ }
57
+ return { date: value.slice(0, 10), time: value.slice(11, 16) };
58
+ }
59
+ function isValidCalendarDate(match) {
60
+ const year = Number(match[1] ?? "");
61
+ const month = Number(match[2] ?? "");
62
+ const day = Number(match[3] ?? "");
63
+ const date2 = new Date(Date.UTC(year, month - 1, day));
64
+ return date2.getUTCFullYear() === year && date2.getUTCMonth() === month - 1 && date2.getUTCDate() === day;
65
+ }
66
+ export {
67
+ date,
68
+ datetime
69
+ };
@@ -0,0 +1,32 @@
1
+ import { customAgent } from "./custom-agent.js";
2
+ import { database } from "./database.js";
3
+ import { date, datetime } from "./date.js";
4
+ import { page } from "./page.js";
5
+ import { teamspace } from "./teamspace.js";
6
+ declare const notionAsCodeFacade: {
7
+ teamspace: typeof teamspace;
8
+ database: typeof database;
9
+ page: typeof page;
10
+ customAgent: typeof customAgent;
11
+ text: (value: string) => string[][];
12
+ number: (value: number) => string[][];
13
+ date: typeof date;
14
+ datetime: typeof datetime;
15
+ select: (value: string) => string;
16
+ status: (value: string) => string;
17
+ multiSelect: (values: readonly string[]) => string;
18
+ checkbox: (value: boolean) => string[][];
19
+ url: (value: string) => (string | string[][])[][];
20
+ email: (value: string) => (string | string[][])[][];
21
+ phone: (value: string) => string[][];
22
+ relation: (value: string | readonly string[]) => string | any[] | readonly string[];
23
+ file: (resourceId: string) => {
24
+ type: "file";
25
+ resourceId: string;
26
+ };
27
+ };
28
+ export type NotionAsCodeFacade = typeof notionAsCodeFacade;
29
+ /** Create the runtime facade used to declare Notion-as-Code project metadata. */
30
+ export declare function createNotion(): NotionAsCodeFacade;
31
+ export {};
32
+ //# sourceMappingURL=handles.d.ts.map
@@ -0,0 +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,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,QAAA,MAAM,kBAAkB;;;;;kBAKT,MAAM;oBACJ,MAAM;;;oBAGN,MAAM;oBACN,MAAM;0BACA,SAAS,MAAM,EAAE;sBACrB,OAAO;iBACZ,MAAM;mBACJ,MAAM;mBACN,MAAM;sBACH,MAAM,GAAG,SAAS,MAAM,EAAE;uBACzB,MAAM;;;;CAIzB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,OAAO,kBAAkB,CAAC;AAE3D,iFAAiF;AACjF,wBAAgB,YAAY,IAAI,kBAAkB,CAEjD"}
@@ -0,0 +1,34 @@
1
+ import { customAgent } from "./custom-agent.js";
2
+ import { database } from "./database.js";
3
+ import { date, datetime } from "./date.js";
4
+ import { page } from "./page.js";
5
+ import { assertUserResourceId } from "./resource.js";
6
+ import { teamspace } from "./teamspace.js";
7
+ const notionAsCodeFacade = {
8
+ teamspace,
9
+ database,
10
+ page,
11
+ customAgent,
12
+ text: (value) => [[value]],
13
+ number: (value) => [[String(value)]],
14
+ date,
15
+ datetime,
16
+ select: (value) => value,
17
+ status: (value) => value,
18
+ multiSelect: (values) => values.join(","),
19
+ checkbox: (value) => [[value ? "Yes" : "No"]],
20
+ url: (value) => [[value, [["a", value]]]],
21
+ email: (value) => [[value, [["a", `mailto:${value}`]]]],
22
+ phone: (value) => [[value]],
23
+ relation: (value) => Array.isArray(value) ? [...value] : value,
24
+ file: (resourceId) => {
25
+ assertUserResourceId(resourceId);
26
+ return { type: "file", resourceId };
27
+ }
28
+ };
29
+ function createNotion() {
30
+ return notionAsCodeFacade;
31
+ }
32
+ export {
33
+ createNotion
34
+ };
@@ -0,0 +1,30 @@
1
+ export { APPS_RESERVED_RESOURCE_ID_PREFIX, APPS_WORKSPACE_RESOURCE_ID } from "./intents.js";
2
+ export type { DataSourceDefinition, NotionAsCodeProperty, Parent } from "./intents.js";
3
+ export type { CustomAgentArgs, CustomAgentHandle } from "./custom-agent.js";
4
+ export type { ChildDatabaseArgs, DataSourceHandle, DatabaseArgs, DatabaseHandle, } from "./database.js";
5
+ export type { ChildPageArgs, PageArgs, PageHandle } from "./page.js";
6
+ export type { TeamspaceArgs, TeamspaceHandle } from "./teamspace.js";
7
+ /** Experimental Notion-as-Code facade for Apps SDK project metadata. */
8
+ export declare const notion: {
9
+ teamspace: typeof import("./teamspace.js").teamspace;
10
+ database: typeof import("./database.js").database;
11
+ page: typeof import("./page.js").page;
12
+ customAgent: typeof import("./custom-agent.js").customAgent;
13
+ text: (value: string) => string[][];
14
+ number: (value: number) => string[][];
15
+ date: typeof import("./date.js").date;
16
+ datetime: typeof import("./date.js").datetime;
17
+ select: (value: string) => string;
18
+ status: (value: string) => string;
19
+ multiSelect: (values: readonly string[]) => string;
20
+ checkbox: (value: boolean) => string[][];
21
+ url: (value: string) => (string | string[][])[][];
22
+ email: (value: string) => (string | string[][])[][];
23
+ phone: (value: string) => string[][];
24
+ relation: (value: string | readonly string[]) => string | any[] | readonly string[];
25
+ file: (resourceId: string) => {
26
+ type: "file";
27
+ resourceId: string;
28
+ };
29
+ };
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACvF,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,YAAY,EACX,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,cAAc,GACd,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACrE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAErE,wEAAwE;AACxE,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;CAAiB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { createNotion } from "./handles.js";
2
+ import { APPS_RESERVED_RESOURCE_ID_PREFIX, APPS_WORKSPACE_RESOURCE_ID } from "./intents.js";
3
+ const notion = createNotion();
4
+ export {
5
+ APPS_RESERVED_RESOURCE_ID_PREFIX,
6
+ APPS_WORKSPACE_RESOURCE_ID,
7
+ notion
8
+ };
@@ -0,0 +1,115 @@
1
+ import type { CustomAgentArgs } from "./custom-agent.js";
2
+ import type { DatabaseArgs } from "./database.js";
3
+ import type { PageArgs } from "./page.js";
4
+ import type { TeamspaceArgs } from "./teamspace.js";
5
+ /** Apps-specific resource IDs used while declaring Notion-as-Code metadata. */
6
+ /** Synthetic workspace parent for teamspaces declared by an Apps project. */
7
+ export declare const APPS_WORKSPACE_RESOURCE_ID = "__notion_apps_workspace__";
8
+ /** Reserved prefix for resource IDs owned by the Apps runtime. */
9
+ export declare const APPS_RESERVED_RESOURCE_ID_PREFIX = "__notion_apps_";
10
+ export type ResourceId = string;
11
+ export type Parent = {
12
+ type: "resourceId";
13
+ resourceId: ResourceId;
14
+ };
15
+ export type NotionAsCodeIcon = {
16
+ type: "emoji";
17
+ emoji: string;
18
+ } | {
19
+ type: "notion_icon";
20
+ description: string;
21
+ color?: string;
22
+ } | {
23
+ type: "file";
24
+ resourceId: ResourceId;
25
+ };
26
+ export type NotionAsCodeSelectColor = "default" | "gray" | "brown" | "orange" | "yellow" | "green" | "blue" | "purple" | "pink" | "red";
27
+ export type NotionAsCodeSelectOption = {
28
+ name: string;
29
+ color?: NotionAsCodeSelectColor;
30
+ };
31
+ export type NotionAsCodeStatusOption = NotionAsCodeSelectOption & {
32
+ default?: boolean;
33
+ };
34
+ type PropertyBase = {
35
+ resourceId: ResourceId;
36
+ name: string;
37
+ icon?: Extract<NotionAsCodeIcon, {
38
+ type: "notion_icon";
39
+ }>;
40
+ description?: string;
41
+ };
42
+ type UnsupportedProperty = PropertyBase & {
43
+ type: "relation" | "formula" | "rollup" | "created_time" | "last_edited_time" | "created_by" | "last_edited_by" | "auto_increment_id" | "person" | "verification";
44
+ [key: string]: unknown;
45
+ };
46
+ export type NotionAsCodeProperty = (PropertyBase & {
47
+ type: "title";
48
+ }) | (PropertyBase & {
49
+ type: "text";
50
+ }) | (PropertyBase & {
51
+ type: "number";
52
+ }) | (PropertyBase & {
53
+ type: "select";
54
+ options?: readonly NotionAsCodeSelectOption[];
55
+ }) | (PropertyBase & {
56
+ type: "multi_select";
57
+ options?: readonly NotionAsCodeSelectOption[];
58
+ }) | {
59
+ resourceId: ResourceId;
60
+ name: string;
61
+ type: "status";
62
+ icon?: Extract<NotionAsCodeIcon, {
63
+ type: "notion_icon";
64
+ }>;
65
+ description?: string;
66
+ options: {
67
+ todo: readonly NotionAsCodeStatusOption[];
68
+ inProgress: readonly NotionAsCodeStatusOption[];
69
+ complete: readonly NotionAsCodeStatusOption[];
70
+ };
71
+ } | (PropertyBase & {
72
+ type: "date";
73
+ }) | (PropertyBase & {
74
+ type: "checkbox";
75
+ }) | (PropertyBase & {
76
+ type: "url";
77
+ }) | (PropertyBase & {
78
+ type: "email";
79
+ }) | (PropertyBase & {
80
+ type: "phone_number";
81
+ }) | (PropertyBase & {
82
+ type: "file";
83
+ }) | UnsupportedProperty;
84
+ export type DataSourceDefinition<Properties extends readonly NotionAsCodeProperty[] = readonly NotionAsCodeProperty[]> = {
85
+ resourceId: ResourceId;
86
+ name: string;
87
+ properties: Properties;
88
+ icon?: NotionAsCodeIcon;
89
+ pageLayout?: unknown;
90
+ };
91
+ export type TeamspaceIntent = TeamspaceArgs & {
92
+ parent: Parent;
93
+ };
94
+ export type DatabaseIntent = DatabaseArgs & {
95
+ dataSources: readonly DataSourceDefinition[];
96
+ };
97
+ export type PageIntent = PageArgs;
98
+ export type CustomAgentIntent = CustomAgentArgs;
99
+ export type ViewIntent = {
100
+ databaseResourceId: ResourceId;
101
+ view: unknown;
102
+ };
103
+ export type InfraAsCodeIntent = ({
104
+ type: "teamspace";
105
+ } & TeamspaceIntent) | ({
106
+ type: "database";
107
+ } & DatabaseIntent) | ({
108
+ type: "page";
109
+ } & PageIntent) | ({
110
+ type: "custom_agent";
111
+ } & CustomAgentIntent) | ({
112
+ type: "view";
113
+ } & ViewIntent);
114
+ export {};
115
+ //# sourceMappingURL=intents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intents.d.ts","sourceRoot":"","sources":["../../src/notion-as-code/intents.ts"],"names":[],"mappings":"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"}