+5
CHANGELOG.md
+5
CHANGELOG.md
+1
-30
DOCS.md
+1
-30
DOCS.md
···
258
258
259
259
The `@external` decorator tells the emitter to skip JSON output for that namespace. This is useful when referencing definitions from other Lexicons that you don't want to re-emit.
260
260
261
-
You could collect external stubs in one file and import them:
262
-
263
-
```typescript
264
-
import "@typelex/emitter";
265
-
import "../atproto-stubs.tsp";
266
-
267
-
namespace app.bsky.actor.profile {
268
-
model Main {
269
-
labels?: (com.atproto.label.defs.SelfLabels | unknown);
270
-
}
271
-
}
272
-
```
273
-
274
-
Then in `atproto-stubs.tsp`:
275
-
276
-
```typescript
277
-
import "@typelex/emitter";
278
-
279
-
@external
280
-
namespace com.atproto.label.defs {
281
-
model SelfLabels { }
282
-
}
283
-
284
-
@external
285
-
namespace com.atproto.repo.defs {
286
-
model StrongRef { }
287
-
@token model SomeToken { } // Note: Tokens still need @token
288
-
}
289
-
// ... more stubs
290
-
```
261
+
Starting with 0.3.0, typelex will automatically generate a `typelex/externals.tsp` file based on the JSON files in your `lexicons/` folder, and enforce that it's imported into your `typelex/main.tsp` entry point. However, this will *not* include Lexicons from your app's namespace, but only external ones.
291
262
292
263
You'll want to ensure the real JSON for external Lexicons is available before running codegen.
293
264
+2
-2
packages/cli/package.json
+2
-2
packages/cli/package.json
···
1
1
{
2
2
"name": "@typelex/cli",
3
-
"version": "0.2.15",
3
+
"version": "0.3.0",
4
4
"main": "dist/index.js",
5
5
"type": "module",
6
6
"bin": {
···
40
40
"@typelex/emitter": "workspace:*"
41
41
},
42
42
"peerDependencies": {
43
-
"@typelex/emitter": "^0.2.0"
43
+
"@typelex/emitter": "^0.3.0"
44
44
}
45
45
}
+6
-5
packages/cli/src/commands/init.ts
+6
-5
packages/cli/src/commands/init.ts
···
58
58
59
59
return new Promise((resolve) => {
60
60
rl.question(
61
-
`Enter your app's root namespace (e.g. ${pc.cyan("com.example.*")}): `,
61
+
`Which Lexicons do you want to write in typelex (e.g. ${pc.cyan("com.example.*")})? `,
62
62
(answer) => {
63
63
rl.close();
64
64
resolve(answer.trim());
···
90
90
return initSetup();
91
91
}
92
92
93
-
console.log(`Adding ${gradientText("typelex")}...\n`);
93
+
console.log(gradientText("Adding typelex...") + "\n");
94
94
95
95
// Detect package manager
96
96
let packageManager = "npm";
···
240
240
241
241
// Inform about external lexicons
242
242
console.log(
243
-
`\nLexicons other than ${pc.cyan(namespace)} will be considered external.`,
243
+
`\nLexicons for ${pc.cyan(namespace)} will now be managed by typelex.`,
244
244
);
245
+
console.log(`You can begin writing them in ${pc.cyan("typelex/main.tsp")}.`);
245
246
console.log(
246
-
`Put them into the ${pc.cyan(displayLexiconsPath)} folder as JSON.\n`,
247
+
`Any external lexicons should remain in ${pc.cyan(displayLexiconsPath)}.\n`,
247
248
);
248
249
249
250
// Create typelex directory
···
321
322
console.log(`\n${pc.green("✓")} ${pc.bold("All set!")}`);
322
323
console.log(`\n${pc.bold("Next steps:")}`);
323
324
console.log(
324
-
` ${pc.dim("1.")} Edit ${pc.cyan("typelex/main.tsp")} to define your lexicons`,
325
+
` ${pc.dim("1.")} Edit ${pc.cyan("typelex/main.tsp")} to define the ${pc.cyan(namespace)} lexicons`,
325
326
);
326
327
console.log(
327
328
` ${pc.dim("2.")} Keep putting external lexicons into ${pc.cyan(displayLexiconsPath)}`,
+1
-1
packages/emitter/package.json
+1
-1
packages/emitter/package.json
+17
packages/website/src/layouts/BaseLayout.astro
+17
packages/website/src/layouts/BaseLayout.astro
···
50
50
51
51
<slot />
52
52
53
+
<script>
54
+
// Smooth scroll to top when clicking logo
55
+
document.addEventListener('DOMContentLoaded', () => {
56
+
const logo = document.querySelector('.logo');
57
+
if (logo) {
58
+
logo.addEventListener('click', (e) => {
59
+
// Allow Ctrl/Cmd+click to open in new tab
60
+
if (e.ctrlKey || e.metaKey || e.shiftKey) {
61
+
return;
62
+
}
63
+
e.preventDefault();
64
+
window.scrollTo({ top: 0, behavior: 'smooth' });
65
+
});
66
+
}
67
+
});
68
+
</script>
69
+
53
70
{transparentNav && (
54
71
<script>
55
72
const nav = document.querySelector('.top-nav');
+4
-33
packages/website/src/pages/index.astro
+4
-33
packages/website/src/pages/index.astro
···
179
179
<div class="step-content">
180
180
<h3>Add typelex to your app</h3>
181
181
<figure class="install-box" set:html={await highlightCode('npx @typelex/cli init', 'bash')} />
182
-
<p class="step-description">This will add a few things to your <code>package.json</code>, and create a <code>typelex/</code> folder.</p>
182
+
<p class="step-description">This will add a few things to your <code>package.json</code> and create a <code>typelex/</code> folder.</p>
183
183
</div>
184
184
</div>
185
185
···
187
187
<div class="step-number">2</div>
188
188
<div class="step-content">
189
189
<h3>Write your lexicons in <code>typelex/main.tsp</code></h3>
190
-
<figure class="install-box install-box-with-link">
191
-
<a href={createPlaygroundUrl(`import "@typelex/emitter";
192
-
import "./externals.tsp";
193
-
194
-
namespace com.myapp.example.profile {
195
-
/** My profile. */
196
-
@rec("literal:self")
197
-
model Main {
198
-
/** Free-form profile description.*/
199
-
@maxGraphemes(256)
200
-
description?: string;
201
-
}
202
-
}`)} target="_blank" rel="noopener noreferrer" class="install-playground-link" aria-label="Open in playground">
203
-
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
204
-
<path d="M6.5 3.5C6.5 3.22386 6.72386 3 7 3H13C13.2761 3 13.5 3.22386 13.5 3.5V9.5C13.5 9.77614 13.2761 10 13 10C12.7239 10 12.5 9.77614 12.5 9.5V4.70711L6.85355 10.3536C6.65829 10.5488 6.34171 10.5488 6.14645 10.3536C5.95118 10.1583 5.95118 9.84171 6.14645 9.64645L11.7929 4H7C6.72386 4 6.5 3.77614 6.5 3.5Z" fill="currentColor"/>
205
-
<path d="M3 5.5C3 4.67157 3.67157 4 4.5 4H5C5.27614 4 5.5 4.22386 5.5 4.5C5.5 4.77614 5.27614 5 5 5H4.5C4.22386 5 4 5.22386 4 5.5V11.5C4 11.7761 4.22386 12 4.5 12H10.5C10.7761 12 11 11.7761 11 11.5V11C11 10.7239 11.2239 10.5 11.5 10.5C11.7761 10.5 12 10.7239 12 11V11.5C12 12.3284 11.3284 13 10.5 13H4.5C3.67157 13 3 12.3284 3 11.5V5.5Z" fill="currentColor"/>
206
-
</svg>
207
-
</a>
208
-
<div set:html={await highlightCode(`import "@typelex/emitter";
209
-
import "./externals.tsp";
210
-
211
-
namespace com.myapp.example.profile {
212
-
/** My profile. */
213
-
@rec("literal:self")
214
-
model Main {
215
-
/** Free-form profile description.*/
216
-
@maxGraphemes(256)
217
-
description?: string;
218
-
}
219
-
}`, 'typespec')} />
220
-
</figure>
190
+
<figure class="install-box" set:html={await highlightCode(installCode, 'typespec')} />
191
+
<p class="step-description">Your app's lexicons go here. They may reference any external ones from <code>lexicons/</code>.</p>
221
192
</div>
222
-
<p class="step-description">Your app's lexicons go here. They may reference any external ones from <code>lexicons/</code>.
223
193
</div>
224
194
225
195
<div class="install-step">
···
622
592
.install-section {
623
593
margin: 0;
624
594
padding: 0;
595
+
scroll-margin-top: 5rem;
625
596
}
626
597
627
598
.install-section h2 {