@jami-studio/core 0.92.27 → 0.92.29

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.
Files changed (56) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +34 -0
  3. package/corpus/core/package.json +2 -1
  4. package/corpus/core/src/deploy/build.ts +120 -2
  5. package/corpus/core/src/event-bus/bus.ts +138 -140
  6. package/corpus/core/src/event-bus/registry.ts +81 -79
  7. package/corpus/core/src/file-upload/registry.ts +135 -125
  8. package/corpus/core/src/notifications/registry.ts +218 -216
  9. package/corpus/core/src/private-blob/registry.ts +246 -242
  10. package/corpus/core/src/secrets/register.ts +132 -129
  11. package/corpus/core/src/shared/global-scope.ts +75 -0
  12. package/corpus/core/src/sharing/registry.ts +193 -194
  13. package/corpus/core/src/tracking/providers.ts +425 -422
  14. package/corpus/core/src/tracking/registry.ts +102 -102
  15. package/dist/collab/routes.d.ts +1 -1
  16. package/dist/deploy/build.d.ts +44 -0
  17. package/dist/deploy/build.d.ts.map +1 -1
  18. package/dist/deploy/build.js +91 -2
  19. package/dist/deploy/build.js.map +1 -1
  20. package/dist/event-bus/bus.d.ts.map +1 -1
  21. package/dist/event-bus/bus.js +8 -6
  22. package/dist/event-bus/bus.js.map +1 -1
  23. package/dist/event-bus/registry.d.ts.map +1 -1
  24. package/dist/event-bus/registry.js +10 -6
  25. package/dist/event-bus/registry.js.map +1 -1
  26. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  27. package/dist/file-upload/registry.d.ts.map +1 -1
  28. package/dist/file-upload/registry.js +28 -8
  29. package/dist/file-upload/registry.js.map +1 -1
  30. package/dist/notifications/registry.d.ts.map +1 -1
  31. package/dist/notifications/registry.js +6 -5
  32. package/dist/notifications/registry.js.map +1 -1
  33. package/dist/observability/routes.d.ts +5 -5
  34. package/dist/private-blob/registry.d.ts.map +1 -1
  35. package/dist/private-blob/registry.js +18 -13
  36. package/dist/private-blob/registry.js.map +1 -1
  37. package/dist/progress/routes.d.ts +1 -1
  38. package/dist/resources/handlers.d.ts +2 -2
  39. package/dist/secrets/register.d.ts.map +1 -1
  40. package/dist/secrets/register.js +11 -7
  41. package/dist/secrets/register.js.map +1 -1
  42. package/dist/secrets/routes.d.ts +9 -9
  43. package/dist/shared/global-scope.d.ts +55 -0
  44. package/dist/shared/global-scope.d.ts.map +1 -0
  45. package/dist/shared/global-scope.js +70 -0
  46. package/dist/shared/global-scope.js.map +1 -0
  47. package/dist/sharing/registry.d.ts.map +1 -1
  48. package/dist/sharing/registry.js +2 -16
  49. package/dist/sharing/registry.js.map +1 -1
  50. package/dist/tracking/providers.d.ts.map +1 -1
  51. package/dist/tracking/providers.js +11 -9
  52. package/dist/tracking/providers.js.map +1 -1
  53. package/dist/tracking/registry.d.ts.map +1 -1
  54. package/dist/tracking/registry.js +5 -5
  55. package/dist/tracking/registry.js.map +1 -1
  56. package/package.json +2 -1
