@fabrika/provider-zerops 0.2.0 → 0.3.2

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 (83) hide show
  1. package/package.json +18 -5
  2. package/src/api/client.ts +522 -0
  3. package/src/api/errors.ts +50 -0
  4. package/src/api/polling.ts +59 -0
  5. package/src/api/readers.ts +185 -0
  6. package/src/api/service-env-response.ts +34 -0
  7. package/src/api/types.ts +602 -0
  8. package/src/api.ts +29 -1378
  9. package/src/authoring.ts +7 -10
  10. package/src/cli-args.ts +2 -6
  11. package/src/cli.ts +3 -28
  12. package/src/collaborators.ts +2 -4
  13. package/src/compile.ts +3 -1
  14. package/src/control.ts +203 -450
  15. package/src/descriptor.ts +179 -0
  16. package/src/index.ts +23 -127
  17. package/src/installation/admin-options.ts +100 -0
  18. package/src/installation/admin.ts +123 -0
  19. package/src/installation/deploy-options.ts +127 -0
  20. package/src/installation/deploy.ts +668 -0
  21. package/src/installation/generated/platform-console-schema.ts +41 -0
  22. package/src/installation/generated/platform-proxy-manifest.ts +72 -0
  23. package/src/installation/hosts.ts +117 -0
  24. package/src/installation/index.ts +390 -0
  25. package/src/installation/init-options.ts +148 -0
  26. package/src/installation/init.ts +394 -0
  27. package/src/installation/install-collaborators.ts +27 -0
  28. package/src/installation/install-environment.ts +193 -0
  29. package/src/installation/install-options.ts +156 -0
  30. package/src/installation/install-project.ts +201 -0
  31. package/src/installation/install-provisioning.ts +185 -0
  32. package/src/installation/install.ts +262 -0
  33. package/src/installation/installation-source.ts +42 -0
  34. package/src/installation/log.ts +77 -0
  35. package/src/installation/machine-key.ts +65 -0
  36. package/src/installation/manifest.ts +95 -0
  37. package/src/installation/placement-options.ts +33 -0
  38. package/src/installation/platform-source.ts +106 -0
  39. package/src/installation/platform-upload.ts +34 -0
  40. package/src/installation/proxy-manifest.ts +113 -0
  41. package/src/installation/secrets.ts +79 -0
  42. package/src/installation/sidecar.ts +125 -0
  43. package/src/installation/source-options.ts +12 -0
  44. package/src/installation/templates/README.md +116 -0
  45. package/src/installation/templates/fabrika.ref +1 -0
  46. package/src/installation/templates/gitignore +3 -0
  47. package/src/installation/templates/platform.yml +144 -0
  48. package/src/installation/topology/artifacts.ts +141 -0
  49. package/src/installation/topology/index.ts +13 -0
  50. package/src/installation/topology/installation-schemas.ts +225 -0
  51. package/src/installation/topology/invariants.ts +86 -0
  52. package/src/installation/topology/setups.ts +442 -0
  53. package/src/installation/topology/topology.ts +501 -0
  54. package/src/installation/topology/validate.ts +26 -0
  55. package/src/installation/upgrade-options.ts +99 -0
  56. package/src/installation/upgrade-output.ts +31 -0
  57. package/src/installation/upgrade.ts +373 -0
  58. package/src/managed-env.ts +113 -0
  59. package/src/manifest.ts +194 -344
  60. package/src/namespace/claims.ts +77 -0
  61. package/src/namespace/codec.ts +179 -0
  62. package/src/namespace/constants.ts +30 -0
  63. package/src/namespace/errors.ts +60 -0
  64. package/src/namespace/manifest.ts +28 -0
  65. package/src/namespace/operator.ts +151 -0
  66. package/src/namespace/provisioning.ts +482 -0
  67. package/src/namespace/proxy-attempt.ts +220 -0
  68. package/src/namespace/proxy-source.ts +22 -0
  69. package/src/namespace/topology.ts +115 -0
  70. package/src/namespace/types.ts +114 -0
  71. package/src/namespace.ts +34 -1271
  72. package/src/plan.ts +21 -23
  73. package/src/provider.ts +266 -241
  74. package/src/source/constants.ts +11 -0
  75. package/src/source/port.ts +49 -0
  76. package/src/source/types.ts +4 -0
  77. package/src/source/validation.ts +72 -0
  78. package/src/source.ts +2 -1220
  79. package/src/types.ts +8 -7
  80. package/src/version-attempt.ts +18 -0
  81. package/src/codec.ts +0 -108
  82. package/src/namespace-command.ts +0 -209
  83. package/src/source-connection.ts +0 -344
package/src/authoring.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { ZEROPS_SHARED_POSTGRES_CONNECTION_STRING } from './namespace'
2
2
  export { zeropsSharedServiceHostname, zeropsSharedServicePrefix } from './service-names'
3
3
  import { APP_PROVIDER, isProviderAuthoredApp, type ProviderAuthoredApp } from '@fabrika/provider-contract'
4
+ import { z } from 'zod'
4
5
  import type { ZeropsAppConfig, ZeropsSharedPostgresBinding } from './types'
