create-glanceway-source 1.1.0 → 1.3.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.
- package/README.md +4 -4
- package/dist/index.js +55 -12
- package/package.json +6 -1
- package/templates/scripts/build.ts +8 -8
- package/templates/scripts/test.ts +1 -1
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ Example prompts:
|
|
|
53
53
|
cd my-source
|
|
54
54
|
npm install
|
|
55
55
|
|
|
56
|
-
# Build: compiles
|
|
56
|
+
# Build: compiles source, creates dist/latest.gwsrc
|
|
57
57
|
npm run build
|
|
58
58
|
|
|
59
59
|
# Test: executes source with mock API, validates emitted items
|
|
@@ -63,15 +63,15 @@ npm run test
|
|
|
63
63
|
npm run test -- --config API_TOKEN=xxx --config USERNAME=yyy
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
The `dist/latest.
|
|
66
|
+
The `dist/latest.gwsrc` file is the importable source package.
|
|
67
67
|
|
|
68
68
|
## Importing into Glanceway
|
|
69
69
|
|
|
70
70
|
1. Open **Glanceway**
|
|
71
71
|
2. Go to **Sources**
|
|
72
72
|
3. Click **Import from file**
|
|
73
|
-
4. Select `dist/latest.
|
|
73
|
+
4. Select `dist/latest.gwsrc`
|
|
74
74
|
|
|
75
75
|
## Submitting to glanceway-sources
|
|
76
76
|
|
|
77
|
-
To share your source with the community, [open an issue](https://github.com/
|
|
77
|
+
To share your source with the community, [open an issue](https://github.com/glanceway/glanceway-sources/issues) on glanceway-sources with a link to your project repository.
|
package/dist/index.js
CHANGED
|
@@ -100,7 +100,7 @@ tags: []
|
|
|
100
100
|
# config:
|
|
101
101
|
# - key: API_TOKEN
|
|
102
102
|
# name: API Token
|
|
103
|
-
# type: secret # string, number, boolean, secret, select, or
|
|
103
|
+
# type: secret # string, number, boolean, secret, select, list, or multiselect
|
|
104
104
|
# required: true
|
|
105
105
|
# description: Your API token
|
|
106
106
|
# - key: SORT
|
|
@@ -111,7 +111,17 @@ tags: []
|
|
|
111
111
|
# options:
|
|
112
112
|
# - hot
|
|
113
113
|
# - new
|
|
114
|
-
# -
|
|
114
|
+
# - label: Top (All Time) # options support label/value format
|
|
115
|
+
# value: top
|
|
116
|
+
# - key: CATEGORIES
|
|
117
|
+
# name: Categories
|
|
118
|
+
# type: multiselect # like select but allows multiple choices
|
|
119
|
+
# options:
|
|
120
|
+
# - label: Technology
|
|
121
|
+
# value: tech
|
|
122
|
+
# - label: Science
|
|
123
|
+
# value: science
|
|
124
|
+
# - sports
|
|
115
125
|
`;
|
|
116
126
|
return manifest;
|
|
117
127
|
}
|
|
@@ -168,13 +178,13 @@ function generateClaudeMd(options) {
|
|
|
168
178
|
|
|
169
179
|
## Project Overview
|
|
170
180
|
|
|
171
|
-
Glanceway source: "${options.name}" by ${options.author}. This is a standalone
|
|
181
|
+
Glanceway source: "${options.name}" by ${options.author}. This is a standalone JavaScript source for [Glanceway](https://glanceway.app), a macOS menu bar app that displays information items.
|
|
172
182
|
|
|
173
183
|
## Commands
|
|
174
184
|
|
|
175
185
|
\`\`\`bash
|
|
176
186
|
npm install # Install dependencies
|
|
177
|
-
npm run build # Build source into dist/ (compile +
|
|
187
|
+
npm run build # Build source into dist/ (compile + package)
|
|
178
188
|
npm run test # Test source (mock API execution + validation)
|
|
179
189
|
\`\`\`
|
|
180
190
|
|
|
@@ -190,7 +200,7 @@ There is no test framework. Build the source to verify it compiles. There is no
|
|
|
190
200
|
- \`src/index.ts\` — Source implementation (main logic)
|
|
191
201
|
- \`src/types.ts\` — GlancewayAPI type definitions (do not modify)
|
|
192
202
|
- \`manifest.yaml\` — Source metadata and config schema
|
|
193
|
-
- \`scripts/build.ts\` — Build script (esbuild compile +
|
|
203
|
+
- \`scripts/build.ts\` — Build script (esbuild compile + package)
|
|
194
204
|
- \`scripts/test.ts\` — Test script (mock API + validation)
|
|
195
205
|
|
|
196
206
|
## Source Development Constraints
|
|
@@ -275,7 +285,7 @@ if (response.ok && response.json) {
|
|
|
275
285
|
|
|
276
286
|
### api.config.get(key: string): unknown
|
|
277
287
|
|
|
278
|
-
Get a user-configured value by key (defined in \`manifest.yaml\` config section). Returns \`string\` for most types, \`string[]\` for \`list\`
|
|
288
|
+
Get a user-configured value by key (defined in \`manifest.yaml\` config section). Returns \`string\` for most types, \`string[]\` for \`list\` and \`multiselect\` types.
|
|
279
289
|
|
|
280
290
|
### api.config.getAll(): Record<string, unknown>
|
|
281
291
|
|
|
@@ -330,7 +340,7 @@ min_app_version: 1.2.0 # Optional: minimum Glanceway app version required
|
|
|
330
340
|
config: # Optional: user-configurable values
|
|
331
341
|
- key: API_TOKEN
|
|
332
342
|
name: API Token
|
|
333
|
-
type: secret # string, number, boolean, secret, select, or
|
|
343
|
+
type: secret # string, number, boolean, secret, select, list, or multiselect
|
|
334
344
|
required: true
|
|
335
345
|
description: Description shown to user
|
|
336
346
|
- key: TAGS
|
|
@@ -346,12 +356,43 @@ config: # Optional: user-configurable values
|
|
|
346
356
|
options:
|
|
347
357
|
- hot
|
|
348
358
|
- new
|
|
349
|
-
-
|
|
359
|
+
- label: Top (All Time) # options support label/value format
|
|
360
|
+
value: top
|
|
361
|
+
- key: CATEGORIES
|
|
362
|
+
name: Categories
|
|
363
|
+
type: multiselect # like select but allows multiple choices (value type: string[])
|
|
364
|
+
options:
|
|
365
|
+
- label: Technology
|
|
366
|
+
value: tech
|
|
367
|
+
- label: Science
|
|
368
|
+
value: science
|
|
369
|
+
- sports
|
|
370
|
+
\`\`\`
|
|
371
|
+
|
|
372
|
+
\`select\` and \`multiselect\` options can be plain strings or label/value objects:
|
|
373
|
+
|
|
374
|
+
\`\`\`yaml
|
|
375
|
+
options:
|
|
376
|
+
- plain_value # value = "plain_value", displayed as "plain_value"
|
|
377
|
+
- label: Display Name # value = "actual_value", displayed as "Display Name"
|
|
378
|
+
value: actual_value
|
|
350
379
|
\`\`\`
|
|
351
380
|
|
|
381
|
+
### Config Field Types
|
|
382
|
+
|
|
383
|
+
| Type | Description | Value type |
|
|
384
|
+
|---------------|------------------------------------------------------|-------------|
|
|
385
|
+
| \`string\` | Free-form text input | \`string\` |
|
|
386
|
+
| \`number\` | Numeric input | \`number\` |
|
|
387
|
+
| \`boolean\` | Toggle switch | \`boolean\` |
|
|
388
|
+
| \`secret\` | Stored in macOS Keychain | \`string\` |
|
|
389
|
+
| \`select\` | Dropdown (requires \`options\` list) | \`string\` |
|
|
390
|
+
| \`list\` | Multiple string values | \`string[]\` |
|
|
391
|
+
| \`multiselect\` | Multiple choice from options (like select but multi) | \`string[]\` |
|
|
392
|
+
|
|
352
393
|
## Source Lifecycle
|
|
353
394
|
|
|
354
|
-
|
|
395
|
+
JavaScript sources have two distinct phases:
|
|
355
396
|
|
|
356
397
|
1. **Start phase**: When the source is first loaded, the default export function (outer closure) runs. The app does **NOT** call \`refresh()\` at this point. Sources should perform their initial data fetch here by \`await\`ing their fetch function before returning.
|
|
357
398
|
2. **Refresh phase**: On each scheduled refresh interval, the app calls \`refresh()\`. This is the only time \`refresh()\` is invoked.
|
|
@@ -386,7 +427,7 @@ export default async (api: GlancewayAPI<Config>): Promise<SourceMethods> => {
|
|
|
386
427
|
- Always make full use of the \`subtitle\` field. If the API response contains summary, description, brief, or any descriptive text, map it to \`subtitle\` so users get maximum information at a glance.
|
|
387
428
|
- **Maximize items per fetch.** The app does not paginate, so each fetch should retrieve as many items as the API allows without hurting performance. The hard upper limit is **500 items** — never exceed this.
|
|
388
429
|
|
|
389
|
-
##
|
|
430
|
+
## Source Code Conventions
|
|
390
431
|
|
|
391
432
|
### File Structure Order
|
|
392
433
|
|
|
@@ -398,6 +439,8 @@ import type { GlancewayAPI, SourceMethods } from "./types";
|
|
|
398
439
|
type Config = {
|
|
399
440
|
API_TOKEN: string;
|
|
400
441
|
TAGS: string[];
|
|
442
|
+
SORT: string; // select → string
|
|
443
|
+
CATEGORIES: string[]; // multiselect → string[]
|
|
401
444
|
};
|
|
402
445
|
|
|
403
446
|
// 3. Helper functions (pure utilities, no api dependency)
|
|
@@ -454,11 +497,11 @@ After building (\`npm run build\`), import into Glanceway:
|
|
|
454
497
|
1. Open Glanceway
|
|
455
498
|
2. Go to Sources
|
|
456
499
|
3. Click "Import from file"
|
|
457
|
-
4. Select \`dist/latest.
|
|
500
|
+
4. Select \`dist/latest.gwsrc\`
|
|
458
501
|
|
|
459
502
|
## Submitting to glanceway-sources
|
|
460
503
|
|
|
461
|
-
To share your source with the community, [open an issue](https://github.com/
|
|
504
|
+
To share your source with the community, [open an issue](https://github.com/glanceway/glanceway-sources/issues) on glanceway-sources with a link to your project repository.
|
|
462
505
|
`;
|
|
463
506
|
}
|
|
464
507
|
// ─── File Operations ───────────────────────────────────────────────────────
|
package/package.json
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-glanceway-source",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Scaffold a standalone Glanceway source project",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"homepage": "https://github.com/glanceway/create-glanceway-source",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/glanceway/create-glanceway-source.git"
|
|
10
|
+
},
|
|
6
11
|
"bin": {
|
|
7
12
|
"create-glanceway-source": "dist/index.js"
|
|
8
13
|
},
|
|
@@ -81,18 +81,18 @@ async function main() {
|
|
|
81
81
|
fs.copyFileSync(manifestPath, distManifestPath);
|
|
82
82
|
console.log(" Created dist/manifest.yaml");
|
|
83
83
|
|
|
84
|
-
// Create versioned
|
|
85
|
-
const
|
|
86
|
-
await createZip(
|
|
84
|
+
// Create versioned .gwsrc package
|
|
85
|
+
const versionedPath = path.join(DIST_DIR, `${version}.gwsrc`);
|
|
86
|
+
await createZip(versionedPath, [
|
|
87
87
|
{ name: "manifest.yaml", content: manifestContent },
|
|
88
88
|
{ name: "index.js", content: compiledJs },
|
|
89
89
|
]);
|
|
90
|
-
console.log(` Created dist/${version}.
|
|
90
|
+
console.log(` Created dist/${version}.gwsrc`);
|
|
91
91
|
|
|
92
|
-
// Create latest.
|
|
93
|
-
const
|
|
94
|
-
fs.copyFileSync(
|
|
95
|
-
console.log(" Created dist/latest.
|
|
92
|
+
// Create latest.gwsrc
|
|
93
|
+
const latestPath = path.join(DIST_DIR, "latest.gwsrc");
|
|
94
|
+
fs.copyFileSync(versionedPath, latestPath);
|
|
95
|
+
console.log(" Created dist/latest.gwsrc");
|
|
96
96
|
|
|
97
97
|
console.log("\nBuild complete!");
|
|
98
98
|
}
|
|
@@ -72,7 +72,7 @@ function resolveConfig(
|
|
|
72
72
|
const override = overrides[entry.key];
|
|
73
73
|
|
|
74
74
|
if (override !== undefined) {
|
|
75
|
-
if (entry.type === "list") {
|
|
75
|
+
if (entry.type === "list" || entry.type === "multiselect") {
|
|
76
76
|
resolved[entry.key] = override.split(",").map((s) => s.trim());
|
|
77
77
|
} else if (entry.type === "boolean") {
|
|
78
78
|
resolved[entry.key] = override === "true" || override === "1";
|