@robono/server 0.18.0 → 0.20.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +54 -0
  3. package/SBOM.spdx.json +8 -8
  4. package/dist/index.d.ts +2 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/messaging.d.ts.map +1 -1
  9. package/dist/messaging.js +30 -3
  10. package/dist/messaging.js.map +1 -1
  11. package/dist/messenger-auth.d.ts +16 -0
  12. package/dist/messenger-auth.d.ts.map +1 -0
  13. package/dist/messenger-auth.js +37 -0
  14. package/dist/messenger-auth.js.map +1 -0
  15. package/dist/messenger-check.js +1 -1
  16. package/dist/messenger-check.js.map +1 -1
  17. package/dist/messenger-connected-templates.d.ts +4 -0
  18. package/dist/messenger-connected-templates.d.ts.map +1 -0
  19. package/dist/messenger-connected-templates.js +135 -0
  20. package/dist/messenger-connected-templates.js.map +1 -0
  21. package/dist/messenger-init-cli.d.ts +3 -0
  22. package/dist/messenger-init-cli.d.ts.map +1 -0
  23. package/dist/messenger-init-cli.js +39 -0
  24. package/dist/messenger-init-cli.js.map +1 -0
  25. package/dist/messenger-init.d.ts +13 -0
  26. package/dist/messenger-init.d.ts.map +1 -0
  27. package/dist/messenger-init.js +120 -0
  28. package/dist/messenger-init.js.map +1 -0
  29. package/dist/messenger-install-cli.d.ts +3 -0
  30. package/dist/messenger-install-cli.d.ts.map +1 -0
  31. package/dist/messenger-install-cli.js +82 -0
  32. package/dist/messenger-install-cli.js.map +1 -0
  33. package/dist/messenger-install.d.ts +35 -0
  34. package/dist/messenger-install.d.ts.map +1 -0
  35. package/dist/messenger-install.js +216 -0
  36. package/dist/messenger-install.js.map +1 -0
  37. package/dist/messenger-preview-template.d.ts +6 -0
  38. package/dist/messenger-preview-template.d.ts.map +1 -0
  39. package/dist/messenger-preview-template.js +43 -0
  40. package/dist/messenger-preview-template.js.map +1 -0
  41. package/dist/messenger-setup-test.js +11 -4
  42. package/dist/messenger-setup-test.js.map +1 -1
  43. package/dist/messenger.d.ts +1 -0
  44. package/dist/messenger.d.ts.map +1 -1
  45. package/dist/messenger.js +1 -1
  46. package/dist/messenger.js.map +1 -1
  47. package/package.json +12 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messenger-init-cli.js","sourceRoot":"","sources":["../src/messenger-init-cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { type MessengerAuthProvider } from './messenger-connected-templates.js';
