@mizchi/k1c 0.2.0 → 0.3.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.
@@ -32,6 +32,8 @@ const volumeSchema = z.object({
32
32
  queueRef: z.object({ name: z.string() }).optional(),
33
33
  vectorizeRef: z.object({ name: z.string() }).optional(),
34
34
  analyticsEngineRef: z.object({ dataset: z.string() }).optional(),
35
+ mtlsCertificateRef: z.object({ certificateId: z.string() }).optional(),
36
+ pipelinesRef: z.object({ pipelineId: z.string() }).optional(),
35
37
  });
36
38
  const containerSchema = z.object({
37
39
  name: z.string(),
@@ -286,6 +288,35 @@ export const logpushJobSchema = z.object({
286
288
  message: 'LogpushJob.spec must specify exactly one of zoneId / accountId',
287
289
  }),
288
290
  });
291
+ const ingressBackendSchema = z.object({
292
+ service: z.object({
293
+ name: z.string().min(1),
294
+ port: z
295
+ .object({
296
+ number: z.number().int().positive().optional(),
297
+ name: z.string().optional(),
298
+ })
299
+ .optional(),
300
+ }),
301
+ });
302
+ const ingressPathSchema = z.object({
303
+ path: z.string().min(1),
304
+ pathType: z.enum(['Prefix', 'Exact', 'ImplementationSpecific']),
305
+ backend: ingressBackendSchema,
306
+ });
307
+ const ingressRuleSchema = z.object({
308
+ host: z.string().min(1).optional(),
309
+ http: z.object({ paths: z.array(ingressPathSchema).min(1) }),
310
+ });
311
+ export const ingressSchema = z.object({
312
+ apiVersion: z.literal('networking.k8s.io/v1'),
313
+ kind: z.literal('Ingress'),
314
+ metadata: objectMetaSchema,
315
+ spec: z.object({
316
+ rules: z.array(ingressRuleSchema).min(1),
317
+ defaultBackend: ingressBackendSchema.optional(),
318
+ }),
319
+ });
289
320
  export const k1cResourceSchema = z.discriminatedUnion('kind', [
290
321
  deploymentSchema,
291
322
  rolloutSchema,
@@ -305,5 +336,6 @@ export const k1cResourceSchema = z.discriminatedUnion('kind', [
305
336
  vectorizeSchema,
306
337
  dnsRecordSchema,
307
338
  logpushJobSchema,
339
+ ingressSchema,
308
340
  ]);
309
341
  //# sourceMappingURL=schemas.js.map
@@ -61,6 +61,12 @@ export interface Volume {
61
61
  readonly analyticsEngineRef?: {
62
62
  readonly dataset: string;
63
63
  };
64
+ readonly mtlsCertificateRef?: {
65
+ readonly certificateId: string;
66
+ };
67
+ readonly pipelinesRef?: {
68
+ readonly pipelineId: string;
69
+ };
64
70
  }
65
71
  export interface PodTemplateSpec {
66
72
  readonly metadata?: ObjectMeta;
@@ -233,7 +239,33 @@ export interface LogpushJobSpec {
233
239
  readonly filter?: string;
234
240
  }
235
241
  export type LogpushJob = BaseResource<'LogpushJob', 'cloudflare.k1c.io/v1alpha1', LogpushJobSpec>;
236
- export type K1cResource = Deployment | Rollout | StatefulSet | CronJob | Job | ConfigMapResource | SecretResource | NamespaceResource | ServiceResource | R2Bucket | KVNamespace | DispatchNamespace | Hyperdrive | D1Database | Queue | Vectorize | DNSRecord | LogpushJob;
242
+ export type IngressPathType = 'Prefix' | 'Exact' | 'ImplementationSpecific';
243
+ export interface IngressBackend {
244
+ readonly service: {
245
+ readonly name: string;
246
+ readonly port?: {
247
+ readonly number?: number;
248
+ readonly name?: string;
249
+ };
250
+ };
251
+ }
252
+ export interface IngressPath {
253
+ readonly path: string;
254
+ readonly pathType: IngressPathType;
255
+ readonly backend: IngressBackend;
256
+ }
257
+ export interface IngressRule {
258
+ readonly host?: string;
259
+ readonly http: {
260
+ readonly paths: ReadonlyArray<IngressPath>;
261
+ };
262
+ }
263
+ export interface IngressSpec {
264
+ readonly rules: ReadonlyArray<IngressRule>;
265
+ readonly defaultBackend?: IngressBackend;
266
+ }
267
+ export type Ingress = BaseResource<'Ingress', 'networking.k8s.io/v1', IngressSpec>;
268
+ export type K1cResource = Deployment | Rollout | StatefulSet | CronJob | Job | ConfigMapResource | SecretResource | NamespaceResource | ServiceResource | R2Bucket | KVNamespace | DispatchNamespace | Hyperdrive | D1Database | Queue | Vectorize | DNSRecord | LogpushJob | Ingress;
237
269
  export type ResourceKind = K1cResource['kind'];
238
270
  export interface ResourceRef {
239
271
  readonly apiVersion: string;
@@ -100,6 +100,14 @@ export type WorkerBinding = {
100
100
  readonly type: 'analytics_engine';
101
101
  readonly name: string;
102
102
  readonly dataset: string;
103
+ } | {
104
+ readonly type: 'mtls_certificate';
105
+ readonly name: string;
106
+ readonly certificateId: string;
107
+ } | {
108
+ readonly type: 'pipelines';
109
+ readonly name: string;
110
+ readonly pipeline: string;
103
111
  };
104
112
  export declare const workerSchema: z.ZodType<WorkerProperties>;
105
113
  export declare const workerProvider: CloudflareResourceProvider<WorkerProperties>;
@@ -64,6 +64,16 @@ export const workerSchema = z.object({
64
64
  name: z.string(),
65
65
  dataset: z.string(),
66
66
  }),
67
+ z.object({
68
+ type: z.literal('mtls_certificate'),
69
+ name: z.string(),
70
+ certificateId: z.string(),
71
+ }),
72
+ z.object({
73
+ type: z.literal('pipelines'),
74
+ name: z.string(),
75
+ pipeline: z.string(),
76
+ }),
67
77
  ]))
68
78
  .optional(),
69
79
  observability: z.object({ enabled: z.boolean() }).optional(),
@@ -137,6 +147,12 @@ function buildBindings(props) {
137
147
  else if (b.type === 'analytics_engine') {
138
148
  out.push({ type: 'analytics_engine', name: b.name, dataset: b.dataset });
139
149
  }
150
+ else if (b.type === 'mtls_certificate') {
151
+ out.push({ type: 'mtls_certificate', name: b.name, certificate_id: b.certificateId });
152
+ }
153
+ else if (b.type === 'pipelines') {
154
+ out.push({ type: 'pipelines', name: b.name, pipeline: b.pipeline });
155
+ }
140
156
  }
141
157
  return out;
142
158
  }