@@ -1,102 +1,102 @@
1
- import type { TrackingProvider, TrackingEvent } from "./types.js";
2
-
3
- const REGISTRY_KEY = Symbol.for("@agent-native/core/tracking.registry");
4
- interface GlobalWithRegistry {
5
- [REGISTRY_KEY]?: Map<string, TrackingProvider>;
6
- }
7
-
8
- function getRegistry(): Map<string, TrackingProvider> {
9
- const g = globalThis as unknown as GlobalWithRegistry;
10
- if (!g[REGISTRY_KEY]) g[REGISTRY_KEY] = new Map();
11
- return g[REGISTRY_KEY];
12
- }
13
-
14
- export function registerTrackingProvider(provider: TrackingProvider): void {
15
- if (!provider?.name) {
16
- throw new Error("registerTrackingProvider: provider.name is required");
17
- }
18
- if (typeof provider.track !== "function") {
19
- throw new Error(
20
- "registerTrackingProvider: provider.track must be a function",
21
- );
22
- }
23
- getRegistry().set(provider.name, provider);
24
- }
25
-
26
- export function unregisterTrackingProvider(name: string): boolean {
27
- return getRegistry().delete(name);
28
- }
29
-
30
- export function listTrackingProviders(): string[] {
31
- return Array.from(getRegistry().keys());
32
- }
33
-
34
- export function track(
35
- name: string,
36
- properties?: Record<string, unknown>,
37
- meta?: { userId?: string },
38
- ): void {
39
- const event: TrackingEvent = {
40
- name,
41
- properties,
42
- timestamp: new Date().toISOString(),
43
- userId: meta?.userId,
44
- };
45
-
46
- for (const provider of getRegistry().values()) {
47
- try {
48
- const result = provider.track(event);
49
- if (result && typeof (result as Promise<void>).catch === "function") {
50
- (result as Promise<void>).catch((err) => {
51
- console.error(
52
- `[tracking] Provider "${provider.name}" rejected:`,
53
- err,
54
- );
55
- });
56
- }
57
- } catch (err) {
58
- console.error(`[tracking] Provider "${provider.name}" threw:`, err);
59
- }
60
- }
61
- }
62
-
63
- export function identify(
64
- userId: string,
65
- traits?: Record<string, unknown>,
66
- ): void {
67
- for (const provider of getRegistry().values()) {
68
- if (!provider.identify) continue;
69
- try {
70
- const result = provider.identify(userId, traits);
71
- if (result && typeof (result as Promise<void>).catch === "function") {
72
- (result as Promise<void>).catch(() => {});
73
- }
74
- } catch {
75
- // best-effort
76
- }
77
- }
78
- }
79
-
80
- export function flushTracking(): Promise<void[]> {
81
- const promises: Promise<void>[] = [];
82
- for (const provider of getRegistry().values()) {
83
- if (!provider.flush) continue;
84
- try {
85
- const result = provider.flush();
86
- if (result) {
87
- promises.push(
88
- result.catch((err) => {
89
- console.error(
90
- `[tracking] Provider "${provider.name}" flush rejected:`,
91
- err,
92
- );
93
- }),
94
- );
95
- }
96
- } catch (err) {
97
- console.error(`[tracking] Provider "${provider.name}" flush threw:`, err);
98
- // best-effort
99
- }
100
- }
101
- return Promise.all(promises);
102
- }
1
+ import { getScopedGlobal } from "../shared/global-scope.js";
2
+ import type { TrackingProvider, TrackingEvent } from "./types.js";
3
+
4
+ // globalThis-pinned so one app's ESM graphs share one provider registry, but
5
+ // scope-aware + lazily resolved so unified workspace deployments (all apps in
6
+ // one isolate) keep per-app tracking providers. See shared/global-scope.
7
+ function getRegistry(): Map<string, TrackingProvider> {
8
+ return getScopedGlobal(
9
+ "agent-native.tracking.registry",
10
+ () => new Map<string, TrackingProvider>(),
11
+ );
12
+ }
13
+
14
+ export function registerTrackingProvider(provider: TrackingProvider): void {
15
+ if (!provider?.name) {
16
+ throw new Error("registerTrackingProvider: provider.name is required");
17
+ }
18
+ if (typeof provider.track !== "function") {
19
+ throw new Error(
20
+ "registerTrackingProvider: provider.track must be a function",
21
+ );
22
+ }
23
+ getRegistry().set(provider.name, provider);
24
+ }
25
+
26
+ export function unregisterTrackingProvider(name: string): boolean {
27
+ return getRegistry().delete(name);
28
+ }
29
+
30
+ export function listTrackingProviders(): string[] {
31
+ return Array.from(getRegistry().keys());
32
+ }
33
+
34
+ export function track(
35
+ name: string,
36
+ properties?: Record<string, unknown>,
37
+ meta?: { userId?: string },
38
+ ): void {
39
+ const event: TrackingEvent = {
40
+ name,
41
+ properties,
42
+ timestamp: new Date().toISOString(),
43
+ userId: meta?.userId,
44
+ };
45
+
46
+ for (const provider of getRegistry().values()) {
47
+ try {
48
+ const result = provider.track(event);
49
+ if (result && typeof (result as Promise<void>).catch === "function") {
50
+ (result as Promise<void>).catch((err) => {
51
+ console.error(
52
+ `[tracking] Provider "${provider.name}" rejected:`,
53
+ err,
54
+ );
55
+ });
56
+ }
57
+ } catch (err) {
58
+ console.error(`[tracking] Provider "${provider.name}" threw:`, err);
59
+ }
60
+ }
61
+ }
62
+
63
+ export function identify(
64
+ userId: string,
65
+ traits?: Record<string, unknown>,
66
+ ): void {
67
+ for (const provider of getRegistry().values()) {
68
+ if (!provider.identify) continue;
69
+ try {
70
+ const result = provider.identify(userId, traits);
71
+ if (result && typeof (result as Promise<void>).catch === "function") {
72
+ (result as Promise<void>).catch(() => {});
73
+ }
74
+ } catch {
75
+ // best-effort
76
+ }
77
+ }
78
+ }
79
+
80
+ export function flushTracking(): Promise<void[]> {
81
+ const promises: Promise<void>[] = [];
82
+ for (const provider of getRegistry().values()) {
83
+ if (!provider.flush) continue;
84
+ try {
85
+ const result = provider.flush();
86
+ if (result) {
87
+ promises.push(
88
+ result.catch((err) => {
89
+ console.error(
90
+ `[tracking] Provider "${provider.name}" flush rejected:`,
91
+ err,
92
+ );
93
+ }),
94
+ );
95
+ }
96
+ } catch (err) {
97
+ console.error(`[tracking] Provider "${provider.name}" flush threw:`, err);
98
+ // best-effort
99
+ }
100
+ }
101
+ return Promise.all(promises);
102
+ }
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
26
26
  * Body: { update: string (base64), requestSource?: string }
