@trypattern/sdk 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/app.js CHANGED
@@ -13,6 +13,7 @@ import { homedir } from 'node:os';
13
13
  import { delimiter, dirname, extname, join, relative, resolve } from 'node:path';
14
14
  import { pathToFileURL } from 'node:url';
15
15
  import { createHash } from 'node:crypto';
16
+ import { z } from 'zod';
16
17
  import { resetLocalDatabase } from "../vite/localWorker.js";
17
18
  import { login, publish, pull, restore, versions as listVersions } from "./publishing.js";
18
19
  import { toolBin } from "./tools.js";
@@ -73,7 +74,13 @@ const CONTACT_SHEET = join(SCREENSHOTS_DIR, 'contact-sheet.png');
73
74
  const SCREENSHOT_WORKER = join(SDK_SOURCE, 'cli', `screenshot${SDK_EXTENSION}`);
74
75
  const VISUAL_URL_ENV = 'PATTERN_VISUAL_URL';
75
76
  const GLOBAL_FLAGS = ['--json', '--help', '-h'];
76
- const VALUE_FLAGS = new Set(['--commands', '--name', '--as']);
77
+ const VALUE_FLAGS = new Set([
78
+ '--commands',
79
+ '--name',
80
+ '--as',
81
+ '--code',
82
+ '--message'
83
+ ]);
77
84
  const SHIM_SOURCE = `#!/bin/sh
78
85
  ${SHIM_MARKER_LINE}
79
86
  dir=$PWD
@@ -266,8 +273,13 @@ and restore sign in the same way when they need to, so this is rarely run on its
266
273
  details: `app pull sundayparty
267
274
  Downloads the source of the site's latest live version into this folder when it is empty, or into
268
275
  ./<name> otherwise, writes pattern.json, installs, and runs app setup. Never needs git; when the
269
- Command Line Tools are installed it also makes a first commit. Signs in first if needed (see app login).`,
270
- run: (argument) => pull(publishingIo(), argument, process.cwd()),
276
+ Command Line Tools are installed it also makes a first commit. Signs in first if needed (see app login).
277
+ --code <setup code> signs in with the one-time setup code from onpattern.app instead of the browser.`,
278
+ run: (argument, options) => {
279
+ const code = options.get('--code');
280
+ return pull(publishingIo(), argument, process.cwd(), typeof code === 'string' ? code : undefined);
281
+ },
282
+ flags: ['--code'],
271
283
  takesArgument: true,
272
284
  runsAnywhere: true
273
285
  },
@@ -278,9 +290,14 @@ git would keep, never .dev.vars, .env, node_modules, dist or .dev) to onpattern.
278
290
  until the new version answers at https://<name>.onpattern.app, printing each step. The database
279
291
  moves forward with any new migrations; nothing is ever deleted from it. If a step fails, the site
280
292
  keeps running the previous version and the error says why. Run app check first.
