starlight-cli 1.0.44 → 1.0.45
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 +222 -38
- package/dist/index.js +26 -4
- package/package.json +1 -1
- package/src/evaluator.js +26 -4
package/README.md
CHANGED
|
@@ -1,71 +1,255 @@
|
|
|
1
|
-
# Starlight Language
|
|
1
|
+
# Starlight Language
|
|
2
2
|
|
|
3
|
-
Starlight is a lightweight, developer-oriented programming language designed for server-side scripting, automation, and general-purpose programming
|
|
3
|
+
Starlight is a lightweight, developer-oriented programming language designed for **server-side scripting, automation, and general-purpose programming**. It combines a clean, readable syntax inspired by JavaScript and Python with powerful runtime features such as async/await, modules, and interactive I/O.
|
|
4
4
|
|
|
5
5
|
**Official Reference:** [https://starlight-learn-lang.pages.dev/](https://starlight-learn-lang.pages.dev/)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
---
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- Async/Await Support: Handle asynchronous operations cleanly.
|
|
11
|
-
- Modules & Imports: Use `import` to bring in libraries or other `.sl` files.
|
|
12
|
-
- Server-side Ready: Ideal for scripting, automation, and backend logic.
|
|
13
|
-
- Interactive Input: Built-in `ask` and `sldeploy` commands for user interaction.
|
|
14
|
-
- Built-in Utilities: `sleep(ms)`, `len()`, `keys()`, `values()`, `fetch()`, `get()`, `post()`.
|
|
9
|
+
## Key Features
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
* **Modern, Simple Syntax** – Familiar to JavaScript and Python developers
|
|
12
|
+
* **Async / Await** – Native support for asynchronous operations
|
|
13
|
+
* **Modules & Imports** – Import JavaScript packages or other `.sl` files
|
|
14
|
+
* **Server-side Ready** – Built on Node.js, ideal for backend logic
|
|
15
|
+
* **Interactive I/O** – Built-in `ask` and `sldeploy`
|
|
16
|
+
* **Built-in Utilities** – `sleep`, `len`, `keys`, `values`, `fetch`, `get`, `post`
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
2. Install via NPM:
|
|
18
|
+
---
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
npm install starlight-cli
|
|
23
|
-
\`\`\`
|
|
20
|
+
## Installation
|
|
24
21
|
|
|
25
|
-
|
|
22
|
+
1. Install **Node.js** (v18+ recommended)
|
|
23
|
+
2. Install Starlight CLI:
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
```
|
|
26
|
+
npm install -g starlight-cli
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Your First Program (`hello.sl`)
|
|
32
|
+
|
|
33
|
+
```
|
|
28
34
|
let name = ask("What is your name?")
|
|
29
|
-
sldeploy
|
|
30
|
-
|
|
35
|
+
sldeploy "Hello, " + name + "!"
|
|
36
|
+
```
|
|
31
37
|
|
|
32
38
|
Run:
|
|
33
39
|
|
|
34
|
-
|
|
40
|
+
```
|
|
35
41
|
starlight hello.sl
|
|
36
|
-
|
|
42
|
+
```
|
|
37
43
|
|
|
38
|
-
|
|
44
|
+
---
|
|
39
45
|
|
|
40
|
-
|
|
46
|
+
## Output
|
|
47
|
+
|
|
48
|
+
```
|
|
41
49
|
What is your name? Alice
|
|
42
50
|
Hello, Alice!
|
|
43
|
-
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Core Language Concepts
|
|
56
|
+
|
|
57
|
+
### Variables
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
let x = 10
|
|
61
|
+
let text = "hello"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
### Functions
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
func add(a, b) {
|
|
70
|
+
return a + b
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
sldeploy add(2, 3)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Async Functions
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
async func load() {
|
|
80
|
+
let data = await get("https://example.com/api")
|
|
81
|
+
sldeploy data
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
load()
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Conditionals
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
if (x > 5) {
|
|
93
|
+
sldeploy "Greater than 5"
|
|
94
|
+
} else {
|
|
95
|
+
sldeploy "5 or less"
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Loops
|
|
102
|
+
|
|
103
|
+
### While Loop
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
let i = 0
|
|
107
|
+
while (i < 3) {
|
|
108
|
+
sldeploy i
|
|
109
|
+
i = i + 1
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
### For Loop (C-style)
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
for (let i = 0; i < 3; i = i + 1) {
|
|
119
|
+
sldeploy i
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
### For-In Loop (Python-style)
|
|
126
|
+
|
|
127
|
+
Iterate over arrays:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
let items = ["apple", "banana", "orange"]
|
|
131
|
+
|
|
132
|
+
for item in items {
|
|
133
|
+
sldeploy item
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
With `let` (scoped variable):
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
for let item in items {
|
|
141
|
+
sldeploy item
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Iterate over object keys:
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
let user = { "name": "Alice", "age": 20 }
|
|
149
|
+
|
|
150
|
+
for key in user {
|
|
151
|
+
sldeploy key + ": " + user[key]
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Objects & Arrays
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
let product = {
|
|
161
|
+
"name": "Star Lamp",
|
|
162
|
+
"price": 50,
|
|
163
|
+
"tags": ["space", "light"]
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
sldeploy product
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## sldeploy (Output)
|
|
172
|
+
|
|
173
|
+
`sldeploy` works like Python's `print` and can display **any type**:
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
sldeploy 42
|
|
177
|
+
sldeploy "hello"
|
|
178
|
+
sldeploy true
|
|
179
|
+
sldeploy [1, 2, 3]
|
|
180
|
+
sldeploy { "a": 1, "b": 2 }
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
It automatically formats arrays, objects, functions, and nested values.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## ask (User Input)
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
let age = ask("Enter your age:")
|
|
191
|
+
sldeploy "You entered: " + age
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Modules & Imports
|
|
197
|
+
|
|
198
|
+
### Import JavaScript Packages
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
import colors from "starlight-color"
|
|
202
|
+
|
|
203
|
+
sldeploy colors.blue("Hello Starlight")
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Import Local Files
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
import { add } from "./math.sl"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Built-in Utilities
|
|
215
|
+
|
|
216
|
+
* `len(value)` – length of array, string, or object
|
|
217
|
+
* `keys(object)` – object keys
|
|
218
|
+
* `values(object)` – object values
|
|
219
|
+
* `sleep(ms)` – async delay
|
|
220
|
+
* `fetch(url)` – low-level fetch
|
|
221
|
+
* `get(url)` – GET request
|
|
222
|
+
* `post(url, data)` – POST request
|
|
223
|
+
* `num(value)` – convert to number
|
|
224
|
+
* `str(value)` – convert to string
|
|
225
|
+
|
|
226
|
+
---
|
|
44
227
|
|
|
45
228
|
## Server-side Example
|
|
46
229
|
|
|
47
|
-
|
|
230
|
+
```
|
|
48
231
|
define server = async () => {
|
|
49
232
|
let response = await get("https://jsonplaceholder.typicode.com/todos/1")
|
|
50
|
-
sldeploy
|
|
233
|
+
sldeploy response
|
|
51
234
|
}
|
|
52
235
|
|
|
53
236
|
server()
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
## Core Concepts
|
|
237
|
+
```
|
|
57
238
|
|
|
58
|
-
|
|
59
|
-
- Functions: `func add(a, b) { return a + b }`
|
|
60
|
-
- Async Functions: `async func fetchData() { ... }`
|
|
61
|
-
- Conditionals: `if (x > 5) { ... } else { ... }`
|
|
62
|
-
- Loops: `while`, `for`
|
|
63
|
-
- Modules: `import { something } from "./module.sl"`
|
|
239
|
+
---
|
|
64
240
|
|
|
65
241
|
## Why Starlight?
|
|
66
242
|
|
|
67
|
-
Starlight is
|
|
243
|
+
Starlight is designed for developers who want:
|
|
244
|
+
|
|
245
|
+
* A **simple but powerful** scripting language
|
|
246
|
+
* **Fast server-side automation**
|
|
247
|
+
* Familiar syntax with **less boilerplate**
|
|
248
|
+
* Full access to the **Node.js ecosystem**
|
|
249
|
+
|
|
250
|
+
---
|
|
68
251
|
|
|
69
|
-
|
|
252
|
+
📘 Full documentation and tutorials:
|
|
253
|
+
[https://starlight-learn-lang.pages.dev/](https://starlight-learn-lang.pages.dev/)
|
|
70
254
|
|
|
71
|
-
License
|
|
255
|
+
**License:** MIT
|
package/dist/index.js
CHANGED
|
@@ -1390,37 +1390,59 @@ class Evaluator {
|
|
|
1390
1390
|
this.setupBuiltins();
|
|
1391
1391
|
}
|
|
1392
1392
|
formatValue(value, seen = new Set()) {
|
|
1393
|
+
// Circular reference handling
|
|
1393
1394
|
if (typeof value === 'object' && value !== null) {
|
|
1394
1395
|
if (seen.has(value)) return '[Circular]';
|
|
1395
1396
|
seen.add(value);
|
|
1396
1397
|
}
|
|
1397
1398
|
|
|
1398
|
-
|
|
1399
|
+
// Python-style null / undefined
|
|
1400
|
+
if (value === null) return 'None';
|
|
1399
1401
|
if (value === undefined) return 'undefined';
|
|
1400
1402
|
|
|
1401
1403
|
const t = typeof value;
|
|
1402
1404
|
|
|
1403
|
-
|
|
1404
|
-
if (t === '
|
|
1405
|
+
// Strings (quoted)
|
|
1406
|
+
if (t === 'string') return `"${value}"`;
|
|
1405
1407
|
|
|
1408
|
+
// Numbers
|
|
1409
|
+
if (t === 'number') return String(value);
|
|
1410
|
+
|
|
1411
|
+
// Booleans (Python-style)
|
|
1412
|
+
if (t === 'boolean') return value ? 'True' : 'False';
|
|
1413
|
+
|
|
1414
|
+
// Native JS functions
|
|
1406
1415
|
if (t === 'function') {
|
|
1407
|
-
return
|
|
1416
|
+
return value.name
|
|
1417
|
+
? `<function ${value.name}>`
|
|
1418
|
+
: '<function>';
|
|
1408
1419
|
}
|
|
1409
1420
|
|
|
1421
|
+
// Arrays
|
|
1410
1422
|
if (Array.isArray(value)) {
|
|
1411
1423
|
return '[' + value.map(v => this.formatValue(v, seen)).join(', ') + ']';
|
|
1412
1424
|
}
|
|
1413
1425
|
|
|
1426
|
+
// Objects (including your language functions)
|
|
1414
1427
|
if (t === 'object') {
|
|
1428
|
+
// Detect user-defined functions (AST-based)
|
|
1429
|
+
if (value.params && value.body) {
|
|
1430
|
+
return value.name
|
|
1431
|
+
? `<function ${value.name}>`
|
|
1432
|
+
: '<function>';
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1415
1435
|
const entries = Object.entries(value).map(
|
|
1416
1436
|
([k, v]) => `${k}: ${this.formatValue(v, seen)}`
|
|
1417
1437
|
);
|
|
1418
1438
|
return '{ ' + entries.join(', ') + ' }';
|
|
1419
1439
|
}
|
|
1420
1440
|
|
|
1441
|
+
// Fallback
|
|
1421
1442
|
return String(value);
|
|
1422
1443
|
}
|
|
1423
1444
|
|
|
1445
|
+
|
|
1424
1446
|
setupBuiltins() {
|
|
1425
1447
|
this.global.define('len', arg => {
|
|
1426
1448
|
if (Array.isArray(arg) || typeof arg === 'string') return arg.length;
|
package/package.json
CHANGED
package/src/evaluator.js
CHANGED
|
@@ -47,37 +47,59 @@ class Evaluator {
|
|
|
47
47
|
this.setupBuiltins();
|
|
48
48
|
}
|
|
49
49
|
formatValue(value, seen = new Set()) {
|
|
50
|
+
// Circular reference handling
|
|
50
51
|
if (typeof value === 'object' && value !== null) {
|
|
51
52
|
if (seen.has(value)) return '[Circular]';
|
|
52
53
|
seen.add(value);
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
// Python-style null / undefined
|
|
57
|
+
if (value === null) return 'None';
|
|
56
58
|
if (value === undefined) return 'undefined';
|
|
57
59
|
|
|
58
60
|
const t = typeof value;
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
if (t === '
|
|
62
|
+
// Strings (quoted)
|
|
63
|
+
if (t === 'string') return `"${value}"`;
|
|
62
64
|
|
|
65
|
+
// Numbers
|
|
66
|
+
if (t === 'number') return String(value);
|
|
67
|
+
|
|
68
|
+
// Booleans (Python-style)
|
|
69
|
+
if (t === 'boolean') return value ? 'True' : 'False';
|
|
70
|
+
|
|
71
|
+
// Native JS functions
|
|
63
72
|
if (t === 'function') {
|
|
64
|
-
return
|
|
73
|
+
return value.name
|
|
74
|
+
? `<function ${value.name}>`
|
|
75
|
+
: '<function>';
|
|
65
76
|
}
|
|
66
77
|
|
|
78
|
+
// Arrays
|
|
67
79
|
if (Array.isArray(value)) {
|
|
68
80
|
return '[' + value.map(v => this.formatValue(v, seen)).join(', ') + ']';
|
|
69
81
|
}
|
|
70
82
|
|
|
83
|
+
// Objects (including your language functions)
|
|
71
84
|
if (t === 'object') {
|
|
85
|
+
// Detect user-defined functions (AST-based)
|
|
86
|
+
if (value.params && value.body) {
|
|
87
|
+
return value.name
|
|
88
|
+
? `<function ${value.name}>`
|
|
89
|
+
: '<function>';
|
|
90
|
+
}
|
|
91
|
+
|
|
72
92
|
const entries = Object.entries(value).map(
|
|
73
93
|
([k, v]) => `${k}: ${this.formatValue(v, seen)}`
|
|
74
94
|
);
|
|
75
95
|
return '{ ' + entries.join(', ') + ' }';
|
|
76
96
|
}
|
|
77
97
|
|
|
98
|
+
// Fallback
|
|
78
99
|
return String(value);
|
|
79
100
|
}
|
|
80
101
|
|
|
102
|
+
|
|
81
103
|
setupBuiltins() {
|
|
82
104
|
this.global.define('len', arg => {
|
|
83
105
|
if (Array.isArray(arg) || typeof arg === 'string') return arg.length;
|