2
+ export interface MessengerStarterOptions {
3
+ platform: 'web' | 'expo';
4
+ framework: 'next' | 'fetch';
5
+ origin: string;
6
+ companyName: string;
7
+ auth?: MessengerAuthProvider;
8
+ }
9
+ /** Pure templates contain no credentials. Host authentication deliberately fails closed. */
10
+ export declare function messengerStarterFiles(options: MessengerStarterOptions): Record<string, string>;
11
+ /** All-or-nothing new directory; never edits a customer's existing app or env file. */
12
+ export declare function writeMessengerStarter(destination: string, options: MessengerStarterOptions): Promise<string[]>;
13
+ //# sourceMappingURL=messenger-init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messenger-init.d.ts","sourceRoot":"","sources":["../src/messenger-init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,qBAAqB,EAAC,MAAM,oCAAoC,CAAC;AAGtG,MAAM,WAAW,uBAAuB;IAAE,QAAQ,EAAC,KAAK,GAAC,MAAM,CAAC;IAAA,SAAS,EAAC,MAAM,GAAC,OAAO,CAAC;IAAA,MAAM,EAAC,MAAM,CAAC;IAAA,WAAW,EAAC,MAAM,CAAC;IAAA,IAAI,CAAC,EAAC,qBAAqB,CAAA;CAAC;AACtJ,4FAA4F;AAC5F,wBAAgB,qBAAqB,CAAC,OAAO,EAAC,uBAAuB,GAAE,MAAM,CAAC,MAAM,EAAC,MAAM,CAAC,CA+E3F;AACD,uFAAuF;AACvF,wBAAsB,qBAAqB,CAAC,WAAW,EAAC,MAAM,EAAC,OAAO,EAAC,uBAAuB,qBAc7F"}
@@ -0,0 +1,120 @@
1
+ import { connectStarterTemplates } from './messenger-connected-templates.js';
2
+ import { mkdir, writeFile, access, realpath, lstat, rm } from 'node:fs/promises';
3
+ import { resolve, dirname, relative, isAbsolute, join } from 'node:path';
4
+ /** Pure templates contain no credentials. Host authentication deliberately fails closed. */
5
+ export function messengerStarterFiles(options) {
6
+ const origin = new URL(options.origin);
7
+ if (origin.origin !== options.origin || origin.username || origin.password || !(origin.protocol === 'https:' || origin.protocol === 'http:' && ['localhost', '127.0.0.1', '[::1]'].includes(origin.hostname)))
8
+ throw Error('Use your exact HTTPS website origin, or localhost for development.');
9
+ if (!['web', 'expo'].includes(options.platform) || !['next', 'fetch'].includes(options.framework) || !options.companyName.trim() || options.companyName.length > 100)
10
+ throw Error('Choose Website or React Native, your server framework, and a company name.');
11
+ if (options.platform === 'expo' && origin.protocol !== 'https:')
12
+ throw Error('Phone apps need an HTTPS server address reachable from the phone.');
13
+ const q = JSON.stringify, route = options.framework === 'next' ? 'app/api/robono/route.ts' : 'server/robono-route.ts';
14
+ const auth = `import type {MessengerAccess} from '@robono/server';
15
+ // Replace ONLY these two functions with your existing account/permission service.
16
+ // Do not read a user ID from the request body. Verify expiry and suspension.
17
+ export async function authenticate(request:Request):Promise<string|null>{
18
+ throw Error('Connect your existing session verification in robono-access.ts');
19
+ }
20
+ // Account operations such as settings, conversations and notifications.register-device
21
+ // have no conversation ID. Allow them only for active, eligible accounts.
22
+ // Chat operations also need current membership and write/read permission checks.
23
+ export async function authorize(access:MessengerAccess):Promise<boolean>{
24
+ throw Error('Connect your existing messaging permission check in robono-access.ts');
25
+ }
26
+ `;
27
+ const files = {
28
+ '.gitignore': '.env\n.env.local\nnode_modules/\n',
29
+ '.env.example': `# Server only. Never prefix this with NEXT_PUBLIC_, VITE_ or EXPO_PUBLIC_.\nROBONO_API_KEY=\n`,
30
+ 'server/robono-access.ts': auth,
31
+ 'server/robono.ts': `import {createRobonoMessengerServer} from '@robono/server';
32
+ import {authenticate,authorize} from './robono-access';
33
+ let messenger:ReturnType<typeof createRobonoMessengerServer>|undefined;
34
+ export function getMessenger(){
35
+ if(messenger)return messenger;
36
+ const apiKey=process.env.ROBONO_API_KEY;
37
+ if(!apiKey)throw Error('Set ROBONO_API_KEY on your server.');
38
+ return messenger=createRobonoMessengerServer({apiKey,authenticate,authorize,allowedOrigins:[${q(options.origin)}]});
39
+ }
40
+ `,
41
+ [route]: `import {getMessenger} from ${q(options.framework === 'next' ? '../../../server/robono' : './robono')};
42
+ ${options.framework === 'next' ? "export const runtime = 'nodejs';\n" : ''}export const GET=(request:Request)=>getMessenger().handle(request);
43
+ export const POST=(request:Request)=>getMessenger().handle(request);
44
+ `,
45
+ 'server/synchronize-contacts.ts': `// Run on your server when your own relationship record changes.
46
+ // Pass the server-only messenger instance from your application. Revisions come from YOUR database.
47
+ export async function synchronizeFriendship(messenger:import('@robono/server').RobonoMessengerServer,friendship:{userA:string;userB:string;canMessage:boolean;revision:number}){
48
+ return messenger.robono.setRelationship({externalUserIds:[friendship.userA,friendship.userB],allowed:friendship.canMessage,revision:friendship.revision});
49
+ }
50
+ `,
51
+ 'ROBONO-SETUP.md': `# Connect ${options.companyName.replace(/[\r\n]/g, ' ')} to Robono\n\nThese are prepared integration files, not a replacement for your app. No existing files were changed.\n\n1. Install the packages listed below in the corresponding server and client projects.\n2. Copy the generated files into your app. Put the Robono key only in the server's environment.\n3. Connect the two functions in robono-access.ts to your existing sign-in and permission checks. They reject access until connected.\n4. When your app permits or removes a friendship, call synchronizeFriendship with its current revision. Supply current contact names/avatars to the client. Group memberships use messenger.robono.setGroup.\n5. Mount GET and POST at /api/robono. Add the client screen, pass your signed-in account and token-refresh function, and call its signOut() before ending a session.\n6. Run robono-messenger-check against your own route with a disposable test-user token. Then exchange a message between two authorized users.\n\nServer: npm install @robono/server\nTypeScript server: npm install --save-dev typescript @types/node\nClient: npm install @robono/messaging @robono/${options.platform === 'web' ? 'messaging-web react react-dom' : 'messaging-react-native'}\n\n${options.platform === 'expo' ? 'For React Native, follow the native dependency and Expo configuration instructions in the package README before rebuilding iPhone and Android. Your app needs its own Apple/Google notification credentials; upload private keys only in Robono’s notification setup.' : 'For website alerts, enter your HTTPS origin and chat page in Robono’s notification setup. The supplied messenger handles the browser helper. No Apple/Google private key is needed.'}\n\nKeep feature choices in Robono’s Features & preview. Do not duplicate them in frontend permission switches. Your server remains responsible for who may use the service. Never return true for every permission request.\n\n## Local connection check\nSet ROBONO_MESSENGER_URL, ROBONO_TEST_USER_TOKEN and ROBONO_WEBSITE_ORIGIN in your local environment. Then run:\n\n\`\`\`sh\nnpx --package @robono/server robono-messenger-check\n# Shareable diagnostic output; contains no token or message content:\nnpx --package @robono/server robono-messenger-check --json\n\`\`\`\n\n## Assistance\nAn AI coding assistant may use these files and package documentation to connect your existing account service. It must preserve authentication, expiry, suspension, current memberships and server-only keys. It must not replace them with a demo password or an always-allow function. Do not send credentials or customer messages to support chat.\n`,
52
+ };
53
+ if (options.platform === 'web')
54
+ files['client/RobonoChat.tsx'] = `'use client';
55
+ import {useEffect,useRef} from 'react';
56
+ import {mountRobonoMessenger} from '@robono/messaging-web';
57
+ type Options=Parameters<typeof mountRobonoMessenger>[1];
58
+ // Keep getAccessToken and contacts stable. The token callback must return a current token.
59
+ export function RobonoChat({userId,getAccessToken,contacts,onReady}:{userId:string;getAccessToken:Options['getAccessToken'];contacts:Options['contacts'];onReady:(chat:ReturnType<typeof mountRobonoMessenger>|null)=>void}){
60
+ const element=useRef<HTMLDivElement>(null);
61
+ useEffect(()=>{
62
+ if(!element.current)return;
63
+ const chat=mountRobonoMessenger(element.current,{endpoint:'/api/robono',companyName:${q(options.companyName)},userId,getAccessToken,contacts});
64
+ onReady(chat);return()=>{onReady(null);chat.unmount();};
65
+ },[userId,getAccessToken,contacts,onReady]);
66
+ return <div ref={element} style={{height:'100%',minHeight:400}}/>;
67
+ }
68
+ // Store onReady's chat handle. Await chat.signOut() BEFORE ending your own session.
69
+ `;
70
+ else
71
+ files['client/RobonoChat.tsx'] = `import React,{useEffect,useState} from 'react';
72
+ import {createExpoMessenger,ExpoMessenger,type ExpoMessengerProps} from '@robono/messaging-react-native/expo';
73
+ type Connection=ReturnType<typeof createExpoMessenger>;
74
+ export function RobonoChat({userId,getAccessToken,contacts,isCallActive,onReady}:{userId:string;getAccessToken:()=>Promise<string>;contacts:ExpoMessengerProps['contacts'];isCallActive:()=>boolean;onReady:(connection:Connection|null)=>void}){
75
+ const [active,setActive]=useState<{userId:string;connection:Connection}|null>(null);
76
+ useEffect(()=>{
77
+ const connection=createExpoMessenger({endpoint:${q(options.origin + '/api/robono')},userId,getAccessToken,isCallActive});
78
+ setActive({userId,connection});onReady(connection);
79
+ return()=>{onReady(null);connection.dispose();};
80
+ },[userId,getAccessToken,isCallActive,onReady]);
81
+ if(!active||active.userId!==userId)return null;
82
+ return <ExpoMessenger {...active.connection} userId={userId} companyName={${q(options.companyName)}} contacts={contacts}/>;
83
+ }
84
+ // Mount inside your app's safe area. Keep callbacks stable. Await connection.signOut()
85
+ // BEFORE ending your session; dispose only detaches the screen.
86
+ `;
87
+ return connectStarterTemplates(files, options);
88
+ }
89
+ /** All-or-nothing new directory; never edits a customer's existing app or env file. */
90
+ export async function writeMessengerStarter(destination, options) {
91
+ const files = messengerStarterFiles(options), target = resolve(destination), parent = await realpath(dirname(target));
92
+ if (join(parent, target.slice(dirname(target).length + 1)) !== target)
93
+ throw Error('Use a destination without symbolic-link parents.');
94
+ try {
95
+ await access(target);
96
+ throw Error('That directory already exists. Choose a new directory.');
97
+ }
98
+ catch (e) {
99
+ if (e.code !== 'ENOENT')
100
+ throw e;
101
+ }
102
+ await mkdir(target, { mode: 0o700 });
103
+ try {
104
+ for (const [name, content] of Object.entries(files)) {
105
+ const path = resolve(target, name), local = relative(target, path);
106
+ if (local.startsWith('..') || isAbsolute(local))
107
+ throw Error('Invalid template path');
108
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
109
+ if ((await lstat(dirname(path))).isSymbolicLink())
110
+ throw Error('Unexpected symbolic link');
111
+ await writeFile(path, content, { flag: 'wx', mode: 0o600 });
112
+ }
113
+ }
114
+ catch (e) {
115
+ await rm(target, { recursive: true, force: true });
116
+ throw e;
117
+ }
118
+ return Object.keys(files);
119
+ }
120
+ //# sourceMappingURL=messenger-init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messenger-init.js","sourceRoot":"","sources":["../src/messenger-init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=messenger-install-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messenger-install-cli.d.ts","sourceRoot":"","sources":["../src/messenger-install-cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env node
2
+ import { createInterface } from 'node:readline/promises';
3
+ import { stdin, stdout } from 'node:process';
4
+ import { planMessengerInstallation, applyMessengerInstallation, messengerInstallationChecklist } from './messenger-install.js';
5
+ import { checkRobonoMessengerSetup } from './messenger-check.js';
6
+ const args = process.argv.slice(2), values = {}, flags = new Set();
7
+ let prompt;
8
+ try {
9
+ for (let i = 0; i < args.length; i++) {
10
+ const arg = args[i];
11
+ if (['--help', '--yes', '--dry-run', '--no-install', '--check', '--json'].includes(arg)) {
12
+ flags.add(arg);
13
+ continue;
14
+ }
15
+ if (!['--project', '--server-project', '--origin', '--company', '--auth'].includes(arg) || !args[i + 1] || args[i + 1].startsWith('--') || values[arg])
16
+ throw Error('Unknown or missing option. Use --help.');
17
+ values[arg] = args[++i];
18
+ }
19
+ if (flags.has('--help')) {
20
+ console.log(`robono-messenger-install [--project .] [--server-project ../server] [--auth supabase|firebase|custom] --origin https://your-company.com --company "Your company"
21
+ Detects Next.js App Router or Expo 55–56, places files, and installs matching packages.
22
+ Expo also needs a separate Next.js server and a static app.json. Existing application screens and .env files are preserved.
23
+ --dry-run lists the exact files and commands without changing anything.
24
+ --yes applies that plan without an interactive prompt. --no-install writes files only.
25
+ --check shows one setup checklist; set the three ROBONO_* test variables to include live checks. --json prints a shareable checklist.
26
+ The development-only /robono-preview route uses fictional people and never sends messages outside the page.`);
27
+ }
28
+ else if (flags.has('--check')) {
29
+ let checks = await messengerInstallationChecklist(values['--project'] ?? '.');
30
+ const endpoint = process.env.ROBONO_MESSENGER_URL, origin = process.env.ROBONO_WEBSITE_ORIGIN, accessToken = process.env.ROBONO_TEST_USER_TOKEN;
31
+ if (endpoint && origin && accessToken) {
32
+ try {
33
+ const live = await checkRobonoMessengerSetup({ endpoint, origin, accessToken });
34
+ checks = [...checks.filter(c => !['Live connection', 'Server key', 'Contacts', 'Notifications'].includes(c.name)), ...live];
35
+ }
36
+ catch {
37
+ checks.push({ name: 'Live connection', status: 'failed', detail: 'Check the exact endpoint, website origin and test-user token. No secret was included in this report.' });
38
+ }
39
+ }
40
+ if (flags.has('--json'))
41
+ console.log(JSON.stringify({ schemaVersion: 1, checks, scope: 'Setup checks; not a complete security or delivery test.' }, null, 2));
42
+ else
43
+ for (const check of checks)
44
+ console.log(`${check.status === 'passed' ? 'PASS' : check.status === 'failed' ? 'FIX' : 'NEXT'} — ${check.name}: ${check.detail}`);
45
+ if (checks.some(c => c.status === 'failed'))
46
+ process.exitCode = 1;
47
+ }
48
+ else {
49
+ if (stdin.isTTY && !flags.has('--yes'))
50
+ prompt = createInterface({ input: stdin, output: stdout });
51
+ const ask = async (key, label) => values[key] ?? (prompt ? (await prompt.question(label + ': ')).trim() : undefined);
52
+ const origin = await ask('--origin', 'Website/server origin (for example https://your-company.com)'), companyName = await ask('--company', 'Company name');
53
+ if (!origin || !companyName)
54
+ throw Error('Supply --origin and --company, or run interactively.');
55
+ const auth = values['--auth'];
56
+ if (auth && !['custom', 'supabase', 'firebase'].includes(auth))
57
+ throw Error('Choose custom, supabase or firebase.');
58
+ const plan = await planMessengerInstallation({ project: values['--project'] ?? '.', origin, companyName, ...(values['--server-project'] ? { serverProject: values['--server-project'] } : {}), ...(auth ? { auth: auth } : {}) });
59
+ for (const file of plan.files)
60
+ console.log('Create: ' + file.path);
61
+ for (const file of plan.replacements)
62
+ console.log('Merge missing Expo plugins: ' + file.path + ' (original saved in .robono)');
63
+ for (const command of plan.commands)
64
+ console.log(`Install in ${command.cwd}: ${command.command} ${command.args.join(' ')}`);
65
+ for (const note of plan.notes)
66
+ console.log(note);
67
+ if (!flags.has('--dry-run')) {
68
+ if (!flags.has('--yes') && (!prompt || !/^y(es)?$/i.test((await prompt.question('Apply this plan? [y/N] ')).trim())))
69
+ throw Error('Nothing changed. Use --yes to apply the displayed plan.');
70
+ await applyMessengerInstallation(plan, !flags.has('--no-install'));
71
+ console.log('Integration files are ready. Open .robono/SETUP.md, then run robono-messenger-install --check. Nothing was deployed.');
72
+ }
73
+ }
74
+ }
75
+ catch (e) {
76
+ console.error(e instanceof Error ? e.message : 'Installation failed.');
77
+ process.exitCode = 1;
78
+ }
79
+ finally {
80
+ prompt?.close();
81
+ }
82
+ //# sourceMappingURL=messenger-install-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messenger-install-cli.js","sourceRoot":"","sources":["../src/messenger-install-cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAC,eAAe,EAAC,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAC,KAAK,EAAC,MAAM,EAAC,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAC,yBAAyB,EAAC,0BAA0B,EAAC,8BAA8B,EAAC,MAAM,wBAAwB,CAAC;AAC3H,OAAO,EAAC,yBAAyB,EAAC,MAAM,sBAAsB,CAAC;AAC/D,MAAM,IAAI,GAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAC,MAAM,GAAuB,EAAE,EAAC,KAAK,GAAC,IAAI,GAAG,EAAU,CAAC;AACzF,IAAI,MAAmD,CAAC;AACxD,IAAG,CAAC;IACH,KAAI,IAAI,CAAC,GAAC,CAAC,EAAC,CAAC,GAAC,IAAI,CAAC,MAAM,EAAC,CAAC,EAAE,EAAC,CAAC;QAC9B,MAAM,GAAG,GAAC,IAAI,CAAC,CAAC,CAAE,CAAC;QACnB,IAAG,CAAC,QAAQ,EAAC,OAAO,EAAC,WAAW,EAAC,cAAc,EAAC,SAAS,EAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAC,CAAC;YAAA,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAAA,SAAS;QAAA,CAAC;QAC5G,IAAG,CAAC,CAAC,WAAW,EAAC,kBAAkB,EAAC,UAAU,EAAC,WAAW,EAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAE,CAAC,IAAI,CAAC,CAAC,GAAC,CAAC,CAAC,IAAE,IAAI,CAAC,CAAC,GAAC,CAAC,CAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAE,MAAM,CAAC,GAAG,CAAC;YAAC,MAAM,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC/L,MAAM,CAAC,GAAG,CAAC,GAAC,IAAI,CAAC,EAAE,CAAC,CAAE,CAAC;IACxB,CAAC;IACD,IAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAC,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC;;;;;;4GAM8F,CAAC,CAAC;IAC7G,CAAC;SAAK,IAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAC,CAAC;QAC9B,IAAI,MAAM,GAAC,MAAM,8BAA8B,CAAC,MAAM,CAAC,WAAW,CAAC,IAAE,GAAG,CAAC,CAAC;QAC1E,MAAM,QAAQ,GAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAC,MAAM,GAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAC,WAAW,GAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;QACxI,IAAG,QAAQ,IAAE,MAAM,IAAE,WAAW,EAAC,CAAC;YACjC,IAAG,CAAC;gBAAA,MAAM,IAAI,GAAC,MAAM,yBAAyB,CAAC,EAAC,QAAQ,EAAC,MAAM,EAAC,WAAW,EAAC,CAAC,CAAC;gBAAA,MAAM,GAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA,EAAE,CAAA,CAAC,CAAC,iBAAiB,EAAC,YAAY,EAAC,UAAU,EAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAC,GAAG,IAAI,CAAC,CAAC;YAAA,CAAC;YACnM,MAAK,CAAC;gBAAA,MAAM,CAAC,IAAI,CAAC,EAAC,IAAI,EAAC,iBAAiB,EAAC,MAAM,EAAC,QAAQ,EAAC,MAAM,EAAC,sGAAsG,EAAC,CAAC,CAAC;YAAA,CAAC;QAC5K,CAAC;QACD,IAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAC,aAAa,EAAC,CAAC,EAAC,MAAM,EAAC,KAAK,EAAC,yDAAyD,EAAC,EAAC,IAAI,EAAC,CAAC,CAAC,CAAC,CAAC;;YAC/I,KAAI,MAAM,KAAK,IAAI,MAAM;gBAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,KAAG,QAAQ,CAAA,CAAC,CAAA,MAAM,CAAA,CAAC,CAAA,KAAK,CAAC,MAAM,KAAG,QAAQ,CAAA,CAAC,CAAA,KAAK,CAAA,CAAC,CAAA,MAAM,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACtJ,IAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA,EAAE,CAAA,CAAC,CAAC,MAAM,KAAG,QAAQ,CAAC;YAAC,OAAO,CAAC,QAAQ,GAAC,CAAC,CAAC;IAC3D,CAAC;SAAI,CAAC;QACL,IAAG,KAAK,CAAC,KAAK,IAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;YAAC,MAAM,GAAC,eAAe,CAAC,EAAC,KAAK,EAAC,KAAK,EAAC,MAAM,EAAC,MAAM,EAAC,CAAC,CAAC;QACxF,MAAM,GAAG,GAAC,KAAK,EAAC,GAAU,EAAC,KAAY,EAAC,EAAE,CAAA,MAAM,CAAC,GAAG,CAAC,IAAE,CAAC,MAAM,CAAA,CAAC,CAAA,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,GAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA,CAAC,CAAA,SAAS,CAAC,CAAC;QACrH,MAAM,MAAM,GAAC,MAAM,GAAG,CAAC,UAAU,EAAC,8DAA8D,CAAC,EAAC,WAAW,GAAC,MAAM,GAAG,CAAC,WAAW,EAAC,cAAc,CAAC,CAAC;QACpJ,IAAG,CAAC,MAAM,IAAE,CAAC,WAAW;YAAC,MAAM,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC7F,MAAM,IAAI,GAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAAA,IAAG,IAAI,IAAE,CAAC,CAAC,QAAQ,EAAC,UAAU,EAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAC,MAAM,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1I,MAAM,IAAI,GAAC,MAAM,yBAAyB,CAAC,EAAC,OAAO,EAAC,MAAM,CAAC,WAAW,CAAC,IAAE,GAAG,EAAC,MAAM,EAAC,WAAW,EAAC,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAA,CAAC,CAAA,EAAC,aAAa,EAAC,MAAM,CAAC,kBAAkB,CAAC,EAAC,CAAA,CAAC,CAAA,EAAG,CAAC,EAAC,GAAG,CAAC,IAAI,CAAA,CAAC,CAAA,EAAC,IAAI,EAAC,IAAsC,EAAC,CAAA,CAAC,CAAA,EAAE,CAAC,EAAC,CAAC,CAAC;QAC5O,KAAI,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK;YAAC,OAAO,CAAC,GAAG,CAAC,UAAU,GAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,KAAI,MAAM,IAAI,IAAI,IAAI,CAAC,YAAY;YAAC,OAAO,CAAC,GAAG,CAAC,8BAA8B,GAAC,IAAI,CAAC,IAAI,GAAC,8BAA8B,CAAC,CAAC;QACzH,KAAI,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ;YAAC,OAAO,CAAC,GAAG,CAAC,cAAc,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC1H,KAAI,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK;YAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAG,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,EAAC,CAAC;YAC3B,IAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAE,CAAC,CAAC,MAAM,IAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBAAC,MAAM,KAAK,CAAC,yDAAyD,CAAC,CAAC;YACvL,MAAM,0BAA0B,CAAC,IAAI,EAAC,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;YAClE,OAAO,CAAC,GAAG,CAAC,sHAAsH,CAAC,CAAC;QACrI,CAAC;IACF,CAAC;AACF,CAAC;AAAA,OAAM,CAAC,EAAC,CAAC;IAAA,OAAO,CAAC,KAAK,CAAC,CAAC,YAAY,KAAK,CAAA,CAAC,CAAA,CAAC,CAAC,OAAO,CAAA,CAAC,CAAA,sBAAsB,CAAC,CAAC;IAAA,OAAO,CAAC,QAAQ,GAAC,CAAC,CAAC;AAAA,CAAC;QAAO,CAAC;IAAA,MAAM,EAAE,KAAK,EAAE,CAAC;AAAA,CAAC"}
@@ -0,0 +1,35 @@
1
+ export interface MessengerInstallOptions {
2
+ project: string;
3
+ serverProject?: string;
4
+ origin: string;
5
+ companyName: string;
6
+ auth?: 'custom' | 'supabase' | 'firebase';
7
+ }
8
+ export interface MessengerInstallPlan {
9
+ platform: 'web' | 'expo';
10
+ auth: 'custom' | 'supabase' | 'firebase';
11
+ files: {
12
+ path: string;
13
+ content: string;
14
+ }[];
15
+ replacements: {
16
+ path: string;
17
+ before: string;
18
+ after: string;
19
+ }[];
20
+ commands: {
21
+ cwd: string;
22
+ command: string;
23
+ args: string[];
24
+ }[];
25
+ notes: string[];
26
+ }
27
+ export declare function planMessengerInstallation(options: MessengerInstallOptions): Promise<MessengerInstallPlan>;
28
+ /** Preflight all files; exclusive writes and rollback avoid overwriting customer work. */
29
+ export declare function applyMessengerInstallation(plan: MessengerInstallPlan, install?: boolean): Promise<void>;
30
+ export declare function messengerInstallationChecklist(directory: string): Promise<{
31
+ name: string;
32
+ status: string;
33
+ detail: string;
34
+ }[]>;
35
+ //# sourceMappingURL=messenger-install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messenger-install.d.ts","sourceRoot":"","sources":["../src/messenger-install.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,uBAAuB;IAAE,OAAO,EAAC,MAAM,CAAC;IAAA,aAAa,CAAC,EAAC,MAAM,CAAC;IAAA,MAAM,EAAC,MAAM,CAAC;IAAA,WAAW,EAAC,MAAM,CAAC;IAAA,IAAI,CAAC,EAAC,QAAQ,GAAC,UAAU,GAAC,UAAU,CAAA;CAAC;AAErJ,MAAM,WAAW,oBAAoB;IAAE,QAAQ,EAAC,KAAK,GAAC,MAAM,CAAC;IAAA,IAAI,EAAC,QAAQ,GAAC,UAAU,GAAC,UAAU,CAAC;IAAA,KAAK,EAAC;QAAC,IAAI,EAAC,MAAM,CAAC;QAAA,OAAO,EAAC,MAAM,CAAA;KAAC,EAAE,CAAC;IAAA,YAAY,EAAC;QAAC,IAAI,EAAC,MAAM,CAAC;QAAA,MAAM,EAAC,MAAM,CAAC;QAAA,KAAK,EAAC,MAAM,CAAA;KAAC,EAAE,CAAC;IAAA,QAAQ,EAAC;QAAC,GAAG,EAAC,MAAM,CAAC;QAAA,OAAO,EAAC,MAAM,CAAC;QAAA,IAAI,EAAC,MAAM,EAAE,CAAA;KAAC,EAAE,CAAC;IAAA,KAAK,EAAC,MAAM,EAAE,CAAA;CAAC;AA6BlQ,wBAAsB,yBAAyB,CAAC,OAAO,EAAC,uBAAuB,GAAE,OAAO,CAAC,oBAAoB,CAAC,CAgE7G;AACD,0FAA0F;AAC1F,wBAAsB,0BAA0B,CAAC,IAAI,EAAC,oBAAoB,EAAC,OAAO,UAAK,iBAYtF;AACD,wBAAsB,8BAA8B,CAAC,SAAS,EAAC,MAAM;;;;KAkBpE"}
@@ -0,0 +1,216 @@
1
+ import { messengerPreviewTemplates } from './messenger-preview-template.js';
2
+ import { readFile, writeFile, mkdir, lstat, realpath, unlink } from 'node:fs/promises';
3
+ import { resolve, join, dirname, relative } from 'node:path';
4
+ import { spawn } from 'node:child_process';
5
+ import { messengerStarterFiles } from './messenger-init.js';
6
+ async function exists(file) { try {
7
+ await lstat(file);
8
+ return true;
9
+ }
10
+ catch (e) {
11
+ if (e.code === 'ENOENT')
12
+ return false;
13
+ throw e;
14
+ } }
15
+ async function project(directory) {
16
+ const root = resolve(directory);
17
+ if (await realpath(root) !== root)
18
+ throw Error('Use a project path without symbolic links.');
19
+ const stat = await lstat(join(root, 'package.json'));
20
+ if (!stat.isFile() || stat.isSymbolicLink())
21
+ throw Error('Use a regular package.json.');
22
+ const pkg = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'));
23
+ return { root, pkg, deps: { ...pkg.devDependencies, ...pkg.dependencies } };
24
+ }
25
+ async function safePath(file) {
26
+ let part = resolve(file);
27
+ while (true) {
28
+ if (await exists(part)) {
29
+ const s = await lstat(part);
30
+ if (s.isSymbolicLink())
31
+ throw Error('Installation paths cannot contain symbolic links.');
32
+ }
33
+ const parent = dirname(part);
34
+ if (parent === part)
35
+ break;
36
+ part = parent;
37
+ }
38
+ }
39
+ async function appRoot(root) {
40
+ for (const base of ['src', ''])
41
+ if (await exists(join(root, base, 'app'))) {
42
+ await safePath(join(root, base, 'app'));
43
+ return base;
44
+ }
45
+ throw Error('Automatic website installation supports Next.js App Router. Create its app directory first, or use robono-messenger-init for another server.');
46
+ }
47
+ function installCommand(root, manager, packages) {
48
+ if (!['npm', 'pnpm', 'yarn'].includes(manager))
49
+ throw Error('Supported package managers: npm, pnpm, yarn.');
50
+ return { cwd: root, command: manager, args: manager === 'npm' ? ['install', '--ignore-scripts', '--', ...packages] : manager === 'pnpm' ? ['add', '--ignore-scripts', '--', ...packages] : ['add', '--ignore-scripts', ...packages] };
51
+ }
52
+ async function manager(root, pkg) {
53
+ const locks = [];
54
+ for (const [file, name] of [['package-lock.json', 'npm'], ['pnpm-lock.yaml', 'pnpm'], ['yarn.lock', 'yarn']])
55
+ if (await exists(join(root, file)))
56
+ locks.push(name);
57
+ const named = pkg.packageManager?.split('@')[0];
58
+ if (locks.length > 1 || named && locks.length && locks[0] !== named)
59
+ throw Error('Conflicting package-manager files. Keep the lockfile used by this project before installing.');
60
+ const result = named ?? locks[0] ?? 'npm';
61
+ // Yarn Berry has different script controls; do not silently run hooks or rewrite its configuration.
62
+ if (result === 'yarn' && pkg.packageManager && !pkg.packageManager.startsWith('yarn@1.'))
63
+ throw Error('Use the generated-file command for Yarn 2+; automatic installation currently supports Yarn 1, npm and pnpm.');
64
+ return result;
65
+ }
66
+ export async function planMessengerInstallation(options) {
67
+ if (Number(process.versions.node.split('.')[0]) < 22)
68
+ throw Error('Use Node.js 22 or later for automatic installation.');
69
+ const client = await project(options.project), platform = client.deps.expo ? 'expo' : client.deps.next ? 'web' : null;
70
+ if (!platform)
71
+ throw Error('Automatic installation supports Next.js App Router and Expo. For other projects use robono-messenger-init.');
72
+ if (platform === 'expo' && !/^[~^]?(55|56)\./.test(client.deps.expo))
73
+ throw Error('The supplied Expo messenger supports Expo 55–56. Keep your current app unchanged and check the mobile installation guide.');
74
+ if (platform === 'expo' && !options.serverProject)
75
+ throw Error('Pass --server-project with your existing Next.js server folder. A phone app must not contain the Robono server key.');
76
+ const server = platform === 'web' ? client : await project(options.serverProject);
77
+ if (!server.deps.next)
78
+ throw Error('The automatic server connection needs Next.js App Router. Use robono-messenger-init for other servers.');
79
+ if (platform === 'expo' && server.root === client.root)
80
+ throw Error('Use a separate server project; never install server credentials inside the phone app.');
81
+ const serverBase = await appRoot(server.root), clientBase = platform === 'web' ? serverBase : (await exists(join(client.root, 'src')) ? 'src' : '');
82
+ const detected = client.deps['@supabase/supabase-js'] ? 'supabase' : client.deps.firebase ? 'firebase' : 'custom';
83
+ if (!options.auth && client.deps['@supabase/supabase-js'] && client.deps.firebase)
84
+ throw Error('Both sign-in providers are installed. Choose --auth supabase, firebase or custom.');
85
+ const auth = options.auth ?? detected;
86
+ const providerName = auth === 'supabase' ? '@supabase/supabase-js' : auth === 'firebase' ? 'firebase' : null;
87
+ if (providerName && client.deps[providerName]) {
88
+ const installed = await readFile(join(client.root, 'node_modules', providerName, 'package.json'), 'utf8').then(value => JSON.parse(value).version).catch(() => client.deps[providerName]);
89
+ const major = Number(installed.match(/^[~^]?(\d+)/)?.[1]);
90
+ if (!major || major < (auth === 'supabase' ? 2 : 9))
91
+ throw Error('This sign-in package needs a newer API. Keep your current sign-in unchanged and use --auth custom, or update it separately.');
92
+ }
93
+ const templates = messengerStarterFiles({ platform, framework: 'next', origin: options.origin, companyName: options.companyName, auth });
94
+ const files = [], replacements = [];
95
+ for (const [name, content] of Object.entries(templates)) {
96
+ if (name.startsWith('client/'))
97
+ files.push({ path: join(client.root, clientBase, 'robono', name), content });
98
+ else if (name.startsWith('server/'))
99
+ files.push({ path: join(server.root, serverBase, 'robono', name), content });
100
+ }
101
+ files.push({ path: join(server.root, serverBase, 'app/api/robono/route.ts'), content: templates['app/api/robono/route.ts'].replace('../../../server/robono', '../../../robono/server/robono') });
102
+ const preview = messengerPreviewTemplates();
103
+ files.push({ path: join(server.root, serverBase, 'app/robono-preview/page.tsx'), content: preview.page }, { path: join(server.root, serverBase, 'robono/client/RobonoPreview.tsx'), content: preview.client });
104
+ const notes = [`Detected ${platform === 'web' ? 'Next.js website' : 'Expo phone app'} and ${auth} sign-in.`,
105
+ 'Start your Next.js development server and open /robono-preview for the two-person local example. It returns 404 in production.',
106
+ 'Connect your current messaging permission check in robono/server/robono-access.ts. Access stays blocked until then.',
107
+ 'Keep provider credentials and the Robono key on the server. The installer never reads or edits your .env files.',
108
+ 'Supply your existing sign-in client once to robonoAccounts, then mount ConnectedRobonoChat with your contacts.',
109
+ 'Connect website alerts or Apple/Google credentials in Robono → Your app → Message notifications. Chat works before alerts are configured.'];
110
+ const setup = { schema: 1, platform, auth, origin: options.origin, serverProject: relative(client.root, server.root) || '.', checks: { files: 'installed', permissions: 'needs-connection', serverKey: 'needs-server-environment', contacts: 'needs-connection', notifications: 'needs-configuration', liveConnection: 'not-tested' } };
111
+ files.push({ path: join(client.root, '.robono/setup.json'), content: JSON.stringify(setup, null, 2) + '\n' });
112
+ files.push({ path: join(client.root, '.robono/SETUP.md'), content: '# Connect your messenger\n\n' + notes.map(x => '- ' + x).join('\n') + '\n\n## Connect your screen\n' + (auth === 'custom' ? 'Implement RobonoAccounts from client/ConnectedRobonoChat.tsx using your existing sign-in.' : 'Create accounts once: useMemo(() => robonoAccounts(yourExistingSignInClient), [yourExistingSignInClient]).') + ' Then render <ConnectedRobonoChat accounts={accounts} contacts={yourContacts}/> inside an area with a height. Keep it mounted in your signed-in application. It follows account changes; names and avatars update without restarting chat. For Supabase use its client; for Firebase use its Auth instance.\n\n## Allow the right people\nConnect authorize in robono-access.ts to current account eligibility, suspension and conversation permissions. It denies access until implemented. When a friendship changes, call synchronizeFriendship(getMessenger(), friendship) on your server. Use revisions from your database; group membership uses getMessenger().robono.setGroup. Never use an always-allow function.\n\n## Sign-out\nThe messenger account menu clears local content and unregisters notifications before provider sign-out. If your own account menu signs out first, provider events still clear the visible chat. Keep account suspension and relationship revocation synchronized with Robono; an expired session cannot reliably unregister a remote device. Never substitute another account’s token.\n\n## One checklist\nRun robono-messenger-install --check. To include live checks, set ROBONO_MESSENGER_URL, ROBONO_WEBSITE_ORIGIN and ROBONO_TEST_USER_TOKEN locally. Add --json for a shareable report without secrets. No local checker can prove your complete permission rules; test denied accounts and cross-account access too.\n\n## Notifications\nFor website alerts configure your HTTPS origin and chat path. For iPhone, upload your APNs .p8 key, key ID, Team ID and Bundle ID in Robono. For Android, configure google-services.json in your app and upload the Firebase messaging service account privately in Robono. Never put private keys in client code. Build both apps after native dependency changes.\n\n## Local preview\nOpen /robono-preview on your Next.js development server. It uses the actual web messenger with fictional Alice and Bob and local text only. It sends no customer requests and returns 404 in production.\n' });
113
+ files.push({ path: join(server.root, '.robono/server.env.example'), content: templates['.env.example'] });
114
+ const serverPackages = ['@robono/server@^0.20.0', ...(platform === 'expo' ? ['@robono/messaging@^0.4.1', '@robono/messaging-web@^0.6.0'] : []), ...(auth === 'supabase' ? ['@supabase/supabase-js@^2'] : auth === 'firebase' ? ['firebase-admin@^14'] : [])];
115
+ const clientPackages = ['@robono/messaging@^0.4.1', `@robono/messaging-${platform === 'web' ? 'web' : 'react-native'}@^0.6.0`, ...(auth === 'supabase' ? ['@supabase/supabase-js@^2'] : auth === 'firebase' ? ['firebase@^13'] : [])];
116
+ const packageName = (spec) => spec.slice(0, spec.lastIndexOf('@'));
117
+ const keepExistingProvider = (spec, deps) => !['firebase', 'firebase-admin', '@supabase/supabase-js'].includes(packageName(spec)) || !deps[packageName(spec)];
118
+ const serverInstall = serverPackages.filter(spec => keepExistingProvider(spec, server.deps)), clientInstall = clientPackages.filter(spec => keepExistingProvider(spec, client.deps));
119
+ const commands = [];
120
+ if (platform === 'web')
121
+ commands.push(installCommand(client.root, await manager(client.root, client.pkg), [...new Set([...serverInstall, ...clientInstall])]));
122
+ else {
123
+ commands.push(installCommand(server.root, await manager(server.root, server.pkg), serverInstall));
124
+ const cm = await manager(client.root, client.pkg);
125
+ commands.push(installCommand(client.root, cm, clientInstall));
126
+ // Expo selects versions compatible with the customer's installed SDK, not arbitrary latest peers.
127
+ commands.push({ cwd: client.root, command: process.execPath, args: [join(client.root, 'node_modules/expo/bin/cli'), 'install', 'expo-audio', 'expo-image-picker', 'expo-document-picker', 'expo-file-system', 'expo-sharing', 'expo-video', 'expo-crypto', 'react-native-safe-area-context', 'react-native-svg', 'expo-clipboard', 'expo-image-manipulator', 'expo-video-thumbnails', 'react-native-webview', 'expo-blur', 'expo-notifications', 'expo-secure-store', '--' + cm] });
128
+ if (await exists(join(client.root, 'app.config.js')) || await exists(join(client.root, 'app.config.ts')))
129
+ throw Error('Your Expo configuration is code. Use robono-messenger-init and the mobile guide so your existing configuration is preserved.');
130
+ const configPath = join(client.root, 'app.json');
131
+ await safePath(configPath);
132
+ const before = await readFile(configPath, 'utf8'), config = JSON.parse(before);
133
+ if (!config.expo || typeof config.expo !== 'object' || Array.isArray(config.expo))
134
+ throw Error('Expected an expo configuration object in app.json.');
135
+ const plugins = config.expo?.plugins ?? [];
136
+ if (!Array.isArray(plugins))
137
+ throw Error('Expected an Expo plugins array in app.json.');
138
+ const names = plugins.map(p => Array.isArray(p) ? p[0] : p);
139
+ const required = [['expo-audio', { microphonePermission: 'Allow microphone access to record voice messages.', enableBackgroundRecording: false }], ['expo-image-picker', { cameraPermission: 'Allow camera access to take photos and videos for messages.' }], 'expo-notifications', '@robono/messaging-react-native'];
140
+ const added = required.filter(p => !names.includes(Array.isArray(p) ? p[0] : p));
141
+ if (added.length) {
142
+ config.expo.plugins = [...plugins, ...added];
143
+ replacements.push({ path: configPath, before, after: JSON.stringify(config, null, 2) + '\n' });
144
+ files.push({ path: join(client.root, '.robono/app.json.before-install'), content: before });
145
+ }
146
+ notes.push('Added missing Expo plugins; existing permission wording is preserved. Rebuild both iPhone and Android after native dependency changes.');
147
+ }
148
+ for (const file of files) {
149
+ await safePath(file.path);
150
+ if (await exists(file.path))
151
+ throw Error(`Already exists: ${file.path}. Nothing was changed. Use --check for an existing installation.`);
152
+ }
153
+ return { platform, auth, files, replacements, commands, notes };
154
+ }
155
+ /** Preflight all files; exclusive writes and rollback avoid overwriting customer work. */
156
+ export async function applyMessengerInstallation(plan, install = true) {
157
+ for (const file of plan.files) {
158
+ await safePath(file.path);
159
+ if (await exists(file.path))
160
+ throw Error(`Already exists: ${file.path}. Nothing was changed.`);
161
+ }
162
+ for (const file of plan.replacements) {
163
+ await safePath(file.path);
164
+ if (await readFile(file.path, 'utf8') !== file.before)
165
+ throw Error('Project configuration changed after planning. Run the installer again.');
166
+ }
167
+ const written = [], replaced = [];
168
+ try {
169
+ for (const file of plan.files) {
170
+ await mkdir(dirname(file.path), { recursive: true });
171
+ await writeFile(file.path, file.content, { flag: 'wx', mode: 0o600 });
172
+ written.push(file.path);
173
+ }
174
+ for (const file of plan.replacements) {
175
+ if (await readFile(file.path, 'utf8') !== file.before)
176
+ throw Error('Project configuration changed during installation. Existing configuration was preserved.');
177
+ await writeFile(file.path, file.after);
178
+ replaced.push(file);
179
+ }
180
+ }
181
+ catch (e) {
182
+ for (const file of replaced)
183
+ await writeFile(file.path, file.before);
184
+ for (const file of written)
185
+ await unlink(file);
186
+ throw e;
187
+ }
188
+ if (install)
189
+ for (const command of plan.commands)
190
+ await new Promise((resolve, reject) => {
191
+ const child = spawn(command.command, command.args, { cwd: command.cwd, stdio: 'inherit', shell: false, env: { ...process.env, npm_config_ignore_scripts: 'true', YARN_ENABLE_SCRIPTS: 'false' } });
192
+ child.on('error', () => reject(Error('Package installation could not start. Files are saved; run the printed install command to retry.')));
193
+ child.on('exit', code => code === 0 ? resolve() : reject(Error('Package installation did not finish. Files are saved; fix the package-manager error and retry the printed command.')));
194
+ });
195
+ }
196
+ export async function messengerInstallationChecklist(directory) {
197
+ const root = resolve(directory), file = join(root, '.robono/setup.json');
198
+ if (!await exists(file))
199
+ return [{ name: 'Install files', status: 'needs-action', detail: 'Run robono-messenger-install in your Next.js or Expo project.' }];
200
+ const setup = JSON.parse(await readFile(file, 'utf8'));
201
+ const server = resolve(root, setup.serverProject), base = await appRoot(server);
202
+ const permissionFile = join(server, base, 'robono/server/robono-access.ts');
203
+ const permission = await readFile(permissionFile, 'utf8').catch(() => 'Connect your existing messaging permission');
204
+ const missingPermission = permission.includes('Connect your existing messaging permission');
205
+ const clientBase = setup.platform === 'web' ? base : (await exists(join(root, 'src')) ? 'src' : '');
206
+ const complete = await exists(join(root, clientBase, 'robono/client/ConnectedRobonoChat.tsx')) && await exists(join(server, base, 'app/api/robono/route.ts'));
207
+ return [
208
+ { name: 'Prepared files', status: complete ? 'passed' : 'failed', detail: `${setup.platform === 'expo' ? 'Expo' : 'Next.js'}; ${setup.auth} sign-in.` },
209
+ { name: 'Account permissions', status: missingPermission ? 'needs-action' : 'configured', detail: missingPermission ? 'Connect robono-access.ts to your current permission rules. The live checker verifies a test account.' : 'Permission code was edited. Verify allowed and denied accounts; file inspection cannot prove your rules.' },
210
+ { name: 'Server key', status: 'needs-action', detail: 'Set ROBONO_API_KEY on the server. This command does not read or print secrets.' },
211
+ { name: 'Contacts', status: 'needs-action', detail: 'Synchronize permitted friendships and group membership; pass names/avatars to ConnectedRobonoChat.' },
212
+ { name: 'Notifications', status: 'needs-action', detail: setup.platform === 'expo' ? 'Add Apple/Google credentials in Robono and rebuild both apps with the installed Expo plugins.' : 'Connect your website origin and chat path in Robono.' },
213
+ { name: 'Live connection', status: 'needs-action', detail: 'Set ROBONO_MESSENGER_URL, ROBONO_WEBSITE_ORIGIN and ROBONO_TEST_USER_TOKEN locally, then run robono-messenger-check.' },
214
+ ];
215
+ }
216
+ //# sourceMappingURL=messenger-install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messenger-install.js","sourceRoot":"","sources":["../src/messenger-install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /** Development-only, in-memory demonstration using the actual shipped messenger. */
2
+ export declare function messengerPreviewTemplates(): {
3
+ page: string;
4
+ client: string;
5
+ };
6
+ //# sourceMappingURL=messenger-preview-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messenger-preview-template.d.ts","sourceRoot":"","sources":["../src/messenger-preview-template.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,wBAAgB,yBAAyB;;;EAqCrC"}