293
+ --message '…' says what changed in a few plain words for the owner ("Pink brand colour and a welcome
294
+ line"); onpattern.app and app versions show it beside the version.
281
295
  --starter (Pattern's admins only) publishes this project as the starter every new site begins from.`,
282
- run: (_argument, options) => publish(publishingIo(), ROOT, options.has('--starter')),
283
- flags: ['--starter']
296
+ run: (_argument, options) => {
297
+ const message = options.get('--message');
298
+ return publish(publishingIo(), ROOT, options.has('--starter'), typeof message === 'string' ? message : undefined);
299
+ },
300
+ flags: ['--starter', '--message']
284
301
  },
285
302
  versions: {
286
303
  summary: 'List the versions that went live, newest first',
@@ -297,7 +314,7 @@ every row and column added since, which version 3's code ignores.`,
297
314
  },
298
315
  setup: {
299
316
  summary: 'Verify Node/pnpm major versions, pnpm install, install the global `app` shim',
300
- details: `Idempotent. Fails unless Node and pnpm have the major versions in .nvmrc and package.json "packageManager".
317
+ details: `Idempotent. Fails unless Node and pnpm have the major versions in .nvmrc and package.json devEngines.
301
318
  Then runs \`pnpm install\` and installs ${SHIM_PATH}, a tiny shim that walks up from the
302
319
  current directory to the nearest project launcher (an executable ./app containing the line
303
320
  ${LAUNCHER_MARKER_LINE}) and runs it, so each project's CLI lives in its repo and the shim
@@ -1217,13 +1234,16 @@ async function build() {
1217
1234
  function majorOf(version) {
1218
1235
  return version.split('.')[0] ?? '';
1219
1236
  }
1237
+ const packagePins = z.object({
1238
+ devEngines: z.object({
1239
+ packageManager: z.object({ version: z.string() })
1240
+ })
1241
+ });
1220
1242
  function readPins() {
1221
1243
  const node = readText(join(ROOT, '.nvmrc')).trim().replace(/^v/, '');
1222
- const pkg = JSON.parse(readText(join(ROOT, 'package.json')));
1223
- const pm = typeof pkg === 'object' && pkg !== null && 'packageManager' in pkg
1224
- ? String(pkg.packageManager)
1225
- : '';
1226
- return { node, pnpm: pm.replace(/^pnpm@/, '').split('+')[0] ?? '' };
1244
+ const pkg = packagePins.safeParse(JSON.parse(readText(join(ROOT, 'package.json'))));
1245
+ const pnpm = pkg.success ? pkg.data.devEngines.packageManager.version : '';
1246
+ return { node, pnpm: pnpm.replace(/^>=/, '') };
1227
1247
  }
1228
1248
  function isPatternShim(source) {
1229
1249
  const lines = source.split('\n');
@@ -1260,7 +1280,7 @@ async function setup() {
1260
1280
  problems.push(`Node ${haveNode} is not Node ${majorOf(pins.node)} (.nvmrc says ${pins.node})\n fix pnpm env use --global ${majorOf(pins.node)}`);
1261
1281
  }
1262
1282
  if (majorOf(havePnpm) !== majorOf(pins.pnpm)) {
1263
- problems.push(`pnpm ${havePnpm || '(not found)'} is not pnpm ${majorOf(pins.pnpm)} (package.json packageManager says ${pins.pnpm})\n fix curl -fsSL https://get.pnpm.io/install.sh | sh -`);
1283
+ problems.push(`pnpm ${havePnpm || '(not found)'} is not pnpm ${majorOf(pins.pnpm)} (package.json devEngines says ${pins.pnpm} or newer)\n fix curl -fsSL https://get.pnpm.io/install.sh | sh -`);
1264
1284
  }
1265
1285
  const versions = { node: haveNode, pnpm: havePnpm, expected: pins };
1266
1286
  if (problems.length > 0) {
@@ -1302,7 +1322,7 @@ async function setup() {
1302
1322
  function help() {
1303
1323
  const width = Math.max(...Object.keys(COMMANDS).map((n) => n.length));
1304
1324
  const lines = Object.entries(COMMANDS).map(([name, cmd]) => `app ${name.padEnd(width)} ${cmd.summary}`);
1305
- lines.push('Flags: --json (machine-readable stdout), <command> --help (details and its own flags: start --no-open, test --visual, screenshot --commands --name --as --signed-out)');
1325
+ lines.push('Flags: --json (machine-readable stdout), <command> --help (details and its own flags: start --no-open, test --visual, screenshot --commands --name --as --signed-out, pull --code, publish --message)');
1306
1326
  return {
1307
1327
  code: 0,
1308
1328
  data: {
@@ -14,8 +14,8 @@ export type PublishingIo = {
14
14
  sdkVersion: string;
15
15
  };
16
16
  export declare function login(io: PublishingIo): Promise<Outcome>;
17
- export declare function pull(io: PublishingIo, name: string | undefined, cwd: string): Promise<Outcome>;
18
- export declare function publish(io: PublishingIo, root: string, isStarter: boolean): Promise<Outcome>;
17
+ export declare function pull(io: PublishingIo, name: string | undefined, cwd: string, setupCode: string | undefined): Promise<Outcome>;
18
+ export declare function publish(io: PublishingIo, root: string, isStarter: boolean, message: string | undefined): Promise<Outcome>;
19
19
  export declare function versions(io: PublishingIo, root: string): Promise<Outcome>;
20
20
  export declare function restore(io: PublishingIo, root: string, number: string | undefined): Promise<Outcome>;
21
21
  export {};
@@ -3,7 +3,7 @@ import { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, st
3
3
  import { homedir, hostname, userInfo } from 'node:os';
4
4
  import { basename, dirname, extname, join, matchesGlob, relative } from 'node:path';
5
5
  import { z } from 'zod';
6
- import { DASHBOARD_URL, UPLOAD, appSummary, isPrivatePath, loginPoll, loginStarted, nameProblem, publishSummary, sourcePathProblem } from "../publishWire.js";
6
+ import { DASHBOARD_URL, UPLOAD, appSummary, isPrivatePath, loginPoll, loginStarted, nameProblem, publishMessage, publishSummary, setupCodeExchanged, sourcePathProblem } from "../publishWire.js";
7
7
  import { appInfo } from "../appTitle.js";
8
8
  import { PROJECT_FILE, readProjectFile } from "../vite/projectFile.js";
9
9
  const CONFIG_DIR = join(homedir(), '.config', 'pattern');
@@ -175,6 +175,20 @@ async function signIn(io, again) {
175
175
  text: `Opened ${started.url} in the browser.\n code ${started.code}\n next tell them: "Check the code on the page is ${started.code}, then click Allow." Then, without waiting for them to reply, run ${again} again: it waits for Allow.`
176
176
  };
177
177
  }
178
+ async function useSetupCode(io, code) {
179
+ const response = await fetch(`${dashboard()}/api/auth/cli/setup-codes/exchange`, {
180
+ method: 'POST',
181
+ headers: { 'content-type': 'application/json' },
182
+ body: JSON.stringify({ code, label: labelOfThisMachine() })
183
+ }).catch(() => undefined);
184
+ const exchanged = setupCodeExchanged.safeParse(await response?.json().catch(() => null));
185
+ if (response?.ok === true && exchanged.success) {
186
+ saveCookie(exchanged.data.cookie);
187
+ io.say('✓ Connected with the setup code');
188
+ return;
189
+ }
190
+ io.say('✗ That setup code has expired or was already used');
191
+ }
178
192
  async function signedIn(io, again, work) {
179
193
  if (savedCookie() === undefined) {
180
194
  const outcome = await signIn(io, again);
@@ -237,7 +251,7 @@ function folderFor(name, cwd) {
237
251
  function commandLineToolsReady() {
238
252
  return spawnSync('xcode-select', ['-p'], { stdio: 'ignore' }).status === 0;
239
253
  }
240
- export async function pull(io, name, cwd) {
254
+ export async function pull(io, name, cwd, setupCode) {
241
255
  if (name === undefined || nameProblem(name) !== undefined) {
242
256
  return {
243
257
  code: 2,
@@ -254,6 +268,8 @@ export async function pull(io, name, cwd) {
254
268
  };
255
269
  }
256
270
  try {
271
+ if (setupCode !== undefined)
272
+ await useSetupCode(io, setupCode);
257
273
  const result = await signedIn(io, `app pull ${name}`, async () => {
258
274
  const app = await callJson(`/api/apps/${name}`, appSummary);
259
275
  const response = await call(`/api/apps/${name}/source`);
@@ -408,11 +424,13 @@ async function followPublish(io, name, started) {
408
424
  }
409
425
  const data = { name, version: publish.number, status: publish.status };
410
426
  if (publish.status === 'live') {
411
- return {
412
- code: 0,
413
- data,
414
- text: `✓ Version ${publish.number} is live at https://${name}.onpattern.app`
415
- };
427
+ const lines = [
428
+ `✓ Version ${publish.number} is live at https://${name}.onpattern.app${publish.message === null ? '' : ` · ${publish.message}`}`
429
+ ];
430
+ if (publish.message === null && publish.restoredFrom === null) {
431
+ lines.push(" tip add --message '…' so the owner sees what changed, in plain words");
432
+ }
433
+ return { code: 0, data, text: lines.join('\n') };
416
434
  }
417
435
  if (publish.status === 'failed') {
418
436
  return {
@@ -427,7 +445,7 @@ async function followPublish(io, name, started) {
427
445
  text: `✗ Version ${publish.number} is still publishing after ${PUBLISH_WAIT_MS / 60_000} minutes\n next app versions shows how it ends`
428
446
  };
429
447
  }
430
- export async function publish(io, root, isStarter) {
448
+ export async function publish(io, root, isStarter, message) {
431
449
  try {
432
450
  const { name } = readProjectFile(root);
433
451
  const built = await io.build();
@@ -435,6 +453,9 @@ export async function publish(io, root, isStarter) {
435
453
  return built;
436
454
  io.say('✓ Built');
437
455
  const { form, sources } = uploadForm(root, io, isStarter);
456
+ const said = publishMessage(message ?? '');
457
+ if (said !== null)
458
+ form.append(UPLOAD.message, said);
438
459
  io.say(`✓ Packed the build and ${sources} source files`);
439
460
  const again = isStarter ? 'app publish --starter' : 'app publish';
440
461
  const result = await signedIn(io, again, async () => {
@@ -476,7 +497,7 @@ export async function versions(io, root) {
476
497
  ? `restored version ${item.restoredFrom}`
477
498
  : item.isStarter
478
499
  ? 'starter site'
479
- : `published by ${item.byEmail}`;
500
+ : (item.message ?? `published by ${item.byEmail}`);
480
501
  return ` ${String(item.number).padStart(3)} ${item.status.padEnd(7)} ${item.startedAt.slice(0, 16).replace('T', ' ')} ${what}`;
481
502
  });
482
503
  return {
@@ -17,7 +17,10 @@ export declare const UPLOAD: {
17
17
  readonly source: "source/";
18
18
  readonly compatibilityDate: "compatibilityDate";
19
19
  readonly sdkVersion: "sdkVersion";
20
+ readonly message: "message";
20
21
  };
22
+ export declare const PUBLISH_MESSAGE_LIMIT = 100;
23
+ export declare function publishMessage(text: string): string | null;
21
24
  export declare const publishStep: z.ZodEnum<{
22
25
  publish: "publish";
23
26
  reserve: "reserve";
@@ -47,6 +50,7 @@ export declare const publishSummary: z.ZodObject<{
47
50
  byEmail: z.ZodString;
48
51
  restoredFrom: z.ZodNullable<z.ZodNumber>;
49
52
  isStarter: z.ZodBoolean;
53
+ message: z.ZodNullable<z.ZodString>;
50
54
  startedAt: z.ZodString;
51
55
  finishedAt: z.ZodNullable<z.ZodString>;
52
56
  }, z.core.$strip>;
@@ -73,6 +77,7 @@ export declare const appSummary: z.ZodObject<{
73
77
  byEmail: z.ZodString;
74
78
  restoredFrom: z.ZodNullable<z.ZodNumber>;
75
79
  isStarter: z.ZodBoolean;
80
+ message: z.ZodNullable<z.ZodString>;
76
81
  startedAt: z.ZodString;
77
82
  finishedAt: z.ZodNullable<z.ZodString>;
78
83
  }, z.core.$strip>>;
@@ -99,6 +104,18 @@ export declare const loginToApprove: z.ZodObject<{
99
104
  code: z.ZodString;
100
105
  label: z.ZodString;
101
106
  }, z.core.$strip>;
107
+ export declare const setupCode: z.ZodObject<{
108
+ code: z.ZodString;
109
+ expiresAt: z.ZodString;
110
+ }, z.core.$strip>;
111
+ export declare const setupCodeExchanged: z.ZodObject<{
112
+ cookie: z.ZodString;
113
+ }, z.core.$strip>;
114
+ export declare const connection: z.ZodObject<{
115
+ label: z.ZodString;
116
+ connectedAt: z.ZodString;
117
+ }, z.core.$strip>;
118
+ export type Connection = z.output<typeof connection>;
102
119
  export declare const publishServices: {
103
120
  readonly apps: {
104
121
  readonly list: NoInfer<import("./services.ts").ServiceCall<"/apps", {}, z.ZodArray<z.ZodObject<{
@@ -123,6 +140,7 @@ export declare const publishServices: {
123
140
  byEmail: z.ZodString;
124
141
  restoredFrom: z.ZodNullable<z.ZodNumber>;
125
142
  isStarter: z.ZodBoolean;
143
+ message: z.ZodNullable<z.ZodString>;
126
144
  startedAt: z.ZodString;
127
145
  finishedAt: z.ZodNullable<z.ZodString>;
128
146
  }, z.core.$strip>>;
@@ -149,6 +167,7 @@ export declare const publishServices: {
149
167
  byEmail: z.ZodString;
150
168
  restoredFrom: z.ZodNullable<z.ZodNumber>;
151
169
  isStarter: z.ZodBoolean;
170
+ message: z.ZodNullable<z.ZodString>;
152
171
  startedAt: z.ZodString;
153
172
  finishedAt: z.ZodNullable<z.ZodString>;
154
173
  }, z.core.$strip>>;
@@ -178,6 +197,7 @@ export declare const publishServices: {
178
197
  byEmail: z.ZodString;
179
198
  restoredFrom: z.ZodNullable<z.ZodNumber>;
180
199
  isStarter: z.ZodBoolean;
200
+ message: z.ZodNullable<z.ZodString>;
181
201
  startedAt: z.ZodString;
182
202
  finishedAt: z.ZodNullable<z.ZodString>;
183
203
  }, z.core.$strip>>;
@@ -215,6 +235,7 @@ export declare const publishServices: {
215
235
  byEmail: z.ZodString;
216
236
  restoredFrom: z.ZodNullable<z.ZodNumber>;
217
237
  isStarter: z.ZodBoolean;
238
+ message: z.ZodNullable<z.ZodString>;
218
239
  startedAt: z.ZodString;
219
240
  finishedAt: z.ZodNullable<z.ZodString>;
220
241
  }, z.core.$strip>>>>;
@@ -235,6 +256,7 @@ export declare const publishServices: {
235
256
  byEmail: z.ZodString;
236
257
  restoredFrom: z.ZodNullable<z.ZodNumber>;
237
258
  isStarter: z.ZodBoolean;
259
+ message: z.ZodNullable<z.ZodString>;
238
260
  startedAt: z.ZodString;
239
261
  finishedAt: z.ZodNullable<z.ZodString>;
240
262
  }, z.core.$strip>>>;
@@ -255,10 +277,24 @@ export declare const publishServices: {
255
277
  byEmail: z.ZodString;
256
278
  restoredFrom: z.ZodNullable<z.ZodNumber>;
257
279
  isStarter: z.ZodBoolean;
280
+ message: z.ZodNullable<z.ZodString>;
258
281
  startedAt: z.ZodString;
259
282
  finishedAt: z.ZodNullable<z.ZodString>;
260
283
  }, z.core.$strip>>>;
261
284
  };
285
+ readonly setup: {
286
+ readonly newCode: NoInfer<import("./services.ts").ServiceCall<"/apps/:name/setup-code", {}, z.ZodObject<{
287
+ code: z.ZodString;
288
+ expiresAt: z.ZodString;
289
+ }, z.core.$strip>>>;
290
+ readonly connection: NoInfer<import("./services.ts").ServiceCall<"/apps/:name/connection", {}, z.ZodNullable<z.ZodObject<{
291
+ label: z.ZodString;
292
+ connectedAt: z.ZodString;
293
+ }, z.core.$strip>>>>;
294
+ readonly disconnect: NoInfer<import("./services.ts").ServiceCall<"/apps/:name/connection/disconnect", {}, z.ZodObject<{
295
+ ok: z.ZodBoolean;
296
+ }, z.core.$strip>>>;
297
+ };
262
298
  readonly logins: {
263
299
  readonly read: NoInfer<import("./services.ts").ServiceCall<"/cli/logins/:approval", {}, z.ZodObject<{
264
300
  code: z.ZodString;
@@ -89,8 +89,14 @@ export const UPLOAD = {
89
89
  migrations: 'migrations/',
90
90
  source: 'source/',
91
91
  compatibilityDate: 'compatibilityDate',
92
- sdkVersion: 'sdkVersion'
92
+ sdkVersion: 'sdkVersion',
93
+ message: 'message'
93
94
  };
95
+ export const PUBLISH_MESSAGE_LIMIT = 100;
96
+ export function publishMessage(text) {
97
+ const firstLine = (text.split('\n')[0] ?? '').replaceAll(/\s+/g, ' ').trim();
98
+ return firstLine === '' ? null : firstLine.slice(0, PUBLISH_MESSAGE_LIMIT);
99
+ }
94
100
  export const publishStep = z.enum(['reserve', 'database', 'sign-in', 'publish']);
95
101
  export const publishStatus = z.enum(['running', 'live', 'failed']);
96
102
  export const publishSummary = z.object({
@@ -101,6 +107,7 @@ export const publishSummary = z.object({
101
107
  byEmail: z.string(),
102
108
  restoredFrom: z.number().nullable(),
103
109
  isStarter: z.boolean(),
110
+ message: z.string().nullable(),
104
111
  startedAt: z.string(),
105
112
  finishedAt: z.string().nullable()
106
113
  });
@@ -126,6 +133,12 @@ export const loginPoll = z.union([
126
133
  z.object({ status: z.literal('approved'), cookie: z.string() })
127
134
  ]);
128
135
  export const loginToApprove = z.object({ code: z.string(), label: z.string() });
136
+ export const setupCode = z.object({ code: z.string(), expiresAt: z.string() });
137
+ export const setupCodeExchanged = z.object({ cookie: z.string() });
138
+ export const connection = z.object({
139
+ label: z.string(),
140
+ connectedAt: z.string()
141
+ });
129
142
  export const publishServices = defineServices({
130
143
  apps: {
131
144
  list: call({ get: '/apps', reply: z.array(appSummary) }),
@@ -158,6 +171,17 @@ export const publishServices = defineServices({
158
171
  reply: publishSummary
159
172
  })
160
173
  },
174
+ setup: {
175
+ newCode: call({ post: '/apps/:name/setup-code', reply: setupCode }),
176
+ connection: call({
177
+ get: '/apps/:name/connection',
178
+ reply: connection.nullable()
179
+ }),
180
+ disconnect: call({
181
+ post: '/apps/:name/connection/disconnect',
182
+ reply: z.object({ ok: z.boolean() })
183
+ })
184
+ },
161
185
  logins: {
162
186
  read: call({ get: '/cli/logins/:approval', reply: loginToApprove }),
163
187
  approve: call({
@@ -5,7 +5,7 @@ export { refused } from '../services.ts';
5
5
  export { serveServices } from './services.ts';
6
6
  export type { ServiceHandlers } from './services.ts';
7
7
  export { sessionCookieFor } from './session.ts';
8
- export { sessions } from './sessions.ts';
8
+ export { deleteSession, sessions } from './sessions.ts';
9
9
  export { readTitle, seedTitleSql, settings, writeTitle } from './settings.ts';
10
10
  export { exchangeReply, exchangeRequest, sendCodeReply, sendCodeRequest, verifiedIdentity, verifyCodeReply, verifyCodeRequest } from './signInWire.ts';
11
11
  export type { VerifiedIdentity } from './signInWire.ts';
@@ -3,7 +3,7 @@ export { seedSql, serveTables, sqlTable, sqlTables } from "./tables.js";
3
3
  export { refused } from "../services.js";
4
4
  export { serveServices } from "./services.js";
5
5
  export { sessionCookieFor } from "./session.js";
6
- export { sessions } from "./sessions.js";
6
+ export { deleteSession, sessions } from "./sessions.js";
7
7
  export { readTitle, seedTitleSql, settings, writeTitle } from "./settings.js";
8
8
  export { exchangeReply, exchangeRequest, sendCodeReply, sendCodeRequest, verifiedIdentity, verifyCodeReply, verifyCodeRequest } from "./signInWire.js";
9
9
  export { findUser, users } from "./users.js";
@@ -17,7 +17,10 @@ export declare function issuePass(c: Context<ServerEnv>, user: StoredUser, sessi
17
17
  recheckAt: number;
18
18
  }>;
19
19
  export declare function startSession(c: Context<ServerEnv>, user: StoredUser): Promise<void>;
20
- export declare function sessionCookieFor(env: ServerEnv['Bindings'], user: StoredUser): Promise<string>;
20
+ export declare function sessionCookieFor(env: ServerEnv['Bindings'], user: StoredUser): Promise<{
21
+ cookie: string;
22
+ sessionId: `${string}-${string}-${string}-${string}-${string}`;
23
+ }>;
21
24
  export declare function readPass(c: Context<ServerEnv>): Promise<{
22
25
  sessionId: string;
23
26
  userId: string;
@@ -37,14 +37,15 @@ export async function startSession(c, user) {
37
37
  await issuePass(c, user, await createSession(c.env.DB, user.id));
38
38
  }
39
39
  export async function sessionCookieFor(env, user) {
40
+ const sessionId = await createSession(env.DB, user.id);
40
41
  const pass = {
41
- sessionId: await createSession(env.DB, user.id),
42
+ sessionId,
42
43
  userId: user.id,
43
44
  email: user.email,
44
45
  recheckAt: nowInSeconds() + RECHECK_SECONDS
45
46
  };
46
47
  const cookie = await serializeSigned(SESSION_COOKIE, JSON.stringify(pass), env.SESSION_SECRET);
47
- return cookie.split(';')[0] ?? cookie;
48
+ return { cookie: cookie.split(';')[0] ?? cookie, sessionId };
48
49
  }
49
50
  export async function readPass(c) {
50
51
  const value = await getSignedCookie(c, c.env.SESSION_SECRET, SESSION_COOKIE);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trypattern/sdk",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",