@@ -306,6 +322,12 @@ function fromCFBinding(b) {
306
322
  if (b.type === 'analytics_engine' && b.dataset !== undefined) {
307
323
  return { type: 'analytics_engine', name: b.name, dataset: b.dataset };
308
324
  }
325
+ if (b.type === 'mtls_certificate' && b.certificate_id !== undefined) {
326
+ return { type: 'mtls_certificate', name: b.name, certificateId: b.certificate_id };
327
+ }
328
+ if (b.type === 'pipelines' && b.pipeline !== undefined) {
329
+ return { type: 'pipelines', name: b.name, pipeline: b.pipeline };
330
+ }
309
331
  return null;
310
332
  }
311
333
  export const workerProvider = {
@@ -102,9 +102,50 @@ function orderByDependencies(operations, desired) {
102
102
  });
103
103
  const sortedMutating = topoSort(nodes).map((n) => n.op);
104
104
  noops.sort((a, b) => a.label.localeCompare(b.label));
105
- deletes.sort((a, b) => a.label.localeCompare(b.label));
105
+ deletes.sort((a, b) => {
106
+ const pa = deletePriority(a.resourceType);
107
+ const pb = deletePriority(b.resourceType);
108
+ if (pa !== pb)
109
+ return pa - pb;
110
+ return a.label.localeCompare(b.label);
111
+ });
106
112
  return [...sortedMutating, ...noops, ...deletes];
107
113
  }
114
+ /**
115
+ * Reverse-topological priority for deletes. Smaller priority is deleted first.
116
+ *
117
+ * The reconciler has no per-instance dependency record for resources that are
118
+ * being deleted (they are no longer in `desired`), so we approximate the
119
+ * dependency direction with a static type ordering that mirrors how creates
120
+ * actually flow in `lower.ts`. Workers depend on data services; CustomDomain /
121
+ * Workflow / LogpushJob depend on Workers; DispatchNamespace hosts Workers.
122
+ *
123
+ * Unknown types fall through with a neutral priority so the sort is still stable.
124
+ */
125
+ function deletePriority(resourceType) {
126
+ switch (resourceType) {
127
+ // Top-level edges — nothing else points at these. Delete first so we do not
128
+ // serve traffic to a Worker we are about to remove.
129
+ case 'CustomDomain':
130
+ case 'DNSRecord':
131
+ case 'LogpushJob':
132
+ case 'Workflow':
133
+ return 0;
134
+ case 'Worker':
135
+ return 1;
136
+ case 'R2Bucket':
137
+ case 'KVNamespace':
138
+ case 'D1Database':
139
+ case 'Hyperdrive':
140
+ case 'Vectorize':
141
+ case 'Queue':
142
+ return 2;
143
+ case 'DispatchNamespace':
144
+ return 3;
145
+ default:
146
+ return 1;
147
+ }
148
+ }
108
149
  export function propertiesEqual(a, b) {
109
150
  return canonicalize(a) === canonicalize(b);
110
151
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mizchi/k1c",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Experimental kubectl-style apply tool for Cloudflare",
5
5
  "keywords": [
6
6
  "cloudflare",