@phpsandbox/sdk 0.4.0 → 0.5.0

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,241 @@
1
+ import { z } from 'zod';
2
+ import type { Client } from './index.js';
3
+ export declare const customerModeSchema: z.ZodEnum<{
4
+ test: "test";
5
+ live: "live";
6
+ }>;
7
+ export type CustomerMode = z.infer<typeof customerModeSchema>;
8
+ export declare const customerSchema: z.ZodObject<{
9
+ id: z.ZodString;
10
+ externalId: z.ZodString;
11
+ email: z.ZodString;
12
+ name: z.ZodNullable<z.ZodString>;
13
+ source: z.ZodNullable<z.ZodString>;
14
+ marketingSubscribed: z.ZodBoolean;
15
+ suppressionReason: z.ZodNullable<z.ZodString>;
16
+ activatedAt: z.ZodNullable<z.ZodString>;
17
+ createdAt: z.ZodNullable<z.ZodString>;
18
+ }, z.core.$strip>;
19
+ export type CustomerData = z.infer<typeof customerSchema>;
20
+ declare const spaceSchema: z.ZodObject<{
21
+ id: z.ZodString;
22
+ mode: z.ZodEnum<{
23
+ test: "test";
24
+ live: "live";
25
+ }>;
26
+ enabled: z.ZodBoolean;
27
+ senderName: z.ZodNullable<z.ZodString>;
28
+ senderEmail: z.ZodNullable<z.ZodString>;
29
+ replyTo: z.ZodNullable<z.ZodString>;
30
+ senderVerified: z.ZodBoolean;
31
+ domainRecords: z.ZodNullable<z.ZodString>;
32
+ provisionedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
33
+ lastRequestAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
34
+ processedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
35
+ }, z.core.$strip>;
36
+ export type CustomerSpaceData = z.infer<typeof spaceSchema>;
37
+ declare const journeyInputSchema: z.ZodObject<{
38
+ enabled: z.ZodBoolean;
39
+ subject: z.ZodString;
40
+ body: z.ZodString;
41
+ delayMinutes: z.ZodNumber;
42
+ activationEvent: z.ZodString;
43
+ }, z.core.$strip>;
44
+ export type CustomerJourneyInput = z.infer<typeof journeyInputSchema>;
45
+ declare const journeySchema: z.ZodObject<{
46
+ enabled: z.ZodBoolean;
47
+ subject: z.ZodString;
48
+ body: z.ZodString;
49
+ delayMinutes: z.ZodNumber;
50
+ activationEvent: z.ZodString;
51
+ kind: z.ZodEnum<{
52
+ setup: "setup";
53
+ welcome: "welcome";
54
+ purchase: "purchase";
55
+ }>;
56
+ version: z.ZodOptional<z.ZodNumber>;
57
+ startsAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
58
+ draft: z.ZodOptional<z.ZodNullable<z.ZodObject<{
59
+ enabled: z.ZodBoolean;
60
+ subject: z.ZodString;
61
+ body: z.ZodString;
62
+ delayMinutes: z.ZodNumber;
63
+ activationEvent: z.ZodString;
64
+ }, z.core.$strip>>>;
65
+ }, z.core.$strip>;
66
+ export type CustomerJourneyData = z.infer<typeof journeySchema>;
67
+ declare const messageSchema: z.ZodObject<{
68
+ id: z.ZodString;
69
+ customerId: z.ZodNullable<z.ZodString>;
70
+ recipient: z.ZodString;
71
+ subject: z.ZodString;
72
+ body: z.ZodString;
73
+ status: z.ZodString;
74
+ error: z.ZodNullable<z.ZodString>;
75
+ dueAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
76
+ attemptedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
77
+ receivedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
78
+ journeyKind: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
79
+ setup: "setup";
80
+ welcome: "welcome";
81
+ purchase: "purchase";
82
+ }>>>;
83
+ journeyVersion: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
84
+ category: z.ZodOptional<z.ZodEnum<{
85
+ marketing: "marketing";
86
+ service: "service";
87
+ }>>;
88
+ from: z.ZodOptional<z.ZodNullable<z.ZodString>>;
89
+ replyTo: z.ZodOptional<z.ZodNullable<z.ZodString>>;
90
+ renderedText: z.ZodOptional<z.ZodNullable<z.ZodString>>;
91
+ unsubscribeUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
92
+ createdAt: z.ZodNullable<z.ZodString>;
93
+ }, z.core.$strip>;
94
+ export type CustomerMessageData = z.infer<typeof messageSchema>;
95
+ declare const overviewSchema: z.ZodObject<{
96
+ space: z.ZodNullable<z.ZodObject<{
97
+ id: z.ZodString;
98
+ mode: z.ZodEnum<{
99
+ test: "test";
100
+ live: "live";
101
+ }>;
102
+ enabled: z.ZodBoolean;
103
+ senderName: z.ZodNullable<z.ZodString>;
104
+ senderEmail: z.ZodNullable<z.ZodString>;
105
+ replyTo: z.ZodNullable<z.ZodString>;
106
+ senderVerified: z.ZodBoolean;
107
+ domainRecords: z.ZodNullable<z.ZodString>;
108
+ provisionedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
109
+ lastRequestAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
110
+ processedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
111
+ }, z.core.$strip>>;
112
+ customers: z.ZodArray<z.ZodObject<{
113
+ id: z.ZodString;
114
+ externalId: z.ZodString;
115
+ email: z.ZodString;
116
+ name: z.ZodNullable<z.ZodString>;
117
+ source: z.ZodNullable<z.ZodString>;
118
+ marketingSubscribed: z.ZodBoolean;
119
+ suppressionReason: z.ZodNullable<z.ZodString>;
120
+ activatedAt: z.ZodNullable<z.ZodString>;
121
+ createdAt: z.ZodNullable<z.ZodString>;
122
+ }, z.core.$strip>>;
123
+ journeys: z.ZodArray<z.ZodObject<{
124
+ enabled: z.ZodBoolean;
125
+ subject: z.ZodString;
126
+ body: z.ZodString;
127
+ delayMinutes: z.ZodNumber;
128
+ activationEvent: z.ZodString;
129
+ kind: z.ZodEnum<{
130
+ setup: "setup";
131
+ welcome: "welcome";
132
+ purchase: "purchase";
133
+ }>;
134
+ version: z.ZodOptional<z.ZodNumber>;
135
+ startsAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
136
+ draft: z.ZodOptional<z.ZodNullable<z.ZodObject<{
137
+ enabled: z.ZodBoolean;
138
+ subject: z.ZodString;
139
+ body: z.ZodString;
140
+ delayMinutes: z.ZodNumber;
141
+ activationEvent: z.ZodString;
142
+ }, z.core.$strip>>>;
143
+ }, z.core.$strip>>;
144
+ messages: z.ZodArray<z.ZodObject<{
145
+ id: z.ZodString;
146
+ customerId: z.ZodNullable<z.ZodString>;
147
+ recipient: z.ZodString;
148
+ subject: z.ZodString;
149
+ body: z.ZodString;
150
+ status: z.ZodString;
151
+ error: z.ZodNullable<z.ZodString>;
152
+ dueAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
153
+ attemptedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
154
+ receivedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
155
+ journeyKind: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
156
+ setup: "setup";
157
+ welcome: "welcome";
158
+ purchase: "purchase";
159
+ }>>>;
160
+ journeyVersion: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
161
+ category: z.ZodOptional<z.ZodEnum<{
162
+ marketing: "marketing";
163
+ service: "service";
164
+ }>>;
165
+ from: z.ZodOptional<z.ZodNullable<z.ZodString>>;
166
+ replyTo: z.ZodOptional<z.ZodNullable<z.ZodString>>;
167
+ renderedText: z.ZodOptional<z.ZodNullable<z.ZodString>>;
168
+ unsubscribeUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
169
+ createdAt: z.ZodNullable<z.ZodString>;
170
+ }, z.core.$strip>>;
171
+ total: z.ZodNumber;
172
+ messageTotal: z.ZodOptional<z.ZodNumber>;
173
+ events: z.ZodOptional<z.ZodArray<z.ZodString>>;
174
+ }, z.core.$strip>;
175
+ export type CustomersOverview = z.infer<typeof overviewSchema>;
176
+ export interface IdentifyCustomerInput {
177
+ externalId: string;
178
+ email: string;
179
+ name?: string;
180
+ source?: string;
181
+ billingStatus?: 'unknown' | 'free' | 'paid';
182
+ }
183
+ export interface CustomerEventInput {
184
+ eventId: string;
185
+ name: string;
186
+ occurredAt?: string;
187
+ properties?: Record<string, string | number | boolean | null>;
188
+ }
189
+ export interface SendCustomerMessageInput {
190
+ requestId: string;
191
+ subject: string;
192
+ body: string;
193
+ category: 'service' | 'marketing';
194
+ }
195
+ /** Use only from trusted app servers with a dedicated Customers credential. */
196
+ export declare class CustomerRuntime {
197
+ private readonly client;
198
+ constructor(client: Client);
199
+ identify(input: IdentifyCustomerInput): Promise<CustomerData>;
200
+ linkIdentity(customerId: string, externalId: string): Promise<CustomerData>;
201
+ get(customerId: string): Promise<CustomerData>;
202
+ event(customerId: string, input: CustomerEventInput): Promise<{
203
+ id: string;
204
+ name: string;
205
+ }>;
206
+ preferences(customerId: string, input: {
207
+ subscribed: boolean;
208
+ source: string;
209
+ }): Promise<CustomerData>;
210
+ send(customerId: string, input: SendCustomerMessageInput): Promise<CustomerMessageData>;
211
+ }
212
+ export declare class CustomersApi {
213
+ private readonly client;
214
+ readonly runtime: CustomerRuntime;
215
+ constructor(client: Client);
216
+ forNotebook(notebookId: string): NotebookCustomers;
217
+ }
218
+ export declare class NotebookCustomers {
219
+ private readonly notebookId;
220
+ private readonly client;
221
+ constructor(notebookId: string, client: Client);
222
+ list(mode?: CustomerMode, query?: {
223
+ search?: string;
224
+ page?: number;
225
+ messagePage?: number;
226
+ }): Promise<CustomersOverview>;
227
+ connect(mode?: CustomerMode): Promise<CustomerSpaceData>;
228
+ provision(mode?: CustomerMode): Promise<CustomerSpaceData>;
229
+ disable(mode?: CustomerMode): Promise<CustomerSpaceData>;
230
+ resume(mode?: CustomerMode): Promise<CustomerSpaceData>;
231
+ rotate(mode?: CustomerMode): Promise<CustomerSpaceData>;
232
+ sender(input: {
233
+ senderName: string;
234
+ senderEmail: string;
235
+ replyTo: string;
236
+ }, mode?: CustomerMode): Promise<CustomerSpaceData>;
237
+ verifySender(mode?: CustomerMode): Promise<CustomerSpaceData>;
238
+ journey(kind: CustomerJourneyData['kind'], input: CustomerJourneyInput, mode?: CustomerMode): Promise<CustomerJourneyData>;
239
+ private path;
240
+ }
241
+ export {};
@@ -0,0 +1,141 @@
1
+ import { z } from 'zod';
2
+ export const customerModeSchema = z.enum(['test', 'live']);
3
+ export const customerSchema = z.object({
4
+ id: z.string(),
5
+ externalId: z.string(),
6
+ email: z.string(),
7
+ name: z.string().nullable(),
8
+ source: z.string().nullable(),
9
+ marketingSubscribed: z.boolean(),
10
+ suppressionReason: z.string().nullable(),
11
+ activatedAt: z.string().nullable(),
12
+ createdAt: z.string().nullable(),
13
+ });
14
+ const spaceSchema = z.object({
15
+ id: z.string(),
16
+ mode: customerModeSchema,
17
+ enabled: z.boolean(),
18
+ senderName: z.string().nullable(),
19
+ senderEmail: z.string().nullable(),
20
+ replyTo: z.string().nullable(),
21
+ senderVerified: z.boolean(),
22
+ domainRecords: z.string().nullable(),
23
+ provisionedAt: z.string().nullable().optional(),
24
+ lastRequestAt: z.string().nullable().optional(),
25
+ processedAt: z.string().nullable().optional(),
26
+ });
27
+ const journeyInputSchema = z.object({
28
+ enabled: z.boolean(),
29
+ subject: z.string(),
30
+ body: z.string(),
31
+ delayMinutes: z.number(),
32
+ activationEvent: z.string(),
33
+ });
34
+ const journeySchema = journeyInputSchema.extend({
35
+ kind: z.enum(['welcome', 'setup', 'purchase']),
36
+ version: z.number().int().optional(),
37
+ startsAt: z.string().nullable().optional(),
38
+ draft: journeyInputSchema.nullable().optional(),
39
+ });
40
+ const messageSchema = z.object({
41
+ id: z.string(),
42
+ customerId: z.string().nullable(),
43
+ recipient: z.string(),
44
+ subject: z.string(),
45
+ body: z.string(),
46
+ status: z.string(),
47
+ error: z.string().nullable(),
48
+ dueAt: z.string().nullable().optional(),
49
+ attemptedAt: z.string().nullable().optional(),
50
+ receivedAt: z.string().nullable().optional(),
51
+ journeyKind: z.enum(['welcome', 'setup', 'purchase']).nullable().optional(),
52
+ journeyVersion: z.number().int().nullable().optional(),
53
+ category: z.enum(['marketing', 'service']).optional(),
54
+ from: z.string().nullable().optional(),
55
+ replyTo: z.string().nullable().optional(),
56
+ renderedText: z.string().nullable().optional(),
57
+ unsubscribeUrl: z.string().nullable().optional(),
58
+ createdAt: z.string().nullable(),
59
+ });
60
+ const overviewSchema = z.object({
61
+ space: spaceSchema.nullable(),
62
+ customers: z.array(customerSchema),
63
+ journeys: z.array(journeySchema),
64
+ messages: z.array(messageSchema),
65
+ total: z.number(),
66
+ messageTotal: z.number().optional(),
67
+ events: z.array(z.string()).optional(),
68
+ });
69
+ /** Use only from trusted app servers with a dedicated Customers credential. */
70
+ export class CustomerRuntime {
71
+ constructor(client) {
72
+ this.client = client;
73
+ }
74
+ async identify(input) {
75
+ return customerSchema.parse((await this.client.post('/platform/customers/runtime/identify', input)).data);
76
+ }
77
+ async linkIdentity(customerId, externalId) {
78
+ return customerSchema.parse((await this.client.post(`/platform/customers/runtime/${encodeURIComponent(customerId)}/identities`, {
79
+ externalId,
80
+ })).data);
81
+ }
82
+ async get(customerId) {
83
+ return customerSchema.parse((await this.client.get(`/platform/customers/runtime/${encodeURIComponent(customerId)}`)).data);
84
+ }
85
+ async event(customerId, input) {
86
+ return z
87
+ .object({ id: z.string(), name: z.string() })
88
+ .parse((await this.client.post(`/platform/customers/runtime/${encodeURIComponent(customerId)}/events`, input)).data);
89
+ }
90
+ async preferences(customerId, input) {
91
+ return customerSchema.parse((await this.client.put(`/platform/customers/runtime/${encodeURIComponent(customerId)}/preferences`, input)).data);
92
+ }
93
+ async send(customerId, input) {
94
+ return messageSchema.parse((await this.client.post(`/platform/customers/runtime/${encodeURIComponent(customerId)}/messages`, input)).data);
95
+ }
96
+ }
97
+ export class CustomersApi {
98
+ constructor(client) {
99
+ this.client = client;
100
+ this.runtime = new CustomerRuntime(client);
101
+ }
102
+ forNotebook(notebookId) {
103
+ return new NotebookCustomers(notebookId, this.client);
104
+ }
105
+ }
106
+ export class NotebookCustomers {
107
+ constructor(notebookId, client) {
108
+ this.notebookId = notebookId;
109
+ this.client = client;
110
+ }
111
+ async list(mode = 'test', query = {}) {
112
+ return overviewSchema.parse((await this.client.get(`${this.path(mode)}?${new URLSearchParams(Object.entries(query).map(([key, value]) => [key, String(value)])).toString()}`)).data);
113
+ }
114
+ async connect(mode = 'test') {
115
+ return spaceSchema.parse((await this.client.put(this.path(mode), {})).data);
116
+ }
117
+ async provision(mode = 'test') {
118
+ return spaceSchema.parse((await this.client.post(`${this.path(mode)}/provision`, {})).data);
119
+ }
120
+ async disable(mode = 'test') {
121
+ return spaceSchema.parse((await this.client.post(`${this.path(mode)}/disable`, {})).data);
122
+ }
123
+ async resume(mode = 'test') {
124
+ return spaceSchema.parse((await this.client.post(`${this.path(mode)}/resume`, {})).data);
125
+ }
126
+ async rotate(mode = 'test') {
127
+ return spaceSchema.parse((await this.client.post(`${this.path(mode)}/rotate`, {})).data);
128
+ }
129
+ async sender(input, mode = 'test') {
130
+ return spaceSchema.parse((await this.client.put(`${this.path(mode)}/sender`, input)).data);
131
+ }
132
+ async verifySender(mode = 'test') {
133
+ return spaceSchema.parse((await this.client.post(`${this.path(mode)}/sender/verify`, {})).data);
134
+ }
135
+ async journey(kind, input, mode = 'test') {
136
+ return journeySchema.parse((await this.client.put(`${this.path(mode)}/journeys/${kind}`, input)).data);
137
+ }
138
+ path(mode) {
139
+ return `/platform/customers/sandboxes/${encodeURIComponent(this.notebookId)}/${mode}`;
140
+ }
141
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import { AppRuntime, type AppRuntimeOptions } from './app.js';
2
+ export { AppRuntime };
3
+ export type { AppRuntimeOptions };
1
4
  import { type Identity } from './identity.js';
2
5
  export type { Identity } from './identity.js';
3
6
  import { NotebookPublication } from './publication/index.js';
@@ -19,6 +22,8 @@ import { ServerApi } from './servers.js';
19
22
  import { Feedback } from './feedback.js';
20
23
  import { IntegrationApi, SandboxIntegrationApi } from './integrations/index.js';
21
24
  import { PaymentsApi, NotebookPayments } from './payments.js';
25
+ import { CustomersApi } from './customers.js';
26
+ export * from './customers.js';
22
27
  export * from './payments.js';
23
28
  export type { Disposable } from './types.js';
24
29
  export { LspConnection } from './lsp.js';
@@ -174,6 +179,8 @@ export interface NotebookSecretData {
174
179
  name: string;
175
180
  type: SecretType;
176
181
  environment: SecretEnvironment;
182
+ managedBy?: string | null;
183
+ inheritOnFork?: boolean;
177
184
  createdAt: string | null;
178
185
  updatedAt: string | null;
179
186
  }
@@ -181,6 +188,9 @@ export interface NotebookSecretListOptions {
181
188
  environment?: SecretEnvironment;
182
189
  }
183
190
  export interface UpsertNotebookSecretInput {
191
+ /** Platform-owned secrets cannot be inherited by forks. Requires a platform credential. */
192
+ managed?: boolean;
193
+ inheritOnFork?: boolean;
184
194
  value: string;
185
195
  type?: SecretType;
186
196
  environment?: SecretEnvironment;
@@ -332,6 +342,7 @@ declare class ClientImplementation {
332
342
  readonly servers: ServerApi;
333
343
  readonly integrations: IntegrationApi;
334
344
  readonly payments: PaymentsApi;
345
+ readonly customers: CustomersApi;
335
346
  readonly options: PHPSandboxClientOptions;
336
347
  private readonly runtimeTransportValue;
337
348
  get runtimeTransport(): RuntimeTransport;
@@ -368,9 +379,11 @@ export declare class PHPSandbox {
368
379
  readonly servers: ServerApi;
369
380
  readonly integrations: IntegrationApi;
370
381
  readonly payments: PaymentsApi;
382
+ readonly customers: CustomersApi;
371
383
  private constructor();
372
384
  whoami(): Promise<Identity>;
373
385
  get runtimeTransport(): RuntimeTransport;
386
+ static app(options?: AppRuntimeOptions): AppRuntime;
374
387
  static realtime(token: string, url?: string, options?: PHPSandboxClientOptions): PHPSandbox;
375
388
  static rest(token: string, url?: string, options?: PHPSandboxClientOptions): PHPSandbox;
376
389
  }
@@ -467,6 +480,15 @@ declare class NotebookMail {
467
480
  private readonly notebookId;
468
481
  constructor(client: Client, notebookId: string);
469
482
  status(): Promise<NotebookMailStateData>;
483
+ /** Capture a platform-generated development email in the notebook inbox. Never sends externally. */
484
+ capture(input: {
485
+ requestId: string;
486
+ from: string;
487
+ fromName: string;
488
+ to: string;
489
+ subject: string;
490
+ text: string;
491
+ }): Promise<NotebookMailData>;
470
492
  enable(): Promise<NotebookMailStateData>;
471
493
  disable(): Promise<void>;
472
494
  list(options?: NotebookMailListOptions): Promise<PaginatedApiResponse<NotebookMailData>>;
package/dist/index.js CHANGED
@@ -10,6 +10,8 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
10
10
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
11
  };
12
12
  var _NotebookInstance_instances, _NotebookInstance_initPromise, _NotebookInstance_init;
13
+ import { AppRuntime, resolveAppConfiguration } from './app.js';
14
+ export { AppRuntime };
13
15
  import { identitySchema } from './identity.js';
14
16
  import { NotebookPublication } from './publication/index.js';
15
17
  import { Filesystem } from './filesystem.js';
@@ -32,6 +34,8 @@ import { Feedback } from './feedback.js';
32
34
  import { IntegrationApi, SandboxIntegrationApi } from './integrations/index.js';
33
35
  import { authenticatedRequest } from './http.js';
34
36
  import { PaymentsApi, NotebookPayments } from './payments.js';
37
+ import { CustomersApi } from './customers.js';
38
+ export * from './customers.js';
35
39
  export * from './payments.js';
36
40
  export { LspConnection } from './lsp.js';
37
41
  export { FileChangeFilter, FileChangeType, FileType } from './filesystem.js';
@@ -89,6 +93,7 @@ class ClientImplementation {
89
93
  this.servers = new ServerApi(this);
90
94
  this.integrations = new IntegrationApi(this);
91
95
  this.payments = new PaymentsApi(this);
96
+ this.customers = new CustomersApi(this);
92
97
  this.options = { ...options };
93
98
  this.runtimeTransportValue = runtimeTransport;
94
99
  this.baseUrl = normalizeApiBaseUrl(url);
@@ -224,6 +229,7 @@ export class PHPSandbox {
224
229
  this.servers = client.servers;
225
230
  this.integrations = client.integrations;
226
231
  this.payments = client.payments;
232
+ this.customers = client.customers;
227
233
  }
228
234
  async whoami() {
229
235
  const { data } = await this.client.get('/auth/whoami');
@@ -236,6 +242,10 @@ export class PHPSandbox {
236
242
  get runtimeTransport() {
237
243
  return this.client.runtimeTransport;
238
244
  }
245
+ static app(options = {}) {
246
+ const { token, url, mode } = resolveAppConfiguration(options);
247
+ return new AppRuntime(new ClientImplementation(token, url, {}, 'rest'), token, mode);
248
+ }
239
249
  static realtime(token, url = 'https://api.phpsandbox.io/v1', options = {}) {
240
250
  return new PHPSandbox(new ClientImplementation(token, url, options));
241
251
  }
@@ -598,6 +608,11 @@ class NotebookMail {
598
608
  const response = await this.client.get(`/notebook/${this.notebookId}/mail`);
599
609
  return response.data;
600
610
  }
611
+ /** Capture a platform-generated development email in the notebook inbox. Never sends externally. */
612
+ async capture(input) {
613
+ const response = await this.client.post(`/notebook/${this.notebookId}/mails`, input);
614
+ return response.data;
615
+ }
601
616
  async enable() {
602
617
  const response = await this.client.put(`/notebook/${this.notebookId}/mail`);
603
618
  return response.data;
@@ -43,6 +43,10 @@ declare const applicationsSchema: z.ZodObject<{
43
43
  }, z.core.$strip>;
44
44
  export type PaymentApplicationsData = z.infer<typeof applicationsSchema>;
45
45
  declare const bindingSchema: z.ZodObject<{
46
+ target: z.ZodOptional<z.ZodEnum<{
47
+ preview: "preview";
48
+ publication: "publication";
49
+ }>>;
46
50
  id: z.ZodString;
47
51
  notebookId: z.ZodString;
48
52
  applicationId: z.ZodNullable<z.ZodString>;
@@ -164,6 +168,10 @@ declare const activationSchema: z.ZodObject<{
164
168
  expiresAt: z.ZodString;
165
169
  blockers: z.ZodArray<z.ZodString>;
166
170
  binding: z.ZodObject<{
171
+ target: z.ZodOptional<z.ZodEnum<{
172
+ preview: "preview";
173
+ publication: "publication";
174
+ }>>;
167
175
  id: z.ZodString;
168
176
  notebookId: z.ZodString;
169
177
  applicationId: z.ZodNullable<z.ZodString>;
@@ -205,6 +213,7 @@ declare const activationSchema: z.ZodObject<{
205
213
  }, z.core.$strip>;
206
214
  export type PaymentActivationReview = z.infer<typeof activationSchema>;
207
215
  export interface ConfigurePaymentsInput {
216
+ target?: 'preview' | 'publication';
208
217
  expectedRevision: number;
209
218
  applicationId?: string | null;
210
219
  callbackPath?: string;
@@ -217,6 +226,7 @@ export interface CreatePaymentPriceInput {
217
226
  currency: string;
218
227
  }
219
228
  export interface CreatePaymentCheckoutInput {
229
+ customerId?: string;
220
230
  requestId: string;
221
231
  orderId: string;
222
232
  priceId: string;
@@ -333,7 +343,13 @@ export type PaymentEvent = z.infer<typeof paymentEventSchema>;
333
343
  export declare function verifyPaymentEvent(body: string, signature: string, token: string, mode: PaymentMode, now?: number): Promise<PaymentEvent>;
334
344
  export declare class PaymentRuntime {
335
345
  private readonly client;
336
- constructor(client: Client);
346
+ private readonly appCredential?;
347
+ constructor(client: Client, appCredential?: {
348
+ token: string;
349
+ mode: PaymentMode;
350
+ } | undefined);
351
+ /** Verify the phpsandbox-signature header against the configured app environment. */
352
+ verifyEvent(body: string, signature: string): Promise<PaymentEvent>;
337
353
  checkout(input: CreatePaymentCheckoutInput): Promise<PaymentTransactionData>;
338
354
  transaction(id: string): Promise<PaymentTransactionData>;
339
355
  subscribe(input: CreatePaymentCheckoutInput): Promise<PaymentSubscriptionData>;
package/dist/payments.js CHANGED
@@ -32,6 +32,7 @@ const applicationsSchema = z.object({
32
32
  })),
33
33
  });
34
34
  const bindingSchema = z.object({
35
+ target: z.enum(['preview', 'publication']).optional(),
35
36
  id: z.string(),
36
37
  notebookId: z.string(),
37
38
  applicationId: z.string().nullable(),
@@ -207,7 +208,7 @@ const paymentEventSchema = z.discriminatedUnion('type', [
207
208
  ]);
208
209
  /** Verify the original bytes before parsing JSON. Use only in trusted server code. */
209
210
  export async function verifyPaymentEvent(body, signature, token, mode, now = Date.now()) {
210
- if (!/^hpay_[a-f0-9]{64}$/.test(token)) {
211
+ if (!/^(?:hpay|happ)_[a-f0-9]{64}$/.test(token)) {
211
212
  throw new Error('Invalid application payment credential.');
212
213
  }
213
214
  const match = /^t=(\d+),v1=([a-f0-9]{64})$/.exec(signature);
@@ -229,8 +230,16 @@ export async function verifyPaymentEvent(body, signature, token, mode, now = Dat
229
230
  return event;
230
231
  }
231
232
  export class PaymentRuntime {
232
- constructor(client) {
233
+ constructor(client, appCredential) {
233
234
  this.client = client;
235
+ this.appCredential = appCredential;
236
+ }
237
+ /** Verify the phpsandbox-signature header against the configured app environment. */
238
+ async verifyEvent(body, signature) {
239
+ if (!this.appCredential) {
240
+ throw new Error('Initialize the server app client with PHPSandbox.app() to verify payment events.');
241
+ }
242
+ return verifyPaymentEvent(body, signature, this.appCredential.token, this.appCredential.mode);
234
243
  }
235
244
  async checkout(input) {
236
245
  return transactionSchema.parse((await this.client.post('/platform/payments/runtime/checkouts', input)).data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phpsandbox/sdk",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "The TypeScript SDK for PHPSandbox cloud development environments",
5
5
  "keywords": [
6
6
  "cloud",