@jskit-ai/agent-docs 0.1.280 → 0.1.282
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/guide/agent/app-extras/assistant-conversation.md +5 -1
- package/guide/agent/app-extras/realtime.md +20 -10
- package/guide/agent/app-setup/authentication.md +20 -1
- package/guide/agent/app-setup/database-layer.md +75 -31
- package/guide/agent/app-setup/existing-application-migration.md +7 -1
- package/guide/agent/app-setup/multi-homing.md +6 -2
- package/guide/agent/app-setup/upgrading-jskit.md +78 -0
- package/guide/agent/framework/client-features.md +35 -1
- package/guide/agent/framework/sanity-checks.md +4 -3
- package/guide/agent/framework/typed-features.md +79 -30
- package/package.json +1 -1
- package/patterns/feature-package/example/booking-engine/package.json +1 -1
- package/patterns/minimal-foundation/example/AGENTS.md +14 -7
- package/patterns/minimal-foundation/example/package.json +3 -3
- package/patterns/minimal-foundation/example/playwright.config.mjs +3 -33
- package/patterns/minimal-foundation/example/server.js +7 -1
- package/patterns/minimal-foundation/example/tests/e2e/startup.spec.ts +13 -0
- package/patterns/shell-foundation/example/AGENTS.md +14 -7
- package/patterns/shell-foundation/example/package.json +4 -4
- package/patterns/shell-foundation/example/packages/main/package.json +1 -1
- package/patterns/shell-foundation/example/playwright.config.mjs +3 -33
- package/patterns/shell-foundation/example/server.js +7 -1
- package/patterns/shell-foundation/example/tests/e2e/startup.spec.ts +13 -0
- package/reference/autogen/KERNEL_MAP.md +2 -0
- package/reference/autogen/PATTERN_INDEX.md +37 -37
- package/reference/autogen/packages/architecture-inspector.md +1 -0
- package/reference/autogen/packages/assistant-runtime.md +1 -1
- package/reference/autogen/packages/auth-provider-local-core.md +2 -1
- package/reference/autogen/packages/connectors-catalog.md +8 -0
- package/reference/autogen/packages/database-runtime.md +33 -0
- package/reference/autogen/packages/http-runtime.md +1 -1
- package/reference/autogen/packages/kernel.md +29 -1
- package/reference/autogen/packages/oidc-issuer-core.md +0 -1
- package/reference/autogen/packages/realtime.md +8 -5
- package/reference/autogen/packages/shell-web.md +4 -3
- package/reference/autogen/packages/workspaces-core.md +1 -1
- package/reference/autogen/tooling/jskit-catalog.md +71 -1
- package/skills/jskit/SKILL.md +8 -6
- package/skills/jskit/references/client-features.md +35 -1
- package/skills/jskit/references/existing-application-migration.md +7 -1
- package/skills/jskit/references/heuristics/client-requests.md +1 -0
- package/skills/jskit/references/heuristics/typed-features.md +2 -2
- package/skills/jskit/references/heuristics/ui-testing.md +21 -16
- package/skills/jskit/references/multi-homing.md +6 -2
- package/skills/jskit/references/pattern-index.md +37 -37
- package/skills/jskit/references/patterns/app/minimal-foundation/example/AGENTS.md +14 -7
- package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +3 -3
- package/skills/jskit/references/patterns/app/minimal-foundation/example/playwright.config.mjs +3 -33
- package/skills/jskit/references/patterns/app/minimal-foundation/example/server.js +7 -1
- package/skills/jskit/references/patterns/app/minimal-foundation/example/tests/e2e/startup.spec.ts +13 -0
- package/skills/jskit/references/patterns/app/shell-foundation/example/AGENTS.md +14 -7
- package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +4 -4
- package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +1 -1
- package/skills/jskit/references/patterns/app/shell-foundation/example/playwright.config.mjs +3 -33
- package/skills/jskit/references/patterns/app/shell-foundation/example/server.js +7 -1
- package/skills/jskit/references/patterns/app/shell-foundation/example/tests/e2e/startup.spec.ts +13 -0
- package/skills/jskit/references/patterns/auth/accounts-hub/example/package.json +2 -2
- package/skills/jskit/references/patterns/auth/oidc-sign-in/example/package.json +2 -2
- package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +1 -1
- package/skills/jskit/references/patterns/connectors/calendar-cli/example/package.json +4 -4
- package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +2 -2
- package/skills/jskit/references/patterns/database/mysql-application/PATTERN.md +34 -24
- package/skills/jskit/references/patterns/database/mysql-application/example/package.json +3 -2
- package/skills/jskit/references/patterns/database/mysql-application/example/tests/e2e/databases.js +25 -0
- package/skills/jskit/references/patterns/database/postgres-application/PATTERN.md +12 -0
- package/skills/jskit/references/patterns/database/postgres-application/example/package.json +3 -2
- package/skills/jskit/references/patterns/database/postgres-application/example/tests/e2e/databases.js +25 -0
- package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +2 -2
- package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +1 -1
- package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +2 -2
- package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +3 -3
- package/skills/jskit/references/sanity-checks.md +4 -3
- package/skills/jskit/references/typed-features.md +79 -30
- package/skills/jskit/references/patterns/database/mysql-application/example/tests/browser/database.js +0 -68
|
@@ -146,7 +146,7 @@ Local functions
|
|
|
146
146
|
|
|
147
147
|
### `src/client/support/subscribeAssistantConversation.js`
|
|
148
148
|
Exports
|
|
149
|
-
- `subscribeAssistantConversation({ socket, conversationId, targetSurfaceId, hostSurfaceId, workspaceSlug, read, onState, onEvent = ignoreConversationEvent, onError = ignoreSubscriptionError })`
|
|
149
|
+
- `subscribeAssistantConversation({ socket, conversationId, targetSurfaceId, hostSurfaceId, workspaceSlug, read, onState, onEvent = ignoreConversationEvent, onError = ignoreSubscriptionError, noticeMs = SUBSCRIPTION_NOTICE_MS })`
|
|
150
150
|
- `refreshedHistoryPages`
|
|
151
151
|
- `patchLoadedHistoryPages(pages, patch)`
|
|
152
152
|
Local functions
|
|
@@ -34,7 +34,8 @@ Exports
|
|
|
34
34
|
- `PROVIDER_ID`
|
|
35
35
|
- `buildAuthPayload({ user, session, profileProjector, profileOptions = {} })`
|
|
36
36
|
- `buildAuthResult({ user, session, appProfile })`
|
|
37
|
-
- `
|
|
37
|
+
- `buildProfileChangePayload({ user, profileProjector })`
|
|
38
|
+
- `buildSessionAuthPayload({ appProfileProjection, devAuth, profileProjector, request, session, user, syncProfile = true, onlyWhenChanged = false })`
|
|
38
39
|
- `findExistingAppProfile(user, profileProjector)`
|
|
39
40
|
- `isAuthenticatingSession(session)`
|
|
40
41
|
Local functions
|
|
@@ -951,6 +951,14 @@ Exports
|
|
|
951
951
|
- `zohoOAuthMetadata(accounts)`
|
|
952
952
|
- `normalizeZohoTokenResponse(response, expectedApiOrigin)`
|
|
953
953
|
|
|
954
|
+
### `src/shared/ai-definition.js`
|
|
955
|
+
Exports
|
|
956
|
+
- `aiAccessLabels`
|
|
957
|
+
- `aiDefinition`
|
|
958
|
+
- `byAccessThenKey(a, b)`
|
|
959
|
+
- `catalogueProvider(provider, connection)`
|
|
960
|
+
- `configurableProviders`
|
|
961
|
+
|
|
954
962
|
### `src/shared/ai.js`
|
|
955
963
|
Exports
|
|
956
964
|
- `aiCatalogue`
|
|
@@ -16,6 +16,7 @@ Use this on demand; do not load the full index at startup.
|
|
|
16
16
|
|
|
17
17
|
### `src/server/database.js`
|
|
18
18
|
Exports
|
|
19
|
+
- `RUNTIME_QUERY_CHANNEL`
|
|
19
20
|
- `createDatabase({ driver, env })`
|
|
20
21
|
Local functions
|
|
21
22
|
- `resolveDriverDialectId(driver)`
|
|
@@ -55,6 +56,38 @@ Local functions
|
|
|
55
56
|
Exports
|
|
56
57
|
- `DatabaseProvider`
|
|
57
58
|
|
|
59
|
+
### `src/server/testDatabaseFile.js`
|
|
60
|
+
Exports
|
|
61
|
+
- None
|
|
62
|
+
Local functions
|
|
63
|
+
- `isRunning(pid)`
|
|
64
|
+
- `claimDatabase(directory, databases)`
|
|
65
|
+
|
|
66
|
+
### `src/server/testDatabases.js`
|
|
67
|
+
Exports
|
|
68
|
+
- `RUN_SETTINGS_FILE`
|
|
69
|
+
- `countQueries(knex, work)`
|
|
70
|
+
- `countRuntimeQueries(work)`
|
|
71
|
+
- `matchesSnapshot(knexConfig, database, snapshot)`
|
|
72
|
+
- `prepareTestDatabases({ knexConfig, environment, variable = "TEST_DB_NAME", count = 1, seed, schema = {}, appRoot = process.cwd() })`
|
|
73
|
+
- `requireDisposableDatabase(environment, variable, count = 1, { connected = "" } = {})`
|
|
74
|
+
- `restoreTestDatabase(knexConfig, database, snapshot)`
|
|
75
|
+
- `testDatabaseNames(name, count)`
|
|
76
|
+
- `testDatabaseRun({ knexConfig, environment, count, schema, appRoot = process.cwd() })`
|
|
77
|
+
- `testDatabaseSnapshotKey(knexConfig, { appRoot = process.cwd(), schemaFiles = [] } = {})`
|
|
78
|
+
- `type TestDatabaseSchema`
|
|
79
|
+
Local functions
|
|
80
|
+
- `folded(value)`
|
|
81
|
+
- `milliseconds(since)`
|
|
82
|
+
- `ledgerOf(knexConfig)`
|
|
83
|
+
- `connectedDatabaseName(environment)`
|
|
84
|
+
- `knexOn(knexConfig, database, connectionOptions = {})`
|
|
85
|
+
- `withKnex(knexConfig, database, use, connectionOptions)`
|
|
86
|
+
- `ledgerNames(knex, ledger, tables)`
|
|
87
|
+
- `dialectOf(knexConfig)`
|
|
88
|
+
- `refusedPrivilege(error)`
|
|
89
|
+
- `recordStatements(listen, work)`
|
|
90
|
+
|
|
58
91
|
### `src/server/types.js`
|
|
59
92
|
Exports
|
|
60
93
|
- `type RuntimeDatabase`
|
|
@@ -35,7 +35,7 @@ Exports
|
|
|
35
35
|
- `createTransientRetryHttpClient(options)`
|
|
36
36
|
Local functions
|
|
37
37
|
- `sleep(delayMs)`
|
|
38
|
-
- `
|
|
38
|
+
- `retriesTransientHttpFailure(error, method)`
|
|
39
39
|
- `requestWithTransientRetry(executor, method, signal)`
|
|
40
40
|
|
|
41
41
|
### `src/client/types.js`
|
|
@@ -87,6 +87,7 @@ Exports
|
|
|
87
87
|
- `toCamelCase`
|
|
88
88
|
- `toSnakeCase`
|
|
89
89
|
- `isTransientQueryError`
|
|
90
|
+
- `markTransientRetriesSpent`
|
|
90
91
|
- `shouldRetryTransientQueryFailure`
|
|
91
92
|
- `transientQueryRetryDelay`
|
|
92
93
|
|
|
@@ -177,6 +178,7 @@ Exports
|
|
|
177
178
|
- `MAX_TRANSIENT_RETRY_DELAY_MS`
|
|
178
179
|
- `normalizeQueryErrorStatus(error)`
|
|
179
180
|
- `isTransientQueryError(error)`
|
|
181
|
+
- `markTransientRetriesSpent(error)`
|
|
180
182
|
- `shouldRetryTransientQueryFailure(failureCount, error)`
|
|
181
183
|
- `transientQueryRetryDelay(attemptIndex)`
|
|
182
184
|
|
|
@@ -538,6 +540,8 @@ Local functions
|
|
|
538
540
|
- `isSurfaceRootRecord(record)`
|
|
539
541
|
- `hostsChildViews(record)`
|
|
540
542
|
- `hashScrollMargin(hash)`
|
|
543
|
+
- `isLazyRouteComponent(component)`
|
|
544
|
+
- `preloadOpeningRouteComponents(router, fallbackRoute)`
|
|
541
545
|
|
|
542
546
|
### `client/shellRouting.js`
|
|
543
547
|
Exports
|
|
@@ -604,8 +608,12 @@ Local functions
|
|
|
604
608
|
- `hasClientExport(packageJson)`
|
|
605
609
|
- `isPathInsideRoot(rootPath, candidatePath)`
|
|
606
610
|
- `splitSpecifierSuffix(source)`
|
|
611
|
+
- `exportFile(target)`
|
|
612
|
+
- `resolveClientBootImports(installedPackage, { packageMetadataUiRoutes, packageMetadataClientProviders })`
|
|
607
613
|
- `resolveClientModulesFromInstalledPackages(installedPackages = [])`
|
|
608
614
|
- `normalizeClientModulePackageMetadataEntries(value)`
|
|
615
|
+
- `normalizeBootProviders(bootImports)`
|
|
616
|
+
- `clientBootSpecifiers(entry)`
|
|
609
617
|
- `resolveClientRuntimeDedupeSpecifiers(userResolveConfig = {})`
|
|
610
618
|
|
|
611
619
|
### `client/vite/index.js`
|
|
@@ -798,6 +806,12 @@ Local functions
|
|
|
798
806
|
- `emptyInput()`
|
|
799
807
|
- `handlerAsGiven(handler)`
|
|
800
808
|
|
|
809
|
+
### `server/http/lib/deepFrozen.js`
|
|
810
|
+
Exports
|
|
811
|
+
- `isDeepFrozen(value)`
|
|
812
|
+
Local functions
|
|
813
|
+
- `isFrozenThroughout(node, checked)`
|
|
814
|
+
|
|
801
815
|
### `server/http/lib/errors.js`
|
|
802
816
|
Exports
|
|
803
817
|
- `HttpKernelError`
|
|
@@ -831,6 +845,10 @@ Exports
|
|
|
831
845
|
- `type ActionCatalogue`
|
|
832
846
|
- `type RuntimeFastify`
|
|
833
847
|
Local functions
|
|
848
|
+
- `sharedValidationSchema(schema)`
|
|
849
|
+
- `namesEveryType(value)`
|
|
850
|
+
- `isSharedResponseSchema(entry)`
|
|
851
|
+
- `copyRouteSchema(schema)`
|
|
834
852
|
- `toFastifyRouteOptions(route)`
|
|
835
853
|
- `shouldStripFastifyBodySchema(route, schema)`
|
|
836
854
|
- `normalizeHeaderValue(value)`
|
|
@@ -860,6 +878,7 @@ Exports
|
|
|
860
878
|
- `resolveRouteValidatorOptions({ method = "", path = "", options = {} } = {})`
|
|
861
879
|
Local functions
|
|
862
880
|
- `stripJsonRestTransportExtensions(value)`
|
|
881
|
+
- `stripSchemaCopy(value)`
|
|
863
882
|
- `normalizeRouteSchemaSection(value, { context = "route section", defaultMode = "patch" } = {})`
|
|
864
883
|
- `normalizeResponseDefinition(value, { context = "route responses" } = {})`
|
|
865
884
|
- `normalizeAdvancedFastifySchema(value, { context = "route validator" } = {})`
|
|
@@ -869,9 +888,14 @@ Local functions
|
|
|
869
888
|
### `server/http/responseSerializerFactory.js`
|
|
870
889
|
Exports
|
|
871
890
|
- `createCachedResponseSerializerFactory(buildSerializer)`
|
|
891
|
+
- `schemaCacheKey(schema)`
|
|
872
892
|
Local functions
|
|
893
|
+
- `schemaTools()`
|
|
873
894
|
- `isJsonValue(value, ancestors = new Set())`
|
|
874
|
-
- `
|
|
895
|
+
- `assertValidSchema(schema, name)`
|
|
896
|
+
- `filedSchemaId(schema, fallback)`
|
|
897
|
+
- `everyRefResolves(schema, externalSchemas)`
|
|
898
|
+
- `compiledOnFirstUse(compile, options, key)`
|
|
875
899
|
|
|
876
900
|
### `server/http/securityHeaders.js`
|
|
877
901
|
Exports
|
|
@@ -1055,6 +1079,7 @@ Exports
|
|
|
1055
1079
|
Local functions
|
|
1056
1080
|
- `fileLockError(message = "", code = FILE_LOCK_ERROR_CODE)`
|
|
1057
1081
|
- `normalizedAbsolutePath(value = "", label = "path", errorCode = FILE_LOCK_ERROR_CODE)`
|
|
1082
|
+
- `lockThroughDescriptor(fd, cwd)`
|
|
1058
1083
|
|
|
1059
1084
|
### `server/support/importFreshModuleFromAbsolutePath.js`
|
|
1060
1085
|
Exports
|
|
@@ -1146,3 +1171,6 @@ Local functions
|
|
|
1146
1171
|
- `resolveFileDependencyRoot(appRoot, specifier = "")`
|
|
1147
1172
|
- `resolveInstalledPackageRoot({ appRoot, packageId, parentPackageRoot = "" })`
|
|
1148
1173
|
- `resolvePackageRoots({ appRoot, packageId, directSpecifier = "", parentPackageRoot = "" })`
|
|
1174
|
+
- `fileStamp(filePath)`
|
|
1175
|
+
- `stampsOf(filePaths)`
|
|
1176
|
+
- `walkInstalledPackages(normalizedAppRoot)`
|
|
@@ -76,6 +76,7 @@ Exports
|
|
|
76
76
|
- `type RuntimeDatabase`
|
|
77
77
|
- `type RuntimeLogger`
|
|
78
78
|
- `type ActorRoomsResolver`
|
|
79
|
+
- `type ActorsRoomsResolver`
|
|
79
80
|
- `type AudienceContributors`
|
|
80
81
|
Local functions
|
|
81
82
|
- `flattenEntries(value)`
|
|
@@ -107,16 +108,17 @@ Exports
|
|
|
107
108
|
|
|
108
109
|
### `src/server/realtimeDelivery.js`
|
|
109
110
|
Exports
|
|
110
|
-
- `createRealtimeDelivery({ io, database, logger, authService, audiences: { mayContribute,
|
|
111
|
+
- `createRealtimeDelivery({ io, database, logger, authService, audiences: { mayContribute, resolveActorsRooms } })`
|
|
111
112
|
- `matchesRealtimeEvent(event)`
|
|
112
113
|
- `type AuthService`
|
|
113
114
|
- `type ActorRoomsResolver`
|
|
115
|
+
- `type ActorsRoomsResolver`
|
|
114
116
|
- `type AudienceContributors`
|
|
115
117
|
Local functions
|
|
116
118
|
- `publicRealtimePayload(event)`
|
|
117
|
-
- `
|
|
118
|
-
- `
|
|
119
|
-
- `
|
|
119
|
+
- `sharedWithinPass(load, keyOf)`
|
|
120
|
+
- `createPassChecks(authService, resolveActorsRooms)`
|
|
121
|
+
- `rememberedActorId(socket)`
|
|
120
122
|
|
|
121
123
|
### `src/server/RealtimeProvider.js`
|
|
122
124
|
Exports
|
|
@@ -133,7 +135,7 @@ Exports
|
|
|
133
135
|
- `REDIS_NAMESPACE_ENV_KEY`
|
|
134
136
|
- `resolveRealtimeRedisUrl(env)`
|
|
135
137
|
- `resolveRealtimeRedisNamespace(env)`
|
|
136
|
-
- `configureSocketIoRedisAdapter(io, { redisUrl = "", redisNamespace = "", logger, createRedisAdapter
|
|
138
|
+
- `configureSocketIoRedisAdapter(io, { redisUrl = "", redisNamespace = "", logger, createRedisAdapter, createRedisConnection })`
|
|
137
139
|
- `closeSocketIoRedisConnections({ pubClient, subClient })`
|
|
138
140
|
- `countConnectedClients(io)`
|
|
139
141
|
Local functions
|
|
@@ -149,6 +151,7 @@ Exports
|
|
|
149
151
|
Exports
|
|
150
152
|
- `type RuntimeRealtime`
|
|
151
153
|
- `type ActorRoomsResolver`
|
|
154
|
+
- `type ActorsRoomsResolver`
|
|
152
155
|
- `type AudienceContributors`
|
|
153
156
|
- `type RealtimeAudienceContributor`
|
|
154
157
|
|
|
@@ -500,10 +500,11 @@ Exports
|
|
|
500
500
|
- `resolveAppPlacementTopologyExport(exported, logger)`
|
|
501
501
|
Local functions
|
|
502
502
|
- `loadAppModule({ importModule, specifier, label, resolve, invalidExportMessage = "", loadFailureMessage, fallback, logger, asyncModuleRecoveryRuntime })`
|
|
503
|
-
- `
|
|
504
|
-
- `
|
|
503
|
+
- `importAppModules()`
|
|
504
|
+
- `loadAppPlacementDefinitions(logger, asyncModuleRecoveryRuntime, pendingImport)`
|
|
505
|
+
- `loadAppPlacementTopology(logger, asyncModuleRecoveryRuntime, pendingImport)`
|
|
505
506
|
- `createErrorConfigToolkit(errorRuntime)`
|
|
506
|
-
- `loadAppErrorConfig(logger, errorRuntime, asyncModuleRecoveryRuntime)`
|
|
507
|
+
- `loadAppErrorConfig(logger, errorRuntime, asyncModuleRecoveryRuntime, pendingImport)`
|
|
507
508
|
- `installVueErrorBridge(vueApp, errorRuntime, logger)`
|
|
508
509
|
- `installRouterErrorBridge(router, errorRuntime, logger)`
|
|
509
510
|
|
|
@@ -252,7 +252,7 @@ Exports
|
|
|
252
252
|
Exports
|
|
253
253
|
- `WorkspacesIntegrationsProvider`
|
|
254
254
|
Local functions
|
|
255
|
-
- `resolveWorkspaceRealtimeScopes(workspaceMemberships,
|
|
255
|
+
- `resolveWorkspaceRealtimeScopes(workspaceMemberships, actorIds)`
|
|
256
256
|
|
|
257
257
|
### `src/server/workspacesRuntime.js`
|
|
258
258
|
Exports
|
|
@@ -14,6 +14,45 @@ Use this on demand; do not load the full index at startup.
|
|
|
14
14
|
|
|
15
15
|
### scripts
|
|
16
16
|
|
|
17
|
+
### `scripts/browser-test-build.mjs`
|
|
18
|
+
Exports
|
|
19
|
+
- `buildFrontend({ appRoot = process.cwd(), build = "npm run build", run = runToCompletion } = {})`
|
|
20
|
+
Local functions
|
|
21
|
+
- `seconds(since)`
|
|
22
|
+
- `digest(file)`
|
|
23
|
+
- `buildFingerprint(appRoot, build, env = process.env)`
|
|
24
|
+
- `runToCompletion(command, appRoot)`
|
|
25
|
+
- `lastBuild(appRoot)`
|
|
26
|
+
- `isRunning(pid)`
|
|
27
|
+
- `lockBuild(appRoot)`
|
|
28
|
+
- `isCurrent(appRoot, inputs)`
|
|
29
|
+
|
|
30
|
+
### `scripts/browser-test-servers.mjs`
|
|
31
|
+
Exports
|
|
32
|
+
- None
|
|
33
|
+
Local functions
|
|
34
|
+
- `seconds(since)`
|
|
35
|
+
- `words(command)`
|
|
36
|
+
- `prepareWorkers(appRoot, prepare, workers, baseUrls)`
|
|
37
|
+
- `signInWorkers(appRoot, signIn, baseUrls, environments, signedInStates)`
|
|
38
|
+
- `waitUntilReady(url, server, name)`
|
|
39
|
+
- `stopServers()`
|
|
40
|
+
|
|
41
|
+
### `scripts/browser-test-times.mjs`
|
|
42
|
+
Exports
|
|
43
|
+
- None
|
|
44
|
+
|
|
45
|
+
### `scripts/browser-tests.mjs`
|
|
46
|
+
Exports
|
|
47
|
+
- `SETTINGS_VARIABLE`
|
|
48
|
+
- `browserTestConfig({ testDir = "./tests/e2e", port = DEFAULT_PORT, server = "node ./bin/server.js", build = "npm run build", prepare = "", signIn = "", env = {}, health = "/api/health", globalTimeout = GLOBAL_TIMEOUT_MS, environment = process.env, cwd = process.cwd() } = {})`
|
|
49
|
+
- `browserTestWorkers({ env = process.env, argv = process.argv } = {})`
|
|
50
|
+
Local functions
|
|
51
|
+
- `positiveInteger(value)`
|
|
52
|
+
- `managedBaseUrl(env)`
|
|
53
|
+
- `commandLineWorkers(argv)`
|
|
54
|
+
- `preparedWorkerEnvironment(file, index)`
|
|
55
|
+
|
|
17
56
|
### `scripts/build-catalog.mjs`
|
|
18
57
|
Exports
|
|
19
58
|
- None
|
|
@@ -245,10 +284,26 @@ Exports
|
|
|
245
284
|
Exports
|
|
246
285
|
- `planTestRuns(args, { cwd = process.cwd(), concurrency = testConcurrency() } = {})`
|
|
247
286
|
- `runTests(args)`
|
|
287
|
+
- `withTimeReporter(run, destination)`
|
|
248
288
|
Local functions
|
|
249
289
|
- `findTestFiles(patterns, cwd)`
|
|
250
290
|
- `readAloneFiles(files, cwd)`
|
|
251
|
-
- `
|
|
291
|
+
- `aloneDestination(destination)`
|
|
292
|
+
- `aloneRunOptions(options)`
|
|
293
|
+
- `aloneShard(files, options)`
|
|
294
|
+
- `runNode(args, env)`
|
|
295
|
+
|
|
296
|
+
### `scripts/test-databases.mjs`
|
|
297
|
+
Exports
|
|
298
|
+
- `DATABASES_OPTION`
|
|
299
|
+
- `testDatabaseRunFor(count, cwd = process.cwd())`
|
|
300
|
+
Local functions
|
|
301
|
+
- `withOwnEnvironment(load)`
|
|
302
|
+
|
|
303
|
+
### `scripts/test-file-stop.mjs`
|
|
304
|
+
Exports
|
|
305
|
+
- `STOPPED_PREFIX`
|
|
306
|
+
- `STOPS_VARIABLE`
|
|
252
307
|
|
|
253
308
|
### `scripts/test-runs.mjs`
|
|
254
309
|
Exports
|
|
@@ -262,8 +317,23 @@ Local functions
|
|
|
262
317
|
- `configOption(args)`
|
|
263
318
|
- `lineOf(contents, needle, after = "")`
|
|
264
319
|
- `findConfig(directory, explicit, names)`
|
|
320
|
+
- `usesBrowserHarness(source)`
|
|
321
|
+
- `developmentServerCommand(source)`
|
|
322
|
+
- `checkPlaywrightIsolation({ file, source, report })`
|
|
265
323
|
- `checkRunnerConfig({ root, configPath, directory, runner, report })`
|
|
266
324
|
|
|
325
|
+
### `scripts/test-time-report.mjs`
|
|
326
|
+
Exports
|
|
327
|
+
- `BOUNDS_FILE`
|
|
328
|
+
- `FILE_TIMES`
|
|
329
|
+
- `checkTestTimes({ bounds, files, tests, wallMs, stopped = [] })`
|
|
330
|
+
- `fileStop({ bound, recorded })`
|
|
331
|
+
- `reportTestTimes({ cwd, collected, directory, wallMs })`
|
|
332
|
+
- `writeFileStops({ cwd, files, directory })`
|
|
333
|
+
Local functions
|
|
334
|
+
- `seconds(ms)`
|
|
335
|
+
- `readTestTimeBounds(cwd)`
|
|
336
|
+
|
|
267
337
|
### `scripts/verify-packages.mjs`
|
|
268
338
|
Exports
|
|
269
339
|
- `main()`
|
package/skills/jskit/SKILL.md
CHANGED
|
@@ -131,9 +131,11 @@ slowest files. Find why a check is slow; never raise its time limit. Typed
|
|
|
131
131
|
features' repository and Tests rules say how.
|
|
132
132
|
|
|
133
133
|
Test files run in parallel by default, bounded by the machine: a script runs
|
|
134
|
-
`jskit test
|
|
135
|
-
|
|
136
|
-
`@jskit-ai/jskit-catalog/
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
134
|
+
`jskit test` (`--databases`: a `TEST_DB_NAME` copy per file), never
|
|
135
|
+
`node --test` or a fixed `--test-concurrency`; Playwright's config is
|
|
136
|
+
`browserTestConfig()` from `@jskit-ai/jskit-catalog/browser-tests` and Vitest's
|
|
137
|
+
`maxWorkers` is `testConcurrency()` from `@jskit-ai/jskit-catalog/test-budget`.
|
|
138
|
+
Plain `jskit check` fails anything else. Files that collide when run together
|
|
139
|
+
get isolated (their own port, temporary directory and database), never
|
|
140
|
+
serialised. A file that truly must run alone says why on its first line,
|
|
141
|
+
`// jskit-test: alone - <reason>`.
|
|
@@ -232,7 +232,7 @@ const ConversationClientProvider = defineProvider({
|
|
|
232
232
|
},
|
|
233
233
|
/** @param {{ components: import("@jskit-ai/kernel/client/types").ClientComponents }} capabilities */
|
|
234
234
|
setup({ components }) {
|
|
235
|
-
components.register("conversation.web.
|
|
235
|
+
components.register("conversation.web.status.widget", ConversationStatusWidget);
|
|
236
236
|
}
|
|
237
237
|
});
|
|
238
238
|
|
|
@@ -241,6 +241,40 @@ const components = new Map();
|
|
|
241
241
|
export function registerComponent(id, component) { components.set(id, component); }
|
|
242
242
|
```
|
|
243
243
|
|
|
244
|
+
### Provider subpaths
|
|
245
|
+
|
|
246
|
+
**Export each client provider by a subpath of its own. The provider's file
|
|
247
|
+
imports only what every page needs, such as a widget the shell always shows; a
|
|
248
|
+
screen that only some routes show is imported by those routes.**
|
|
249
|
+
|
|
250
|
+
Why: every page of every app loads the client providers, and what they import,
|
|
251
|
+
before it shows anything. The client bootstrap imports a provider through the
|
|
252
|
+
subpath export that names its file, so the screens `./client` re-exports, and
|
|
253
|
+
their libraries, load only with the routes that show them. A provider without a
|
|
254
|
+
subpath, or a `./client` that declares `routeComponents` or `clientRoutes` or
|
|
255
|
+
uses `export *`, brings all of `./client` to every page.
|
|
256
|
+
|
|
257
|
+
```json
|
|
258
|
+
// good: package.json
|
|
259
|
+
"exports": {
|
|
260
|
+
"./client": "./src/client/index.js",
|
|
261
|
+
"./client/providers/ConversationClientProvider": "./src/client/providers/ConversationClientProvider.js"
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// bad: package.json, no subpath for the provider, so every page loads all of ./client
|
|
265
|
+
"exports": {
|
|
266
|
+
"./client": "./src/client/index.js"
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
```js
|
|
271
|
+
// good: the provider's file imports the widget every page shows
|
|
272
|
+
import ConversationStatusWidget from "../components/ConversationStatusWidget.vue";
|
|
273
|
+
|
|
274
|
+
// bad: the provider's file imports a screen that only its route shows
|
|
275
|
+
import ConversationSettingsScreen from "../components/ConversationSettingsScreen.vue";
|
|
276
|
+
```
|
|
277
|
+
|
|
244
278
|
### Injected values
|
|
245
279
|
|
|
246
280
|
**`inject()` takes the owner's exported key, never a literal. A required value
|
|
@@ -128,7 +128,13 @@ The foundation servers reuse compiled response serializers for identical JSON
|
|
|
128
128
|
schemas through `createCachedResponseSerializerFactory` from
|
|
129
129
|
`@jskit-ai/kernel/server/http`. This reduces duplicate startup compilation and
|
|
130
130
|
retained memory in applications with many routes. Each Fastify compiler context
|
|
131
|
-
keeps its own cache; request data and response payloads are not cached.
|
|
131
|
+
keeps its own cache; request data and response payloads are not cached. A
|
|
132
|
+
serializer is compiled when a response first uses it, in every environment, so
|
|
133
|
+
startup compiles none. Startup still checks every response schema as
|
|
134
|
+
fast-json-stringify would before building it: an invalid schema or a `$ref`
|
|
135
|
+
that does not resolve stops the server. A problem fast-json-stringify only
|
|
136
|
+
finds while generating a serializer fails the first response that uses it, so
|
|
137
|
+
keep a test that calls each route.
|
|
132
138
|
|
|
133
139
|
Existing applications adopt the same setup in their own `server.js` after
|
|
134
140
|
upgrading JSKIT and declaring the directly used
|
|
@@ -76,6 +76,7 @@ Why this is the standard JSKIT shape:
|
|
|
76
76
|
- `httpWebClient` already handles credentials and CSRF behavior.
|
|
77
77
|
- Standard read composables forward TanStack Query cancellation to the HTTP client. A custom `queryFn` must also pass its `signal` to `request()`; a custom client must honor it.
|
|
78
78
|
- Ordinary `GET`/`HEAD` requests have a 30-second deadline through JSON body reading even without a caller signal. Client `readTimeoutMs` and request `timeoutMs` accept positive finite integer milliseconds. CSRF session reads use `readTimeoutMs`. The transient HTTP client does not retry cancellations or deadline expiry; deadlines apply per HTTP attempt, not to an entire query lifecycle.
|
|
79
|
+
- One layer retries a failed request. The transient HTTP client retries a `GET`/`HEAD` that failed for a transient reason (no response, 502, 503, 504) twice, one and two seconds apart, and marks the error; `shouldRetryTransientQueryFailure` then does not retry that query, so an unreachable read is three requests and reaches request recovery in about three seconds. Query reads the client did not retry (other methods, custom fetches) keep the query's two transient retries. Do not add retries around either layer.
|
|
79
80
|
- Writes and `requestStream()` have no default overall deadline; pass `timeoutMs` explicitly when appropriate and cancel long-lived streams when their owner stops. Read deadlines do not impose a concurrency limit or protect raw `fetch` calls.
|
|
80
81
|
- `useEndpointResource()` is the shared endpoint primitive for loading, saving, and standard load/save error handling. Higher-level runtimes add UI feedback and field-error handling on top.
|
|
81
82
|
- Use `requestQueryParams` for endpoint query strings on list, view, and add/edit runtimes.
|
|
@@ -85,9 +85,9 @@ ends with the same link.
|
|
|
85
85
|
- [Tests are not callers](../typed-features.md#tests-are-not-callers)
|
|
86
86
|
- `…ForTests`, `__reset…`, `testOnly…` exports (`jskit/no-test-only-export`)
|
|
87
87
|
- [No test-only exports](../typed-features.md#no-test-only-exports)
|
|
88
|
-
- a list, batch or write test with one to three rows, no query count, a fixed query ceiling tuned to pass, a slow endpoint first seen with real data
|
|
88
|
+
- a list, batch or write test with one to three rows, no query count, a fixed query ceiling tuned to pass, a slow endpoint first seen with real data, a hand-written `knex.on("query")` counter, a patched `Client.prototype.query`, `countQueries`, `countRuntimeQueries`, a route's query count
|
|
89
89
|
- [Query counts at realistic sizes](../typed-features.md#query-counts-at-realistic-sizes)
|
|
90
|
-
- `node --test --test-concurrency=1`, `workers: 1`, `fileParallelism: false`, a suite that runs one file at a time, test files that collide when run together, `test/*` findings of `jskit check`
|
|
90
|
+
- `node --test --test-concurrency=1`, `workers: 1`, `fileParallelism: false`, a suite that runs one file at a time, test files that collide when run together, a Playwright webServer running `npm run develop` or `vite`, a browser suite that takes hours, `test/*` findings of `jskit check`
|
|
91
91
|
- [Test files run in parallel](../typed-features.md#test-files-run-in-parallel)
|
|
92
92
|
- `knex.migrate.latest()` in each test file, a template database rebuilt by migrating, test preparation slower than its tests
|
|
93
93
|
- [Test databases are prepared once](../typed-features.md#test-databases-are-prepared-once)
|
|
@@ -50,23 +50,28 @@ Rules:
|
|
|
50
50
|
## Keep startup incremental
|
|
51
51
|
|
|
52
52
|
Run related cases in one suite invocation. Prepare the isolated database and
|
|
53
|
-
fixtures once for that invocation, never once per test.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
53
|
+
fixtures once for that invocation, never once per test. An app's
|
|
54
|
+
`playwright.config.mjs` is `browserTestConfig()` from
|
|
55
|
+
`@jskit-ai/jskit-catalog/browser-tests`: the production build, made once and
|
|
56
|
+
reused while its sources are unchanged, and one server, port and database per
|
|
57
|
+
worker. Its `prepare` module (the `database/mysql-application` and
|
|
58
|
+
`database/postgres-application` patterns' `example/tests/e2e/databases.js`)
|
|
59
|
+
restores each worker's copy of `BROWSER_TEST_DB_NAME` from the stored schema
|
|
60
|
+
snapshot and runs the fixture seed, which restores any migration-owned
|
|
61
|
+
baseline rows. The migrations are replayed only when one changes, so a second
|
|
62
|
+
run reports a stored snapshot, no stale rows, and an unchanged normal
|
|
63
|
+
database.
|
|
64
|
+
|
|
65
|
+
Use `BROWSER_TEST_DB_NAME` for the browser copies and a different
|
|
66
|
+
`TEST_DB_NAME` for disposable integration and migration tests; the harness
|
|
67
|
+
refuses a collision, or one with the application's database, before
|
|
68
|
+
connecting.
|
|
69
|
+
|
|
70
|
+
Do not replay completed migrations, build every module fixture, or run a
|
|
71
|
+
production frontend build for each focused check. A
|
|
68
72
|
build made once for a whole run is different: it is the fix when a development
|
|
69
|
-
server makes every page load slow
|
|
73
|
+
server makes every page load slow, and browser tests never run on the
|
|
74
|
+
development server. Choose small fixture sets for the selected
|
|
70
75
|
suite; realistic row counts belong in the database tests that compare each
|
|
71
76
|
endpoint's query counts. Fresh-schema
|
|
72
77
|
migration tests and production-artifact tests are separate operations. Measure
|
|
@@ -56,8 +56,12 @@ config.tenancyPolicy = {
|
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
Provisioning runs in the users profile-sync lifecycle after registration and
|
|
59
|
-
sign-in
|
|
60
|
-
|
|
59
|
+
sign-in, at each session refresh, and on a request whose identity's email or
|
|
60
|
+
display name changed. The first run creates the personal workspace, its owner
|
|
61
|
+
membership and its settings; later runs reuse it. An ordinary request only reads
|
|
62
|
+
the existing profile, so a personal workspace, owner membership or settings row
|
|
63
|
+
deleted while the person is signed in comes back at their next sign-in or
|
|
64
|
+
session refresh, not at their next request. The default name is the user's display name,
|
|
61
65
|
or email, followed by "'s Workspace". To choose another, provide the
|
|
62
66
|
`workspaces.personal-workspace-name` capability from an application feature. It
|
|
63
67
|
receives the synchronized profile (`id`, `displayName`, `email`, `username`), and
|