5
6
 
6
7
  /** Declare consumption of the namespace-owned `postgres` service without resolving its credential. */
@@ -20,14 +21,10 @@ export const defineApp = (config: ZeropsAppConfig): ZeropsAuthoredAppConfig => {
20
21
  return { ...config, [APP_PROVIDER]: 'zerops' }
21
22
  }
22
23
 
23
- const property = (value: unknown, key: string): unknown => typeof value === 'object' && value !== null ? Reflect.get(value, key) : undefined
24
+ const zeropsAppConfigSchema = z.object({
25
+ id: z.string().refine((id) => id.trim() !== ''),
26
+ target: z.object({ platform: z.literal('zerops'), services: z.function() }),
27
+ })
24
28
 
25
- export const isZeropsAppConfig = (value: unknown): value is ZeropsAuthoredAppConfig => {
26
- const id = property(value, 'id')
27
- const target = property(value, 'target')
28
- return isProviderAuthoredApp(value, 'zerops')
29
- && typeof id === 'string'
30
- && id.trim() !== ''
31
- && property(target, 'platform') === 'zerops'
32
- && typeof property(target, 'services') === 'function'
33
- }
29
+ export const isZeropsAppConfig = (value: unknown): value is ZeropsAuthoredAppConfig =>
30
+ isProviderAuthoredApp(value, 'zerops') && zeropsAppConfigSchema.safeParse(value).success
package/src/cli-args.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { describeArgument } from '@fabrika/installation-init'
1
2
  export interface ZeropsCliArgs {
2
3
  command: string | undefined
3
4
  subcommand: string | undefined
@@ -13,7 +14,6 @@ export interface ZeropsCliArgs {
13
14
  publicAccess: string | undefined
14
15
  postgresType: string | undefined
15
16
  postgresProfile: string | undefined
16
- proxyBuildFromGit: string | undefined
17
17
  controlUrl: string | undefined
18
18
  help: boolean
19
19
  }
@@ -33,7 +33,6 @@ export const parseZeropsCliArgs = (argv: readonly string[]): ZeropsCliArgs => {
33
33
  let publicAccess: string | undefined
34
34
  let postgresType: string | undefined
35
35
  let postgresProfile: string | undefined
36
- let proxyBuildFromGit: string | undefined
37
36
  let controlUrl: string | undefined
38
37
  let help = false
39
38
 
@@ -64,8 +63,6 @@ export const parseZeropsCliArgs = (argv: readonly string[]): ZeropsCliArgs => {
64
63
  postgresType = arg.slice('--postgres-type='.length)
65
64
  } else if (arg.startsWith('--postgres-profile=')) {
66
65
  postgresProfile = arg.slice('--postgres-profile='.length)
67
- } else if (arg.startsWith('--proxy-build-from-git=')) {
68
- proxyBuildFromGit = arg.slice('--proxy-build-from-git='.length)
69
66
  } else if (arg.startsWith('--control-url=')) {
70
67
  controlUrl = arg.slice('--control-url='.length)
71
68
  } else if (arg.startsWith('-')) {
@@ -75,7 +72,7 @@ export const parseZeropsCliArgs = (argv: readonly string[]): ZeropsCliArgs => {
75
72
  } else if (subcommand === undefined && command === 'namespace') {
76
73
  subcommand = arg
77
74
  } else {
78
- throw new Error(`Unexpected argument: ${arg}`)
75
+ throw new Error(`Unexpected argument: ${describeArgument(arg)}`)
79
76
  }
80
77
  }
81
78
 
@@ -94,7 +91,6 @@ export const parseZeropsCliArgs = (argv: readonly string[]): ZeropsCliArgs => {
94
91
  publicAccess,
95
92
  postgresType,
96
93
  postgresProfile,
97
- proxyBuildFromGit,
98
94
  controlUrl,
99
95
  help,
100
96
  }
package/src/cli.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  import { constants } from 'node:fs'
3
3
  import { open } from 'node:fs/promises'
4
4
  import { resolve } from 'node:path'
5
+ import { z } from 'zod'
5
6
  import { isZeropsAppConfig } from './authoring'
6
7
  import { parseZeropsCliArgs } from './cli-args'
7
8
  import {
@@ -10,44 +11,26 @@ import {
10
11
  manifestServiceHostnames,
11
12
  ZEROPS_SOURCE_DESCRIPTOR_MAX_BYTES,
12
13
  } from './manifest'
13
- import { runZeropsNamespaceCommand } from './namespace-command'
14
14
  import type { ZeropsAppConfig } from './types'
15
15
 
16
16
  const USAGE = `Zerops app tools
17
17
 
18
18
  Usage:
19
19
  fabrika app build --provider=zerops --env=<env> [--config=<path>] [--output=<path>]
20
- fabrika namespace plan --provider=zerops --id=<id> --env=<env> --preset=<cheap|mid|full> [namespace options]
21
- fabrika namespace create --provider=zerops --id=<id> --env=<env> --preset=<cheap|mid|full> [namespace options] [--control-url=<url>]
22
- fabrika namespace adopt --provider=zerops --id=<id> --env=<env> --preset=<cheap|mid|full> --project-id=<id> [namespace options] [--control-url=<url>]
23
- fabrika namespace reconcile --provider=zerops --id=<id> [--control-url=<url>]
24
20
 
25
21
  Options:
26
22
  --env=<env> Environment.
27
23
  --config=<path> App config (default: ./fabrika.config.ts).
28
24
  --output=<path> Artifact path (default: ./fabrika.manifest.json).
29
- --id=<id> Namespace id.
30
- --preset=<cheap|mid|full> Provider-owned namespace preset.
31
- --exclusive-app=<id> App reserved by a full namespace.
32
- --project-id=<id> Existing Zerops project id for adoption.
33
- --project-name=<name> Zerops project name (default: namespace id).
34
- --core-package=<tier> LIGHT or SERIOUS.
35
- --public-access=<mode> custom-domain or zerops-subdomain.
36
- --postgres-type=<type> Cheap-tier PostgreSQL type.
37
- --postgres-profile=<profile> Cheap-tier PostgreSQL profile.
38
- --proxy-build-from-git=<url> Public proxy source; or FABRIKA_ZEROPS_PROXY_BUILD_FROM_GIT.
39
- --control-url=<url> Control origin; or FABRIKA_CONTROL_URL.
40
25
  -h, --help Show this help.
41
-
42
- Mutating namespace commands read the Bearer credential from FABRIKA_CONTROL_TOKEN.
43
26
  `
44
27
 
45
- const property = (value: unknown, key: string): unknown => typeof value === 'object' && value !== null ? Reflect.get(value, key) : undefined
28
+ const configModuleSchema = z.object({ default: z.unknown() })
46
29
 
47
30
  const loadConfig = async (path: string): Promise<ZeropsAppConfig> => {
48
31
  const absolute = resolve(process.cwd(), path)
49
32
  const loaded: unknown = await import(absolute)
50
- const config = property(loaded, 'default')
33
+ const config = configModuleSchema.safeParse(loaded).data?.default
51
34
  if (!isZeropsAppConfig(config)) {
52
35
  throw new Error(`Config at ${absolute} must default-export defineApp({ target: { platform: 'zerops', ... } })`)
53
36
  }
@@ -92,14 +75,6 @@ export const runZeropsCli = async (argv: readonly string[]): Promise<void> => {
92
75
  console.info(USAGE)
93
76
  return
94
77
  }
95
- if (args.command === 'namespace') {
96
- await runZeropsNamespaceCommand(args, {
97
- source: process.env,
98
- fetch: globalThis.fetch,
99
- write: (value) => console.info(value.trimEnd()),
100
- })
101
- return
102
- }
103
78
  if (args.command !== 'build') {
104
79
  throw new Error(`Unknown command: ${args.command}\n${USAGE}`)
105
80
  }
@@ -1,7 +1,7 @@
1
1
  import { reconcileSchema } from '@fabrika/auth'
2
2
  import type { SchemaReconciler } from '@fabrika/provider-contract'
3
3
  import { createZeropsApi, type ZeropsApi } from './api'
4
- import type { ZeropsSourceClient } from './source'
4
+ import type { ZeropsSourcePort } from './source/port'
5
5
  import type { ZeropsRuntimeTarget } from './types'
6
6
 
7
7
  export type Sleeper = (ms: number, signal: AbortSignal) => Promise<void>
@@ -26,9 +26,7 @@ export const defaultSleep: Sleeper = (ms, signal) =>
26
26
  export interface ZeropsCollaborators {
27
27
  api: ZeropsApi
28
28
  /** Injected by the Zerops control composition; dry runs do not require it. */
29
- source?: ZeropsSourceClient
30
- /** Independently bounds best-effort source cancellation without delaying Zerops cleanup. */
31
- sourceCancelSleep?: Sleeper
29
+ source?: ZeropsSourcePort
32
30
  reconcileSchema: SchemaReconciler
33
31
  sleep: Sleeper
34
32
  }
package/src/compile.ts CHANGED
@@ -280,6 +280,8 @@ const isYamlHostileCodePoint = (code: number): boolean =>
280
280
  || code === 0x2028
281
281
  || code === 0x2029
282
282
  || code === 0xfeff
283
+ || code === 0xfffe
284
+ || code === 0xffff
283
285
  || (code >= 0xd800 && code <= 0xdfff)
284
286
 
285
287
  /** `JSON.stringify` leaves DEL, the C1 block, U+2028/9 and U+FEFF raw; YAML's own `\uXXXX` carries them. */
@@ -291,7 +293,7 @@ const escapeYamlHostile = (quoted: string): string =>
291
293
 
292
294
  const scalar = (value: string): string => {
293
295
  // Reserved plain scalars that YAML would read as booleans/null, plus anything with structure.
294
- const reserved = new Set(['true', 'false', 'null', 'yes', 'no', 'on', 'off', '~'])
296
+ const reserved = new Set(['true', 'false', 'null', 'yes', 'no', 'y', 'n', 'on', 'off', '~'])
295
297
  if (value !== '' && PLAIN.test(value) && !reserved.has(value.toLowerCase())) {
296
298
  return value
297
299
  }