gg-wf-scripts 2.5.0 → 3.0.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 +33 -0
- package/dist/action-engine.d.ts +2 -0
- package/dist/action-engine.js +97 -0
- package/dist/action-engine.js.map +1 -0
- package/dist/actions.d.ts +5 -0
- package/dist/actions.js +2 -0
- package/dist/actions.js.map +1 -0
- package/dist/attrs.d.ts +59 -0
- package/dist/attrs.js +67 -0
- package/dist/attrs.js.map +1 -0
- package/dist/auth.d.ts +6 -0
- package/dist/auth.js +28 -0
- package/dist/auth.js.map +1 -0
- package/dist/bridges.d.ts +1 -0
- package/dist/bridges.js +43 -0
- package/dist/bridges.js.map +1 -0
- package/dist/data-engine.d.ts +2 -0
- package/dist/data-engine.js +153 -0
- package/dist/data-engine.js.map +1 -0
- package/dist/dialog.d.ts +1 -0
- package/dist/dialog.js +93 -0
- package/dist/dialog.js.map +1 -0
- package/dist/dom-observer.d.ts +4 -0
- package/dist/dom-observer.js +47 -0
- package/dist/dom-observer.js.map +1 -0
- package/dist/engine-deps.d.ts +23 -0
- package/dist/engine-deps.js +2 -0
- package/dist/engine-deps.js.map +1 -0
- package/dist/errors.d.ts +25 -0
- package/dist/errors.js +30 -0
- package/dist/errors.js.map +1 -0
- package/dist/form-action-engine.d.ts +2 -0
- package/dist/form-action-engine.js +173 -0
- package/dist/form-action-engine.js.map +1 -0
- package/dist/form-actions.d.ts +10 -0
- package/dist/form-actions.js +2 -0
- package/dist/form-actions.js.map +1 -0
- package/dist/form-visibility.d.ts +1 -0
- package/dist/form-visibility.js +109 -0
- package/dist/form-visibility.js.map +1 -0
- package/dist/helpers/dom.d.ts +16 -0
- package/dist/helpers/dom.js +39 -0
- package/dist/helpers/dom.js.map +1 -0
- package/dist/helpers/form-field.d.ts +19 -0
- package/dist/helpers/form-field.js +58 -0
- package/dist/helpers/form-field.js.map +1 -0
- package/dist/helpers/path.d.ts +2 -0
- package/dist/helpers/path.js +9 -0
- package/dist/helpers/path.js.map +1 -0
- package/dist/helpers/run-handler.d.ts +26 -0
- package/dist/helpers/run-handler.js +36 -0
- package/dist/helpers/run-handler.js.map +1 -0
- package/dist/helpers/run-with-loading.d.ts +6 -0
- package/dist/helpers/run-with-loading.js +28 -0
- package/dist/helpers/run-with-loading.js.map +1 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/queries.d.ts +1 -0
- package/dist/queries.js +2 -0
- package/dist/queries.js.map +1 -0
- package/dist/query-params.d.ts +19 -0
- package/dist/query-params.js +160 -0
- package/dist/query-params.js.map +1 -0
- package/dist/switch-engine.d.ts +1 -0
- package/dist/switch-engine.js +28 -0
- package/dist/switch-engine.js.map +1 -0
- package/package.json +25 -2
- package/src/action-engine.js +0 -64
- package/src/actions.js +0 -14
- package/src/auth.js +0 -28
- package/src/bridges.js +0 -31
- package/src/data-engine.js +0 -165
- package/src/dialog.js +0 -86
- package/src/form-action-engine.js +0 -149
- package/src/form-actions.js +0 -21
- package/src/form-visibility.js +0 -122
- package/src/helpers/dom.js +0 -35
- package/src/helpers/log.js +0 -34
- package/src/helpers/path.js +0 -4
- package/src/index.js +0 -60
- package/src/queries.js +0 -14
- package/src/query-params.js +0 -144
- package/src/switch-engine.js +0 -22
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.js","sourceRoot":"","sources":["../../src/helpers/path.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,MAAM,UAAU,OAAO,CAAC,GAAY,EAAE,IAAY;IAChD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAU,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAClD,IAAI,GAAG,IAAI,IAAI;YAAE,OAAO,SAAS,CAAC;QAClC,OAAQ,GAA+B,CAAC,GAAG,CAAC,CAAC;IAC/C,CAAC,EAAE,GAAG,CAAC,CAAC;AACV,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { GgErrorEvent } from "../errors.js";
|
|
2
|
+
type RunHandlerOptions = {
|
|
3
|
+
prefix: string;
|
|
4
|
+
id: string;
|
|
5
|
+
fields: Record<string, unknown>;
|
|
6
|
+
debug: boolean;
|
|
7
|
+
emitError?: (event: GgErrorEvent) => void;
|
|
8
|
+
};
|
|
9
|
+
export type RunHandlerResult<T> = {
|
|
10
|
+
ok: true;
|
|
11
|
+
value: T;
|
|
12
|
+
} | {
|
|
13
|
+
ok: false;
|
|
14
|
+
error: unknown;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Run a registered handler with debug logging and errors-as-values.
|
|
18
|
+
*
|
|
19
|
+
* Catches throws so engine code can branch on a result instead of try/catch.
|
|
20
|
+
* On success, returns { ok: true, value } where value is whatever the handler
|
|
21
|
+
* returned. On throw, returns { ok: false, error }, logs the error, and emits
|
|
22
|
+
* a GgErrorEvent so consumers subscribed via app.onError() can ship it to
|
|
23
|
+
* their error tracker.
|
|
24
|
+
*/
|
|
25
|
+
export declare function runHandler<T>({ prefix, id, fields, debug, emitError }: RunHandlerOptions, fn: () => Promise<T> | T): Promise<RunHandlerResult<T>>;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run a registered handler with debug logging and errors-as-values.
|
|
3
|
+
*
|
|
4
|
+
* Catches throws so engine code can branch on a result instead of try/catch.
|
|
5
|
+
* On success, returns { ok: true, value } where value is whatever the handler
|
|
6
|
+
* returned. On throw, returns { ok: false, error }, logs the error, and emits
|
|
7
|
+
* a GgErrorEvent so consumers subscribed via app.onError() can ship it to
|
|
8
|
+
* their error tracker.
|
|
9
|
+
*/
|
|
10
|
+
export async function runHandler({ prefix, id, fields, debug, emitError }, fn) {
|
|
11
|
+
if (debug) {
|
|
12
|
+
console.groupCollapsed(`${prefix} "${id}"`);
|
|
13
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
14
|
+
console.log(`${key}:`, value);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const startedAt = debug ? performance.now() : 0;
|
|
18
|
+
try {
|
|
19
|
+
const value = await fn();
|
|
20
|
+
if (debug) {
|
|
21
|
+
const ms = (performance.now() - startedAt).toFixed(1);
|
|
22
|
+
console.log(`result (${ms}ms):`, value);
|
|
23
|
+
}
|
|
24
|
+
return { ok: true, value };
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
console.error(`${prefix} "${id}" threw:`, error);
|
|
28
|
+
emitError?.({ prefix, id, error, fields });
|
|
29
|
+
return { ok: false, error };
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
if (debug)
|
|
33
|
+
console.groupEnd();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=run-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-handler.js","sourceRoot":"","sources":["../../src/helpers/run-handler.ts"],"names":[],"mappings":"AAcA;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAqB,EAC3D,EAAwB;IAExB,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,cAAc,CAAC,GAAG,MAAM,KAAK,EAAE,GAAG,CAAC,CAAC;QAC5C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,EAAE,EAAE,CAAC;QACzB,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACtD,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,KAAK,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;QACjD,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;YAAS,CAAC;QACT,IAAI,KAAK;YAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;IAChC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Set gg-loading="true" on each element while fn runs, clearing it (in a
|
|
3
|
+
* finally block) when fn resolves or throws. Form controls (button, input)
|
|
4
|
+
* also get native `disabled` toggled.
|
|
5
|
+
*/
|
|
6
|
+
export declare function runWithLoading<T>(elements: Iterable<Element>, fn: () => Promise<T> | T): Promise<T>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Set gg-loading="true" on each element while fn runs, clearing it (in a
|
|
3
|
+
* finally block) when fn resolves or throws. Form controls (button, input)
|
|
4
|
+
* also get native `disabled` toggled.
|
|
5
|
+
*/
|
|
6
|
+
export async function runWithLoading(elements, fn) {
|
|
7
|
+
const targets = [...elements];
|
|
8
|
+
targets.forEach(applyLoading);
|
|
9
|
+
try {
|
|
10
|
+
return await fn();
|
|
11
|
+
}
|
|
12
|
+
finally {
|
|
13
|
+
targets.forEach(clearLoading);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function applyLoading(el) {
|
|
17
|
+
el.setAttribute("gg-loading", "true");
|
|
18
|
+
if (el instanceof HTMLButtonElement || el instanceof HTMLInputElement) {
|
|
19
|
+
el.disabled = true;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function clearLoading(el) {
|
|
23
|
+
el.removeAttribute("gg-loading");
|
|
24
|
+
if (el instanceof HTMLButtonElement || el instanceof HTMLInputElement) {
|
|
25
|
+
el.disabled = false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=run-with-loading.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-with-loading.js","sourceRoot":"","sources":["../../src/helpers/run-with-loading.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAA2B,EAC3B,EAAwB;IAExB,MAAM,OAAO,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC;IAC9B,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAChC,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,EAAW;IAC/B,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACtC,IAAI,EAAE,YAAY,iBAAiB,IAAI,EAAE,YAAY,gBAAgB,EAAE,CAAC;QACtE,EAAE,CAAC,QAAQ,GAAG,IAAI,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,EAAW;IAC/B,EAAE,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;IACjC,IAAI,EAAE,YAAY,iBAAiB,IAAI,EAAE,YAAY,gBAAgB,EAAE,CAAC;QACtE,EAAE,CAAC,QAAQ,GAAG,KAAK,CAAC;IACtB,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Query } from "./queries.js";
|
|
2
|
+
import type { Action } from "./actions.js";
|
|
3
|
+
import type { FormAction } from "./form-actions.js";
|
|
4
|
+
import { setQueryParams, removeQueryParams } from "./query-params.js";
|
|
5
|
+
import { type AuthAdapter } from "./auth.js";
|
|
6
|
+
import { type ErrorHandler } from "./errors.js";
|
|
7
|
+
export { setQueryParams, removeQueryParams };
|
|
8
|
+
export { getPath } from "./helpers/path.js";
|
|
9
|
+
export type { AuthAdapter } from "./auth.js";
|
|
10
|
+
export type { Query } from "./queries.js";
|
|
11
|
+
export type { Action, ActionResult } from "./actions.js";
|
|
12
|
+
export type { FormAction, FormActionResult, FormFieldError } from "./form-actions.js";
|
|
13
|
+
export type { GgErrorEvent, ErrorHandler } from "./errors.js";
|
|
14
|
+
export type InitOptions<TContext = unknown> = {
|
|
15
|
+
/**
|
|
16
|
+
* Arbitrary object passed to every query and action. Put backend clients
|
|
17
|
+
* (Supabase, fetch wrappers, etc.) or anything else your queries need on it.
|
|
18
|
+
*/
|
|
19
|
+
context?: TContext;
|
|
20
|
+
/**
|
|
21
|
+
* Auth adapter. If omitted, gg-auth/gg-role attrs are never set.
|
|
22
|
+
*/
|
|
23
|
+
auth?: AuthAdapter<TContext>;
|
|
24
|
+
/**
|
|
25
|
+
* When true, every query and action is logged to the console with its
|
|
26
|
+
* trigger/container, data, result, and duration.
|
|
27
|
+
*/
|
|
28
|
+
debug?: boolean;
|
|
29
|
+
};
|
|
30
|
+
export type App<TContext = unknown> = {
|
|
31
|
+
context: TContext;
|
|
32
|
+
debug: boolean;
|
|
33
|
+
queries: Record<string, Query<TContext>>;
|
|
34
|
+
actions: Record<string, Action<TContext>>;
|
|
35
|
+
formActions: Record<string, FormAction<TContext>>;
|
|
36
|
+
/**
|
|
37
|
+
* Register a query. Optionally pin the result type at the call site:
|
|
38
|
+
* `app.addQuery<User[]>("users.list", ...)` for autocomplete on the
|
|
39
|
+
* handler's return value.
|
|
40
|
+
*/
|
|
41
|
+
addQuery: <TResult = unknown>(id: string, fn: Query<TContext, TResult>) => void;
|
|
42
|
+
/**
|
|
43
|
+
* Register an action. Optionally pin the data shape:
|
|
44
|
+
* `app.addAction<{ id: string }>("posts.delete", ...)`.
|
|
45
|
+
*/
|
|
46
|
+
addAction: <TData extends Record<string, unknown> = Record<string, unknown>>(id: string, fn: Action<TContext, TData>) => void;
|
|
47
|
+
addFormAction: (id: string, fn: FormAction<TContext>) => void;
|
|
48
|
+
/**
|
|
49
|
+
* Subscribe to errors from any registered handler — including thrown
|
|
50
|
+
* exceptions, missing-handler lookups, and `{ ok: false }` returns. Useful
|
|
51
|
+
* for shipping errors to Sentry or similar. Returns an unsubscribe fn.
|
|
52
|
+
*/
|
|
53
|
+
onError: (handler: ErrorHandler) => () => void;
|
|
54
|
+
/**
|
|
55
|
+
* Mount all engines. Idempotent only in the sense that calling start()
|
|
56
|
+
* twice without dispose() will double-bind listeners — don't do that.
|
|
57
|
+
*/
|
|
58
|
+
start: () => void;
|
|
59
|
+
/**
|
|
60
|
+
* Detach every listener and observer the library installed. Call from
|
|
61
|
+
* SPA route changes, HMR teardown, or test cleanup. Handler registrations
|
|
62
|
+
* are kept so you can call start() again on the same App.
|
|
63
|
+
*/
|
|
64
|
+
dispose: () => void;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Create a gg-scripts app instance.
|
|
68
|
+
*/
|
|
69
|
+
export declare function init<TContext = unknown>({ context, auth, debug }?: InitOptions<TContext>): App<TContext>;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { setQueryParams, removeQueryParams, initQueryParams } from "./query-params.js";
|
|
2
|
+
import { initAuth } from "./auth.js";
|
|
3
|
+
import { initSwitchEngine } from "./switch-engine.js";
|
|
4
|
+
import { initDialog } from "./dialog.js";
|
|
5
|
+
import { initBridges } from "./bridges.js";
|
|
6
|
+
import { initFormVisibility } from "./form-visibility.js";
|
|
7
|
+
import { initDataEngine } from "./data-engine.js";
|
|
8
|
+
import { initActionEngine } from "./action-engine.js";
|
|
9
|
+
import { initFormActionEngine } from "./form-action-engine.js";
|
|
10
|
+
import { startDomObserver } from "./dom-observer.js";
|
|
11
|
+
import { createErrorBus } from "./errors.js";
|
|
12
|
+
export { setQueryParams, removeQueryParams };
|
|
13
|
+
export { getPath } from "./helpers/path.js";
|
|
14
|
+
/**
|
|
15
|
+
* Create a gg-scripts app instance.
|
|
16
|
+
*/
|
|
17
|
+
export function init({ context = {}, auth, debug = false } = {}) {
|
|
18
|
+
const queries = {};
|
|
19
|
+
const actions = {};
|
|
20
|
+
const formActions = {};
|
|
21
|
+
const errorBus = createErrorBus();
|
|
22
|
+
let cleanups = [];
|
|
23
|
+
const app = {
|
|
24
|
+
context,
|
|
25
|
+
debug,
|
|
26
|
+
queries,
|
|
27
|
+
actions,
|
|
28
|
+
formActions,
|
|
29
|
+
addQuery: (id, fn) => {
|
|
30
|
+
queries[id] = fn;
|
|
31
|
+
},
|
|
32
|
+
addAction: (id, fn) => {
|
|
33
|
+
actions[id] = fn;
|
|
34
|
+
},
|
|
35
|
+
addFormAction: (id, fn) => {
|
|
36
|
+
formActions[id] = fn;
|
|
37
|
+
},
|
|
38
|
+
onError: (handler) => errorBus.subscribe(handler),
|
|
39
|
+
start() {
|
|
40
|
+
function run() {
|
|
41
|
+
const core = {
|
|
42
|
+
context,
|
|
43
|
+
debug,
|
|
44
|
+
emitError: (event) => errorBus.emit(event),
|
|
45
|
+
};
|
|
46
|
+
if (auth)
|
|
47
|
+
initAuth(context, auth);
|
|
48
|
+
cleanups.push(startDomObserver());
|
|
49
|
+
cleanups.push(initSwitchEngine());
|
|
50
|
+
cleanups.push(initQueryParams());
|
|
51
|
+
cleanups.push(initDialog());
|
|
52
|
+
cleanups.push(initBridges());
|
|
53
|
+
cleanups.push(initFormVisibility());
|
|
54
|
+
cleanups.push(initDataEngine({ ...core, queries }));
|
|
55
|
+
cleanups.push(initActionEngine({ ...core, actions }));
|
|
56
|
+
cleanups.push(initFormActionEngine({ ...core, formActions }));
|
|
57
|
+
}
|
|
58
|
+
if (document.readyState === "loading") {
|
|
59
|
+
document.addEventListener("DOMContentLoaded", run);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
run();
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
dispose() {
|
|
66
|
+
cleanups.forEach((c) => c());
|
|
67
|
+
cleanups = [];
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
return app;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type Query<TContext = unknown, TResult = unknown> = (context: TContext, params: URLSearchParams) => Promise<TResult> | TResult;
|
package/dist/queries.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queries.js","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type QueryChangeCallback = (key: string, value: string | null) => void;
|
|
2
|
+
/**
|
|
3
|
+
* Snapshot of the current URL query string as a URLSearchParams instance.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getParams(): URLSearchParams;
|
|
6
|
+
export declare function onQueryChanged(callback: QueryChangeCallback): () => void;
|
|
7
|
+
/**
|
|
8
|
+
* Set one or more URL query params and notify subscribers.
|
|
9
|
+
*/
|
|
10
|
+
export declare function setQueryParams(params: Array<{
|
|
11
|
+
key: string;
|
|
12
|
+
value: string;
|
|
13
|
+
}>): void;
|
|
14
|
+
/**
|
|
15
|
+
* Remove one or more URL query params and notify subscribers.
|
|
16
|
+
*/
|
|
17
|
+
export declare function removeQueryParams(keys: string[]): void;
|
|
18
|
+
export declare function initQueryParams(): () => void;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { ATTR, SEL } from "./attrs.js";
|
|
2
|
+
import { onElement } from "./dom-observer.js";
|
|
3
|
+
const subscribers = [];
|
|
4
|
+
/**
|
|
5
|
+
* Snapshot of the current URL query string as a URLSearchParams instance.
|
|
6
|
+
*/
|
|
7
|
+
export function getParams() {
|
|
8
|
+
return new URL(window.location.href).searchParams;
|
|
9
|
+
}
|
|
10
|
+
export function onQueryChanged(callback) {
|
|
11
|
+
subscribers.push(callback);
|
|
12
|
+
return () => {
|
|
13
|
+
const idx = subscribers.indexOf(callback);
|
|
14
|
+
if (idx >= 0)
|
|
15
|
+
subscribers.splice(idx, 1);
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function notify(key, value) {
|
|
19
|
+
subscribers.forEach((cb) => cb(key, value));
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Set one or more URL query params and notify subscribers.
|
|
23
|
+
*/
|
|
24
|
+
export function setQueryParams(params) {
|
|
25
|
+
const url = new URL(window.location.href);
|
|
26
|
+
params.forEach(({ key, value }) => url.searchParams.set(key, value));
|
|
27
|
+
history.pushState({}, "", url);
|
|
28
|
+
params.forEach(({ key, value }) => notify(key, value));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Remove one or more URL query params and notify subscribers.
|
|
32
|
+
*/
|
|
33
|
+
export function removeQueryParams(keys) {
|
|
34
|
+
const url = new URL(window.location.href);
|
|
35
|
+
keys.forEach((key) => url.searchParams.delete(key));
|
|
36
|
+
history.pushState({}, "", url);
|
|
37
|
+
keys.forEach((key) => notify(key, null));
|
|
38
|
+
}
|
|
39
|
+
// ---- click delegation for gg-query-set / gg-query-remove ----
|
|
40
|
+
function handleQueryClick(target) {
|
|
41
|
+
if (!target)
|
|
42
|
+
return;
|
|
43
|
+
const setTrigger = target.closest(`[${ATTR.querySet}]`);
|
|
44
|
+
if (setTrigger) {
|
|
45
|
+
const attr = setTrigger.getAttribute(ATTR.querySet) ?? "";
|
|
46
|
+
const params = attr
|
|
47
|
+
.split(",")
|
|
48
|
+
.filter(Boolean)
|
|
49
|
+
.map((pair) => {
|
|
50
|
+
const [key, value] = pair.split(":");
|
|
51
|
+
return { key: key?.trim() ?? "", value: value?.trim() ?? "" };
|
|
52
|
+
})
|
|
53
|
+
.filter((p) => p.key && p.value);
|
|
54
|
+
if (params.length)
|
|
55
|
+
setQueryParams(params);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const removeTrigger = target.closest(`[${ATTR.queryRemove}]`);
|
|
59
|
+
if (removeTrigger) {
|
|
60
|
+
const attr = removeTrigger.getAttribute(ATTR.queryRemove) ?? "";
|
|
61
|
+
const keys = attr
|
|
62
|
+
.split(",")
|
|
63
|
+
.map((k) => k.trim())
|
|
64
|
+
.filter(Boolean);
|
|
65
|
+
if (keys.length)
|
|
66
|
+
removeQueryParams(keys);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function initQueryParams() {
|
|
71
|
+
const onClick = (e) => {
|
|
72
|
+
handleQueryClick(e.target instanceof Element ? e.target : null);
|
|
73
|
+
};
|
|
74
|
+
const onShadowClick = (e) => {
|
|
75
|
+
const detail = e.detail;
|
|
76
|
+
handleQueryClick(detail?.target ?? null);
|
|
77
|
+
};
|
|
78
|
+
document.addEventListener("click", onClick);
|
|
79
|
+
document.addEventListener("gg:shadow:click", onShadowClick);
|
|
80
|
+
const unbindBindings = initQueryBindings();
|
|
81
|
+
return () => {
|
|
82
|
+
document.removeEventListener("click", onClick);
|
|
83
|
+
document.removeEventListener("gg:shadow:click", onShadowClick);
|
|
84
|
+
unbindBindings();
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function syncBindInputFromUrl(el) {
|
|
88
|
+
const key = el.getAttribute(ATTR.queryBind);
|
|
89
|
+
if (!key)
|
|
90
|
+
return;
|
|
91
|
+
const value = new URL(window.location.href).searchParams.get(key) ?? "";
|
|
92
|
+
if (el.value !== value)
|
|
93
|
+
el.value = value;
|
|
94
|
+
}
|
|
95
|
+
const boundInputs = new WeakSet();
|
|
96
|
+
function setupQueryBindInput(el) {
|
|
97
|
+
if (boundInputs.has(el))
|
|
98
|
+
return;
|
|
99
|
+
const key = el.getAttribute(ATTR.queryBind);
|
|
100
|
+
if (!key)
|
|
101
|
+
return;
|
|
102
|
+
boundInputs.add(el);
|
|
103
|
+
const debounceMs = parseInt(el.getAttribute(ATTR.queryDebounce) ?? "0", 10) || 0;
|
|
104
|
+
syncBindInputFromUrl(el);
|
|
105
|
+
let timer;
|
|
106
|
+
let suppress = false;
|
|
107
|
+
el.addEventListener("input", () => {
|
|
108
|
+
if (suppress)
|
|
109
|
+
return;
|
|
110
|
+
if (timer !== undefined)
|
|
111
|
+
clearTimeout(timer);
|
|
112
|
+
const fire = () => {
|
|
113
|
+
const value = el.value;
|
|
114
|
+
if (value === "") {
|
|
115
|
+
removeQueryParams([key]);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
setQueryParams([{ key, value }]);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
if (debounceMs > 0) {
|
|
122
|
+
timer = setTimeout(fire, debounceMs);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
fire();
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
// When the URL changes from elsewhere (back button, programmatic), mirror
|
|
129
|
+
// it into the input without re-firing the input listener.
|
|
130
|
+
onQueryChanged((changedKey, value) => {
|
|
131
|
+
if (changedKey !== key)
|
|
132
|
+
return;
|
|
133
|
+
const next = value ?? "";
|
|
134
|
+
if (el.value === next)
|
|
135
|
+
return;
|
|
136
|
+
suppress = true;
|
|
137
|
+
el.value = next;
|
|
138
|
+
suppress = false;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function initQueryBindings() {
|
|
142
|
+
const unbind = onElement(SEL.queryBind, (el) => {
|
|
143
|
+
if (el instanceof HTMLInputElement ||
|
|
144
|
+
el instanceof HTMLTextAreaElement ||
|
|
145
|
+
el instanceof HTMLSelectElement) {
|
|
146
|
+
setupQueryBindInput(el);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
const onPopstate = () => {
|
|
150
|
+
document
|
|
151
|
+
.querySelectorAll(SEL.queryBind)
|
|
152
|
+
.forEach(syncBindInputFromUrl);
|
|
153
|
+
};
|
|
154
|
+
window.addEventListener("popstate", onPopstate);
|
|
155
|
+
return () => {
|
|
156
|
+
unbind();
|
|
157
|
+
window.removeEventListener("popstate", onPopstate);
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=query-params.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-params.js","sourceRoot":"","sources":["../src/query-params.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function initSwitchEngine(): () => void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ATTR, SEL } from "./attrs.js";
|
|
2
|
+
import { applySwitchState } from "./helpers/dom.js";
|
|
3
|
+
import { onElement } from "./dom-observer.js";
|
|
4
|
+
export function initSwitchEngine() {
|
|
5
|
+
// Re-apply whenever gg-switch-state changes on any element.
|
|
6
|
+
const observer = new MutationObserver((mutations) => {
|
|
7
|
+
mutations.forEach((m) => {
|
|
8
|
+
if (m.attributeName === ATTR.switchState &&
|
|
9
|
+
m.target instanceof Element) {
|
|
10
|
+
applySwitchState(m.target);
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
observer.observe(document.body, {
|
|
15
|
+
attributes: true,
|
|
16
|
+
attributeFilter: [ATTR.switchState],
|
|
17
|
+
subtree: true,
|
|
18
|
+
});
|
|
19
|
+
// Initial pass for elements present at start AND any inserted later — the
|
|
20
|
+
// mutation observer above only fires on attribute *changes*, so freshly
|
|
21
|
+
// inserted nodes need an explicit apply.
|
|
22
|
+
const unbind = onElement(SEL.switchState, applySwitchState);
|
|
23
|
+
return () => {
|
|
24
|
+
observer.disconnect();
|
|
25
|
+
unbind();
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=switch-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switch-engine.js","sourceRoot":"","sources":["../src/switch-engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,MAAM,UAAU,gBAAgB;IAC9B,4DAA4D;IAC5D,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,CAAC,SAAS,EAAE,EAAE;QAClD,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACtB,IACE,CAAC,CAAC,aAAa,KAAK,IAAI,CAAC,WAAW;gBACpC,CAAC,CAAC,MAAM,YAAY,OAAO,EAC3B,CAAC;gBACD,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE;QAC9B,UAAU,EAAE,IAAI;QAChB,eAAe,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;QACnC,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IAEH,0EAA0E;IAC1E,wEAAwE;IACxE,yCAAyC;IACzC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;IAE5D,OAAO,GAAG,EAAE;QACV,QAAQ,CAAC,UAAU,EAAE,CAAC;QACtB,MAAM,EAAE,CAAC;IACX,CAAC,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gg-wf-scripts",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"exports":
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"default": "./dist/index.js"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"clean": "rimraf dist",
|
|
16
|
+
"build": "npm run clean && tsc",
|
|
17
|
+
"typecheck": "tsc --noEmit",
|
|
18
|
+
"prepublishOnly": "npm run build",
|
|
19
|
+
"docs:dev": "vitepress dev docs",
|
|
20
|
+
"docs:build": "vitepress build docs",
|
|
21
|
+
"docs:preview": "vitepress preview docs"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"rimraf": "^6.1.3",
|
|
25
|
+
"typescript": "^6.0.3",
|
|
26
|
+
"vitepress": "^1.6.4",
|
|
27
|
+
"vitepress-plugin-llms": "^1.12.1"
|
|
28
|
+
}
|
|
6
29
|
}
|
package/src/action-engine.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { actionRegistry } from "./actions.js";
|
|
2
|
-
import { withDebugLog } from "./helpers/log.js";
|
|
3
|
-
import { getParams } from "./query-params.js";
|
|
4
|
-
|
|
5
|
-
function parseActionData(el) {
|
|
6
|
-
const attr = el.getAttribute("gg-action-data");
|
|
7
|
-
if (!attr) return {};
|
|
8
|
-
const data = {};
|
|
9
|
-
attr
|
|
10
|
-
.split(",")
|
|
11
|
-
.filter(Boolean)
|
|
12
|
-
.forEach((pair) => {
|
|
13
|
-
const [key, value] = pair.split(":");
|
|
14
|
-
if (key?.trim()) data[key.trim()] = value?.trim() ?? "";
|
|
15
|
-
});
|
|
16
|
-
return data;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function findRecord(el) {
|
|
20
|
-
let node = el.parentElement;
|
|
21
|
-
while (node) {
|
|
22
|
-
if (node.__ggRecord) return node.__ggRecord;
|
|
23
|
-
node = node.parentElement;
|
|
24
|
-
}
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function initActionEngine(context, { debug = false } = {}) {
|
|
29
|
-
async function handleAction(el) {
|
|
30
|
-
const id = el.getAttribute("gg-action");
|
|
31
|
-
const action = actionRegistry[id];
|
|
32
|
-
if (!action) {
|
|
33
|
-
console.warn(`[gg-action] no action registered for "${id}"`);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const record = findRecord(el);
|
|
38
|
-
const explicit = parseActionData(el);
|
|
39
|
-
const data = record ? { ...record, ...explicit } : explicit;
|
|
40
|
-
const params = getParams();
|
|
41
|
-
|
|
42
|
-
const result = await withDebugLog(
|
|
43
|
-
"[gg-action]",
|
|
44
|
-
id,
|
|
45
|
-
{ trigger: el, data, params: Object.fromEntries(params) },
|
|
46
|
-
debug,
|
|
47
|
-
() => action(context, data, params),
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
if (result?.ok === false) {
|
|
51
|
-
console.warn(`[gg-action] "${id}" failed:`, result.error ?? "unknown error");
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
document.addEventListener("click", (e) => {
|
|
56
|
-
const trigger = e.target.closest("[gg-action]");
|
|
57
|
-
if (trigger) handleAction(trigger);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
document.addEventListener("gg:shadow:click", (e) => {
|
|
61
|
-
const trigger = e.detail.target.closest("[gg-action]");
|
|
62
|
-
if (trigger) handleAction(trigger);
|
|
63
|
-
});
|
|
64
|
-
}
|
package/src/actions.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export const actionRegistry = {};
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Register an action triggered by gg-action="<id>" on click.
|
|
5
|
-
*
|
|
6
|
-
* @param {string} id - The action identifier, referenced by gg-action="<id>" in markup.
|
|
7
|
-
* @param {(context: object, data: object, params: URLSearchParams) => Promise<{ok: boolean, error?: any}>} fn
|
|
8
|
-
* Receives the context object passed to init(), a data object (merged from the nearest
|
|
9
|
-
* gg-data record and any explicit gg-action-data attribute), and a URLSearchParams snapshot
|
|
10
|
-
* of the current URL query string. Return { ok: true } or { ok: false, error }.
|
|
11
|
-
*/
|
|
12
|
-
export function registerAction(id, fn) {
|
|
13
|
-
actionRegistry[id] = fn;
|
|
14
|
-
}
|
package/src/auth.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export async function initAuth(context, auth) {
|
|
2
|
-
const { getUser, onChange, roleQuery } = auth;
|
|
3
|
-
|
|
4
|
-
async function applyAuthAttrs(userId) {
|
|
5
|
-
const body = document.body;
|
|
6
|
-
if (!userId) {
|
|
7
|
-
body.setAttribute("gg-auth", "false");
|
|
8
|
-
body.removeAttribute("gg-role");
|
|
9
|
-
return;
|
|
10
|
-
}
|
|
11
|
-
body.setAttribute("gg-auth", "true");
|
|
12
|
-
if (roleQuery) {
|
|
13
|
-
const role = await roleQuery(context, userId);
|
|
14
|
-
if (role) {
|
|
15
|
-
body.setAttribute("gg-role", role);
|
|
16
|
-
} else {
|
|
17
|
-
body.removeAttribute("gg-role");
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const userId = await getUser();
|
|
23
|
-
applyAuthAttrs(userId ?? null);
|
|
24
|
-
|
|
25
|
-
if (onChange) {
|
|
26
|
-
onChange((userId) => applyAuthAttrs(userId ?? null));
|
|
27
|
-
}
|
|
28
|
-
}
|