@plures/praxis 0.2.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/FRAMEWORK.md +420 -0
- package/LICENSE +21 -0
- package/README.md +1310 -0
- package/dist/adapters/cli.d.ts +43 -0
- package/dist/adapters/cli.d.ts.map +1 -0
- package/dist/adapters/cli.js +126 -0
- package/dist/adapters/cli.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +26 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +233 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/cloud.d.ts +27 -0
- package/dist/cli/commands/cloud.d.ts.map +1 -0
- package/dist/cli/commands/cloud.js +232 -0
- package/dist/cli/commands/cloud.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +25 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +168 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +179 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cloud/auth.d.ts +51 -0
- package/dist/cloud/auth.d.ts.map +1 -0
- package/dist/cloud/auth.js +194 -0
- package/dist/cloud/auth.js.map +1 -0
- package/dist/cloud/billing.d.ts +184 -0
- package/dist/cloud/billing.d.ts.map +1 -0
- package/dist/cloud/billing.js +179 -0
- package/dist/cloud/billing.js.map +1 -0
- package/dist/cloud/client.d.ts +39 -0
- package/dist/cloud/client.d.ts.map +1 -0
- package/dist/cloud/client.js +176 -0
- package/dist/cloud/client.js.map +1 -0
- package/dist/cloud/index.d.ts +44 -0
- package/dist/cloud/index.d.ts.map +1 -0
- package/dist/cloud/index.js +44 -0
- package/dist/cloud/index.js.map +1 -0
- package/dist/cloud/marketplace.d.ts +166 -0
- package/dist/cloud/marketplace.d.ts.map +1 -0
- package/dist/cloud/marketplace.js +159 -0
- package/dist/cloud/marketplace.js.map +1 -0
- package/dist/cloud/provisioning.d.ts +110 -0
- package/dist/cloud/provisioning.d.ts.map +1 -0
- package/dist/cloud/provisioning.js +148 -0
- package/dist/cloud/provisioning.js.map +1 -0
- package/dist/cloud/relay/endpoints.d.ts +62 -0
- package/dist/cloud/relay/endpoints.d.ts.map +1 -0
- package/dist/cloud/relay/endpoints.js +217 -0
- package/dist/cloud/relay/endpoints.js.map +1 -0
- package/dist/cloud/relay/health/index.d.ts +5 -0
- package/dist/cloud/relay/health/index.d.ts.map +1 -0
- package/dist/cloud/relay/health/index.js +9 -0
- package/dist/cloud/relay/health/index.js.map +1 -0
- package/dist/cloud/relay/stats/index.d.ts +5 -0
- package/dist/cloud/relay/stats/index.d.ts.map +1 -0
- package/dist/cloud/relay/stats/index.js +9 -0
- package/dist/cloud/relay/stats/index.js.map +1 -0
- package/dist/cloud/relay/sync/index.d.ts +5 -0
- package/dist/cloud/relay/sync/index.d.ts.map +1 -0
- package/dist/cloud/relay/sync/index.js +9 -0
- package/dist/cloud/relay/sync/index.js.map +1 -0
- package/dist/cloud/relay/usage/index.d.ts +5 -0
- package/dist/cloud/relay/usage/index.d.ts.map +1 -0
- package/dist/cloud/relay/usage/index.js +9 -0
- package/dist/cloud/relay/usage/index.js.map +1 -0
- package/dist/cloud/sponsors.d.ts +81 -0
- package/dist/cloud/sponsors.d.ts.map +1 -0
- package/dist/cloud/sponsors.js +130 -0
- package/dist/cloud/sponsors.js.map +1 -0
- package/dist/cloud/types.d.ts +169 -0
- package/dist/cloud/types.d.ts.map +1 -0
- package/dist/cloud/types.js +7 -0
- package/dist/cloud/types.js.map +1 -0
- package/dist/components/index.d.ts +43 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +17 -0
- package/dist/components/index.js.map +1 -0
- package/dist/core/actors.d.ts +95 -0
- package/dist/core/actors.d.ts.map +1 -0
- package/dist/core/actors.js +158 -0
- package/dist/core/actors.js.map +1 -0
- package/dist/core/component/generator.d.ts +122 -0
- package/dist/core/component/generator.d.ts.map +1 -0
- package/dist/core/component/generator.js +307 -0
- package/dist/core/component/generator.js.map +1 -0
- package/dist/core/engine.d.ts +92 -0
- package/dist/core/engine.d.ts.map +1 -0
- package/dist/core/engine.js +199 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/introspection.d.ts +141 -0
- package/dist/core/introspection.d.ts.map +1 -0
- package/dist/core/introspection.js +208 -0
- package/dist/core/introspection.js.map +1 -0
- package/dist/core/logic/generator.d.ts +76 -0
- package/dist/core/logic/generator.d.ts.map +1 -0
- package/dist/core/logic/generator.js +339 -0
- package/dist/core/logic/generator.js.map +1 -0
- package/dist/core/pluresdb/generator.d.ts +58 -0
- package/dist/core/pluresdb/generator.d.ts.map +1 -0
- package/dist/core/pluresdb/generator.js +162 -0
- package/dist/core/pluresdb/generator.js.map +1 -0
- package/dist/core/protocol.d.ts +121 -0
- package/dist/core/protocol.d.ts.map +1 -0
- package/dist/core/protocol.js +46 -0
- package/dist/core/protocol.js.map +1 -0
- package/dist/core/rules.d.ts +120 -0
- package/dist/core/rules.d.ts.map +1 -0
- package/dist/core/rules.js +81 -0
- package/dist/core/rules.js.map +1 -0
- package/dist/core/schema/loader.d.ts +47 -0
- package/dist/core/schema/loader.d.ts.map +1 -0
- package/dist/core/schema/loader.js +189 -0
- package/dist/core/schema/loader.js.map +1 -0
- package/dist/core/schema/normalize.d.ts +72 -0
- package/dist/core/schema/normalize.d.ts.map +1 -0
- package/dist/core/schema/normalize.js +190 -0
- package/dist/core/schema/normalize.js.map +1 -0
- package/dist/core/schema/types.d.ts +370 -0
- package/dist/core/schema/types.d.ts.map +1 -0
- package/dist/core/schema/types.js +161 -0
- package/dist/core/schema/types.js.map +1 -0
- package/dist/dsl/index.d.ts +152 -0
- package/dist/dsl/index.d.ts.map +1 -0
- package/dist/dsl/index.js +132 -0
- package/dist/dsl/index.js.map +1 -0
- package/dist/dsl.d.ts +124 -0
- package/dist/dsl.d.ts.map +1 -0
- package/dist/dsl.js +130 -0
- package/dist/dsl.js.map +1 -0
- package/dist/examples/advanced-todo/index.d.ts +55 -0
- package/dist/examples/advanced-todo/index.d.ts.map +1 -0
- package/dist/examples/advanced-todo/index.js +222 -0
- package/dist/examples/advanced-todo/index.js.map +1 -0
- package/dist/examples/auth-basic/index.d.ts +17 -0
- package/dist/examples/auth-basic/index.d.ts.map +1 -0
- package/dist/examples/auth-basic/index.js +122 -0
- package/dist/examples/auth-basic/index.js.map +1 -0
- package/dist/examples/cart/index.d.ts +19 -0
- package/dist/examples/cart/index.d.ts.map +1 -0
- package/dist/examples/cart/index.js +202 -0
- package/dist/examples/cart/index.js.map +1 -0
- package/dist/examples/hero-ecommerce/index.d.ts +39 -0
- package/dist/examples/hero-ecommerce/index.d.ts.map +1 -0
- package/dist/examples/hero-ecommerce/index.js +506 -0
- package/dist/examples/hero-ecommerce/index.js.map +1 -0
- package/dist/examples/svelte-counter/index.d.ts +31 -0
- package/dist/examples/svelte-counter/index.d.ts.map +1 -0
- package/dist/examples/svelte-counter/index.js +123 -0
- package/dist/examples/svelte-counter/index.js.map +1 -0
- package/dist/flows.d.ts +125 -0
- package/dist/flows.d.ts.map +1 -0
- package/dist/flows.js +160 -0
- package/dist/flows.js.map +1 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/pluresdb.d.ts +56 -0
- package/dist/integrations/pluresdb.d.ts.map +1 -0
- package/dist/integrations/pluresdb.js +46 -0
- package/dist/integrations/pluresdb.js.map +1 -0
- package/dist/integrations/svelte.d.ts +306 -0
- package/dist/integrations/svelte.d.ts.map +1 -0
- package/dist/integrations/svelte.js +447 -0
- package/dist/integrations/svelte.js.map +1 -0
- package/dist/registry.d.ts +94 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +181 -0
- package/dist/registry.js.map +1 -0
- package/dist/runtime/terminal-adapter.d.ts +105 -0
- package/dist/runtime/terminal-adapter.d.ts.map +1 -0
- package/dist/runtime/terminal-adapter.js +113 -0
- package/dist/runtime/terminal-adapter.js.map +1 -0
- package/dist/step.d.ts +34 -0
- package/dist/step.d.ts.map +1 -0
- package/dist/step.js +111 -0
- package/dist/step.js.map +1 -0
- package/dist/types.d.ts +63 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/docs/MONETIZATION.md +394 -0
- package/docs/TERMINAL_NODE.md +588 -0
- package/docs/guides/canvas.md +389 -0
- package/docs/guides/getting-started.md +347 -0
- package/docs/guides/history-state-pattern.md +618 -0
- package/docs/guides/orchestration.md +617 -0
- package/docs/guides/parallel-state-pattern.md +767 -0
- package/docs/guides/svelte-integration.md +691 -0
- package/package.json +96 -0
- package/src/__tests__/actors.test.ts +270 -0
- package/src/__tests__/billing.test.ts +175 -0
- package/src/__tests__/cloud.test.ts +247 -0
- package/src/__tests__/dsl.test.ts +154 -0
- package/src/__tests__/edge-cases.test.ts +475 -0
- package/src/__tests__/engine.test.ts +137 -0
- package/src/__tests__/generators.test.ts +270 -0
- package/src/__tests__/introspection.test.ts +321 -0
- package/src/__tests__/protocol.test.ts +40 -0
- package/src/__tests__/provisioning.test.ts +162 -0
- package/src/__tests__/schema.test.ts +241 -0
- package/src/__tests__/svelte-integration.test.ts +431 -0
- package/src/__tests__/terminal-node.test.ts +352 -0
- package/src/adapters/cli.ts +175 -0
- package/src/cli/commands/auth.ts +271 -0
- package/src/cli/commands/cloud.ts +281 -0
- package/src/cli/commands/generate.ts +225 -0
- package/src/cli/index.ts +190 -0
- package/src/cloud/README.md +383 -0
- package/src/cloud/auth.ts +245 -0
- package/src/cloud/billing.ts +336 -0
- package/src/cloud/client.ts +221 -0
- package/src/cloud/index.ts +121 -0
- package/src/cloud/marketplace.ts +303 -0
- package/src/cloud/provisioning.ts +254 -0
- package/src/cloud/relay/endpoints.ts +307 -0
- package/src/cloud/relay/health/function.json +17 -0
- package/src/cloud/relay/health/index.ts +10 -0
- package/src/cloud/relay/host.json +15 -0
- package/src/cloud/relay/local.settings.json +8 -0
- package/src/cloud/relay/stats/function.json +17 -0
- package/src/cloud/relay/stats/index.ts +10 -0
- package/src/cloud/relay/sync/function.json +17 -0
- package/src/cloud/relay/sync/index.ts +10 -0
- package/src/cloud/relay/usage/function.json +17 -0
- package/src/cloud/relay/usage/index.ts +10 -0
- package/src/cloud/sponsors.ts +213 -0
- package/src/cloud/types.ts +198 -0
- package/src/components/README.md +125 -0
- package/src/components/TerminalNode.svelte +457 -0
- package/src/components/index.ts +46 -0
- package/src/core/actors.ts +205 -0
- package/src/core/component/generator.ts +432 -0
- package/src/core/engine.ts +243 -0
- package/src/core/introspection.ts +329 -0
- package/src/core/logic/generator.ts +420 -0
- package/src/core/pluresdb/generator.ts +229 -0
- package/src/core/protocol.ts +132 -0
- package/src/core/rules.ts +167 -0
- package/src/core/schema/loader.ts +247 -0
- package/src/core/schema/normalize.ts +322 -0
- package/src/core/schema/types.ts +557 -0
- package/src/dsl/index.ts +218 -0
- package/src/dsl.ts +214 -0
- package/src/examples/advanced-todo/App.svelte +506 -0
- package/src/examples/advanced-todo/README.md +371 -0
- package/src/examples/advanced-todo/index.ts +309 -0
- package/src/examples/auth-basic/index.ts +163 -0
- package/src/examples/cart/index.ts +259 -0
- package/src/examples/hero-ecommerce/index.ts +657 -0
- package/src/examples/svelte-counter/index.ts +168 -0
- package/src/flows.ts +268 -0
- package/src/index.ts +154 -0
- package/src/integrations/pluresdb.ts +93 -0
- package/src/integrations/svelte.ts +617 -0
- package/src/registry.ts +223 -0
- package/src/runtime/terminal-adapter.ts +175 -0
- package/src/step.ts +151 -0
- package/src/types.ts +70 -0
- package/templates/basic-app/README.md +147 -0
- package/templates/fullstack-app/README.md +279 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-Provisioning
|
|
3
|
+
*
|
|
4
|
+
* Automatic tenant/storage provisioning based on GitHub identity.
|
|
5
|
+
*/
|
|
6
|
+
import type { GitHubUser } from "./types.js";
|
|
7
|
+
import type { Subscription } from "./billing.js";
|
|
8
|
+
/**
|
|
9
|
+
* Tenant information
|
|
10
|
+
*/
|
|
11
|
+
export interface Tenant {
|
|
12
|
+
/**
|
|
13
|
+
* Tenant ID (derived from GitHub user/org)
|
|
14
|
+
*/
|
|
15
|
+
id: string;
|
|
16
|
+
/**
|
|
17
|
+
* GitHub user ID
|
|
18
|
+
*/
|
|
19
|
+
githubUserId: number;
|
|
20
|
+
/**
|
|
21
|
+
* GitHub login (username or org name)
|
|
22
|
+
*/
|
|
23
|
+
githubLogin: string;
|
|
24
|
+
/**
|
|
25
|
+
* Tenant type
|
|
26
|
+
*/
|
|
27
|
+
type: "user" | "organization";
|
|
28
|
+
/**
|
|
29
|
+
* Subscription
|
|
30
|
+
*/
|
|
31
|
+
subscription: Subscription;
|
|
32
|
+
/**
|
|
33
|
+
* Storage namespace
|
|
34
|
+
*/
|
|
35
|
+
storageNamespace: string;
|
|
36
|
+
/**
|
|
37
|
+
* Creation timestamp
|
|
38
|
+
*/
|
|
39
|
+
createdAt: number;
|
|
40
|
+
/**
|
|
41
|
+
* Last accessed timestamp
|
|
42
|
+
*/
|
|
43
|
+
lastAccessedAt: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Generate a storage namespace from GitHub login
|
|
47
|
+
*
|
|
48
|
+
* Namespace format: gh-{login}-{hash}
|
|
49
|
+
* This ensures uniqueness and follows Azure Blob Storage naming rules.
|
|
50
|
+
*/
|
|
51
|
+
export declare function generateStorageNamespace(githubLogin: string, userId: number): string;
|
|
52
|
+
/**
|
|
53
|
+
* Generate tenant ID from GitHub user
|
|
54
|
+
*/
|
|
55
|
+
export declare function generateTenantId(githubUser: GitHubUser): string;
|
|
56
|
+
/**
|
|
57
|
+
* Create a tenant from GitHub user
|
|
58
|
+
*/
|
|
59
|
+
export declare function createTenant(githubUser: GitHubUser, subscription: Subscription): Tenant;
|
|
60
|
+
/**
|
|
61
|
+
* Validate storage namespace
|
|
62
|
+
*
|
|
63
|
+
* Ensures namespace follows Azure Blob Storage naming rules:
|
|
64
|
+
* - 3-63 characters
|
|
65
|
+
* - lowercase letters, numbers, and hyphens only
|
|
66
|
+
* - must start with letter or number
|
|
67
|
+
* - no consecutive hyphens
|
|
68
|
+
*/
|
|
69
|
+
export declare function validateStorageNamespace(namespace: string): {
|
|
70
|
+
valid: boolean;
|
|
71
|
+
error?: string;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Get storage container name for an app
|
|
75
|
+
*/
|
|
76
|
+
export declare function getAppStorageContainer(tenantNamespace: string, appId: string): string;
|
|
77
|
+
/**
|
|
78
|
+
* Provisioning result
|
|
79
|
+
*/
|
|
80
|
+
export interface ProvisioningResult {
|
|
81
|
+
/**
|
|
82
|
+
* Whether provisioning was successful
|
|
83
|
+
*/
|
|
84
|
+
success: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Tenant (if successful)
|
|
87
|
+
*/
|
|
88
|
+
tenant?: Tenant;
|
|
89
|
+
/**
|
|
90
|
+
* Error message (if failed)
|
|
91
|
+
*/
|
|
92
|
+
error?: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Provision a new tenant
|
|
96
|
+
*
|
|
97
|
+
* This would typically:
|
|
98
|
+
* 1. Create storage containers
|
|
99
|
+
* 2. Set up access policies
|
|
100
|
+
* 3. Initialize tenant metadata
|
|
101
|
+
* 4. Register with billing system
|
|
102
|
+
*/
|
|
103
|
+
export declare function provisionTenant(githubUser: GitHubUser, subscription: Subscription): Promise<ProvisioningResult>;
|
|
104
|
+
/**
|
|
105
|
+
* Get or create tenant
|
|
106
|
+
*
|
|
107
|
+
* Checks if tenant exists, creates if not.
|
|
108
|
+
*/
|
|
109
|
+
export declare function getOrCreateTenant(githubUser: GitHubUser, subscription: Subscription, tenantLookup: (id: string) => Promise<Tenant | null>): Promise<Tenant>;
|
|
110
|
+
//# sourceMappingURL=provisioning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provisioning.d.ts","sourceRoot":"","sources":["../../src/cloud/provisioning.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,cAAc,CAAC;IAE9B;;OAEG;IACH,YAAY,EAAE,YAAY,CAAC;IAE3B;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CASpF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAE/D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,YAAY,GACzB,MAAM,CAiBR;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG;IAC3D,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CA8BA;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,MAAM,GACZ,MAAM,CAIR;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,kBAAkB,CAAC,CAiC7B;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GACnD,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-Provisioning
|
|
3
|
+
*
|
|
4
|
+
* Automatic tenant/storage provisioning based on GitHub identity.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Generate a storage namespace from GitHub login
|
|
8
|
+
*
|
|
9
|
+
* Namespace format: gh-{login}-{hash}
|
|
10
|
+
* This ensures uniqueness and follows Azure Blob Storage naming rules.
|
|
11
|
+
*/
|
|
12
|
+
export function generateStorageNamespace(githubLogin, userId) {
|
|
13
|
+
// Sanitize login: lowercase, replace non-alphanumeric with hyphens
|
|
14
|
+
const sanitized = githubLogin.toLowerCase().replace(/[^a-z0-9]/g, "-");
|
|
15
|
+
// Create a simple hash from user ID for uniqueness
|
|
16
|
+
const hash = userId.toString(36).padStart(6, "0");
|
|
17
|
+
// Combine with prefix
|
|
18
|
+
return `gh-${sanitized}-${hash}`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Generate tenant ID from GitHub user
|
|
22
|
+
*/
|
|
23
|
+
export function generateTenantId(githubUser) {
|
|
24
|
+
return `github-${githubUser.id}`;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Create a tenant from GitHub user
|
|
28
|
+
*/
|
|
29
|
+
export function createTenant(githubUser, subscription) {
|
|
30
|
+
const tenantId = generateTenantId(githubUser);
|
|
31
|
+
const storageNamespace = generateStorageNamespace(githubUser.login, githubUser.id);
|
|
32
|
+
return {
|
|
33
|
+
id: tenantId,
|
|
34
|
+
githubUserId: githubUser.id,
|
|
35
|
+
githubLogin: githubUser.login,
|
|
36
|
+
type: "user", // Could be "organization" if checking org membership
|
|
37
|
+
subscription,
|
|
38
|
+
storageNamespace,
|
|
39
|
+
createdAt: Date.now(),
|
|
40
|
+
lastAccessedAt: Date.now(),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Validate storage namespace
|
|
45
|
+
*
|
|
46
|
+
* Ensures namespace follows Azure Blob Storage naming rules:
|
|
47
|
+
* - 3-63 characters
|
|
48
|
+
* - lowercase letters, numbers, and hyphens only
|
|
49
|
+
* - must start with letter or number
|
|
50
|
+
* - no consecutive hyphens
|
|
51
|
+
*/
|
|
52
|
+
export function validateStorageNamespace(namespace) {
|
|
53
|
+
if (namespace.length < 3 || namespace.length > 63) {
|
|
54
|
+
return {
|
|
55
|
+
valid: false,
|
|
56
|
+
error: "Namespace must be 3-63 characters",
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (!/^[a-z0-9]/.test(namespace)) {
|
|
60
|
+
return {
|
|
61
|
+
valid: false,
|
|
62
|
+
error: "Namespace must start with a letter or number",
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (!/^[a-z0-9-]+$/.test(namespace)) {
|
|
66
|
+
return {
|
|
67
|
+
valid: false,
|
|
68
|
+
error: "Namespace can only contain lowercase letters, numbers, and hyphens",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (/--/.test(namespace)) {
|
|
72
|
+
return {
|
|
73
|
+
valid: false,
|
|
74
|
+
error: "Namespace cannot contain consecutive hyphens",
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return { valid: true };
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get storage container name for an app
|
|
81
|
+
*/
|
|
82
|
+
export function getAppStorageContainer(tenantNamespace, appId) {
|
|
83
|
+
// Sanitize app ID
|
|
84
|
+
const sanitizedAppId = appId.toLowerCase().replace(/[^a-z0-9]/g, "-");
|
|
85
|
+
return `${tenantNamespace}-${sanitizedAppId}`;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Provision a new tenant
|
|
89
|
+
*
|
|
90
|
+
* This would typically:
|
|
91
|
+
* 1. Create storage containers
|
|
92
|
+
* 2. Set up access policies
|
|
93
|
+
* 3. Initialize tenant metadata
|
|
94
|
+
* 4. Register with billing system
|
|
95
|
+
*/
|
|
96
|
+
export async function provisionTenant(githubUser, subscription) {
|
|
97
|
+
try {
|
|
98
|
+
const tenant = createTenant(githubUser, subscription);
|
|
99
|
+
// Validate storage namespace
|
|
100
|
+
const validation = validateStorageNamespace(tenant.storageNamespace);
|
|
101
|
+
if (!validation.valid) {
|
|
102
|
+
return {
|
|
103
|
+
success: false,
|
|
104
|
+
error: validation.error,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
// TODO: In production, this would:
|
|
108
|
+
// 1. Create Azure Blob Storage container
|
|
109
|
+
// 2. Set up access policies
|
|
110
|
+
// 3. Store tenant metadata in database
|
|
111
|
+
// 4. Send welcome email
|
|
112
|
+
// 5. Log provisioning event
|
|
113
|
+
console.log(`Provisioned tenant: ${tenant.id}`);
|
|
114
|
+
console.log(`Storage namespace: ${tenant.storageNamespace}`);
|
|
115
|
+
return {
|
|
116
|
+
success: true,
|
|
117
|
+
tenant,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
return {
|
|
122
|
+
success: false,
|
|
123
|
+
error: error instanceof Error ? error.message : String(error),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get or create tenant
|
|
129
|
+
*
|
|
130
|
+
* Checks if tenant exists, creates if not.
|
|
131
|
+
*/
|
|
132
|
+
export async function getOrCreateTenant(githubUser, subscription, tenantLookup) {
|
|
133
|
+
const tenantId = generateTenantId(githubUser);
|
|
134
|
+
// Try to get existing tenant
|
|
135
|
+
const existing = await tenantLookup(tenantId);
|
|
136
|
+
if (existing) {
|
|
137
|
+
// Update last accessed time
|
|
138
|
+
existing.lastAccessedAt = Date.now();
|
|
139
|
+
return existing;
|
|
140
|
+
}
|
|
141
|
+
// Provision new tenant
|
|
142
|
+
const result = await provisionTenant(githubUser, subscription);
|
|
143
|
+
if (!result.success || !result.tenant) {
|
|
144
|
+
throw new Error(`Failed to provision tenant: ${result.error}`);
|
|
145
|
+
}
|
|
146
|
+
return result.tenant;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=provisioning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provisioning.js","sourceRoot":"","sources":["../../src/cloud/provisioning.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Azure Functions Relay Endpoints
|
|
3
|
+
*
|
|
4
|
+
* HTTP-triggered Azure Functions for Praxis Cloud Relay.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Azure Function context (simplified interface)
|
|
8
|
+
*/
|
|
9
|
+
export interface AzureContext {
|
|
10
|
+
log: (message: string) => void;
|
|
11
|
+
done: (err?: Error, result?: unknown) => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Azure HTTP request
|
|
15
|
+
*/
|
|
16
|
+
export interface AzureHttpRequest {
|
|
17
|
+
method: string;
|
|
18
|
+
url: string;
|
|
19
|
+
headers: Record<string, string>;
|
|
20
|
+
query: Record<string, string>;
|
|
21
|
+
body?: unknown;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Azure HTTP response
|
|
25
|
+
*/
|
|
26
|
+
export interface AzureHttpResponse {
|
|
27
|
+
status: number;
|
|
28
|
+
headers?: Record<string, string>;
|
|
29
|
+
body?: unknown;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Health check endpoint
|
|
33
|
+
* GET /health
|
|
34
|
+
*/
|
|
35
|
+
export declare function healthEndpoint(context: AzureContext, _req: AzureHttpRequest): Promise<AzureHttpResponse>;
|
|
36
|
+
/**
|
|
37
|
+
* CRDT sync endpoint
|
|
38
|
+
* POST /sync
|
|
39
|
+
*/
|
|
40
|
+
export declare function syncEndpoint(context: AzureContext, req: AzureHttpRequest): Promise<AzureHttpResponse>;
|
|
41
|
+
/**
|
|
42
|
+
* Usage metrics endpoint
|
|
43
|
+
* GET /usage?appId=<appId>
|
|
44
|
+
*/
|
|
45
|
+
export declare function usageEndpoint(context: AzureContext, req: AzureHttpRequest): Promise<AzureHttpResponse>;
|
|
46
|
+
/**
|
|
47
|
+
* Stats endpoint for aggregated metrics
|
|
48
|
+
* GET /stats?appId=<appId>
|
|
49
|
+
*/
|
|
50
|
+
export declare function statsEndpoint(context: AzureContext, req: AzureHttpRequest): Promise<AzureHttpResponse>;
|
|
51
|
+
/**
|
|
52
|
+
* Event forwarding endpoint
|
|
53
|
+
* POST /events
|
|
54
|
+
*/
|
|
55
|
+
export declare function eventsEndpoint(context: AzureContext, req: AzureHttpRequest): Promise<AzureHttpResponse>;
|
|
56
|
+
/**
|
|
57
|
+
* Schema registry endpoint
|
|
58
|
+
* GET /schema?appId=<appId>
|
|
59
|
+
* POST /schema (to register a schema)
|
|
60
|
+
*/
|
|
61
|
+
export declare function schemaEndpoint(context: AzureContext, req: AzureHttpRequest): Promise<AzureHttpResponse>;
|
|
62
|
+
//# sourceMappingURL=endpoints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoints.d.ts","sourceRoot":"","sources":["../../../src/cloud/relay/endpoints.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAUD;;;GAGG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,YAAY,EACrB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,iBAAiB,CAAC,CAoB5B;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,YAAY,EACrB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,iBAAiB,CAAC,CAwD5B;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,YAAY,EACrB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,iBAAiB,CAAC,CA0B5B;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,YAAY,EACrB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,iBAAiB,CAAC,CAyB5B;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,YAAY,EACrB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,iBAAiB,CAAC,CAgC5B;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,YAAY,EACrB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,iBAAiB,CAAC,CA8C5B"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Azure Functions Relay Endpoints
|
|
3
|
+
*
|
|
4
|
+
* HTTP-triggered Azure Functions for Praxis Cloud Relay.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* In-memory storage for demo (replace with Azure Storage in production)
|
|
8
|
+
*/
|
|
9
|
+
const storage = {
|
|
10
|
+
syncs: new Map(),
|
|
11
|
+
usage: new Map(),
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Health check endpoint
|
|
15
|
+
* GET /health
|
|
16
|
+
*/
|
|
17
|
+
export async function healthEndpoint(context, _req) {
|
|
18
|
+
context.log("Health check requested");
|
|
19
|
+
const response = {
|
|
20
|
+
status: "healthy",
|
|
21
|
+
timestamp: Date.now(),
|
|
22
|
+
version: "0.1.0",
|
|
23
|
+
services: {
|
|
24
|
+
relay: true,
|
|
25
|
+
eventGrid: true,
|
|
26
|
+
storage: true,
|
|
27
|
+
auth: true,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
return {
|
|
31
|
+
status: 200,
|
|
32
|
+
headers: { "Content-Type": "application/json" },
|
|
33
|
+
body: response,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* CRDT sync endpoint
|
|
38
|
+
* POST /sync
|
|
39
|
+
*/
|
|
40
|
+
export async function syncEndpoint(context, req) {
|
|
41
|
+
context.log("Sync request received");
|
|
42
|
+
// Validate request
|
|
43
|
+
if (req.method !== "POST") {
|
|
44
|
+
return {
|
|
45
|
+
status: 405,
|
|
46
|
+
body: { error: "Method not allowed" },
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const message = req.body;
|
|
50
|
+
if (!message || !message.appId) {
|
|
51
|
+
return {
|
|
52
|
+
status: 400,
|
|
53
|
+
body: { error: "Invalid sync message" },
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
// Store sync message
|
|
57
|
+
const appSyncs = storage.syncs.get(message.appId) || [];
|
|
58
|
+
appSyncs.push(message);
|
|
59
|
+
storage.syncs.set(message.appId, appSyncs);
|
|
60
|
+
// Update usage metrics
|
|
61
|
+
const usage = storage.usage.get(message.appId) || {
|
|
62
|
+
appId: message.appId,
|
|
63
|
+
syncCount: 0,
|
|
64
|
+
eventCount: 0,
|
|
65
|
+
factCount: 0,
|
|
66
|
+
storageBytes: 0,
|
|
67
|
+
periodStart: Date.now(),
|
|
68
|
+
periodEnd: Date.now(),
|
|
69
|
+
};
|
|
70
|
+
usage.syncCount++;
|
|
71
|
+
usage.eventCount += message.events?.length || 0;
|
|
72
|
+
usage.factCount += message.facts?.length || 0;
|
|
73
|
+
usage.storageBytes += JSON.stringify(message).length;
|
|
74
|
+
usage.periodEnd = Date.now();
|
|
75
|
+
storage.usage.set(message.appId, usage);
|
|
76
|
+
context.log(`Synced for app ${message.appId}: ${usage.syncCount} total syncs`);
|
|
77
|
+
// Return updated vector clock
|
|
78
|
+
return {
|
|
79
|
+
status: 200,
|
|
80
|
+
headers: { "Content-Type": "application/json" },
|
|
81
|
+
body: {
|
|
82
|
+
success: true,
|
|
83
|
+
clock: message.clock,
|
|
84
|
+
timestamp: Date.now(),
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Usage metrics endpoint
|
|
90
|
+
* GET /usage?appId=<appId>
|
|
91
|
+
*/
|
|
92
|
+
export async function usageEndpoint(context, req) {
|
|
93
|
+
context.log("Usage metrics requested");
|
|
94
|
+
const appId = req.query.appId;
|
|
95
|
+
if (!appId) {
|
|
96
|
+
return {
|
|
97
|
+
status: 400,
|
|
98
|
+
body: { error: "appId query parameter is required" },
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const usage = storage.usage.get(appId);
|
|
102
|
+
if (!usage) {
|
|
103
|
+
return {
|
|
104
|
+
status: 404,
|
|
105
|
+
body: { error: "No usage data found for this app" },
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
status: 200,
|
|
110
|
+
headers: { "Content-Type": "application/json" },
|
|
111
|
+
body: usage,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Stats endpoint for aggregated metrics
|
|
116
|
+
* GET /stats?appId=<appId>
|
|
117
|
+
*/
|
|
118
|
+
export async function statsEndpoint(context, req) {
|
|
119
|
+
context.log("Stats requested");
|
|
120
|
+
const appId = req.query.appId;
|
|
121
|
+
if (!appId) {
|
|
122
|
+
return {
|
|
123
|
+
status: 400,
|
|
124
|
+
body: { error: "appId query parameter is required" },
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const usage = storage.usage.get(appId);
|
|
128
|
+
const syncs = storage.syncs.get(appId) || [];
|
|
129
|
+
return {
|
|
130
|
+
status: 200,
|
|
131
|
+
headers: { "Content-Type": "application/json" },
|
|
132
|
+
body: {
|
|
133
|
+
appId,
|
|
134
|
+
totalSyncs: syncs.length,
|
|
135
|
+
usage: usage || null,
|
|
136
|
+
lastSync: syncs.length > 0 ? syncs[syncs.length - 1].timestamp : null,
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Event forwarding endpoint
|
|
142
|
+
* POST /events
|
|
143
|
+
*/
|
|
144
|
+
export async function eventsEndpoint(context, req) {
|
|
145
|
+
context.log("Event forwarding requested");
|
|
146
|
+
if (req.method !== "POST") {
|
|
147
|
+
return {
|
|
148
|
+
status: 405,
|
|
149
|
+
body: { error: "Method not allowed" },
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
const { appId, events } = req.body;
|
|
153
|
+
if (!appId || !events) {
|
|
154
|
+
return {
|
|
155
|
+
status: 400,
|
|
156
|
+
body: { error: "Invalid event forwarding request" },
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
context.log(`Forwarding ${events.length} events for app ${appId}`);
|
|
160
|
+
// In production, publish to Azure Event Grid / Service Bus
|
|
161
|
+
// For now, just acknowledge receipt
|
|
162
|
+
return {
|
|
163
|
+
status: 200,
|
|
164
|
+
headers: { "Content-Type": "application/json" },
|
|
165
|
+
body: {
|
|
166
|
+
success: true,
|
|
167
|
+
forwarded: events.length,
|
|
168
|
+
timestamp: Date.now(),
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Schema registry endpoint
|
|
174
|
+
* GET /schema?appId=<appId>
|
|
175
|
+
* POST /schema (to register a schema)
|
|
176
|
+
*/
|
|
177
|
+
export async function schemaEndpoint(context, req) {
|
|
178
|
+
context.log("Schema registry requested");
|
|
179
|
+
if (req.method === "POST") {
|
|
180
|
+
const { appId, schema } = req.body;
|
|
181
|
+
if (!appId || !schema) {
|
|
182
|
+
return {
|
|
183
|
+
status: 400,
|
|
184
|
+
body: { error: "Invalid schema registration request" },
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
context.log(`Schema registered for app ${appId}`);
|
|
188
|
+
return {
|
|
189
|
+
status: 200,
|
|
190
|
+
headers: { "Content-Type": "application/json" },
|
|
191
|
+
body: {
|
|
192
|
+
success: true,
|
|
193
|
+
schemaId: `${appId}-${Date.now()}`,
|
|
194
|
+
timestamp: Date.now(),
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
// GET request
|
|
199
|
+
const appId = req.query.appId;
|
|
200
|
+
if (!appId) {
|
|
201
|
+
return {
|
|
202
|
+
status: 400,
|
|
203
|
+
body: { error: "appId query parameter is required" },
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
// Return placeholder schema
|
|
207
|
+
return {
|
|
208
|
+
status: 200,
|
|
209
|
+
headers: { "Content-Type": "application/json" },
|
|
210
|
+
body: {
|
|
211
|
+
appId,
|
|
212
|
+
schema: null,
|
|
213
|
+
message: "Schema not found",
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=endpoints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoints.js","sourceRoot":"","sources":["../../../src/cloud/relay/endpoints.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cloud/relay/health/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,yBAA+B,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,iBAGpD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/cloud/relay/health/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,CAAC,OAAO,CAAC,KAAK,WAAW,OAAY,EAAE,GAAQ;IACnD,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,GAAG,QAAQ,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cloud/relay/stats/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,yBAA+B,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,iBAGpD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/cloud/relay/stats/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,CAAC,OAAO,CAAC,KAAK,WAAW,OAAY,EAAE,GAAQ;IACnD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,GAAG,QAAQ,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cloud/relay/sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,yBAA+B,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,iBAGpD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/cloud/relay/sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,CAAC,OAAO,CAAC,KAAK,WAAW,OAAY,EAAE,GAAQ;IACnD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,GAAG,QAAQ,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cloud/relay/usage/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,yBAA+B,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,iBAGpD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/cloud/relay/usage/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,CAAC,OAAO,CAAC,KAAK,WAAW,OAAY,EAAE,GAAQ;IACnD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,GAAG,QAAQ,CAAC;AACzB,CAAC"}
|