@somewhere-tech/cli 0.34.3 → 0.35.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.
@@ -1,230 +0,0 @@
1
- import { INIT_AGENTS_MD, INIT_CLAUDE_MD } from './init-agent-guide.js';
2
- // The default `somewhere init` starter: cookie sign-in through the SDK client
3
- // and the SDK's packaged /api/auth handler, plus one protected endpoint.
4
- // `--template minimal` keeps the no-auth starter (init-green-template.ts).
5
- const PACKAGE_JSON = `{
6
- "name": "somewhere-starter",
7
- "private": true,
8
- "version": "0.1.0",
9
- "type": "module",
10
- "scripts": {
11
- "dev": "somewhere dev",
12
- "typecheck": "somewhere typecheck"
13
- },
14
- "dependencies": {
15
- "@somewhere-tech/sdk": "0.9.0",
16
- "react": "19.2.7",
17
- "react-dom": "19.2.7"
18
- },
19
- "devDependencies": {
20
- "@types/react": "19.2.2",
21
- "@types/react-dom": "19.2.2",
22
- "typescript": "5.9.3",
23
- "vite": "7.2.2"
24
- }
25
- }
26
- `;
27
- const TSCONFIG = `{
28
- "compilerOptions": {
29
- "target": "ES2022",
30
- "lib": ["ES2022", "DOM", "DOM.Iterable"],
31
- "strict": true,
32
- "noEmit": true,
33
- "skipLibCheck": true,
34
- "module": "ESNext",
35
- "moduleResolution": "Bundler",
36
- "isolatedModules": true,
37
- "jsx": "react-jsx"
38
- },
39
- "include": ["src", "api", "db", "types"]
40
- }
41
- `;
42
- const APP_TYPES = `export interface GreetingResponse {
43
- message: string;
44
- }
45
- `;
46
- const SCHEMA = `import { id, schema, serverOnly, table, text } from 'somewhere/db';
47
-
48
- export default schema({
49
- greetings: table({
50
- id: id(),
51
- message: text({ default: 'You are signed in.' }),
52
- }, {
53
- scope: serverOnly(),
54
- }),
55
- });
56
- `;
57
- const AUTH_API = `export { somewhereAuth as default } from '@somewhere-tech/sdk/server';
58
- `;
59
- const GREETING_API = `export default sw.endpoint({
60
- auth: 'required',
61
- rateLimit: '30/minute',
62
- handler: async ({ user }, sw) => {
63
- const result = await sw.db.from('greetings', { limit: 1 });
64
- const message = result.data[0]?.message;
65
- return { message: \`\${typeof message === 'string' ? message : 'You are signed in.'} (\${user.email ?? user.id})\` };
66
- },
67
- });
68
- `;
69
- const AUTH_SERVICE = `import { createSomewhereAuth, type User } from '@somewhere-tech/sdk/auth';
70
-
71
- // Talks to api/auth/[...path].ts. The session is an httpOnly cookie; this
72
- // code never sees a token.
73
- export const auth = createSomewhereAuth();
74
- export type { User };
75
- `;
76
- const GREETING_SERVICE = `import type { GreetingResponse } from '../../types/app';
77
-
78
- export async function loadGreeting(): Promise<GreetingResponse> {
79
- const response = await fetch('/api/greeting', { credentials: 'include' });
80
- const body = (await response.json().catch(() => ({}))) as Partial<GreetingResponse> & { message?: string };
81
- if (!response.ok) throw new Error(body.message ?? \`Request failed (\${response.status})\`);
82
- return { message: body.message ?? '' };
83
- }
84
- `;
85
- const APP = `import { useEffect, useState, type FormEvent } from 'react';
86
- import { auth, type User } from './services/auth';
87
- import { loadGreeting } from './services/greeting';
88
-
89
- export function App() {
90
- const [user, setUser] = useState<User | null>(auth.getCachedUser());
91
- const [checking, setChecking] = useState(true);
92
- const [mode, setMode] = useState<'signIn' | 'signUp'>('signIn');
93
- const [email, setEmail] = useState('');
94
- const [password, setPassword] = useState('');
95
- const [error, setError] = useState('');
96
- const [message, setMessage] = useState('');
97
-
98
- useEffect(() => {
99
- void auth.getUser().then(setUser).finally(() => setChecking(false));
100
- }, []);
101
-
102
- useEffect(() => {
103
- if (!user) return;
104
- void loadGreeting()
105
- .then((result) => setMessage(result.message))
106
- .catch((reason: unknown) => setMessage(reason instanceof Error ? reason.message : 'Could not load the greeting.'));
107
- }, [user]);
108
-
109
- async function submit(event: FormEvent<HTMLFormElement>) {
110
- event.preventDefault();
111
- setError('');
112
- try {
113
- const next = mode === 'signIn'
114
- ? await auth.signIn({ email, password })
115
- : await auth.signUp({ email, password });
116
- setUser(next);
117
- } catch (reason: unknown) {
118
- setError(reason instanceof Error ? reason.message : 'Sign-in failed.');
119
- }
120
- }
121
-
122
- async function signOut() {
123
- await auth.signOut();
124
- setUser(null);
125
- setMessage('');
126
- setMode('signIn');
127
- }
128
-
129
- if (checking && !user) return <main><p className="hint">Loading…</p></main>;
130
-
131
- if (user) {
132
- return (
133
- <main>
134
- <p className="eyebrow">somewhere.tech starter</p>
135
- <h1>You are signed in.</h1>
136
- <p className="message">{message || 'Loading your greeting…'}</p>
137
- <button type="button" onClick={() => void signOut()}>Sign out</button>
138
- </main>
139
- );
140
- }
141
-
142
- return (
143
- <main>
144
- <p className="eyebrow">somewhere.tech starter</p>
145
- <h1>{mode === 'signIn' ? 'Sign in' : 'Create an account'}</h1>
146
- <form onSubmit={(event) => void submit(event)}>
147
- <label>Email<input type="email" name="email" autoComplete="email" required value={email} onChange={(event) => setEmail(event.target.value)} /></label>
148
- <label>Password<input type="password" name="password" autoComplete={mode === 'signIn' ? 'current-password' : 'new-password'} required minLength={8} value={password} onChange={(event) => setPassword(event.target.value)} /></label>
149
- {error ? <p className="error" role="alert">{error}</p> : null}
150
- <button type="submit">{mode === 'signIn' ? 'Sign in' : 'Create account'}</button>
151
- </form>
152
- <button type="button" className="link" onClick={() => { setMode(mode === 'signIn' ? 'signUp' : 'signIn'); setError(''); }}>
153
- {mode === 'signIn' ? 'New here? Create an account' : 'Have an account? Sign in'}
154
- </button>
155
- </main>
156
- );
157
- }
158
- `;
159
- const MAIN = `import { StrictMode } from 'react';
160
- import { createRoot } from 'react-dom/client';
161
- import { App } from './App';
162
- import './styles.css';
163
-
164
- createRoot(document.getElementById('root')!).render(
165
- <StrictMode>
166
- <App />
167
- </StrictMode>,
168
- );
169
- `;
170
- const STYLES = `:root {
171
- font-family: Inter, ui-sans-serif, system-ui, sans-serif;
172
- color: #17201c;
173
- background: #edf4ef;
174
- }
175
-
176
- * { box-sizing: border-box; }
177
- body { margin: 0; min-width: 320px; }
178
- main { width: min(480px, calc(100% - 32px)); margin: 12vh auto; }
179
- h1 { margin: 12px 0 24px; font-size: clamp(2.2rem, 7vw, 3.6rem); line-height: 1; letter-spacing: -.04em; }
180
- .eyebrow { color: #14734c; font-weight: 750; text-transform: uppercase; letter-spacing: .12em; }
181
- form { display: grid; gap: 14px; }
182
- label { display: grid; gap: 6px; font-weight: 600; }
183
- input { padding: 12px 14px; border: 1px solid #c6d8ce; border-radius: 10px; font: inherit; }
184
- button { padding: 12px 16px; border: 0; border-radius: 10px; background: #14734c; color: #fff; font: inherit; font-weight: 650; cursor: pointer; }
185
- button.link { margin-top: 12px; padding: 0; background: none; color: #0e6542; }
186
- .message { padding: 20px 22px; border: 1px solid #c6d8ce; border-radius: 16px; background: rgba(255, 255, 255, .82); }
187
- .error { margin: 0; color: #a3261b; }
188
- .hint { color: #4f665b; }
189
- `;
190
- const README = `# somewhere.tech starter
191
-
192
- This project starts signed in: a React page signs users up and in with the
193
- SDK client (\`src/services/auth.ts\`), \`api/auth/[...path].ts\` is the SDK's
194
- packaged auth handler, and \`api/greeting.ts\` is a protected endpoint
195
- (\`sw.endpoint({ auth: 'required' })\`). The session is an httpOnly cookie.
196
-
197
- \`\`\`sh
198
- somewhere typecheck
199
- somewhere deploy
200
- somewhere verify
201
- \`\`\`
202
-
203
- Deploy the raw source. The platform compiles it; do not create or deploy a
204
- \`dist/\` or \`build/\` directory. For a starter without sign-in, run
205
- \`somewhere init --template minimal\` in an empty directory.
206
- `;
207
- export function createAuthTemplate() {
208
- return [
209
- { path: '.gitignore', content: 'node_modules\ndist\nbuild\n.env\n' },
210
- { path: 'AGENTS.md', content: INIT_AGENTS_MD },
211
- { path: 'CLAUDE.md', content: INIT_CLAUDE_MD },
212
- { path: 'README.md', content: README },
213
- { path: 'package.json', content: PACKAGE_JSON },
214
- { path: 'tsconfig.json', content: TSCONFIG },
215
- {
216
- path: 'index.html',
217
- content: '<!doctype html>\n<html lang="en">\n <head>\n <meta charset="UTF-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1.0" />\n <title>somewhere.tech starter</title>\n </head>\n <body>\n <div id="root"></div>\n <script type="module" src="/src/main.tsx"></script>\n </body>\n</html>\n',
218
- },
219
- { path: 'src/App.tsx', content: APP },
220
- { path: 'src/main.tsx', content: MAIN },
221
- { path: 'src/services/auth.ts', content: AUTH_SERVICE },
222
- { path: 'src/services/greeting.ts', content: GREETING_SERVICE },
223
- { path: 'src/styles.css', content: STYLES },
224
- { path: 'api/auth/[...path].ts', content: AUTH_API },
225
- { path: 'api/greeting.ts', content: GREETING_API },
226
- { path: 'db/schema.ts', content: SCHEMA },
227
- { path: 'types/app.ts', content: APP_TYPES },
228
- ];
229
- }
230
- //# sourceMappingURL=init-auth-template.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"init-auth-template.js","sourceRoot":"","sources":["../../src/lib/init-auth-template.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvE,8EAA8E;AAC9E,yEAAyE;AACzE,2EAA2E;AAE3E,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;CAqBpB,CAAC;AAEF,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;CAchB,CAAC;AAEF,MAAM,SAAS,GAAG;;;CAGjB,CAAC;AAEF,MAAM,MAAM,GAAG;;;;;;;;;;CAUd,CAAC;AAEF,MAAM,QAAQ,GAAG;CAChB,CAAC;AAEF,MAAM,YAAY,GAAG;;;;;;;;;CASpB,CAAC;AAEF,MAAM,YAAY,GAAG;;;;;;CAMpB,CAAC;AAEF,MAAM,gBAAgB,GAAG;;;;;;;;CAQxB,CAAC;AAEF,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyEX,CAAC;AAEF,MAAM,IAAI,GAAG;;;;;;;;;;CAUZ,CAAC;AAEF,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;CAmBd,CAAC;AAEF,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;CAgBd,CAAC;AAEF,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,mCAAmC,EAAE;QACpE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,EAAE;QAC9C,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,EAAE;QAC9C,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE;QACtC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,EAAE;QAC/C,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,QAAQ,EAAE;QAC5C;YACE,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,mUAAmU;SAC7U;QACD,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,EAAE;QACrC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE;QACvC,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,YAAY,EAAE;QACvD,EAAE,IAAI,EAAE,0BAA0B,EAAE,OAAO,EAAE,gBAAgB,EAAE;QAC/D,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,EAAE;QAC3C,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,QAAQ,EAAE;QACpD,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,YAAY,EAAE;QAClD,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE;QACzC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE;KAC7C,CAAC;AACJ,CAAC"}