27
27
  */
28
28
  export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
29
- error: string;
30
29
  ok?: undefined;
30
+ error: string;
31
31
  } | {
32
32
  error?: undefined;
33
33
  ok: boolean;
@@ -30,7 +30,30 @@ export declare function uninstalledOptionalAiSdkStubs(appDir: string): Record<st
30
30
  export declare const CLOUDFLARE_WORKER_NODE_BUILTIN_STUB_MODULES: Record<string, string>;
31
31
  export interface GenerateWorkerEntryOptions {
32
32
  includeReactRouterSsr?: boolean;
33
+ /**
34
+ * Per-app global-registry scope id for unified workspace deployments.
35
+ * When set, the generated entry's FIRST import is `./_scope-init.js`
36
+ * (written by the build via `generateScopeInitSource`), which calls
37
+ * core's `setGlobalScopeId(appId)` before any other module in the app
38
+ * bundle evaluates — so every globalThis-pinned registry in this app's
39
+ * module graph resolves per-app keys instead of colliding with sibling
40
+ * apps in the shared isolate (issue: /assets uploads served by clips'
41
+ * provider).
42
+ */
43
+ appScopeId?: string | null;
33
44
  }
45
+ /**
46
+ * Source of the `_scope-init.js` module the worker entry imports first on
47
+ * unified workspace deployments. Must stay dependency-free beyond core's
48
+ * lean `global-scope` subpath so nothing registry-touching evaluates before
49
+ * the scope id is set (ESM evaluates imports depth-first in order).
50
+ */
51
+ export declare function generateScopeInitSource(appScopeId: string): string;
52
+ /**
53
+ * Derive the workspace app id from a mounted app base path ("/assets" →
54
+ * "assets"). Returns null for unmounted (root) builds.
55
+ */
56
+ export declare function workspaceAppScopeIdFromBasePath(basePath: string | undefined): string | null;
34
57
  interface ReactRouterAssetManifest {
35
58
  entry: ReactRouterAssetManifestEntry;
36
59
  routes: Record<string, ReactRouterAssetManifestRoute>;
@@ -47,6 +70,7 @@ interface ReactRouterAssetManifestRoute {
47
70
  imports?: string[];
48
71
  css?: string[];
49
72
  hasLoader?: boolean;
73
+ hasAction?: boolean;
50
74
  clientActionModule?: string;
51
75
  clientLoaderModule?: string;
52
76
  clientMiddlewareModule?: string;
@@ -67,6 +91,26 @@ export declare function addImmutableAssetRouteRulesForClientBuild(routeRules: Ro
67
91
  * inheritance model: app local > workspace core > framework default.
68
92
  */
69
93
  export declare function generateWorkerEntry(routes: DiscoveredRoute[], pluginPaths: string[], defaultPluginStems?: string[], actions?: DiscoveredAction[], workspaceCore?: WorkspaceCoreExports | null, immutableAssetPaths?: string[], builtAppBasePath?: string, options?: GenerateWorkerEntryOptions): string;
94
+ /**
95
+ * Align the React Router CLIENT manifest with the static-shell worker.
96
+ *
97
+ * The Cloudflare Pages worker intentionally ships NO React Router request
98
+ * handler (`includeReactRouterSsr = false` keeps the merged worker under the
99
+ * platform bundle-size limit; navigations get the static app shell instead).
100
+ * Templates build with `ssr: true`, so the emitted client manifest still
101
+ * advertises `hasLoader`/`hasAction` for routes with server exports — and the
102
+ * hydrated router then issues single-fetch `GET <route>.data` requests on
103
+ * every client-side navigation into such a route. Nothing serves them: the
104
+ * request 404s and React Router trips the route ErrorBoundary
105
+ * (`No result found for routeId "..."`), breaking in-app navigation on every
106
+ * app of a unified workspace deployment.
107
+ *
108
+ * Stripping the server-only flags makes client-side navigation behave exactly
109
+ * like the initial static-shell load already does: render with client data
110
+ * only (server loaders never run anywhere in this deployment shape).
111
+ * `hasClientLoader` / `hasClientAction` are preserved untouched.
112
+ */
113
+ export declare function stripServerDataFlagsFromClientManifest(distDir: string): void;
70
114
  export declare function generateCloudflarePagesStaticShellFromManifest(manifest: ReactRouterAssetManifest, basePath?: string): string;
71
115
  export declare function getNodeBuiltinNames(): string[];
72
116
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/deploy/build.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/deploy/build.ts"],"names":[],"mappings":"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"}
@@ -517,6 +517,32 @@ export const CLOUDFLARE_WORKER_NODE_BUILTIN_STUB_MODULES = {
517
517
  wasi: cloudflareNodeBuiltinStubSource("wasi", ["WASI"]),
518
518
  worker_threads: cloudflareNodeBuiltinStubSource("worker_threads", ["MessageChannel", "MessagePort", "Worker", "isMainThread", "parentPort"], ["export const isMainThread = true;", "export const parentPort = null;"]),
519
519
  };
520
+ /**
521
+ * Source of the `_scope-init.js` module the worker entry imports first on
522
+ * unified workspace deployments. Must stay dependency-free beyond core's
523
+ * lean `global-scope` subpath so nothing registry-touching evaluates before
524
+ * the scope id is set (ESM evaluates imports depth-first in order).
525
+ */
526
+ export function generateScopeInitSource(appScopeId) {
527
+ return `// AUTO-GENERATED by @agent-native/core deploy build
528
+ // Scope globalThis-pinned framework registries to this app's module graph.
529
+ // Evaluated FIRST in the worker entry's import graph so the scope is set
530
+ // before any registry module initializes. See core shared/global-scope.
531
+ import { setGlobalScopeId } from "@agent-native/core/global-scope";
532
+ setGlobalScopeId(${JSON.stringify(appScopeId)});
533
+ `;
534
+ }
535
+ /**
536
+ * Derive the workspace app id from a mounted app base path ("/assets" →
537
+ * "assets"). Returns null for unmounted (root) builds.
538
+ */
539
+ export function workspaceAppScopeIdFromBasePath(basePath) {
540
+ const normalized = normalizeAppBasePath(basePath ?? "");
541
+ if (!normalized)
542
+ return null;
543
+ const [first] = normalized.slice(1).split("/");
544
+ return first || null;
545
+ }
520
546
  function normalizeConfiguredAppBasePath() {
521
547
  return normalizeAppBasePath(process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH);
522
548
  }
@@ -589,6 +615,7 @@ export function addImmutableAssetRouteRulesForClientBuild(routeRules, clientDir,
589
615
  */
590
616
  export function generateWorkerEntry(routes, pluginPaths, defaultPluginStems = [], actions = [], workspaceCore = null, immutableAssetPaths = [], builtAppBasePath = normalizeConfiguredAppBasePath(), options = {}) {
591
617
  const includeReactRouterSsr = options.includeReactRouterSsr ?? true;
618
+ const appScopeId = options.appScopeId ?? null;
592
619
  const routeImports = [];
593
620
  const routeRegistrations = [];
594
621
  for (let i = 0; i < routes.length; i++) {
@@ -684,7 +711,7 @@ export function generateWorkerEntry(routes, pluginPaths, defaultPluginStems = []
684
711
  }
685
712
  return `
686
713
  // Auto-generated worker entry point for ${preset}
687
- import { H3, defineEventHandler, readBody, toResponse } from "h3";
714
+ ${appScopeId ? 'import "./_scope-init.js";\n' : ""}import { H3, defineEventHandler, readBody, toResponse } from "h3";
688
715
  ${includeReactRouterSsr ? 'import { createRequestHandler } from "react-router";' : ""}
689
716
  ${includeReactRouterSsr ? 'import * as serverBuild from "./server-build.js";' : ""}
690
717
 
@@ -1223,6 +1250,56 @@ function findReactRouterManifest(distDir) {
1223
1250
  }
1224
1251
  return JSON.parse(match[1].replace(/;$/, ""));
1225
1252
  }
1253
+ /**
1254
+ * Align the React Router CLIENT manifest with the static-shell worker.
1255
+ *
1256
+ * The Cloudflare Pages worker intentionally ships NO React Router request
1257
+ * handler (`includeReactRouterSsr = false` keeps the merged worker under the
1258
+ * platform bundle-size limit; navigations get the static app shell instead).
1259
+ * Templates build with `ssr: true`, so the emitted client manifest still
1260
+ * advertises `hasLoader`/`hasAction` for routes with server exports — and the
1261
+ * hydrated router then issues single-fetch `GET <route>.data` requests on
1262
+ * every client-side navigation into such a route. Nothing serves them: the
1263
+ * request 404s and React Router trips the route ErrorBoundary
1264
+ * (`No result found for routeId "..."`), breaking in-app navigation on every
1265
+ * app of a unified workspace deployment.
1266
+ *
1267
+ * Stripping the server-only flags makes client-side navigation behave exactly
1268
+ * like the initial static-shell load already does: render with client data
1269
+ * only (server loaders never run anywhere in this deployment shape).
1270
+ * `hasClientLoader` / `hasClientAction` are preserved untouched.
1271
+ */
1272
+ export function stripServerDataFlagsFromClientManifest(distDir) {
1273
+ const assetsDir = path.join(distDir, "assets");
1274
+ if (!fs.existsSync(assetsDir))
1275
+ return;
1276
+ const manifestFile = fs
1277
+ .readdirSync(assetsDir)
1278
+ .find((file) => /^manifest-[\w-]+\.js$/.test(file));
1279
+ if (!manifestFile)
1280
+ return;
1281
+ const manifestPath = path.join(assetsDir, manifestFile);
1282
+ const source = fs.readFileSync(manifestPath, "utf8");
1283
+ const match = source.match(/^window\.__reactRouterManifest=(.*);?\s*$/);
1284
+ if (!match)
1285
+ return;
1286
+ const manifest = JSON.parse(match[1].replace(/;$/, ""));
1287
+ let stripped = 0;
1288
+ for (const route of Object.values(manifest.routes ?? {})) {
1289
+ if (route.hasLoader) {
1290
+ route.hasLoader = false;
1291
+ stripped++;
1292
+ }
1293
+ if (route.hasAction) {
1294
+ route.hasAction = false;
1295
+ stripped++;
1296
+ }
1297
+ }
1298
+ if (stripped === 0)
1299
+ return;
1300
+ fs.writeFileSync(manifestPath, `window.__reactRouterManifest=${JSON.stringify(manifest)};`);
1301
+ console.log(`[deploy] Stripped ${stripped} server loader/action flag(s) from ${manifestFile} — the static-shell worker has no React Router handler, so single-fetch .data requests would 404.`);
1302
+ }
1226
1303
  function collectModulePreloads(manifest, route) {
1227
1304
  const paths = new Set();
1228
1305
  const add = (value) => {
@@ -1377,6 +1454,11 @@ async function buildCloudflarePages() {
1377
1454
  const tmpDir = path.join(cwd, ".deploy-tmp");
1378
1455
  fs.mkdirSync(tmpDir, { recursive: true });
1379
1456
  writeCloudflarePagesStaticShell({ serverDir, distDir, tmpDir });
1457
+ // AFTER the shell is written (its manifest fallback reads the original
1458
+ // hasLoader flag to pick the embedded root-loader turbo stream): align the
1459
+ // client manifest with the handler-less worker so client-side navigations
1460
+ // don't issue .data single-fetch requests that can only 404.
1461
+ stripServerDataFlagsFromClientManifest(distDir);
1380
1462
  // Exclude _worker.js from being served as a public asset
1381
1463
  fs.writeFileSync(path.join(distDir, ".assetsignore"), "_worker.js\n");
1382
1464
  // Write package metadata inside _worker.js/ for the ES module worker that
@@ -1400,7 +1482,11 @@ async function buildCloudflarePages() {
1400
1482
  console.log(`[deploy] ${routes.length} API routes, ${actions.length} actions, ${plugins.length} plugins (${plugins.filter((p) => isNodeOnlyPlugin(p)).length} skipped as Node-only), ${missingDefaults.length} auto-mounted defaults${workspaceCore ? `, workspace-core ${workspaceCore.packageName} (${workspaceSlotCount} plugin slots)` : ""}`);
1401
1483
  // Generate the worker entry
1402
1484
  const immutableAssetPaths = collectImmutableAssetPaths(clientDir);
1403
- const entrySource = generateWorkerEntry(routes, plugins, missingDefaults, actions, workspaceCore, immutableAssetPaths, normalizeConfiguredAppBasePath(), { includeReactRouterSsr });
1485
+ // Per-app global-registry scoping for unified workspace deploys: mounted
1486
+ // builds (APP_BASE_PATH=/<app>) get a scope-init module evaluated first so
1487
+ // globalThis-pinned registries stay per-app in the shared isolate.
1488
+ const appScopeId = workspaceAppScopeIdFromBasePath(normalizeConfiguredAppBasePath());
1489
+ const entrySource = generateWorkerEntry(routes, plugins, missingDefaults, actions, workspaceCore, immutableAssetPaths, normalizeConfiguredAppBasePath(), { includeReactRouterSsr, appScopeId });
1404
1490
  // Create _worker.js output directory
1405
1491
  const workerOutDir = path.join(distDir, "_worker.js");
1406
1492
  fs.mkdirSync(workerOutDir, { recursive: true });
@@ -1419,6 +1505,9 @@ async function buildCloudflarePages() {
1419
1505
  // matching the _worker.js/index.js entry point that Cloudflare Pages expects.
1420
1506
  const tmpEntry = path.join(tmpDir, "index.js");
1421
1507
  fs.writeFileSync(tmpEntry, adjustedEntry);
1508
+ if (appScopeId) {
1509
+ fs.writeFileSync(path.join(tmpDir, "_scope-init.js"), generateScopeInitSource(appScopeId));
1510
+ }
1422
1511
  if (includeReactRouterSsr) {
1423
1512
  copyDir(serverDir, path.join(tmpDir, "server"));
1424
1513
  }