@netlify/ai 0.2.1

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.
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/bootstrap/main.ts
21
+ var main_exports = {};
22
+ __export(main_exports, {
23
+ fetchAIGatewayToken: () => fetchAIGatewayToken,
24
+ fetchAIProviders: () => fetchAIProviders,
25
+ parseAIGatewayContext: () => parseAIGatewayContext,
26
+ setupAIGateway: () => setupAIGateway
27
+ });
28
+ module.exports = __toCommonJS(main_exports);
29
+ var isValidTokenResponse = (data) => {
30
+ return typeof data === "object" && data !== null && typeof data.token === "string" && typeof data.url === "string";
31
+ };
32
+ var isValidProvidersResponse = (data) => {
33
+ return typeof data === "object" && data !== null && typeof data.providers === "object" && data.providers !== null;
34
+ };
35
+ var fetchAIProviders = async ({ api }) => {
36
+ try {
37
+ if (!api.accessToken) {
38
+ return [];
39
+ }
40
+ const url = `${api.scheme}://${api.host}/api/v1/ai-gateway/providers`;
41
+ const response = await fetch(url, {
42
+ method: "GET",
43
+ headers: {
44
+ Authorization: `Bearer ${api.accessToken}`,
45
+ "Content-Type": "application/json"
46
+ }
47
+ });
48
+ if (!response.ok) {
49
+ if (response.status === 404) {
50
+ return [];
51
+ }
52
+ throw new Error(`HTTP ${String(response.status)}: ${response.statusText}`);
53
+ }
54
+ const data = await response.json();
55
+ if (!isValidProvidersResponse(data)) {
56
+ throw new Error("Invalid providers response format");
57
+ }
58
+ const envVars = [];
59
+ for (const provider of Object.values(data.providers)) {
60
+ envVars.push({
61
+ key: provider.token_env_var,
62
+ url: provider.url_env_var
63
+ });
64
+ }
65
+ return envVars;
66
+ } catch (error) {
67
+ console.warn(`Failed to fetch AI providers: ${error instanceof Error ? error.message : String(error)}`);
68
+ return [];
69
+ }
70
+ };
71
+ var fetchAIGatewayToken = async ({
72
+ api,
73
+ siteId
74
+ }) => {
75
+ try {
76
+ if (!api.accessToken) {
77
+ return null;
78
+ }
79
+ const url = `${api.scheme}://${api.host}/api/v1/sites/${siteId}/ai-gateway/token`;
80
+ const response = await fetch(url, {
81
+ method: "GET",
82
+ headers: {
83
+ Authorization: `Bearer ${api.accessToken}`,
84
+ "Content-Type": "application/json"
85
+ }
86
+ });
87
+ if (!response.ok) {
88
+ if (response.status === 404) {
89
+ return null;
90
+ }
91
+ throw new Error(`HTTP ${String(response.status)}: ${response.statusText}`);
92
+ }
93
+ const data = await response.json();
94
+ if (!isValidTokenResponse(data)) {
95
+ throw new Error("Invalid response: missing token or url");
96
+ }
97
+ return {
98
+ token: data.token,
99
+ url: data.url
100
+ };
101
+ } catch (error) {
102
+ console.warn(
103
+ `Failed to fetch AI Gateway token for site ${siteId}: ${error instanceof Error ? error.message : String(error)}`
104
+ );
105
+ return null;
106
+ }
107
+ };
108
+ var setupAIGateway = async (config) => {
109
+ const { api, env, siteID, siteURL } = config;
110
+ if (siteID && siteID !== "unlinked" && siteURL) {
111
+ const [aiGatewayToken, envVars] = await Promise.all([
112
+ fetchAIGatewayToken({ api, siteId: siteID }),
113
+ fetchAIProviders({ api })
114
+ ]);
115
+ if (aiGatewayToken) {
116
+ const aiGatewayContext = JSON.stringify({
117
+ token: aiGatewayToken.token,
118
+ url: `${siteURL}/.netlify/ai`,
119
+ envVars
120
+ });
121
+ const base64Context = Buffer.from(aiGatewayContext).toString("base64");
122
+ env.AI_GATEWAY = { sources: ["internal"], value: base64Context };
123
+ }
124
+ }
125
+ };
126
+ var parseAIGatewayContext = (aiGatewayValue) => {
127
+ try {
128
+ if (aiGatewayValue) {
129
+ const decodedContext = Buffer.from(aiGatewayValue, "base64").toString("utf8");
130
+ const aiGatewayContext = JSON.parse(decodedContext);
131
+ return aiGatewayContext;
132
+ }
133
+ } catch {
134
+ }
135
+ return void 0;
136
+ };
137
+ // Annotate the CommonJS export names for ESM import in node:
138
+ 0 && (module.exports = {
139
+ fetchAIGatewayToken,
140
+ fetchAIProviders,
141
+ parseAIGatewayContext,
142
+ setupAIGateway
143
+ });
144
+ //# sourceMappingURL=main.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/bootstrap/main.ts"],"sourcesContent":["import type { NetlifyAPI } from '@netlify/api'\n\nexport interface AIGatewayContext {\n token: string\n url: string\n}\n\nexport interface AIGatewayConfig {\n api: NetlifyAPI\n env: Record<string, { sources: string[]; value: string }>\n siteID: string | undefined\n siteURL: string | undefined\n}\n\nexport interface AIProviderEnvVar {\n key: string\n url: string\n}\n\nexport interface AIGatewayTokenResponse {\n token: string\n url: string\n envVars?: AIProviderEnvVar[]\n}\n\nexport interface AIProvider {\n token_env_var: string\n url_env_var: string\n models: string[]\n}\n\nexport interface ProvidersResponse {\n providers: Record<string, AIProvider>\n}\n\nconst isValidTokenResponse = (data: unknown): data is AIGatewayTokenResponse => {\n return (\n typeof data === 'object' &&\n data !== null &&\n typeof (data as Record<string, unknown>).token === 'string' &&\n typeof (data as Record<string, unknown>).url === 'string'\n )\n}\n\nconst isValidProvidersResponse = (data: unknown): data is ProvidersResponse => {\n return (\n typeof data === 'object' &&\n data !== null &&\n typeof (data as Record<string, unknown>).providers === 'object' &&\n (data as Record<string, unknown>).providers !== null\n )\n}\n\nexport const fetchAIProviders = async ({ api }: { api: NetlifyAPI }): Promise<AIProviderEnvVar[]> => {\n try {\n if (!api.accessToken) {\n return []\n }\n\n const url = `${api.scheme}://${api.host}/api/v1/ai-gateway/providers`\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${api.accessToken}`,\n 'Content-Type': 'application/json',\n },\n })\n\n if (!response.ok) {\n if (response.status === 404) {\n return []\n }\n throw new Error(`HTTP ${String(response.status)}: ${response.statusText}`)\n }\n\n const data: unknown = await response.json()\n\n if (!isValidProvidersResponse(data)) {\n throw new Error('Invalid providers response format')\n }\n\n const envVars: AIProviderEnvVar[] = []\n\n for (const provider of Object.values(data.providers)) {\n envVars.push({\n key: provider.token_env_var,\n url: provider.url_env_var,\n })\n }\n\n return envVars\n } catch (error) {\n console.warn(`Failed to fetch AI providers: ${error instanceof Error ? error.message : String(error)}`)\n return []\n }\n}\n\nexport const fetchAIGatewayToken = async ({\n api,\n siteId,\n}: {\n api: NetlifyAPI\n siteId: string\n}): Promise<AIGatewayTokenResponse | null> => {\n try {\n if (!api.accessToken) {\n return null\n }\n\n // TODO: update once available in openApi\n const url = `${api.scheme}://${api.host}/api/v1/sites/${siteId}/ai-gateway/token`\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${api.accessToken}`,\n 'Content-Type': 'application/json',\n },\n })\n\n if (!response.ok) {\n if (response.status === 404) {\n return null\n }\n throw new Error(`HTTP ${String(response.status)}: ${response.statusText}`)\n }\n\n const data: unknown = await response.json()\n\n if (!isValidTokenResponse(data)) {\n throw new Error('Invalid response: missing token or url')\n }\n\n return {\n token: data.token,\n url: data.url,\n }\n } catch (error) {\n console.warn(\n `Failed to fetch AI Gateway token for site ${siteId}: ${error instanceof Error ? error.message : String(error)}`,\n )\n return null\n }\n}\n\nexport const setupAIGateway = async (config: AIGatewayConfig): Promise<void> => {\n const { api, env, siteID, siteURL } = config\n\n if (siteID && siteID !== 'unlinked' && siteURL) {\n const [aiGatewayToken, envVars] = await Promise.all([\n fetchAIGatewayToken({ api, siteId: siteID }),\n fetchAIProviders({ api }),\n ])\n\n if (aiGatewayToken) {\n const aiGatewayContext = JSON.stringify({\n token: aiGatewayToken.token,\n url: `${siteURL}/.netlify/ai`,\n envVars,\n })\n const base64Context = Buffer.from(aiGatewayContext).toString('base64')\n env.AI_GATEWAY = { sources: ['internal'], value: base64Context }\n }\n }\n}\n\nexport const parseAIGatewayContext = (aiGatewayValue?: string): AIGatewayTokenResponse | undefined => {\n try {\n if (aiGatewayValue) {\n const decodedContext = Buffer.from(aiGatewayValue, 'base64').toString('utf8')\n const aiGatewayContext = JSON.parse(decodedContext) as AIGatewayTokenResponse\n return aiGatewayContext\n }\n } catch {\n // Ignore parsing errors - AI Gateway is optional\n }\n return undefined\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,43 @@
1
+ import { NetlifyAPI } from '@netlify/api';
2
+
3
+ interface AIGatewayContext {
4
+ token: string;
5
+ url: string;
6
+ }
7
+ interface AIGatewayConfig {
8
+ api: NetlifyAPI;
9
+ env: Record<string, {
10
+ sources: string[];
11
+ value: string;
12
+ }>;
13
+ siteID: string | undefined;
14
+ siteURL: string | undefined;
15
+ }
16
+ interface AIProviderEnvVar {
17
+ key: string;
18
+ url: string;
19
+ }
20
+ interface AIGatewayTokenResponse {
21
+ token: string;
22
+ url: string;
23
+ envVars?: AIProviderEnvVar[];
24
+ }
25
+ interface AIProvider {
26
+ token_env_var: string;
27
+ url_env_var: string;
28
+ models: string[];
29
+ }
30
+ interface ProvidersResponse {
31
+ providers: Record<string, AIProvider>;
32
+ }
33
+ declare const fetchAIProviders: ({ api }: {
34
+ api: NetlifyAPI;
35
+ }) => Promise<AIProviderEnvVar[]>;
36
+ declare const fetchAIGatewayToken: ({ api, siteId, }: {
37
+ api: NetlifyAPI;
38
+ siteId: string;
39
+ }) => Promise<AIGatewayTokenResponse | null>;
40
+ declare const setupAIGateway: (config: AIGatewayConfig) => Promise<void>;
41
+ declare const parseAIGatewayContext: (aiGatewayValue?: string) => AIGatewayTokenResponse | undefined;
42
+
43
+ export { type AIGatewayConfig, type AIGatewayContext, type AIGatewayTokenResponse, type AIProvider, type AIProviderEnvVar, type ProvidersResponse, fetchAIGatewayToken, fetchAIProviders, parseAIGatewayContext, setupAIGateway };
@@ -0,0 +1,43 @@
1
+ import { NetlifyAPI } from '@netlify/api';
2
+
3
+ interface AIGatewayContext {
4
+ token: string;
5
+ url: string;
6
+ }
7
+ interface AIGatewayConfig {
8
+ api: NetlifyAPI;
9
+ env: Record<string, {
10
+ sources: string[];
11
+ value: string;
12
+ }>;
13
+ siteID: string | undefined;
14
+ siteURL: string | undefined;
15
+ }
16
+ interface AIProviderEnvVar {
17
+ key: string;
18
+ url: string;
19
+ }
20
+ interface AIGatewayTokenResponse {
21
+ token: string;
22
+ url: string;
23
+ envVars?: AIProviderEnvVar[];
24
+ }
25
+ interface AIProvider {
26
+ token_env_var: string;
27
+ url_env_var: string;
28
+ models: string[];
29
+ }
30
+ interface ProvidersResponse {
31
+ providers: Record<string, AIProvider>;
32
+ }
33
+ declare const fetchAIProviders: ({ api }: {
34
+ api: NetlifyAPI;
35
+ }) => Promise<AIProviderEnvVar[]>;
36
+ declare const fetchAIGatewayToken: ({ api, siteId, }: {
37
+ api: NetlifyAPI;
38
+ siteId: string;
39
+ }) => Promise<AIGatewayTokenResponse | null>;
40
+ declare const setupAIGateway: (config: AIGatewayConfig) => Promise<void>;
41
+ declare const parseAIGatewayContext: (aiGatewayValue?: string) => AIGatewayTokenResponse | undefined;
42
+
43
+ export { type AIGatewayConfig, type AIGatewayContext, type AIGatewayTokenResponse, type AIProvider, type AIProviderEnvVar, type ProvidersResponse, fetchAIGatewayToken, fetchAIProviders, parseAIGatewayContext, setupAIGateway };
@@ -0,0 +1,116 @@
1
+ // src/bootstrap/main.ts
2
+ var isValidTokenResponse = (data) => {
3
+ return typeof data === "object" && data !== null && typeof data.token === "string" && typeof data.url === "string";
4
+ };
5
+ var isValidProvidersResponse = (data) => {
6
+ return typeof data === "object" && data !== null && typeof data.providers === "object" && data.providers !== null;
7
+ };
8
+ var fetchAIProviders = async ({ api }) => {
9
+ try {
10
+ if (!api.accessToken) {
11
+ return [];
12
+ }
13
+ const url = `${api.scheme}://${api.host}/api/v1/ai-gateway/providers`;
14
+ const response = await fetch(url, {
15
+ method: "GET",
16
+ headers: {
17
+ Authorization: `Bearer ${api.accessToken}`,
18
+ "Content-Type": "application/json"
19
+ }
20
+ });
21
+ if (!response.ok) {
22
+ if (response.status === 404) {
23
+ return [];
24
+ }
25
+ throw new Error(`HTTP ${String(response.status)}: ${response.statusText}`);
26
+ }
27
+ const data = await response.json();
28
+ if (!isValidProvidersResponse(data)) {
29
+ throw new Error("Invalid providers response format");
30
+ }
31
+ const envVars = [];
32
+ for (const provider of Object.values(data.providers)) {
33
+ envVars.push({
34
+ key: provider.token_env_var,
35
+ url: provider.url_env_var
36
+ });
37
+ }
38
+ return envVars;
39
+ } catch (error) {
40
+ console.warn(`Failed to fetch AI providers: ${error instanceof Error ? error.message : String(error)}`);
41
+ return [];
42
+ }
43
+ };
44
+ var fetchAIGatewayToken = async ({
45
+ api,
46
+ siteId
47
+ }) => {
48
+ try {
49
+ if (!api.accessToken) {
50
+ return null;
51
+ }
52
+ const url = `${api.scheme}://${api.host}/api/v1/sites/${siteId}/ai-gateway/token`;
53
+ const response = await fetch(url, {
54
+ method: "GET",
55
+ headers: {
56
+ Authorization: `Bearer ${api.accessToken}`,
57
+ "Content-Type": "application/json"
58
+ }
59
+ });
60
+ if (!response.ok) {
61
+ if (response.status === 404) {
62
+ return null;
63
+ }
64
+ throw new Error(`HTTP ${String(response.status)}: ${response.statusText}`);
65
+ }
66
+ const data = await response.json();
67
+ if (!isValidTokenResponse(data)) {
68
+ throw new Error("Invalid response: missing token or url");
69
+ }
70
+ return {
71
+ token: data.token,
72
+ url: data.url
73
+ };
74
+ } catch (error) {
75
+ console.warn(
76
+ `Failed to fetch AI Gateway token for site ${siteId}: ${error instanceof Error ? error.message : String(error)}`
77
+ );
78
+ return null;
79
+ }
80
+ };
81
+ var setupAIGateway = async (config) => {
82
+ const { api, env, siteID, siteURL } = config;
83
+ if (siteID && siteID !== "unlinked" && siteURL) {
84
+ const [aiGatewayToken, envVars] = await Promise.all([
85
+ fetchAIGatewayToken({ api, siteId: siteID }),
86
+ fetchAIProviders({ api })
87
+ ]);
88
+ if (aiGatewayToken) {
89
+ const aiGatewayContext = JSON.stringify({
90
+ token: aiGatewayToken.token,
91
+ url: `${siteURL}/.netlify/ai`,
92
+ envVars
93
+ });
94
+ const base64Context = Buffer.from(aiGatewayContext).toString("base64");
95
+ env.AI_GATEWAY = { sources: ["internal"], value: base64Context };
96
+ }
97
+ }
98
+ };
99
+ var parseAIGatewayContext = (aiGatewayValue) => {
100
+ try {
101
+ if (aiGatewayValue) {
102
+ const decodedContext = Buffer.from(aiGatewayValue, "base64").toString("utf8");
103
+ const aiGatewayContext = JSON.parse(decodedContext);
104
+ return aiGatewayContext;
105
+ }
106
+ } catch {
107
+ }
108
+ return void 0;
109
+ };
110
+ export {
111
+ fetchAIGatewayToken,
112
+ fetchAIProviders,
113
+ parseAIGatewayContext,
114
+ setupAIGateway
115
+ };
116
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/bootstrap/main.ts"],"sourcesContent":["import type { NetlifyAPI } from '@netlify/api'\n\nexport interface AIGatewayContext {\n token: string\n url: string\n}\n\nexport interface AIGatewayConfig {\n api: NetlifyAPI\n env: Record<string, { sources: string[]; value: string }>\n siteID: string | undefined\n siteURL: string | undefined\n}\n\nexport interface AIProviderEnvVar {\n key: string\n url: string\n}\n\nexport interface AIGatewayTokenResponse {\n token: string\n url: string\n envVars?: AIProviderEnvVar[]\n}\n\nexport interface AIProvider {\n token_env_var: string\n url_env_var: string\n models: string[]\n}\n\nexport interface ProvidersResponse {\n providers: Record<string, AIProvider>\n}\n\nconst isValidTokenResponse = (data: unknown): data is AIGatewayTokenResponse => {\n return (\n typeof data === 'object' &&\n data !== null &&\n typeof (data as Record<string, unknown>).token === 'string' &&\n typeof (data as Record<string, unknown>).url === 'string'\n )\n}\n\nconst isValidProvidersResponse = (data: unknown): data is ProvidersResponse => {\n return (\n typeof data === 'object' &&\n data !== null &&\n typeof (data as Record<string, unknown>).providers === 'object' &&\n (data as Record<string, unknown>).providers !== null\n )\n}\n\nexport const fetchAIProviders = async ({ api }: { api: NetlifyAPI }): Promise<AIProviderEnvVar[]> => {\n try {\n if (!api.accessToken) {\n return []\n }\n\n const url = `${api.scheme}://${api.host}/api/v1/ai-gateway/providers`\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${api.accessToken}`,\n 'Content-Type': 'application/json',\n },\n })\n\n if (!response.ok) {\n if (response.status === 404) {\n return []\n }\n throw new Error(`HTTP ${String(response.status)}: ${response.statusText}`)\n }\n\n const data: unknown = await response.json()\n\n if (!isValidProvidersResponse(data)) {\n throw new Error('Invalid providers response format')\n }\n\n const envVars: AIProviderEnvVar[] = []\n\n for (const provider of Object.values(data.providers)) {\n envVars.push({\n key: provider.token_env_var,\n url: provider.url_env_var,\n })\n }\n\n return envVars\n } catch (error) {\n console.warn(`Failed to fetch AI providers: ${error instanceof Error ? error.message : String(error)}`)\n return []\n }\n}\n\nexport const fetchAIGatewayToken = async ({\n api,\n siteId,\n}: {\n api: NetlifyAPI\n siteId: string\n}): Promise<AIGatewayTokenResponse | null> => {\n try {\n if (!api.accessToken) {\n return null\n }\n\n // TODO: update once available in openApi\n const url = `${api.scheme}://${api.host}/api/v1/sites/${siteId}/ai-gateway/token`\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${api.accessToken}`,\n 'Content-Type': 'application/json',\n },\n })\n\n if (!response.ok) {\n if (response.status === 404) {\n return null\n }\n throw new Error(`HTTP ${String(response.status)}: ${response.statusText}`)\n }\n\n const data: unknown = await response.json()\n\n if (!isValidTokenResponse(data)) {\n throw new Error('Invalid response: missing token or url')\n }\n\n return {\n token: data.token,\n url: data.url,\n }\n } catch (error) {\n console.warn(\n `Failed to fetch AI Gateway token for site ${siteId}: ${error instanceof Error ? error.message : String(error)}`,\n )\n return null\n }\n}\n\nexport const setupAIGateway = async (config: AIGatewayConfig): Promise<void> => {\n const { api, env, siteID, siteURL } = config\n\n if (siteID && siteID !== 'unlinked' && siteURL) {\n const [aiGatewayToken, envVars] = await Promise.all([\n fetchAIGatewayToken({ api, siteId: siteID }),\n fetchAIProviders({ api }),\n ])\n\n if (aiGatewayToken) {\n const aiGatewayContext = JSON.stringify({\n token: aiGatewayToken.token,\n url: `${siteURL}/.netlify/ai`,\n envVars,\n })\n const base64Context = Buffer.from(aiGatewayContext).toString('base64')\n env.AI_GATEWAY = { sources: ['internal'], value: base64Context }\n }\n }\n}\n\nexport const parseAIGatewayContext = (aiGatewayValue?: string): AIGatewayTokenResponse | undefined => {\n try {\n if (aiGatewayValue) {\n const decodedContext = Buffer.from(aiGatewayValue, 'base64').toString('utf8')\n const aiGatewayContext = JSON.parse(decodedContext) as AIGatewayTokenResponse\n return aiGatewayContext\n }\n } catch {\n // Ignore parsing errors - AI Gateway is optional\n }\n return undefined\n}\n"],"mappings":"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","names":[]}
package/dist/main.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=main.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/main.js ADDED
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@netlify/ai",
3
+ "version": "0.2.1",
4
+ "description": "TypeScript utilities for interacting with Netlify AI features",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=20.6.1"
8
+ },
9
+ "main": "./dist/main.cjs",
10
+ "module": "./dist/main.js",
11
+ "types": "./dist/main.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "require": {
15
+ "types": "./dist/main.d.cts",
16
+ "default": "./dist/main.cjs"
17
+ },
18
+ "import": {
19
+ "types": "./dist/main.d.ts",
20
+ "default": "./dist/main.js"
21
+ },
22
+ "default": {
23
+ "types": "./dist/main.d.ts",
24
+ "default": "./dist/main.js"
25
+ }
26
+ },
27
+ "./package.json": "./package.json",
28
+ "./bootstrap": {
29
+ "require": {
30
+ "types": "./dist/bootstrap/main.d.cts",
31
+ "default": "./dist/bootstrap/main.cjs"
32
+ },
33
+ "import": {
34
+ "types": "./dist/bootstrap/main.d.ts",
35
+ "default": "./dist/bootstrap/main.js"
36
+ },
37
+ "default": {
38
+ "types": "./dist/bootstrap/main.d.ts",
39
+ "default": "./dist/bootstrap/main.js"
40
+ }
41
+ }
42
+ },
43
+ "files": [
44
+ "dist/**/*"
45
+ ],
46
+ "scripts": {
47
+ "build": "tsup-node",
48
+ "dev": "tsup-node --watch",
49
+ "prepack": "npm run build",
50
+ "test": "run-s build test:ci",
51
+ "test:dev": "run-s build test:dev:*",
52
+ "test:ci": "run-s build test:ci:*",
53
+ "test:dev:vitest": "vitest",
54
+ "test:dev:vitest:watch": "vitest watch",
55
+ "test:ci:vitest": "vitest run",
56
+ "publint": "npx -y publint --strict"
57
+ },
58
+ "dependencies": {
59
+ "@netlify/api": "^14.0.4"
60
+ },
61
+ "devDependencies": {
62
+ "@types/node": "20.14.15",
63
+ "npm-run-all2": "^7.0.2",
64
+ "tsup": "8.5.0",
65
+ "typescript": "5.9.2",
66
+ "vitest": "^3.0.0"
67
+ },
68
+ "peerDependencies": {
69
+ "@netlify/api": ">=14.0.0"
70
+ },
71
+ "repository": {
72
+ "type": "git",
73
+ "url": "https://github.com/netlify/primitives.git",
74
+ "directory": "packages/ai"
75
+ },
76
+ "homepage": "https://github.com/netlify/primitives/tree/main/packages/ai",
77
+ "bugs": {
78
+ "url": "https://github.com/netlify/primitives/issues"
79
+ }
80
+ }