@xanots/xanoscript 0.0.1
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/LICENSE +21 -0
- package/README.md +69 -0
- package/dist/chunk-677U72GF.js +21488 -0
- package/dist/index.d.ts +249 -0
- package/dist/index.js +67 -0
- package/dist/plugin.d.ts +30 -0
- package/dist/plugin.js +483 -0
- package/package.json +88 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
interface KindValue {
|
|
2
|
+
getKind(): string;
|
|
3
|
+
getType(): string;
|
|
4
|
+
getName(): string | null;
|
|
5
|
+
toString(): string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface Kind {
|
|
9
|
+
getKind(): string;
|
|
10
|
+
getLabels(): string[];
|
|
11
|
+
getType(): string;
|
|
12
|
+
getSchemaType(): unknown;
|
|
13
|
+
isNullable(): boolean;
|
|
14
|
+
parse(data: unknown): KindValue;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The mutable render flags the engine keeps in CoroutineState / statics.
|
|
19
|
+
*
|
|
20
|
+
* The PHP encoder reads a handful of process-wide switches while rendering:
|
|
21
|
+
* verbose (legacy `!var "x"` tags), the object-literal indent counter, the
|
|
22
|
+
* quote/multiline modes the parser honours, the forced-multiline switch, the
|
|
23
|
+
* pipe registry currently in effect, and the transform context stack. One
|
|
24
|
+
* emit call owns this state for its duration; `withRenderState` snapshots and
|
|
25
|
+
* restores it so nested or sequential emits never leak flags into each other.
|
|
26
|
+
*/
|
|
27
|
+
type PipeMode = "pipes" | "filters" | "aggregates";
|
|
28
|
+
interface RenderState {
|
|
29
|
+
/** the engine's `isVerbose()` — legacy tagged rendering. Production output is minimal. */
|
|
30
|
+
verbose: boolean;
|
|
31
|
+
/** `Script.INDEX` — nesting depth while wrapping object/array literals. */
|
|
32
|
+
index: number;
|
|
33
|
+
/** `Parser.QUOTE_MODE` — force a quote character for text (tests only). */
|
|
34
|
+
quoteMode: '"' | "'" | null;
|
|
35
|
+
/** `Parser.QUOTE_MULTILINE` — allow `"""` blocks. */
|
|
36
|
+
multilineQuotes: boolean;
|
|
37
|
+
/** `Parser.TICK_MULTILINE` — allow ```` ``` ```` blocks. */
|
|
38
|
+
multilineTicks: boolean;
|
|
39
|
+
/** `MultiLineValue.FORCE` — always emit block syntax for multi-line text. */
|
|
40
|
+
multilineForce: boolean;
|
|
41
|
+
/** `Transform::$PIPE_MODE` — which registry resolves pipe display names. */
|
|
42
|
+
pipeMode: PipeMode;
|
|
43
|
+
/** `Transform::$CONTEXT` — the object being encoded (mocks resolve test names off it). */
|
|
44
|
+
contextStack: unknown[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** the engine — export-time switches. */
|
|
48
|
+
type Feature = "guid" | "workspaceEnv" | "tableItems";
|
|
49
|
+
/** A name → id map, or a lazy loader for one. */
|
|
50
|
+
type NameMap = Record<string, unknown> | (() => Record<string, unknown>);
|
|
51
|
+
/** The id → name maps the emitter resolves references through. */
|
|
52
|
+
interface ScriptMaps {
|
|
53
|
+
function?: Record<string, unknown>;
|
|
54
|
+
workflowTest?: Record<string, unknown>;
|
|
55
|
+
app?: Record<string, unknown>;
|
|
56
|
+
/** Keyed `name|verb|app.id`. */
|
|
57
|
+
query?: Record<string, unknown>;
|
|
58
|
+
dbo?: Record<string, unknown>;
|
|
59
|
+
addon?: Record<string, unknown>;
|
|
60
|
+
task?: Record<string, unknown>;
|
|
61
|
+
trigger?: Record<string, unknown>;
|
|
62
|
+
tool?: Record<string, unknown>;
|
|
63
|
+
toolset?: Record<string, unknown>;
|
|
64
|
+
middleware?: Record<string, unknown>;
|
|
65
|
+
/** v1 realtime channels, keyed by pattern. */
|
|
66
|
+
channel?: Record<string, unknown>;
|
|
67
|
+
realtimeServer?: Record<string, unknown>;
|
|
68
|
+
/** v2 channels, keyed `server|path`. */
|
|
69
|
+
v2Channel?: Record<string, unknown>;
|
|
70
|
+
/** Keyed `name|channel.id`. */
|
|
71
|
+
message?: Record<string, unknown>;
|
|
72
|
+
action?: Record<string, unknown>;
|
|
73
|
+
actionPackage?: Record<string, unknown>;
|
|
74
|
+
}
|
|
75
|
+
declare class ScriptContext {
|
|
76
|
+
private kinds;
|
|
77
|
+
private aliases;
|
|
78
|
+
private features;
|
|
79
|
+
private maps;
|
|
80
|
+
/** Every reference a render could not name — the diagnostic `compile --format xs` reports. */
|
|
81
|
+
private unresolved;
|
|
82
|
+
private readonly pipes;
|
|
83
|
+
constructor();
|
|
84
|
+
private registerKindAssign;
|
|
85
|
+
private registerKindStatic;
|
|
86
|
+
private registerKindSchema;
|
|
87
|
+
registerKind(kind: Kind): void;
|
|
88
|
+
setAlias(kind: string, alias: string): void;
|
|
89
|
+
getAlias(alias: string): string | null;
|
|
90
|
+
getKind(kind: string): Kind;
|
|
91
|
+
/** Kind names carrying ALL the given labels, in registration order. */
|
|
92
|
+
getKinds(labels?: string[] | string): string[];
|
|
93
|
+
getFeature(feature: Feature): boolean;
|
|
94
|
+
setFeature(feature: Feature, value: boolean): void;
|
|
95
|
+
setFeatures(features: Record<Feature, boolean>): void;
|
|
96
|
+
registerMap(name: keyof ScriptMaps, map: NameMap): void;
|
|
97
|
+
/**
|
|
98
|
+
* Per-map reverse index (`String(id or alias)` → first name carrying it),
|
|
99
|
+
* built on first lookup and dropped when the map is replaced. A multidoc
|
|
100
|
+
* resolves one reference per statement against maps holding every object of
|
|
101
|
+
* the workspace, so the plain scan is O(references × objects); the index is
|
|
102
|
+
* the same answer in O(1) for the string/number ids every map carries. The
|
|
103
|
+
* loose scan remains the fallback for the rest ("05" is 5 to the engine).
|
|
104
|
+
*/
|
|
105
|
+
private reverse;
|
|
106
|
+
private reverseIndex;
|
|
107
|
+
/** The map key whose value (or alias) equals `id`, by index first, then by the engine's loose compare. */
|
|
108
|
+
private keyForId;
|
|
109
|
+
registerMaps(maps: ScriptMaps): void;
|
|
110
|
+
getMap(name: keyof ScriptMaps): Record<string, unknown>;
|
|
111
|
+
/** The references no map could name since the last call, oldest first; clears the record. */
|
|
112
|
+
takeUnresolved(): Array<{
|
|
113
|
+
label: string;
|
|
114
|
+
id: unknown;
|
|
115
|
+
}>;
|
|
116
|
+
/**
|
|
117
|
+
* A map value is the object's id, or a list of aliases for it: an SDK bundle
|
|
118
|
+
* references objects by guid while a pulled workspace uses numeric ids, so a
|
|
119
|
+
* row that carries both registers both and resolves from either.
|
|
120
|
+
*/
|
|
121
|
+
private idToName;
|
|
122
|
+
mapIdToFunctionName(id: unknown): string;
|
|
123
|
+
mapIdToWorkflowTestName(id: unknown): string;
|
|
124
|
+
mapIdToAppName(id: unknown, doThrow?: boolean): string;
|
|
125
|
+
mapIdToQuery(id: unknown): string;
|
|
126
|
+
parseQuery(query: string): {
|
|
127
|
+
name: string;
|
|
128
|
+
verb: string;
|
|
129
|
+
appId: string;
|
|
130
|
+
};
|
|
131
|
+
mapIdToDboName(id: unknown, doThrow?: boolean): string;
|
|
132
|
+
mapIdToAddonName(id: unknown): string;
|
|
133
|
+
mapIdToTaskName(id: unknown): string;
|
|
134
|
+
mapIdToTriggerName(id: unknown): string;
|
|
135
|
+
mapIdToToolName(id: unknown): string;
|
|
136
|
+
mapIdToToolsetName(id: unknown, doThrow?: boolean): string;
|
|
137
|
+
mapIdToMiddlewareName(id: unknown): string;
|
|
138
|
+
mapIdToChannelName(id: unknown, doThrow?: boolean): string;
|
|
139
|
+
mapIdToRealtimeServerName(id: unknown, doThrow?: boolean): string;
|
|
140
|
+
v2ChannelMapKey(serverName: unknown, channelPath: unknown): string;
|
|
141
|
+
mapIdToV2ChannelName(id: unknown, doThrow?: boolean): string;
|
|
142
|
+
mapIdToV2ChannelServerName(id: unknown, doThrow?: boolean): string;
|
|
143
|
+
actionNameOf(id: unknown): string;
|
|
144
|
+
actionPackageNameOf(id: unknown): string;
|
|
145
|
+
/** `setV2Channel`: key by `{serverName}|{path}` resolving the server through the server map. */
|
|
146
|
+
setV2Channel(map: Record<string, unknown>, item: {
|
|
147
|
+
id: unknown;
|
|
148
|
+
name: string;
|
|
149
|
+
server?: {
|
|
150
|
+
id?: unknown;
|
|
151
|
+
};
|
|
152
|
+
}): void;
|
|
153
|
+
getPipeDisplay(mode: PipeMode, name: string): string | null;
|
|
154
|
+
getPipeInternalNames(mode: PipeMode): string[];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
type Row = Record<string, unknown>;
|
|
158
|
+
interface MultidocSections {
|
|
159
|
+
workspace?: Row;
|
|
160
|
+
dbo?: Row[];
|
|
161
|
+
function?: Row[];
|
|
162
|
+
middleware?: Row[];
|
|
163
|
+
app?: Row[];
|
|
164
|
+
query?: Row[];
|
|
165
|
+
task?: Row[];
|
|
166
|
+
addon?: Row[];
|
|
167
|
+
toolset?: Row[];
|
|
168
|
+
tool?: Row[];
|
|
169
|
+
trigger?: Row[];
|
|
170
|
+
workflow_test?: Row[];
|
|
171
|
+
realtime_server?: Row[];
|
|
172
|
+
channel?: Row[];
|
|
173
|
+
message?: Row[];
|
|
174
|
+
microservice?: Row[];
|
|
175
|
+
[key: string]: unknown;
|
|
176
|
+
}
|
|
177
|
+
interface MultidocOptions {
|
|
178
|
+
/** Which document groups to emit; everything defaults to on. */
|
|
179
|
+
include?: Partial<Record<"table" | "function" | "query" | "task" | "addon" | "middleware" | "ai" | "action" | "workflow_test" | "trigger" | "realtime" | "realtime_v2" | "microservice", boolean>>;
|
|
180
|
+
/** Engine export features: `guid` lines, workspace `env`, table `items` (records). */
|
|
181
|
+
features?: Partial<Record<Feature, boolean>>;
|
|
182
|
+
/** Extra name → id entries laid over the maps derived from the payload (a reference to an object outside it). */
|
|
183
|
+
maps?: ScriptMaps;
|
|
184
|
+
/** Reuse a prepared context. */
|
|
185
|
+
context?: ScriptContext;
|
|
186
|
+
}
|
|
187
|
+
declare function emitWorkspaceMultidoc(input: MultidocSections | {
|
|
188
|
+
payload: MultidocSections;
|
|
189
|
+
}, options?: MultidocOptions): string;
|
|
190
|
+
|
|
191
|
+
/** A document's header facts, as the CLI reads them off the text. */
|
|
192
|
+
interface ParsedDocument {
|
|
193
|
+
apiGroup?: string;
|
|
194
|
+
canonical?: string;
|
|
195
|
+
/** Owning channel path for realtime v2 `message` documents. */
|
|
196
|
+
channel?: string;
|
|
197
|
+
content: string;
|
|
198
|
+
guid?: string;
|
|
199
|
+
name: string;
|
|
200
|
+
/** Owning realtime_server name for realtime v2 `channel` documents. */
|
|
201
|
+
server?: string;
|
|
202
|
+
type: string;
|
|
203
|
+
verb?: string;
|
|
204
|
+
}
|
|
205
|
+
/** A document's resolved location relative to the tree root, plus its content. */
|
|
206
|
+
interface PlacedDocument {
|
|
207
|
+
content: string;
|
|
208
|
+
/** POSIX-style path relative to the root, e.g. `api/pdf/documents_GET.xs`. */
|
|
209
|
+
relPath: string;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Parse one document's type, name and the references its placement needs.
|
|
213
|
+
* Leading `//` comment lines are skipped to find the declaration.
|
|
214
|
+
*/
|
|
215
|
+
declare function parseDocument(content: string): ParsedDocument | null;
|
|
216
|
+
/** Split a multidoc into parsed documents, skipping empties and unparseable fragments. */
|
|
217
|
+
declare function splitMultidoc(blob: string): ParsedDocument[];
|
|
218
|
+
/**
|
|
219
|
+
* Where each document of a batch lands: `resolveDocumentPath` plus the `.xs`
|
|
220
|
+
* extension, with a `_N` suffix on a second document that would take a name
|
|
221
|
+
* already used in the same directory (`say.xs`, then `say_2.xs`).
|
|
222
|
+
*/
|
|
223
|
+
declare function placeDocuments(documents: ParsedDocument[]): PlacedDocument[];
|
|
224
|
+
/** A multidoc as the files `xano workspace pull` would write for it. */
|
|
225
|
+
declare function placeMultidoc(multidoc: string): PlacedDocument[];
|
|
226
|
+
/**
|
|
227
|
+
* The top-level directories the layout can write into, derived from the
|
|
228
|
+
* placement rules themselves (each type placed with and without the references
|
|
229
|
+
* that change its home), so a writer that owns the tree prunes every directory
|
|
230
|
+
* a document could have landed in.
|
|
231
|
+
*/
|
|
232
|
+
declare function layoutRoots(): string[];
|
|
233
|
+
|
|
234
|
+
interface EmitOptions {
|
|
235
|
+
/** id → name maps for every cross-reference the object makes. */
|
|
236
|
+
maps?: ScriptMaps;
|
|
237
|
+
/** Engine export features (`guid` emits guid lines, etc.). */
|
|
238
|
+
features?: Partial<Record<Feature, boolean>>;
|
|
239
|
+
/** Render flags; the defaults are what the engine's export path uses. */
|
|
240
|
+
render?: Partial<Omit<RenderState, "index" | "contextStack" | "pipeMode">>;
|
|
241
|
+
/** Reuse a prepared context (its maps stay registered across calls). */
|
|
242
|
+
context?: ScriptContext;
|
|
243
|
+
}
|
|
244
|
+
/** A context with the vendored engine kinds loaded; cached because the registry is large. */
|
|
245
|
+
declare function createScriptContext(maps?: ScriptMaps, features?: Partial<Record<Feature, boolean>>): ScriptContext;
|
|
246
|
+
/** Render one object (`schema:function`, `schema:query`, a statement kind, …) to XanoScript. */
|
|
247
|
+
declare function emitXanoScript(kind: string, data: unknown, options?: EmitOptions): string;
|
|
248
|
+
|
|
249
|
+
export { type EmitOptions, type Feature, type MultidocOptions, type MultidocSections, type ParsedDocument, type PlacedDocument, ScriptContext, type ScriptMaps, createScriptContext, emitWorkspaceMultidoc, emitXanoScript, layoutRoots, parseDocument, placeDocuments, placeMultidoc, splitMultidoc };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ScriptContext,
|
|
3
|
+
emitWorkspaceMultidoc,
|
|
4
|
+
layoutRoots,
|
|
5
|
+
parseDocument,
|
|
6
|
+
placeDocuments,
|
|
7
|
+
placeMultidoc,
|
|
8
|
+
processConvert,
|
|
9
|
+
splitMultidoc,
|
|
10
|
+
withRenderState,
|
|
11
|
+
withScriptContext
|
|
12
|
+
} from "./chunk-677U72GF.js";
|
|
13
|
+
|
|
14
|
+
// src/index.ts
|
|
15
|
+
var shared = null;
|
|
16
|
+
function createScriptContext(maps, features) {
|
|
17
|
+
const ctx = new ScriptContext();
|
|
18
|
+
if (maps) ctx.registerMaps(maps);
|
|
19
|
+
if (features) {
|
|
20
|
+
for (const [k, v] of Object.entries(features)) ctx.setFeature(k, Boolean(v));
|
|
21
|
+
}
|
|
22
|
+
return ctx;
|
|
23
|
+
}
|
|
24
|
+
function contextFor(o) {
|
|
25
|
+
if (o.context) {
|
|
26
|
+
if (o.maps) o.context.registerMaps(o.maps);
|
|
27
|
+
if (o.features) o.context.setFeatures({ guid: false, workspaceEnv: false, tableItems: false, ...o.features });
|
|
28
|
+
return o.context;
|
|
29
|
+
}
|
|
30
|
+
if (o.maps) return createScriptContext(o.maps, { guid: false, workspaceEnv: false, tableItems: false, ...o.features ?? {} });
|
|
31
|
+
if (!shared) shared = new ScriptContext();
|
|
32
|
+
shared.setFeatures({ guid: false, workspaceEnv: false, tableItems: false, ...o.features ?? {} });
|
|
33
|
+
return shared;
|
|
34
|
+
}
|
|
35
|
+
function emitXanoScript(kind, data, options = {}) {
|
|
36
|
+
const ctx = contextFor(options);
|
|
37
|
+
const out = withScriptContext(
|
|
38
|
+
ctx,
|
|
39
|
+
() => withRenderState(
|
|
40
|
+
{
|
|
41
|
+
verbose: false,
|
|
42
|
+
quoteMode: null,
|
|
43
|
+
multilineQuotes: true,
|
|
44
|
+
multilineTicks: true,
|
|
45
|
+
multilineForce: false,
|
|
46
|
+
pipeMode: "pipes",
|
|
47
|
+
index: 0,
|
|
48
|
+
...options.render ?? {}
|
|
49
|
+
},
|
|
50
|
+
() => processConvert(kind, data).output
|
|
51
|
+
)
|
|
52
|
+
);
|
|
53
|
+
if (!options.context) ctx.takeUnresolved();
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
ScriptContext,
|
|
58
|
+
createScriptContext,
|
|
59
|
+
emitWorkspaceMultidoc,
|
|
60
|
+
emitXanoScript,
|
|
61
|
+
layoutRoots,
|
|
62
|
+
parseDocument,
|
|
63
|
+
placeDocuments,
|
|
64
|
+
placeMultidoc,
|
|
65
|
+
splitMultidoc
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=index.js.map
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ToolchainPlugin } from '@xanots/sdk/plugin';
|
|
2
|
+
|
|
3
|
+
/** The range as `package.json` spells it, so one edit cannot move without the other. */
|
|
4
|
+
declare const PEER_RANGE = ">=0.0.29 <0.1.0";
|
|
5
|
+
/**
|
|
6
|
+
* Refuse, by name and before any work, an SDK this module does not understand.
|
|
7
|
+
*
|
|
8
|
+
* The install-time peer warning cannot carry this: the peer is declared
|
|
9
|
+
* non-optional precisely so npm prints one, but a warning during `npm install`
|
|
10
|
+
* is read by nobody three weeks later, and the failure it describes is SILENT —
|
|
11
|
+
* an older SDK has no toolchain loader at all, so the hook simply never fires
|
|
12
|
+
* and the tree quietly stops being written. A hook that DID fire on a version
|
|
13
|
+
* outside the range is the case this catches: the shapes it is handed are not
|
|
14
|
+
* the shapes it was written against.
|
|
15
|
+
*
|
|
16
|
+
* An unparsable version, or one carrying a PRERELEASE suffix, is allowed
|
|
17
|
+
* through. The SDK reads the version from its own `package.json`, and a source
|
|
18
|
+
* checkout reads `0.0.0-dev` — refusing that would break exactly the linked
|
|
19
|
+
* development setup KTD5 asks for. The cost is that a prerelease of an
|
|
20
|
+
* out-of-range SDK is not caught, which is the trade npm's own ranges make.
|
|
21
|
+
*/
|
|
22
|
+
declare function assertSdkVersion(sdkVersion: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* The default export the SDK's loader reads. `kind` is repeated from the
|
|
25
|
+
* manifest so the two must agree — a mismatch means one of them is stale, and
|
|
26
|
+
* guessing which would run code the manifest did not describe.
|
|
27
|
+
*/
|
|
28
|
+
declare const plugin: ToolchainPlugin;
|
|
29
|
+
|
|
30
|
+
export { PEER_RANGE, assertSdkVersion, plugin as default };
|